Skip to content

Commit 6cca42d

Browse files
authored
Merge pull request #281 from Strilanc/dev
v1.9b
2 parents e8c5d42 + 19a6911 commit 6cca42d

10 files changed

Lines changed: 248 additions & 35 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"title": "Quirk",
44
"description": "A drag-and-drop toy for exploring and understanding small quantum circuits.",
55
"license": "Apache-2.0",
6-
"version": "1.9.0",
6+
"version": "1.9.1",
77
"homepage": "https://github.com/Strilanc/Quirk",
88
"bugs": {
99
"url": "https://github.com/Strilanc/Quirk/issues"

src/circuit/Serializer.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,19 @@ import {MysteryGateSymbol, MysteryGateMakerWithMatrix} from "src/gates/Joke_Myst
1515
import {seq} from "src/base/Seq.js"
1616
import {circuitDefinitionToGate} from "src/circuit/CircuitComputeUtil.js"
1717

18+
/** @type {!function(!GateDrawParams)} */
1819
let matrixDrawer = undefined;
20+
/** @type {!function(!GateDrawParams)} */
1921
let circuitDrawer = undefined;
20-
function initSerializer(gateMatrixDrawer, gateCircuitDrawer) {
22+
/** @type {!function(!GateDrawParams)} */
23+
let labelDrawer = undefined;
24+
/**
25+
* @param {!function(!GateDrawParams)} gateLabelDrawer
26+
* @param {!function(!GateDrawParams)} gateMatrixDrawer
27+
* @param {!function(!GateDrawParams)} gateCircuitDrawer
28+
*/
29+
function initSerializer(gateLabelDrawer, gateMatrixDrawer, gateCircuitDrawer) {
30+
labelDrawer = gateLabelDrawer;
2131
matrixDrawer = gateMatrixDrawer;
2232
circuitDrawer = gateCircuitDrawer;
2333
}
@@ -193,9 +203,12 @@ let fromJson_Gate_Matrix = props => {
193203

194204
let height = Math.round(Math.log2(mat.height()));
195205
let width = props.symbol === '' ? height : 1;
206+
let matrix = _parseGateMatrix(props.matrix);
196207

197-
return Gate.fromKnownMatrix(props.symbol, _parseGateMatrix(props.matrix), props.name, '').
198-
withCustomDrawer(props.symbol === "" ? matrixDrawer : undefined).
208+
return Gate.fromKnownMatrix(props.symbol, matrix, props.name, '').
209+
withCustomDrawer(props.symbol === "" ? matrixDrawer
210+
: matrix.isIdentity() ? labelDrawer
211+
: undefined).
199212
withSerializedId(props.id).
200213
withHeight(height).
201214
withWidth(width);

src/draw/GatePainting.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ GatePainting.paintBackground =
2828
args.painter.fillRect(args.rect, backColor);
2929
};
3030

31+
/**
32+
* @param {!GateDrawParams} args
33+
*/
34+
GatePainting.LABEL_DRAWER = args => {
35+
if (args.positionInCircuit === undefined || args.isHighlighted) {
36+
GatePainting.DEFAULT_DRAWER(args);
37+
return;
38+
}
39+
40+
let cut = Math.max(0, args.rect.h - Config.GATE_RADIUS*2)/2;
41+
args.painter.fillRect(args.rect.skipTop(cut).skipBottom(cut), Config.GATE_FILL_COLOR);
42+
43+
GatePainting.paintGateSymbol(args);
44+
};
45+
3146
/**
3247
* @param {!string=} toolboxFillColor
3348
* @param {!string=} normalFillColor

src/gates/CountingGates.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ import {makeCycleBitsMatrix, cycleBits} from "src/gates/CycleBitsGates.js"
1010
let CountingGates = {};
1111

1212
const staircaseCurve = steps => {
13+
steps = Math.min(128, steps);
1314
let curve = [];
1415
for (let i = 0; i < steps; i++) {
1516
let x = i/steps;
1617
let y = i/(steps-1);
17-
curve.push(new Point(x, y));
18-
curve.push(new Point(x + 1/steps, y));
18+
if (steps < 128) {
19+
curve.push(new Point(x, y));
20+
}
21+
curve.push(new Point(x + 1 / steps, y));
1922
}
2023
return curve;
2124
};
@@ -83,7 +86,7 @@ CountingGates.QuarterPhaseClockPulseGate = Gate.fromVaryingMatrix(
8386
withCustomDrawer(STAIRCASE_DRAWER(0.75, 2)).
8487
withStableDuration(0.25);
8588

86-
CountingGates.CountingFamily = Gate.generateFamily(1, 8, span => Gate.withoutKnownMatrix(
89+
CountingGates.CountingFamily = Gate.generateFamily(1, 16, span => Gate.withoutKnownMatrix(
8790
"+⌈t⌉",
8891
"Counting Gate",
8992
"Adds an increasing little-endian count into a block of qubits.").
@@ -96,7 +99,7 @@ CountingGates.CountingFamily = Gate.generateFamily(1, 8, span => Gate.withoutKno
9699
withStableDuration(1.0 / (1<<span)).
97100
withCustomShader(ctx => incrementShaderFunc(ctx, span, Math.floor(ctx.time*(1<<span)))));
98101

99-
CountingGates.UncountingFamily = Gate.generateFamily(1, 8, span => Gate.withoutKnownMatrix(
102+
CountingGates.UncountingFamily = Gate.generateFamily(1, 16, span => Gate.withoutKnownMatrix(
100103
"-⌈t⌉",
101104
"Down Counting Gate",
102105
"Subtracts an increasing little-endian count from a block of qubits.").

src/gates/MultiplyAccumulateGates.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,55 @@ MultiplyAccumulateGates.MultiplySubtractInputsFamily = Gate.generateFamily(1, 16
150150
-1)
151151
}));
152152

153+
MultiplyAccumulateGates.SquareAddInputFamily = Gate.generateFamily(1, 16, span => Gate.withoutKnownMatrix(
154+
"+=A^2",
155+
"Square-Add Gate [Input A]",
156+
"Adds the square of input A into the qubits covered by this gate.").
157+
markedAsOnlyPermutingAndPhasing().
158+
markedAsStable().
159+
withSerializedId("+=AA" + span).
160+
withHeight(span).
161+
withRequiredContextKeys('Input Range A').
162+
withCustomShader(ctx => {
163+
let {offset: inputOffsetA, length: inputLengthA} = ctx.customContextFromGates.get('Input Range A');
164+
return multiplyAccumulate(
165+
ctx,
166+
span,
167+
inputOffsetA,
168+
inputLengthA,
169+
inputOffsetA,
170+
inputLengthA,
171+
+1)
172+
}));
173+
174+
MultiplyAccumulateGates.SquareSubtractInputFamily = Gate.generateFamily(1, 16, span => Gate.withoutKnownMatrix(
175+
"-=A^2",
176+
"Square-Subtract Gate [Input A]",
177+
"Subtracts the square of input A out of the qubits covered by this gate.").
178+
markedAsOnlyPermutingAndPhasing().
179+
markedAsStable().
180+
withSerializedId("-=AA" + span).
181+
withHeight(span).
182+
withRequiredContextKeys('Input Range A').
183+
withCustomShader(ctx => {
184+
let {offset: inputOffsetA, length: inputLengthA} = ctx.customContextFromGates.get('Input Range A');
185+
return multiplyAccumulate(
186+
ctx,
187+
span,
188+
inputOffsetA,
189+
inputLengthA,
190+
inputOffsetA,
191+
inputLengthA,
192+
-1)
193+
}));
194+
153195
MultiplyAccumulateGates.all = [
154196
...MultiplyAccumulateGates.MultiplyAddFamily.all,
155197
...MultiplyAccumulateGates.MultiplySubtractFamily.all,
156198
...MultiplyAccumulateGates.MultiplyAddInputsFamily.all,
157-
...MultiplyAccumulateGates.MultiplySubtractInputsFamily.all
199+
...MultiplyAccumulateGates.MultiplySubtractInputsFamily.all,
200+
...MultiplyAccumulateGates.SquareAddInputFamily.all,
201+
...MultiplyAccumulateGates.SquareSubtractInputFamily.all,
158202
];
159203

160204
export {MultiplyAccumulateGates}

src/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {initTitleSync} from "src/ui/title.js"
2727
import {simulate} from "src/ui/sim.js"
2828
import {GatePainting} from "src/draw/GatePainting.js"
2929
import {GATE_CIRCUIT_DRAWER} from "src/ui/DisplayedCircuit.js"
30-
initSerializer(GatePainting.MATRIX_DRAWER, GATE_CIRCUIT_DRAWER);
30+
initSerializer(GatePainting.LABEL_DRAWER, GatePainting.MATRIX_DRAWER, GATE_CIRCUIT_DRAWER);
3131

3232
const canvasDiv = document.getElementById("canvasDiv");
3333

src/ui/DisplayedCircuit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1465,7 +1465,7 @@ let _cachedColLabelDrawer = new CachablePainting(
14651465
painter,
14661466
dw,
14671467
colCount,
1468-
i => prefix + Util.bin(colCount-1-i, rowWires),
1468+
i => prefix + Util.bin(colCount-1-i, colWires),
14691469
SUPERPOSITION_GRID_LABEL_SPAN);
14701470
});
14711471

src/ui/menu.js

Lines changed: 148 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,28 @@ const groverLink = {
2424
],
2525
"gates":[{"id":"~vn6c","name":"Oracle","circuit":{"cols":[["Z","•","◦","•","•"]]}}]
2626
};
27-
const teleportLink = {"cols":[
28-
[1,"H"],
29-
[1,"•",1,1,"X"],
30-
["…","…",1,1,"…"],
31-
["…","…",1,1,"…"],
32-
["e^-iYt"],
33-
["X^t"],
34-
["Bloch"],
35-
["•","X"],
36-
["H"],
37-
["Measure","Measure"],
38-
[1,"•",1,1,"X"],
39-
["•",1,1,1,"Z"],
40-
[1,1,1,1,"Bloch"]]
27+
const teleportLink = {
28+
"cols":[
29+
[1,"H"],
30+
[1,"•",1,1,"X"],
31+
["…","…",1,1,"…"],
32+
["…","…",1,1,"…"],
33+
["~87lj"],
34+
["Bloch"],
35+
["•","X"],
36+
["H"],
37+
["Measure","Measure"],
38+
[1,"•",1,1,"X"],
39+
["•",1,1,1,"Z"],
40+
[1,1,1,1,"Bloch"],
41+
[1,1,1,1,"~f7c0"]
42+
],
43+
"gates":[
44+
{"id":"~87lj","name":"message","circuit":{"cols":[["e^-iYt"],["X^t"]]}},
45+
{"id":"~f7c0","name":"received","matrix":"{{1,0},{0,1}}"}
46+
]
4147
};
42-
const erasureLink = {"cols":[
48+
const eraserLink = {"cols":[
4349
[1,"H"],
4450
[1,"•",1,1,"X"],
4551
[1,1,"QFT7"],
@@ -57,6 +63,121 @@ const erasureLink = {"cols":[
5763
["•","◦","Chance7"],
5864
["•","•","Chance7"]
5965
]};
66+
const chshTestLink = {
67+
"cols": [
68+
["H"],
69+
["◦",1,1,1,"X"],
70+
["X^-¼"],
71+
["…","…","…","…","…"],
72+
["~da85","~5s2n",1,"~5s2n","~ahov"],
73+
[1,"H",1,"H"],
74+
[1,"Measure",1,"Measure"],
75+
["X^½","•"],
76+
[1,1,1,"•","X^½"],
77+
["Measure",1,1,1,"Measure"],
78+
["…","…","…","…","…"],
79+
[1,"•","X","•"],
80+
["•",1,"X"],
81+
[1,1,"X",1,"•"],
82+
[1,1,"Chance"],
83+
[1,1,"~q6e"]
84+
],
85+
"gates": [
86+
{"id":"~da85","name":"Alice","matrix":"{{1,0},{0,1}}"},
87+
{"id":"~ahov","name":"Bob","matrix":"{{1,0},{0,1}}"},
88+
{"id":"~5s2n","name":"Referee","matrix":"{{1,0},{0,1}}"},
89+
{"id":"~q6e","name":"Win?","matrix":"{{1,0},{0,1}}"}
90+
]
91+
};
92+
const additionLink = {"cols":[
93+
["Counting5",1,1,1,1,1,1,1,1,"X"],
94+
["Chance5",1,1,1,1,"Measure","Chance5"],
95+
["…","…","…","…","…","…","…","…","…","…","…"],
96+
["X","X","X","X","•",1,1,"X","X","X"],
97+
["Swap",1,1,1,"Swap",1,"•"],
98+
[1,1,1,1,"•",1,1,"X"],
99+
[1,"Swap",1,1,"Swap",1,1,"•"],
100+
[1,1,1,1,"•",1,1,1,"X"],
101+
[1,1,"Swap",1,"Swap",1,1,1,"•"],
102+
[1,1,1,1,"•",1,1,1,1,"X"],
103+
[1,1,1,"Swap","Swap",1,1,1,1,"•"],
104+
[1,1,1,1,"•",1,1,1,1,1,"X"],
105+
[1,1,1,"Swap","Swap",1,1,1,1,"•"],
106+
[1,1,"Swap",1,"Swap",1,1,1,"•"],
107+
[1,"Swap",1,1,"Swap",1,1,"•"],
108+
["Swap",1,1,1,"Swap",1,"•"],
109+
["X","X","X","X","•"],
110+
[1,1,1,"•",1,1,1,1,1,"X"],
111+
[1,1,"•",1,1,1,1,1,"X"],
112+
[1,"•",1,1,1,1,1,"X"],
113+
["•",1,1,1,1,1,"X"],
114+
["…","…","…","…","…","…","…","…","…","…","…"],
115+
["Chance5",1,1,1,1,1,"Chance5"]
116+
]};
117+
const qftLink = {"cols":[
118+
["Counting8"],
119+
["Chance8"],
120+
["…","…","…","…","…","…","…","…"],
121+
["rev8"],
122+
["H"],
123+
["Z^½","•"],
124+
[1,"H"],
125+
["Z^¼","Z^½","•"],
126+
[1,1,"H"],
127+
["Z^⅛","Z^¼","Z^½","•"],
128+
[1,1,1,"H"],
129+
["Z^⅟₁₆","Z^⅛","Z^¼","Z^½","•"],
130+
[1,1,1,1,"H"],
131+
["Z^⅟₃₂","Z^⅟₁₆","Z^⅛","Z^¼","Z^½","•"],
132+
[1,1,1,1,1,"H"],
133+
["Z^⅟₆₄","Z^⅟₃₂","Z^⅟₁₆","Z^⅛","Z^¼","Z^½","•"],
134+
[1,1,1,1,1,1,"H"],
135+
["Z^⅟₁₂₈","Z^⅟₆₄","Z^⅟₃₂","Z^⅟₁₆","Z^⅛","Z^¼","Z^½","•"],
136+
[1,1,1,1,1,1,1,"H"]
137+
]};
138+
const superdenseCodingLink = {"cols":[
139+
[1,1,"H"],
140+
[1,1,"•",1,1,1,"X"],
141+
["…","…","…","…","…","…","…"],
142+
["Counting2"],
143+
["Measure","Measure"],
144+
["Chance","Chance"],
145+
[1,"•","X"],
146+
["•",1,"Z"],
147+
[1,1,"Swap",1,1,"Swap"],
148+
[1,1,1,1,1,"•","X"],
149+
[1,1,1,1,1,"H"],
150+
[1,1,1,1,1,"Measure","Measure"],
151+
[1,1,1,1,1,"Chance","Chance"]
152+
]};
153+
const symmetryBreakingLink = {
154+
"cols":[
155+
["~tpqg",1,"~r2ku"],
156+
["…","…","…","…"],
157+
["H"],
158+
[1,1,"H"],
159+
["•","X"],
160+
[1,1,"•","X"],
161+
[1,"Swap",1,"Swap"],
162+
["•","X"],
163+
[1,1,"•","X"],
164+
["X^½","◦"],
165+
[1,1,"X^½","◦"],
166+
[1,"X^½"],
167+
[1,1,1,"X^½"],
168+
["Measure","Measure","Measure","Measure"],
169+
[1,"~57au"],
170+
["•",1,"Chance"],
171+
[1,"•",1,"Chance"],
172+
["◦",1,"Chance"],
173+
[1,"◦",1,"Chance"]
174+
],
175+
"gates": [
176+
{"id":"~tpqg","name":"Alice^1","matrix":"{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}"},
177+
{"id":"~r2ku","name":"Alice^2","matrix":"{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}"},
178+
{"id":"~57au","name":"disagree","matrix":"{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}"}
179+
]
180+
};
60181

61182
/**
62183
* @param {!Revision} revision
@@ -89,11 +210,21 @@ function initMenu(revision, obsIsAnyOverlayShowing) {
89210

90211
const groverAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-anchor-grover');
91212
const teleportAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-anchor-teleport');
92-
const erasureAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-anchor-delayed-erasure');
213+
const eraserAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-anchor-delayed-eraser');
214+
const additionAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-addition');
215+
const superdenseCodeAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-superdense-coding');
216+
const symmetryBreakAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-symmetry-break');
217+
const chshTestAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-chsh-test');
218+
const qftAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-qft');
93219

94220
for (let [a, t] of [[groverAnchor, groverLink],
95221
[teleportAnchor, teleportLink],
96-
[erasureAnchor, erasureLink]]) {
222+
[eraserAnchor, eraserLink],
223+
[additionAnchor, additionLink],
224+
[superdenseCodeAnchor, superdenseCodingLink],
225+
[symmetryBreakAnchor, symmetryBreakingLink],
226+
[chshTestAnchor, chshTestLink],
227+
[qftAnchor, qftLink]]) {
97228
let text = JSON.stringify(t);
98229
a.href = "#circuit=" + text;
99230
a.onclick = ev => {

template/menu.partial.html

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,16 @@
3939
</a>
4040
</div>
4141
</div>
42-
<div style="display:inline-block; vertical-align:top; padding:20px 15px 20px 5px; background-color:#DDD; border:1px solid gray; margin:10px 0 0 -5px;">
43-
Example Circuits<br><br>
44-
<a id="example-anchor-grover">Grover Search</a><br><br>
45-
<a id="example-anchor-teleport">Quantum Teleportation</a><br><br>
46-
<a id="example-anchor-delayed-erasure">Delayed Choice Erasure</a>
42+
<div style="display:inline-block; vertical-align:top; line-height: 2; padding:15px 15px 15px 5px; background-color:#DDD; border:1px solid gray; margin:10px 0 0 -5px;">
43+
Example Circuits<br>
44+
<a id="example-anchor-grover">Grover Search</a><br>
45+
<a id="example-chsh-test">Bell Inequality Test (CHSH)</a><br>
46+
<a id="example-qft">Quantum Fourier Transform</a><br>
47+
<a id="example-anchor-teleport">Quantum Teleportation</a><br>
48+
<a id="example-superdense-coding">Superdense Coding</a><br>
49+
<a id="example-anchor-delayed-eraser">Delayed Choice Eraser</a><br>
50+
<a id="example-addition">Reversible Addition</a><br>
51+
<a id="example-symmetry-break">Symmetry Breaking</a><br>
4752
</div>
4853
</div>
4954
</div>

0 commit comments

Comments
 (0)