Skip to content

Commit

Permalink
Implement up gate alternation dragging
Browse files Browse the repository at this point in the history
- Grabbing a gate with alt held swiches to its alternate
- Alternate of control is anti-control, alternate of rotation is opposite rotation, etc
- Add 'alternate' property to Gate
- Specify alternates for existing gates
- Refactor 'silly' toolbox section into 'scalar'
  • Loading branch information
Strilanc committed Aug 12, 2019
1 parent 4cbf0ac commit 25e189d
Show file tree
Hide file tree
Showing 31 changed files with 251 additions and 82 deletions.
56 changes: 45 additions & 11 deletions src/circuit/Gate.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ class Gate {
* @private
*/
this._isDefinitelyUnitary = false;
/**
* The alternate gate for this one, used when shift+alt dragging.
* @type {!Gate}
*/
this.alternate = this;
/**
* Returns context provided by this gate to other gates in the same column (or later columns in some cases).
* @param {!int} qubit
Expand Down Expand Up @@ -235,22 +240,23 @@ class Gate {
* @param {!string} name
* @param {!string} blurb
* @param {undefined|!string} serializedId
* @param {undefined|!Gate=} alternate
* @returns {!Gate}
*/
static fromKnownMatrix(symbol, matrix, name='', blurb='', serializedId=undefined) {
static fromKnownMatrix(symbol, matrix, name='', blurb='', serializedId=undefined, alternate=undefined) {
if (!(matrix instanceof Matrix)) {
throw new DetailedError("Bad matrix.", {symbol, matrix, name, blurb});
}
let g = new Gate();
g.symbol = symbol;
g.serializedId = serializedId === undefined ? symbol : serializedId;
g.name = name;
g.blurb = blurb;
g._isDefinitelyUnitary = matrix.isUnitary(0.01);
g._hasNoEffect = matrix.isIdentity();
g._stableDuration = Infinity;
g._knownMatrix = matrix;
return g;
let builder = new GateBuilder().
setSymbol(symbol).
setSerializedId(serializedId === undefined ? symbol : serializedId).
setTitle(name).
setBlurb(blurb).
setKnownEffectToMatrix(matrix);
if (alternate !== undefined) {
builder = builder.setAlternate(alternate);
}
return builder.gate;
}

/**
Expand All @@ -263,6 +269,7 @@ class Gate {
g.symbol = this.symbol;
g.name = this.name;
g.blurb = this.blurb;
g.alternate = this.alternate;
g.serializedId = this.serializedId;
g.onClickGateFunc = this.onClickGateFunc;
g.tag = this.tag;
Expand Down Expand Up @@ -489,6 +496,33 @@ class GateBuilder {
return this;
}

/**
* @param {!{all: !Array.<!Gate>, ofSize: !function(!int) : !Gate}} alternateFamily
* @returns {!GateBuilder}
*/
setAlternateFromFamily(alternateFamily) {
return this.setAlternate(alternateFamily.ofSize(this.gate.height));
}

/**
* @param {!Gate} alternate
* @returns {!GateBuilder}
*/
setAlternate(alternate) {
if (alternate === undefined) {
throw new Error("alternate === undefined");
}
if (alternate.height !== this.gate.height) {
throw new Error("alternate.height !== this.gate.height");
}
if (alternate.alternate !== alternate) {
throw new Error("alternate.alternate !== alternate");
}
alternate.alternate = this.gate;
this.gate.alternate = alternate;
return this;
}

/**
* Specifies the id to use when serializing/parsing this gate (instead of defaulting to the symbol).
* @param {!string} serializedId
Expand Down
30 changes: 21 additions & 9 deletions src/gates/AllGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ import {ErrorInjectionGate} from "src/gates/Debug_ErrorInjectionGate.js"
import {ExponentiatingGates} from "src/gates/ExponentiatingGates.js"
import {FourierTransformGates} from "src/gates/FourierTransformGates.js"
import {HalfTurnGates} from "src/gates/HalfTurnGates.js"
import {ImaginaryGate} from "src/gates/Joke_ImaginaryGate.js"
import {
ImaginaryGate,
AntiImaginaryGate,
SqrtImaginaryGate,
AntiSqrtImaginaryGate
} from "src/gates/Joke_ImaginaryGate.js"
import {IncrementGates} from "src/gates/IncrementGates.js"
import {InputGates} from "src/gates/InputGates.js"
import {InterleaveBitsGates} from "src/gates/InterleaveBitsGates.js"
Expand Down Expand Up @@ -91,6 +96,9 @@ Gates.Exponentiating = ExponentiatingGates;
Gates.FourierTransformGates = FourierTransformGates;
Gates.HalfTurns = HalfTurnGates;
Gates.ImaginaryGate = ImaginaryGate;
Gates.AntiImaginaryGate = AntiImaginaryGate;
Gates.SqrtImaginaryGate = SqrtImaginaryGate;
Gates.AntiSqrtImaginaryGate = AntiSqrtImaginaryGate;
Gates.IncrementGates = IncrementGates;
Gates.InputGates = InputGates;
Gates.InterleaveBitsGates = InterleaveBitsGates;
Expand Down Expand Up @@ -129,6 +137,9 @@ Gates.KnownToSerializer = [
ZeroGate,
NeGate,
ImaginaryGate,
AntiImaginaryGate,
SqrtImaginaryGate,
AntiSqrtImaginaryGate,

...AmplitudeDisplayFamily.all,
...ProbabilityDisplayFamily.all,
Expand Down Expand Up @@ -250,14 +261,6 @@ Gates.TopToolboxGroups = [
Detectors.XDetector, Detectors.XDetectControlClear,
]
},
{
hint: 'Silly',
gates: [
ZeroGate, MysteryGateMaker(),
NeGate, ImaginaryGate,
SpacerGate, undefined,
]
},
];

/** @type {!Array<!{hint: !string, gates: !Array<undefined|!Gate>}>} */
Expand Down Expand Up @@ -332,6 +335,15 @@ Gates.BottomToolboxGroups = [
ModularMultiplicationGates.TimesInverseBToTheAModRFamily.ofSize(2),
]
},
{
hint: 'Scalar',
gates: [
SpacerGate, ZeroGate,
NeGate, undefined,
ImaginaryGate, AntiImaginaryGate,
SqrtImaginaryGate, AntiSqrtImaginaryGate,
]
},
];

/** @type {!Map.<undefined|!string, !Array.<!Gate>>} */
Expand Down
2 changes: 2 additions & 0 deletions src/gates/ArithmeticGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ ArithmeticGates.Legacy_AdditionFamily = Gate.buildFamily(2, 16, (span, builder)
setKnownEffectToPermutation(chunkedScaledAdditionPermutationMaker(span, 1)));

ArithmeticGates.Legacy_SubtractionFamily = Gate.buildFamily(2, 16, (span, builder) => builder.
setAlternateFromFamily(ArithmeticGates.Legacy_AdditionFamily).
setSerializedId("sub" + span).
setSymbol("b-=a").
setTitle("Subtraction Gate").
Expand All @@ -76,6 +77,7 @@ ArithmeticGates.PlusAFamily = Gate.buildFamily(1, 16, (span, builder) => builder
setKnownEffectToParametrizedPermutation((v, a) => (v + a) & ((1 << span) - 1)));

ArithmeticGates.MinusAFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(ArithmeticGates.PlusAFamily).
setSerializedId("-=A" + span).
setSymbol("−A").
setTitle("Subtraction Gate [input A]").
Expand Down
1 change: 1 addition & 0 deletions src/gates/BitCountGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ BitCountGates.PlusBitCountAFamily = Gate.buildFamily(1, 16, (span, builder) => b
setKnownEffectToParametrizedPermutation((t, a) => (t + Util.numberOfSetBits(a)) & ((1 << span) - 1)));

BitCountGates.MinusBitCountAFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(BitCountGates.PlusBitCountAFamily).
setSerializedIdAndSymbol("-cntA" + span).
setSymbol("-1s(A)").
setTitle("Bit Un-Count Gate").
Expand Down
3 changes: 3 additions & 0 deletions src/gates/ComparisonGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ ComparisonGates.ALessThanB = new GateBuilder().
gate;

ComparisonGates.AGreaterThanB = new GateBuilder().
setAlternate(ComparisonGates.ALessThanB).
setSerializedId("^A>B").
setSymbol("⊕A>B").
setTitle("Greater-Than Gate").
Expand All @@ -67,6 +68,7 @@ ComparisonGates.ALessThanOrEqualToB = new GateBuilder().
gate;

ComparisonGates.AGreaterThanOrEqualToB = new GateBuilder().
setAlternate(ComparisonGates.ALessThanOrEqualToB).
setSerializedId("^A>=B").
setSymbol("⊕A≥B").
setTitle("At-Least Gate").
Expand All @@ -87,6 +89,7 @@ ComparisonGates.AEqualToB = new GateBuilder().
gate;

ComparisonGates.ANotEqualToB = new GateBuilder().
setAlternate(ComparisonGates.AEqualToB).
setSerializedId("^A!=B").
setSymbol("⊕A≠B").
setTitle("Inequality Gate").
Expand Down
3 changes: 3 additions & 0 deletions src/gates/Controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Controls.Control = new GateBuilder().
gate;

Controls.AntiControl = new GateBuilder().
setAlternate(Controls.Control).
setSerializedIdAndSymbol("◦").
setTitle("Anti-Control").
setBlurb("Conditions on a qubit being OFF.\nGates in the same column only apply to states meeting the condition.").
Expand Down Expand Up @@ -80,6 +81,7 @@ Controls.XAntiControl = new GateBuilder().
gate;

Controls.XControl = new GateBuilder().
setAlternate(Controls.XAntiControl).
setSerializedId("⊖"). // The drawn +/- convention was changed, but the serialized id must stay the same.
setSymbol("⊕").
setTitle("X-Axis Control").
Expand Down Expand Up @@ -135,6 +137,7 @@ Controls.YAntiControl = new GateBuilder().
gate;

Controls.YControl = new GateBuilder().
setAlternate(Controls.YAntiControl).
setSerializedId("(/)"). // The drawn cross/slash convention was changed, but the serialized id must stay the same.
setSymbol("⊗").
setTitle("Y-Axis Control").
Expand Down
1 change: 1 addition & 0 deletions src/gates/CountingGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ CountingGates.CountingFamily = Gate.buildFamily(1, 16, (span, builder) => builde
setKnownEffectToTimeVaryingPermutation((t, i) => offsetPermutation(t, +1, span, i)));

CountingGates.UncountingFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(CountingGates.CountingFamily).
setSerializedId("Uncounting" + span).
setSymbol("-⌈t⌉").
setTitle("Down Counting Gate").
Expand Down
1 change: 1 addition & 0 deletions src/gates/CycleBitsGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ CycleBitsGates.CycleBitsFamily = Gate.buildFamily(2, 16, (span, builder) => buil
setKnownEffectToBitPermutation(i => (i + 1) % span));

CycleBitsGates.ReverseCycleBitsFamily = Gate.buildFamily(2, 16, (span, builder) => builder.
setAlternateFromFamily(CycleBitsGates.CycleBitsFamily).
setSerializedId(">>" + span).
setSymbol(">>>").
setTitle("Right Rotate").
Expand Down
3 changes: 3 additions & 0 deletions src/gates/ExponentiatingGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ ExponentiatingGates.XForward = new GateBuilder().
gate;

ExponentiatingGates.XBackward = new GateBuilder().
setAlternate(ExponentiatingGates.XForward).
setSerializedIdAndSymbol("e^iXt").
setTitle("X-Exponentiating Gate (backward)").
setBlurb("Left-hand rotation around the X axis.\nPasses through ±iX instead of X.").
Expand All @@ -63,6 +64,7 @@ ExponentiatingGates.YForward = new GateBuilder().
gate;

ExponentiatingGates.YBackward = new GateBuilder().
setAlternate(ExponentiatingGates.YForward).
setSerializedIdAndSymbol("e^iYt").
setTitle("Y-Exponentiating Gate (backward)").
setBlurb("Left-hand rotation around the Y axis.\nPasses through ±iY instead of Y.").
Expand All @@ -81,6 +83,7 @@ ExponentiatingGates.ZForward = new GateBuilder().
gate;

ExponentiatingGates.ZBackward = new GateBuilder().
setAlternate(ExponentiatingGates.ZForward).
setSerializedIdAndSymbol("e^iZt").
setTitle("Z-Exponentiating Gate (backward)").
setBlurb("Left-hand rotation around the Z axis.\nPasses through ±iZ instead of Z.").
Expand Down
1 change: 1 addition & 0 deletions src/gates/FourierTransformGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ FourierTransformGates.FourierTransformFamily = Gate.buildFamily(1, 16, (span, bu
FourierTransformGates.InverseFourierTransformFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setSerializedId("QFT†" + span).
setSymbol("QFT^†").
setAlternateFromFamily(FourierTransformGates.FourierTransformFamily).
setTitle("Inverse Fourier Transform Gate").
setBlurb("Transforms from/to phase frequency space.").
setActualEffectToUpdateFunc(ctx => applyBackwardGradientShaders(ctx, span)).
Expand Down
1 change: 1 addition & 0 deletions src/gates/IncrementGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ IncrementGates.IncrementFamily = Gate.buildFamily(1, 16, (span, builder) => buil
setKnownEffectToPermutation(t => (t + 1) & ((1 << span) - 1)));

IncrementGates.DecrementFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(IncrementGates.IncrementFamily).
setSerializedId("dec" + span).
setSymbol("−1").
setTitle("Decrement Gate").
Expand Down
1 change: 1 addition & 0 deletions src/gates/InterleaveBitsGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ InterleaveBitsGates.InterleaveBitsGateFamily = Gate.buildFamily(4, 16, (span, bu
setKnownEffectToBitPermutation(b => interleaveBit(b, span)));

InterleaveBitsGates.DeinterleaveBitsGateFamily = Gate.buildFamily(4, 16, (span, builder) => builder.
setAlternateFromFamily(InterleaveBitsGates.InterleaveBitsGateFamily).
setSerializedId("split" + span).
setSymbol("Deinterleave").
setTitle("Deinterleave").
Expand Down
37 changes: 36 additions & 1 deletion src/gates/Joke_ImaginaryGate.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,39 @@ const ImaginaryGate = new GateBuilder().
setKnownEffectToMatrix(Matrix.square(Complex.I, 0, 0, Complex.I)).
gate;

export {ImaginaryGate}
const AntiImaginaryGate = new GateBuilder().
setAlternate(ImaginaryGate).
setSerializedIdAndSymbol("-i").
setTitle("Anti-Imaginary Gate").
setBlurb("Phases everything by -i.").
setDrawer(args => {
GatePainting.paintLocationIndependentFrame(args);
GatePainting.paintGateSymbol(args);
}).
setKnownEffectToMatrix(Matrix.square(Complex.I.neg(), 0, 0, Complex.I.neg())).
gate;

const SqrtImaginaryGate = new GateBuilder().
setSerializedIdAndSymbol("√i").
setTitle("Half Imaginary Gate").
setBlurb("Phases everything by √i.").
setDrawer(args => {
GatePainting.paintLocationIndependentFrame(args);
GatePainting.paintGateSymbol(args);
}).
setKnownEffectToMatrix(Matrix.square(1, 0, 0, 1).times(new Complex(Math.sqrt(0.5), Math.sqrt(0.5)))).
gate;

const AntiSqrtImaginaryGate = new GateBuilder().
setAlternate(SqrtImaginaryGate).
setSerializedIdAndSymbol("√-i").
setTitle("Half Anti-Imaginary Gate").
setBlurb("Phases everything by √-i.").
setDrawer(args => {
GatePainting.paintLocationIndependentFrame(args);
GatePainting.paintGateSymbol(args);
}).
setKnownEffectToMatrix(Matrix.square(1, 0, 0, 1).times(new Complex(Math.sqrt(0.5), -Math.sqrt(0.5)))).
gate;

export {AntiImaginaryGate, ImaginaryGate, SqrtImaginaryGate, AntiSqrtImaginaryGate}
1 change: 1 addition & 0 deletions src/gates/ModularAdditionGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ ModularAdditionGates.PlusAModRFamily = Gate.buildFamily(1, 16, (span, builder) =
setKnownEffectToParametrizedPermutation((t, a, r) => t < r ? (t + a) % r : t));

ModularAdditionGates.MinusAModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(ModularAdditionGates.PlusAModRFamily).
setSerializedId("-AmodR" + span).
setSymbol("−A\nmod R").
setTitle("Modular Subtraction Gate").
Expand Down
1 change: 1 addition & 0 deletions src/gates/ModularIncrementGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ ModularIncrementGates.IncrementModRFamily = Gate.buildFamily(1, 16, (span, build
setKnownEffectToParametrizedPermutation((t, a) => t < a ? (t + 1) % a : t));

ModularIncrementGates.DecrementModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(ModularIncrementGates.IncrementModRFamily).
setSerializedId("decmodR" + span).
setSymbol("−1\nmod R").
setTitle("Modular Decrement Gate").
Expand Down
2 changes: 2 additions & 0 deletions src/gates/ModularMultiplicationGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ ModularMultiplicationGates.TimesAModRFamily = Gate.buildFamily(1, 16, (span, bui
setKnownEffectToParametrizedPermutation(modularMultiply));

ModularMultiplicationGates.TimesAModRInverseFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(ModularMultiplicationGates.TimesAModRFamily).
setSerializedId("/AmodR" + span).
setSymbol("×A^-1\nmod R").
setTitle("Modular Division Gate").
Expand Down Expand Up @@ -253,6 +254,7 @@ ModularMultiplicationGates.TimesBToTheAModRFamily = Gate.buildFamily(1, 16, (spa
setKnownEffectToParametrizedPermutation((t, a, b, r) => modularPowerMultiply(t, b, a, r)));

ModularMultiplicationGates.TimesInverseBToTheAModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(ModularMultiplicationGates.TimesBToTheAModRFamily).
setSerializedId("/BToAmodR" + span).
setSymbol("×B^-A\nmod R").
setTitle("Modular Power Division Gate").
Expand Down
1 change: 1 addition & 0 deletions src/gates/ModularMultiplyAccumulateGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ ModularMultiplyAccumulateGates.PlusABModRFamily = Gate.buildFamily(1, 16, (span,
setKnownEffectToParametrizedPermutation((t, a, b, r) => t < r ? (t + a*b) % r : t));

ModularMultiplyAccumulateGates.MinusABModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(ModularMultiplyAccumulateGates.PlusABModRFamily).
setSerializedId("-ABmodR" + span).
setSymbol("−AB\nmod R").
setTitle("Modular Multiply-Subtract Gate").
Expand Down
1 change: 1 addition & 0 deletions src/gates/MultiplicationGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ MultiplicationGates.TimesAFamily = Gate.buildFamily(1, 16, (span, builder) => bu
setKnownEffectToParametrizedPermutation((x, a) => modularMultiply(x, a, 1<<span)));

MultiplicationGates.TimesAInverseFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setAlternateFromFamily(MultiplicationGates.TimesAFamily).
setSerializedId("/A" + span).
setSymbol("×A^-1").
setTitle("Inverse Multiplication Gate").
Expand Down
Loading

0 comments on commit 25e189d

Please sign in to comment.