Skip to content

Commit

Permalink
Merge pull request #281 from Strilanc/dev
Browse files Browse the repository at this point in the history
v1.9b
  • Loading branch information
Strilanc authored Mar 5, 2017
2 parents e8c5d42 + 19a6911 commit 6cca42d
Show file tree
Hide file tree
Showing 10 changed files with 248 additions and 35 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"title": "Quirk",
"description": "A drag-and-drop toy for exploring and understanding small quantum circuits.",
"license": "Apache-2.0",
"version": "1.9.0",
"version": "1.9.1",
"homepage": "https://github.com/Strilanc/Quirk",
"bugs": {
"url": "https://github.com/Strilanc/Quirk/issues"
Expand Down
19 changes: 16 additions & 3 deletions src/circuit/Serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,19 @@ import {MysteryGateSymbol, MysteryGateMakerWithMatrix} from "src/gates/Joke_Myst
import {seq} from "src/base/Seq.js"
import {circuitDefinitionToGate} from "src/circuit/CircuitComputeUtil.js"

/** @type {!function(!GateDrawParams)} */
let matrixDrawer = undefined;
/** @type {!function(!GateDrawParams)} */
let circuitDrawer = undefined;
function initSerializer(gateMatrixDrawer, gateCircuitDrawer) {
/** @type {!function(!GateDrawParams)} */
let labelDrawer = undefined;
/**
* @param {!function(!GateDrawParams)} gateLabelDrawer
* @param {!function(!GateDrawParams)} gateMatrixDrawer
* @param {!function(!GateDrawParams)} gateCircuitDrawer
*/
function initSerializer(gateLabelDrawer, gateMatrixDrawer, gateCircuitDrawer) {
labelDrawer = gateLabelDrawer;
matrixDrawer = gateMatrixDrawer;
circuitDrawer = gateCircuitDrawer;
}
Expand Down Expand Up @@ -193,9 +203,12 @@ let fromJson_Gate_Matrix = props => {

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

return Gate.fromKnownMatrix(props.symbol, _parseGateMatrix(props.matrix), props.name, '').
withCustomDrawer(props.symbol === "" ? matrixDrawer : undefined).
return Gate.fromKnownMatrix(props.symbol, matrix, props.name, '').
withCustomDrawer(props.symbol === "" ? matrixDrawer
: matrix.isIdentity() ? labelDrawer
: undefined).
withSerializedId(props.id).
withHeight(height).
withWidth(width);
Expand Down
15 changes: 15 additions & 0 deletions src/draw/GatePainting.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,21 @@ GatePainting.paintBackground =
args.painter.fillRect(args.rect, backColor);
};

/**
* @param {!GateDrawParams} args
*/
GatePainting.LABEL_DRAWER = args => {
if (args.positionInCircuit === undefined || args.isHighlighted) {
GatePainting.DEFAULT_DRAWER(args);
return;
}

let cut = Math.max(0, args.rect.h - Config.GATE_RADIUS*2)/2;
args.painter.fillRect(args.rect.skipTop(cut).skipBottom(cut), Config.GATE_FILL_COLOR);

GatePainting.paintGateSymbol(args);
};

/**
* @param {!string=} toolboxFillColor
* @param {!string=} normalFillColor
Expand Down
11 changes: 7 additions & 4 deletions src/gates/CountingGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ import {makeCycleBitsMatrix, cycleBits} from "src/gates/CycleBitsGates.js"
let CountingGates = {};

const staircaseCurve = steps => {
steps = Math.min(128, steps);
let curve = [];
for (let i = 0; i < steps; i++) {
let x = i/steps;
let y = i/(steps-1);
curve.push(new Point(x, y));
curve.push(new Point(x + 1/steps, y));
if (steps < 128) {
curve.push(new Point(x, y));
}
curve.push(new Point(x + 1 / steps, y));
}
return curve;
};
Expand Down Expand Up @@ -83,7 +86,7 @@ CountingGates.QuarterPhaseClockPulseGate = Gate.fromVaryingMatrix(
withCustomDrawer(STAIRCASE_DRAWER(0.75, 2)).
withStableDuration(0.25);

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

CountingGates.UncountingFamily = Gate.generateFamily(1, 8, span => Gate.withoutKnownMatrix(
CountingGates.UncountingFamily = Gate.generateFamily(1, 16, span => Gate.withoutKnownMatrix(
"-⌈t⌉",
"Down Counting Gate",
"Subtracts an increasing little-endian count from a block of qubits.").
Expand Down
46 changes: 45 additions & 1 deletion src/gates/MultiplyAccumulateGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,55 @@ MultiplyAccumulateGates.MultiplySubtractInputsFamily = Gate.generateFamily(1, 16
-1)
}));

MultiplyAccumulateGates.SquareAddInputFamily = Gate.generateFamily(1, 16, span => Gate.withoutKnownMatrix(
"+=A^2",
"Square-Add Gate [Input A]",
"Adds the square of input A into the qubits covered by this gate.").
markedAsOnlyPermutingAndPhasing().
markedAsStable().
withSerializedId("+=AA" + span).
withHeight(span).
withRequiredContextKeys('Input Range A').
withCustomShader(ctx => {
let {offset: inputOffsetA, length: inputLengthA} = ctx.customContextFromGates.get('Input Range A');
return multiplyAccumulate(
ctx,
span,
inputOffsetA,
inputLengthA,
inputOffsetA,
inputLengthA,
+1)
}));

MultiplyAccumulateGates.SquareSubtractInputFamily = Gate.generateFamily(1, 16, span => Gate.withoutKnownMatrix(
"-=A^2",
"Square-Subtract Gate [Input A]",
"Subtracts the square of input A out of the qubits covered by this gate.").
markedAsOnlyPermutingAndPhasing().
markedAsStable().
withSerializedId("-=AA" + span).
withHeight(span).
withRequiredContextKeys('Input Range A').
withCustomShader(ctx => {
let {offset: inputOffsetA, length: inputLengthA} = ctx.customContextFromGates.get('Input Range A');
return multiplyAccumulate(
ctx,
span,
inputOffsetA,
inputLengthA,
inputOffsetA,
inputLengthA,
-1)
}));

MultiplyAccumulateGates.all = [
...MultiplyAccumulateGates.MultiplyAddFamily.all,
...MultiplyAccumulateGates.MultiplySubtractFamily.all,
...MultiplyAccumulateGates.MultiplyAddInputsFamily.all,
...MultiplyAccumulateGates.MultiplySubtractInputsFamily.all
...MultiplyAccumulateGates.MultiplySubtractInputsFamily.all,
...MultiplyAccumulateGates.SquareAddInputFamily.all,
...MultiplyAccumulateGates.SquareSubtractInputFamily.all,
];

export {MultiplyAccumulateGates}
2 changes: 1 addition & 1 deletion src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {initTitleSync} from "src/ui/title.js"
import {simulate} from "src/ui/sim.js"
import {GatePainting} from "src/draw/GatePainting.js"
import {GATE_CIRCUIT_DRAWER} from "src/ui/DisplayedCircuit.js"
initSerializer(GatePainting.MATRIX_DRAWER, GATE_CIRCUIT_DRAWER);
initSerializer(GatePainting.LABEL_DRAWER, GatePainting.MATRIX_DRAWER, GATE_CIRCUIT_DRAWER);

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

Expand Down
2 changes: 1 addition & 1 deletion src/ui/DisplayedCircuit.js
Original file line number Diff line number Diff line change
Expand Up @@ -1465,7 +1465,7 @@ let _cachedColLabelDrawer = new CachablePainting(
painter,
dw,
colCount,
i => prefix + Util.bin(colCount-1-i, rowWires),
i => prefix + Util.bin(colCount-1-i, colWires),
SUPERPOSITION_GRID_LABEL_SPAN);
});

Expand Down
165 changes: 148 additions & 17 deletions src/ui/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,28 @@ const groverLink = {
],
"gates":[{"id":"~vn6c","name":"Oracle","circuit":{"cols":[["Z","•","◦","•","•"]]}}]
};
const teleportLink = {"cols":[
[1,"H"],
[1,"•",1,1,"X"],
["…","…",1,1,"…"],
["…","…",1,1,"…"],
["e^-iYt"],
["X^t"],
["Bloch"],
["•","X"],
["H"],
["Measure","Measure"],
[1,"•",1,1,"X"],
["•",1,1,1,"Z"],
[1,1,1,1,"Bloch"]]
const teleportLink = {
"cols":[
[1,"H"],
[1,"•",1,1,"X"],
["…","…",1,1,"…"],
["…","…",1,1,"…"],
["~87lj"],
["Bloch"],
["•","X"],
["H"],
["Measure","Measure"],
[1,"•",1,1,"X"],
["•",1,1,1,"Z"],
[1,1,1,1,"Bloch"],
[1,1,1,1,"~f7c0"]
],
"gates":[
{"id":"~87lj","name":"message","circuit":{"cols":[["e^-iYt"],["X^t"]]}},
{"id":"~f7c0","name":"received","matrix":"{{1,0},{0,1}}"}
]
};
const erasureLink = {"cols":[
const eraserLink = {"cols":[
[1,"H"],
[1,"•",1,1,"X"],
[1,1,"QFT7"],
Expand All @@ -57,6 +63,121 @@ const erasureLink = {"cols":[
["•","◦","Chance7"],
["•","•","Chance7"]
]};
const chshTestLink = {
"cols": [
["H"],
["◦",1,1,1,"X"],
["X^-¼"],
["…","…","…","…","…"],
["~da85","~5s2n",1,"~5s2n","~ahov"],
[1,"H",1,"H"],
[1,"Measure",1,"Measure"],
["X^½","•"],
[1,1,1,"•","X^½"],
["Measure",1,1,1,"Measure"],
["…","…","…","…","…"],
[1,"•","X","•"],
["•",1,"X"],
[1,1,"X",1,"•"],
[1,1,"Chance"],
[1,1,"~q6e"]
],
"gates": [
{"id":"~da85","name":"Alice","matrix":"{{1,0},{0,1}}"},
{"id":"~ahov","name":"Bob","matrix":"{{1,0},{0,1}}"},
{"id":"~5s2n","name":"Referee","matrix":"{{1,0},{0,1}}"},
{"id":"~q6e","name":"Win?","matrix":"{{1,0},{0,1}}"}
]
};
const additionLink = {"cols":[
["Counting5",1,1,1,1,1,1,1,1,"X"],
["Chance5",1,1,1,1,"Measure","Chance5"],
["…","…","…","…","…","…","…","…","…","…","…"],
["X","X","X","X","•",1,1,"X","X","X"],
["Swap",1,1,1,"Swap",1,"•"],
[1,1,1,1,"•",1,1,"X"],
[1,"Swap",1,1,"Swap",1,1,"•"],
[1,1,1,1,"•",1,1,1,"X"],
[1,1,"Swap",1,"Swap",1,1,1,"•"],
[1,1,1,1,"•",1,1,1,1,"X"],
[1,1,1,"Swap","Swap",1,1,1,1,"•"],
[1,1,1,1,"•",1,1,1,1,1,"X"],
[1,1,1,"Swap","Swap",1,1,1,1,"•"],
[1,1,"Swap",1,"Swap",1,1,1,"•"],
[1,"Swap",1,1,"Swap",1,1,"•"],
["Swap",1,1,1,"Swap",1,"•"],
["X","X","X","X","•"],
[1,1,1,"•",1,1,1,1,1,"X"],
[1,1,"•",1,1,1,1,1,"X"],
[1,"•",1,1,1,1,1,"X"],
["•",1,1,1,1,1,"X"],
["…","…","…","…","…","…","…","…","…","…","…"],
["Chance5",1,1,1,1,1,"Chance5"]
]};
const qftLink = {"cols":[
["Counting8"],
["Chance8"],
["…","…","…","…","…","…","…","…"],
["rev8"],
["H"],
["Z^½","•"],
[1,"H"],
["Z^¼","Z^½","•"],
[1,1,"H"],
["Z^⅛","Z^¼","Z^½","•"],
[1,1,1,"H"],
["Z^⅟₁₆","Z^⅛","Z^¼","Z^½","•"],
[1,1,1,1,"H"],
["Z^⅟₃₂","Z^⅟₁₆","Z^⅛","Z^¼","Z^½","•"],
[1,1,1,1,1,"H"],
["Z^⅟₆₄","Z^⅟₃₂","Z^⅟₁₆","Z^⅛","Z^¼","Z^½","•"],
[1,1,1,1,1,1,"H"],
["Z^⅟₁₂₈","Z^⅟₆₄","Z^⅟₃₂","Z^⅟₁₆","Z^⅛","Z^¼","Z^½","•"],
[1,1,1,1,1,1,1,"H"]
]};
const superdenseCodingLink = {"cols":[
[1,1,"H"],
[1,1,"•",1,1,1,"X"],
["…","…","…","…","…","…","…"],
["Counting2"],
["Measure","Measure"],
["Chance","Chance"],
[1,"•","X"],
["•",1,"Z"],
[1,1,"Swap",1,1,"Swap"],
[1,1,1,1,1,"•","X"],
[1,1,1,1,1,"H"],
[1,1,1,1,1,"Measure","Measure"],
[1,1,1,1,1,"Chance","Chance"]
]};
const symmetryBreakingLink = {
"cols":[
["~tpqg",1,"~r2ku"],
["…","…","…","…"],
["H"],
[1,1,"H"],
["•","X"],
[1,1,"•","X"],
[1,"Swap",1,"Swap"],
["•","X"],
[1,1,"•","X"],
["X^½","◦"],
[1,1,"X^½","◦"],
[1,"X^½"],
[1,1,1,"X^½"],
["Measure","Measure","Measure","Measure"],
[1,"~57au"],
["•",1,"Chance"],
[1,"•",1,"Chance"],
["◦",1,"Chance"],
[1,"◦",1,"Chance"]
],
"gates": [
{"id":"~tpqg","name":"Alice^1","matrix":"{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}"},
{"id":"~r2ku","name":"Alice^2","matrix":"{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}"},
{"id":"~57au","name":"disagree","matrix":"{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}"}
]
};

/**
* @param {!Revision} revision
Expand Down Expand Up @@ -89,11 +210,21 @@ function initMenu(revision, obsIsAnyOverlayShowing) {

const groverAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-anchor-grover');
const teleportAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-anchor-teleport');
const erasureAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-anchor-delayed-erasure');
const eraserAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-anchor-delayed-eraser');
const additionAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-addition');
const superdenseCodeAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-superdense-coding');
const symmetryBreakAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-symmetry-break');
const chshTestAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-chsh-test');
const qftAnchor = /** @type {!HTMLAnchorElement} */ document.getElementById('example-qft');

for (let [a, t] of [[groverAnchor, groverLink],
[teleportAnchor, teleportLink],
[erasureAnchor, erasureLink]]) {
[eraserAnchor, eraserLink],
[additionAnchor, additionLink],
[superdenseCodeAnchor, superdenseCodingLink],
[symmetryBreakAnchor, symmetryBreakingLink],
[chshTestAnchor, chshTestLink],
[qftAnchor, qftLink]]) {
let text = JSON.stringify(t);
a.href = "#circuit=" + text;
a.onclick = ev => {
Expand Down
15 changes: 10 additions & 5 deletions template/menu.partial.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,16 @@
</a>
</div>
</div>
<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;">
Example Circuits<br><br>
<a id="example-anchor-grover">Grover Search</a><br><br>
<a id="example-anchor-teleport">Quantum Teleportation</a><br><br>
<a id="example-anchor-delayed-erasure">Delayed Choice Erasure</a>
<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;">
Example Circuits<br>
<a id="example-anchor-grover">Grover Search</a><br>
<a id="example-chsh-test">Bell Inequality Test (CHSH)</a><br>
<a id="example-qft">Quantum Fourier Transform</a><br>
<a id="example-anchor-teleport">Quantum Teleportation</a><br>
<a id="example-superdense-coding">Superdense Coding</a><br>
<a id="example-anchor-delayed-eraser">Delayed Choice Eraser</a><br>
<a id="example-addition">Reversible Addition</a><br>
<a id="example-symmetry-break">Symmetry Breaking</a><br>
</div>
</div>
</div>
Loading

0 comments on commit 6cca42d

Please sign in to comment.