<NME> DisplayedCircuit.test.js
<BEF> /**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
    ['H', Gates.HalfTurns.H],
    ['•', Gates.Special.Control],
    ['◦', Gates.Special.AntiControl],
    ['.', Gates.Misc.SpacerGate],

    ['M', Gates.Special.Measurement],
    ['%', Gates.Displays.ChanceDisplay],
import {CircuitStats} from "../../src/circuit/CircuitStats.js"
import {Gates} from "../../src/gates/AllGates.js"
import {Point} from "../../src/math/Point.js"
import {RestartableRng} from "../../src/base/RestartableRng.js"
import {Hand} from "../../src/ui/Hand.js"
import {Painter} from "../../src/draw/Painter.js"

const COMMON_GATES = new Map([
    ['X', Gates.HalfTurns.X],
    ['Y', Gates.HalfTurns.Y],
    ['Z', Gates.HalfTurns.Z],
    ['H', Gates.HalfTurns.H],
    ['Q', Gates.FourierTransformGates.FourierTransformFamily],
    ['•', Gates.Controls.Control],
    ['◦', Gates.Controls.AntiControl],

    ['M', Gates.Special.Measurement],
    ['%', Gates.Displays.ChanceDisplay],
    ['@', Gates.Displays.BlochSphereDisplay],
    ['s', Gates.Special.SwapHalf],
    ['!', Gates.PostSelectionGates.PostSelectOn],

    ['-', undefined],
    ['+', undefined],
    ['0', null],
    ['1', null],
    ['2', null],
    ['3', null],
    ['4', null],
    ['5', null],
    ['6', null],
    ['7', null],
    ['8', null],
    ['9', null],

    ['/', null]
]);

let circuit = (diagramText, ...extraGateEntries) => CircuitDefinition.fromTextDiagram(
    new Map([
        ...COMMON_GATES.entries(),
        ...extraGateEntries
    ]),
    diagramText);

/**
 * @param {!string} diagramText
 * @param {!Array<*>} extraGateEntries
 * @returns {!{circuit: !DisplayedCircuit, pts: !Array.<!Point>}}
 */
let displayedCircuit = (diagramText, ...extraGateEntries) => DisplayedCircuit.fromTextDiagram(
    new Map([
        ...COMMON_GATES.entries(),
        ...extraGateEntries
    ]),
    diagramText);

/**
 * @param {!string} diagramText
 * @param {undefined|!{duplicate: undefined|!boolean, wholeColumn: undefined|!boolean}} options
 * @param {!Array<*>} extraGateEntries
 * @returns {{
 *   beforeGrab: !DisplayedCircuit,
 *   afterGrab: !DisplayedCircuit,
 *   hovers: !Array.<!DisplayedCircuit>,
 *   afterDrop: !DisplayedCircuit,
 *   afterDropAndTidy: !DisplayedCircuit,
 * }}
 */
let simulateDrag = (diagramText, options={}, ...extraGateEntries) => {
    let duplicate = options.duplicate || false;
    let wholeColumn = options.wholeColumn || false;

    let {circuit: beforeGrab, pts} = displayedCircuit(diagramText, ...extraGateEntries);
    let {newCircuit: afterGrab, newHand: fullHand} =
        beforeGrab.tryGrab(Hand.EMPTY.withPos(pts[0]), duplicate, wholeColumn);
    let hovers = [];
    for (let pt of pts) {
        hovers.push(afterGrab.previewDrop(fullHand.withPos(pt)));
    }
    let afterDrop = afterGrab.afterDropping(fullHand.withPos(pts[pts.length - 1]));
    let afterDropAndTidy = afterDrop.afterTidyingUp();
    return {beforeGrab, afterGrab, hovers, afterDrop, afterDropAndTidy};
};

let suite = new Suite("DisplayedCircuit");

suite.test("constructor_vs_isEqualTo", () => {
    let d1 = CircuitDefinition.fromTextDiagram(COMMON_GATES, `+H+
                                                              X+Y`);
    let d2 = CircuitDefinition.fromTextDiagram(COMMON_GATES, `++++
                                                              ZHHH`);
    //noinspection JSCheckFunctionSignatures
    assertThrows(() => new DisplayedCircuit(23, "not a circuit", undefined, undefined, undefined));
    //noinspection JSCheckFunctionSignatures
    assertThrows(() => new DisplayedCircuit("not a number", d1, undefined, undefined, undefined));

    let c1 = new DisplayedCircuit(45, d1, undefined, undefined, undefined);
    let c2 = new DisplayedCircuit(67, d2, 1, {col: 1, row: 1, resizeStyle: true}, 1);
    assertThat(c1.top).isEqualTo(45);
    assertThat(c1.circuitDefinition).isEqualTo(d1);

    assertThat(c1).isEqualTo(c1);
    assertThat(c1).isNotEqualTo(c2);
    assertThat(c2).isEqualTo(c2);
    assertThat(c2).isNotEqualTo(c1);

    assertThat(c1).isEqualTo(new DisplayedCircuit(45, d1, undefined, undefined, undefined));
    assertThat(c1).isNotEqualTo(new DisplayedCircuit(46, d1, undefined, undefined, undefined));
    assertThat(c1).isNotEqualTo(new DisplayedCircuit(45, d2, undefined, undefined, undefined));
    assertThat(c1).isNotEqualTo(new DisplayedCircuit(45, d1, 1, undefined, undefined));
    assertThat(c1).isNotEqualTo(new DisplayedCircuit(45, d1, undefined, {col:1, row:1, resizeStyle:false}, undefined));
    assertThat(c1).isNotEqualTo(new DisplayedCircuit(45, d1, undefined, undefined, 0));

    assertThat(c2).isEqualTo(new DisplayedCircuit(67, d2, 1, {col: 1, row: 1, resizeStyle: true}, 1));
    assertThat(c2).isNotEqualTo(new DisplayedCircuit(68, d2, 1, {col: 1, row: 1, resizeStyle: true}, 1));
    assertThat(c2).isNotEqualTo(new DisplayedCircuit(67, d1, 1, {col: 1, row: 1, resizeStyle: true}, 1));
    assertThat(c2).isNotEqualTo(new DisplayedCircuit(67, d2, 2, {col: 1, row: 1, resizeStyle: true}, 1));
    assertThat(c2).isNotEqualTo(new DisplayedCircuit(67, d2, 1, {col: 2, row: 1, resizeStyle: true}, 1));
    assertThat(c2).isNotEqualTo(new DisplayedCircuit(67, d2, 1, {col: 2, row: 1, resizeStyle: true}, 2));
});

suite.test("bootstrap_diagram", () => {
    assertThat(displayedCircuit(`|
                                 |-X-D//-
                                 |   ///
                                 |-+-///-
                                 |`,
                                 ['D', Gates.Displays.DensityMatrixDisplay2])).isEqualTo({
        circuit: new DisplayedCircuit(
            10,
            circuit(`XD/
                     +//`, ['D', Gates.Displays.DensityMatrixDisplay2]),
            undefined,
            undefined,
            undefined),
        pts: []
    });

    assertThat(displayedCircuit(`|
                                 |-+-H-+-
                                 |
                                 |-+-Y-+-
                                 |`)).isEqualTo({
        circuit: new DisplayedCircuit(
            10,
            circuit(`+H+
                     +Y+`),
            undefined,
            undefined,
            undefined),
        pts: []
    });

    assertThat(displayedCircuit(`|01
                                 |2+-H-+-
                                 |  3
                                 |-+-Y4+-
                                 |  5^   `)).isEqualTo({
        circuit: new DisplayedCircuit(
            10,
            circuit(`+H+
                     +Y+`),
            undefined,
            undefined,
            undefined),
        pts: [
            new Point(35.5, 10.5),
            new Point(60.5, 10.5),
            new Point(35.5, 35.5),
            new Point(85.5, 60.5),
            new Point(135.5, 85.5),
            new Point(110.5, 85.5)
        ]
    });
});

suite.test("indexOfDisplayedRowAt", () => {
    let {circuit, pts} = displayedCircuit(`|0
                                           |1+-+-
                                           |   2
                                           |-+3+-
                                           |  4`);

    assertThat(circuit.indexOfDisplayedRowAt(-9999)).isEqualTo(undefined);
    assertThat(circuit.indexOfDisplayedRowAt(+9999)).isEqualTo(undefined);

    assertThat(circuit.indexOfDisplayedRowAt(pts[0].y)).isEqualTo(0);
    assertThat(circuit.indexOfDisplayedRowAt(pts[1].y)).isEqualTo(0);
    assertThat(circuit.indexOfDisplayedRowAt(pts[2].y)).isEqualTo(1);
    assertThat(circuit.indexOfDisplayedRowAt(pts[3].y)).isEqualTo(1);
    assertThat(circuit.indexOfDisplayedRowAt(pts[4].y)).isEqualTo(undefined);
});

suite.testUsingWebGL("drawCircuitCompletes_QuantumTeleportation", () => {
    let teleportCircuit = CircuitDefinition.fromTextDiagram(
        new Map([
            ['X', Gates.HalfTurns.X],
            ['Z', Gates.HalfTurns.Z],
            ['H', Gates.HalfTurns.H],
            ['M', Gates.Special.Measurement],
            ['•', Gates.Controls.Control],
            ['@', Gates.Displays.BlochSphereDisplay],
            ['t', Gates.Powering.YForward],
            ['-', undefined],
            ['=', undefined],
            ['|', undefined]
        ]),
        `------t@--•-H-M===•===
         -H-•------X---M=•=|===
         ---X------------X-Z-@-`);
    let stats = CircuitStats.fromCircuitAtTime(teleportCircuit, 0.1);
    let displayed = DisplayedCircuit.empty(0).withCircuit(teleportCircuit);
    let canvas = /** @type {HTMLCanvasElement} */ document.createElement("canvas");
    canvas.width = 1000;
    canvas.height = 1000;
    let painter = new Painter(canvas, new RestartableRng());

    // We're just checking that this runs to completion without throwing an exception.
    displayed.paint(painter, Hand.EMPTY, stats);

    // And now a superfluous check to avoid the 'no assertions' warning.
    let inputState = stats.qubitDensityMatrix(7, 0);
    let outputState = stats.qubitDensityMatrix(Infinity, 2);
    assertThat(outputState).isApproximatelyEqualTo(inputState);
});

suite.test("dragXIntoCNot", () => {
    let drag = simulateDrag(`|
                             |-H-•-X-
                             |    0^
                             |-+3421-
                             |`);

    assertThat(drag.beforeGrab.circuitDefinition).isEqualTo(circuit(`H•X
                                                                     ---`));
    assertThat(drag.afterGrab.circuitDefinition).isEqualTo(circuit(`H•-
                                                                    ---`));
    assertThat(drag.hovers.map(e => e.circuitDefinition)).isEqualTo([
        circuit(`H•X
                 ---`),
        circuit(`H•-
                 --X`),
        circuit(`H•--
                 --X-`),
        circuit(`H-•-
                 -X--`),
        circuit(`H•-
                 -X-`)]);
    assertThat(drag.afterDrop.circuitDefinition).isEqualTo(circuit(`H•-
                                                                    -X-`));
    assertThat(drag.afterDropAndTidy.circuitDefinition).isEqualTo(circuit(`H•
                                                                           -X`));
});

suite.test("resizeQft", () => {
    let drag = simulateDrag(`|
                             |-Q-
                             | 1
                             |-/-
                             | 0
                             |-+-
                             |
                             |-+-
                             | 2`);

    assertThat(drag.beforeGrab.circuitDefinition).isEqualTo(circuit(`Q
                                                                     /
                                                                     -
                                                                     -`));
    assertThat(drag.afterGrab.circuitDefinition).isEqualTo(circuit(`Q
                                                                    /
                                                                    -
                                                                    -`));
    assertThat(drag.hovers.map(e => e.circuitDefinition)).isEqualTo([
        circuit(`Q
                 /
                 -
                 -`),
        circuit(`Q
                 -
                 -
                 -`),
        circuit(`Q
                 /
                 /
                 /`)]);
    assertThat(drag.afterDrop.circuitDefinition).isEqualTo(circuit(`Q
                                                                    /
                                                                    /
                                                                    /`));
    assertThat(drag.afterDropAndTidy.circuitDefinition).isEqualTo(circuit(`Q
                                                                           /
                                                                           /
                                                                           /`));
});

suite.test("dragQft", () => {
    let drag = simulateDrag(`|
                             |-Q-
                             | 0
                             |-/-
                             |
                             |-+-
                             | 1
                             |-+-
                             |`);

    assertThat(drag.beforeGrab.circuitDefinition).isEqualTo(circuit(`Q
                                                                     /
                                                                     -
                                                                     -`));
    assertThat(drag.afterGrab.circuitDefinition).isEqualTo(circuit(`-
                                                                    -
                                                                    -
                                                                    -`));
    assertThat(drag.hovers.map(e => e.circuitDefinition)).isEqualTo([
        circuit(`Q
                 /
                 -
                 -`),
        circuit(`-
                 -
                 Q
                 /`)]);
    assertThat(drag.afterDrop.circuitDefinition).isEqualTo(circuit(`-
                                                                    -
                                                                    Q
                                                                    /`));
    assertThat(drag.afterDropAndTidy.circuitDefinition).isEqualTo(circuit(`-
                                                                           -
                                                                           Q
                                                                           /`));
});

<MSG> Pulled MysteryGate stuff out of AllGates

<DFF> @@ -14,7 +14,7 @@ const TEST_GATES = new Map([
     ['H', Gates.HalfTurns.H],
     ['•', Gates.Special.Control],
     ['◦', Gates.Special.AntiControl],
-    ['.', Gates.Misc.SpacerGate],
+    ['.', Gates.SpacerGate],
 
     ['M', Gates.Special.Measurement],
     ['%', Gates.Displays.ChanceDisplay],

{'commit': 'diff --git a/src/circuit/CircuitDefinition.js b/src/circuit/CircuitDefinition.js\nindex 50e8d67..88a6697 100644\n--- a/src/circuit/CircuitDefinition.js\n+++ b/src/circuit/CircuitDefinition.js\n@@ -494,7 +494,7 @@ class CircuitDefinition {\n         return g !== undefined &&\n             g !== Gates.Special.Control &&\n             g !== Gates.Special.AntiControl &&\n-            g !== Gates.Misc.SpacerGate &&\n+            g !== Gates.SpacerGate &&\n             (g !== Gates.Special.SwapHalf || this.colHasEnabledSwapGate(pt.x));\n     }\n \ndiff --git a/src/circuit/Serializer.js b/src/circuit/Serializer.js\nindex 416124c..019c45a 100644\n--- a/src/circuit/Serializer.js\n+++ b/src/circuit/Serializer.js\n@@ -10,8 +10,9 @@ import GatePainting from "src/ui/GatePainting.js"\n import Gates from "src/gates/AllGates.js"\n import Matrix from "src/math/Matrix.js"\n import Util from "src/base/Util.js"\n+import {notifyAboutRecoveryFromUnexpectedError} from "src/fallback.js"\n+import {MysteryGateSymbol, MysteryGateMakerWithMatrix} from "src/gates/Joke_MysteryGate.js"\n import {seq, Seq} from "src/base/Seq.js"\n-import { notifyAboutRecoveryFromUnexpectedError } from "src/fallback.js"\n \n /**\n  * Serializes supported values to/from json elements.\n@@ -172,8 +173,8 @@ let fromJson_Gate = json => {\n             withCustomDrawer(drawer).withTag(json);\n     }\n \n-    if (symbol === Gates.Misc.MysteryGateSymbol && matrix !== undefined) {\n-        return Gates.Misc.MysteryGateMakerWithMatrix(matrix);\n+    if (symbol === MysteryGateSymbol && matrix !== undefined) {\n+        return MysteryGateMakerWithMatrix(matrix);\n     }\n \n     return Gate.fromKnownMatrix(symbol, matrix, symbol, "").withCustomDrawer(drawer);\ndiff --git a/src/gates/AllGates.js b/src/gates/AllGates.js\nindex bcd296c..9242fca 100644\n--- a/src/gates/AllGates.js\n+++ b/src/gates/AllGates.js\n@@ -37,13 +37,12 @@ import UniversalNotGate from "src/gates/Impossible_UniversalNotGate.js"\n import VariousXGates from "src/gates/VariousXGates.js"\n import VariousYGates from "src/gates/VariousYGates.js"\n import VariousZGates from "src/gates/VariousZGates.js"\n+import {MysteryGateMaker} from "src/gates/Joke_MysteryGate.js"\n \n let Gates = {};\n export default Gates;\n \n-/**\n- * Gates that have special behavior requiring custom code / logic to handle.\n- */\n+/** Gates that have special behavior requiring custom code / logic to handle. */\n Gates.Special = {\n     Control: Controls.Control,\n     AntiControl: Controls.AntiControl,\n@@ -78,24 +77,7 @@ Gates.PhaseGradientGates = PhaseGradientGates;\n Gates.PostSelectionGates = PostSelectionGates;\n Gates.Powering = PoweringGates;\n Gates.QuarterTurns = QuarterTurnGates;\n-\n-Gates.Misc = {\n-    MysteryGateSymbol: "?",\n-    MysteryGateMakerWithMatrix: matrix => Gate.fromKnownMatrix(\n-        Gates.Misc.MysteryGateSymbol,\n-        matrix,\n-        "Mystery Gate",\n-        "Every time you grab this gate out of the toolbox, it changes.\\n" +\n-        "Duplicate gates in the circuit by holding shift before dragging.").\n-        withCustomDrawer(GatePainting.MATRIX_SYMBOL_DRAWER_EXCEPT_IN_TOOLBOX),\n-    MysteryGateMaker: () => Gates.Misc.MysteryGateMakerWithMatrix(Matrix.square(\n-            new Complex(Math.random() - 0.5, Math.random() - 0.5),\n-            new Complex(Math.random() - 0.5, Math.random() - 0.5),\n-            new Complex(Math.random() - 0.5, Math.random() - 0.5),\n-            new Complex(Math.random() - 0.5, Math.random() - 0.5)\n-        ).closestUnitary()),\n-    SpacerGate: SpacerGate\n-};\n+Gates.SpacerGate = SpacerGate;\n \n const CYCLE_BITS_MATRIX_MAKER = span => Matrix.generate(1<<span, 1<<span, (r, c) => {\n     let expected = r;\n@@ -184,7 +166,7 @@ Gates.Sets = [\n             null,\n             FourierTransformGates.FourierTransformFamily.ofSize(2),\n             PhaseGradientGates.PhaseDegradientFamily.ofSize(2),\n-            Gates.Misc.MysteryGateMaker(),\n+            MysteryGateMaker(),\n             SpacerGate\n         ]\n     },\ndiff --git a/src/gates/Joke_MysteryGate.js b/src/gates/Joke_MysteryGate.js\nnew file mode 100644\nindex 0000000..8f59ee8\n--- /dev/null\n+++ b/src/gates/Joke_MysteryGate.js\n@@ -0,0 +1,23 @@\n+import Complex from "src/math/Complex.js"\n+import Gate from "src/circuit/Gate.js"\n+import GatePainting from "src/ui/GatePainting.js"\n+import Matrix from "src/math/Matrix.js"\n+\n+let MysteryGateSymbol = "?";\n+\n+let MysteryGateMakerWithMatrix = matrix => Gate.fromKnownMatrix(\n+    MysteryGateSymbol,\n+    matrix,\n+    "Mystery Gate",\n+    "Every time you grab this gate out of the toolbox, it changes.\\n" +\n+        "Duplicate gates in the circuit by holding shift before dragging.").\n+    withCustomDrawer(GatePainting.MATRIX_SYMBOL_DRAWER_EXCEPT_IN_TOOLBOX);\n+\n+let MysteryGateMaker = () => MysteryGateMakerWithMatrix(Matrix.square(\n+    new Complex(Math.random() - 0.5, Math.random() - 0.5),\n+    new Complex(Math.random() - 0.5, Math.random() - 0.5),\n+    new Complex(Math.random() - 0.5, Math.random() - 0.5),\n+    new Complex(Math.random() - 0.5, Math.random() - 0.5)\n+).closestUnitary());\n+\n+export {MysteryGateSymbol, MysteryGateMaker, MysteryGateMakerWithMatrix};\ndiff --git a/src/widgets/ToolboxWidget.js b/src/widgets/ToolboxWidget.js\nindex e82a33a..e96ce50 100644\n--- a/src/widgets/ToolboxWidget.js\n+++ b/src/widgets/ToolboxWidget.js\n@@ -9,6 +9,7 @@ import {seq, Seq} from "src/base/Seq.js"\n import Config from "src/Config.js"\n import Painter from "src/ui/Painter.js"\n import WidgetPainter from "src/ui/WidgetPainter.js"\n+import {MysteryGateSymbol, MysteryGateMaker} from "src/gates/Joke_MysteryGate.js"\n \n class ToolboxWidget {\n     /**\n@@ -162,8 +163,8 @@ class ToolboxWidget {\n             return hand;\n         }\n \n-        if (f.gate.symbol === Gates.Misc.MysteryGateSymbol) {\n-            Gates.Sets[f.groupIndex].gates[f.gateIndex] = Gates.Misc.MysteryGateMaker();\n+        if (f.gate.symbol === MysteryGateSymbol) {\n+            Gates.Sets[f.groupIndex].gates[f.gateIndex] = MysteryGateMaker();\n         }\n         return hand.withHeldGate(f.gate, new Point(Config.GATE_RADIUS, Config.GATE_RADIUS));\n     }\ndiff --git a/test/circuit/CircuitDefinition.test.js b/test/circuit/CircuitDefinition.test.js\nindex feae3c2..19007d0 100644\n--- a/test/circuit/CircuitDefinition.test.js\n+++ b/test/circuit/CircuitDefinition.test.js\n@@ -26,7 +26,7 @@ const TEST_GATES = new Map([\n     [\'H\', H],\n     [\'•\', C],\n     [\'◦\', A],\n-    [\'.\', Gates.Misc.SpacerGate],\n+    [\'.\', Gates.SpacerGate],\n \n     [\'M\', M],\n     [\'%\', Gates.Displays.ChanceDisplay],\ndiff --git a/test/circuit/Serializer.test.js b/test/circuit/Serializer.test.js\nindex 2b25590..f4f07f0 100644\n--- a/test/circuit/Serializer.test.js\n+++ b/test/circuit/Serializer.test.js\n@@ -9,6 +9,7 @@ import GateColumn from "src/circuit/GateColumn.js"\n import GatePainting from "src/ui/GatePainting.js"\n import Gates from "src/gates/AllGates.js"\n import Matrix from "src/math/Matrix.js"\n+import {MysteryGateMaker} from "src/gates/Joke_MysteryGate.js"\n \n let suite = new Suite("Serializer");\n \n@@ -39,7 +40,7 @@ suite.test("roundTrip_Gate", () => {\n         assertRoundTrip(Gate, g, g.serializedId);\n     }\n \n-    let f = Gates.Misc.MysteryGateMaker();\n+    let f = MysteryGateMaker();\n     assertThat(Serializer.fromJson(Gate, Serializer.toJson(f))).isEqualTo(f);\n \n     let g = Gate.fromKnownMatrix(\ndiff --git a/test/ui/DisplayedCircuit.test.js b/test/ui/DisplayedCircuit.test.js\nindex 6e5e016..066b0b3 100644\n--- a/test/ui/DisplayedCircuit.test.js\n+++ b/test/ui/DisplayedCircuit.test.js\n@@ -14,7 +14,7 @@ const TEST_GATES = new Map([\n     [\'H\', Gates.HalfTurns.H],\n     [\'•\', Gates.Special.Control],\n     [\'◦\', Gates.Special.AntiControl],\n-    [\'.\', Gates.Misc.SpacerGate],\n+    [\'.\', Gates.SpacerGate],\n \n     [\'M\', Gates.Special.Measurement],\n     [\'%\', Gates.Displays.ChanceDisplay],\n', 'commit_subject': 'Pulled MysteryGate stuff out of AllGates', 'repo_name': 'Strilanc/Quirk', 'committer': {'name': 'Craig Gidney', 'email': '4a8c8431fb5d2eab9aaa5bedb253e5c73287c466@gmail.com', 'time_sec': '1463872501', 'tz_offset': '-240', 'date': {'seconds': '1463872501'}}, 'commit_tree': 'a909eb44391f65b1fbcf18da3fea4f2784244b54', 'commit_message': 'Pulled MysteryGate stuff out of AllGates\n', 'language_name': 'HTML', 'license': 'apache-2.0', 'hunks': "@@ -14,7 +14,7 @@ const TEST_GATES = new Map([\n     ['H', Gates.HalfTurns.H],\n     ['•', Gates.Special.Control],\n     ['◦', Gates.Special.AntiControl],\n-    ['.', Gates.Misc.SpacerGate],\n+    ['.', Gates.SpacerGate],\n \n     ['M', Gates.Special.Measurement],\n     ['%', Gates.Displays.ChanceDisplay],\n", 'addition_count': 1, 'deletion_count': 1, 'src_file': 'a/test/ui/DisplayedCircuit.test.js', 'tgt_file': 'b/test/ui/DisplayedCircuit.test.js', 'file_extension': '.js', 'before_file': '/**\n * Copyright 2017 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n    [\'H\', Gates.HalfTurns.H],\n    [\'•\', Gates.Special.Control],\n    [\'◦\', Gates.Special.AntiControl],\n    [\'.\', Gates.Misc.SpacerGate],\n\n    [\'M\', Gates.Special.Measurement],\n    [\'%\', Gates.Displays.ChanceDisplay],\nimport {CircuitStats} from "../../src/circuit/CircuitStats.js"\nimport {Gates} from "../../src/gates/AllGates.js"\nimport {Point} from "../../src/math/Point.js"\nimport {RestartableRng} from "../../src/base/RestartableRng.js"\nimport {Hand} from "../../src/ui/Hand.js"\nimport {Painter} from "../../src/draw/Painter.js"\n\nconst COMMON_GATES = new Map([\n    [\'X\', Gates.HalfTurns.X],\n    [\'Y\', Gates.HalfTurns.Y],\n    [\'Z\', Gates.HalfTurns.Z],\n    [\'H\', Gates.HalfTurns.H],\n    [\'Q\', Gates.FourierTransformGates.FourierTransformFamily],\n    [\'•\', Gates.Controls.Control],\n    [\'◦\', Gates.Controls.AntiControl],\n\n    [\'M\', Gates.Special.Measurement],\n    [\'%\', Gates.Displays.ChanceDisplay],\n    [\'@\', Gates.Displays.BlochSphereDisplay],\n    [\'s\', Gates.Special.SwapHalf],\n    [\'!\', Gates.PostSelectionGates.PostSelectOn],\n\n    [\'-\', undefined],\n    [\'+\', undefined],\n    [\'0\', null],\n    [\'1\', null],\n    [\'2\', null],\n    [\'3\', null],\n    [\'4\', null],\n    [\'5\', null],\n    [\'6\', null],\n    [\'7\', null],\n    [\'8\', null],\n    [\'9\', null],\n\n    [\'/\', null]\n]);\n\nlet circuit = (diagramText, ...extraGateEntries) => CircuitDefinition.fromTextDiagram(\n    new Map([\n        ...COMMON_GATES.entries(),\n        ...extraGateEntries\n    ]),\n    diagramText);\n\n/**\n * @param {!string} diagramText\n * @param {!Array<*>} extraGateEntries\n * @returns {!{circuit: !DisplayedCircuit, pts: !Array.<!Point>}}\n */\nlet displayedCircuit = (diagramText, ...extraGateEntries) => DisplayedCircuit.fromTextDiagram(\n    new Map([\n        ...COMMON_GATES.entries(),\n        ...extraGateEntries\n    ]),\n    diagramText);\n\n/**\n * @param {!string} diagramText\n * @param {undefined|!{duplicate: undefined|!boolean, wholeColumn: undefined|!boolean}} options\n * @param {!Array<*>} extraGateEntries\n * @returns {{\n *   beforeGrab: !DisplayedCircuit,\n *   afterGrab: !DisplayedCircuit,\n *   hovers: !Array.<!DisplayedCircuit>,\n *   afterDrop: !DisplayedCircuit,\n *   afterDropAndTidy: !DisplayedCircuit,\n * }}\n */\nlet simulateDrag = (diagramText, options={}, ...extraGateEntries) => {\n    let duplicate = options.duplicate || false;\n    let wholeColumn = options.wholeColumn || false;\n\n    let {circuit: beforeGrab, pts} = displayedCircuit(diagramText, ...extraGateEntries);\n    let {newCircuit: afterGrab, newHand: fullHand} =\n        beforeGrab.tryGrab(Hand.EMPTY.withPos(pts[0]), duplicate, wholeColumn);\n    let hovers = [];\n    for (let pt of pts) {\n        hovers.push(afterGrab.previewDrop(fullHand.withPos(pt)));\n    }\n    let afterDrop = afterGrab.afterDropping(fullHand.withPos(pts[pts.length - 1]));\n    let afterDropAndTidy = afterDrop.afterTidyingUp();\n    return {beforeGrab, afterGrab, hovers, afterDrop, afterDropAndTidy};\n};\n\nlet suite = new Suite("DisplayedCircuit");\n\nsuite.test("constructor_vs_isEqualTo", () => {\n    let d1 = CircuitDefinition.fromTextDiagram(COMMON_GATES, `+H+\n                                                              X+Y`);\n    let d2 = CircuitDefinition.fromTextDiagram(COMMON_GATES, `++++\n                                                              ZHHH`);\n    //noinspection JSCheckFunctionSignatures\n    assertThrows(() => new DisplayedCircuit(23, "not a circuit", undefined, undefined, undefined));\n    //noinspection JSCheckFunctionSignatures\n    assertThrows(() => new DisplayedCircuit("not a number", d1, undefined, undefined, undefined));\n\n    let c1 = new DisplayedCircuit(45, d1, undefined, undefined, undefined);\n    let c2 = new DisplayedCircuit(67, d2, 1, {col: 1, row: 1, resizeStyle: true}, 1);\n    assertThat(c1.top).isEqualTo(45);\n    assertThat(c1.circuitDefinition).isEqualTo(d1);\n\n    assertThat(c1).isEqualTo(c1);\n    assertThat(c1).isNotEqualTo(c2);\n    assertThat(c2).isEqualTo(c2);\n    assertThat(c2).isNotEqualTo(c1);\n\n    assertThat(c1).isEqualTo(new DisplayedCircuit(45, d1, undefined, undefined, undefined));\n    assertThat(c1).isNotEqualTo(new DisplayedCircuit(46, d1, undefined, undefined, undefined));\n    assertThat(c1).isNotEqualTo(new DisplayedCircuit(45, d2, undefined, undefined, undefined));\n    assertThat(c1).isNotEqualTo(new DisplayedCircuit(45, d1, 1, undefined, undefined));\n    assertThat(c1).isNotEqualTo(new DisplayedCircuit(45, d1, undefined, {col:1, row:1, resizeStyle:false}, undefined));\n    assertThat(c1).isNotEqualTo(new DisplayedCircuit(45, d1, undefined, undefined, 0));\n\n    assertThat(c2).isEqualTo(new DisplayedCircuit(67, d2, 1, {col: 1, row: 1, resizeStyle: true}, 1));\n    assertThat(c2).isNotEqualTo(new DisplayedCircuit(68, d2, 1, {col: 1, row: 1, resizeStyle: true}, 1));\n    assertThat(c2).isNotEqualTo(new DisplayedCircuit(67, d1, 1, {col: 1, row: 1, resizeStyle: true}, 1));\n    assertThat(c2).isNotEqualTo(new DisplayedCircuit(67, d2, 2, {col: 1, row: 1, resizeStyle: true}, 1));\n    assertThat(c2).isNotEqualTo(new DisplayedCircuit(67, d2, 1, {col: 2, row: 1, resizeStyle: true}, 1));\n    assertThat(c2).isNotEqualTo(new DisplayedCircuit(67, d2, 1, {col: 2, row: 1, resizeStyle: true}, 2));\n});\n\nsuite.test("bootstrap_diagram", () => {\n    assertThat(displayedCircuit(`|\n                                 |-X-D//-\n                                 |   ///\n                                 |-+-///-\n                                 |`,\n                                 [\'D\', Gates.Displays.DensityMatrixDisplay2])).isEqualTo({\n        circuit: new DisplayedCircuit(\n            10,\n            circuit(`XD/\n                     +//`, [\'D\', Gates.Displays.DensityMatrixDisplay2]),\n            undefined,\n            undefined,\n            undefined),\n        pts: []\n    });\n\n    assertThat(displayedCircuit(`|\n                                 |-+-H-+-\n                                 |\n                                 |-+-Y-+-\n                                 |`)).isEqualTo({\n        circuit: new DisplayedCircuit(\n            10,\n            circuit(`+H+\n                     +Y+`),\n            undefined,\n            undefined,\n            undefined),\n        pts: []\n    });\n\n    assertThat(displayedCircuit(`|01\n                                 |2+-H-+-\n                                 |  3\n                                 |-+-Y4+-\n                                 |  5^   `)).isEqualTo({\n        circuit: new DisplayedCircuit(\n            10,\n            circuit(`+H+\n                     +Y+`),\n            undefined,\n            undefined,\n            undefined),\n        pts: [\n            new Point(35.5, 10.5),\n            new Point(60.5, 10.5),\n            new Point(35.5, 35.5),\n            new Point(85.5, 60.5),\n            new Point(135.5, 85.5),\n            new Point(110.5, 85.5)\n        ]\n    });\n});\n\nsuite.test("indexOfDisplayedRowAt", () => {\n    let {circuit, pts} = displayedCircuit(`|0\n                                           |1+-+-\n                                           |   2\n                                           |-+3+-\n                                           |  4`);\n\n    assertThat(circuit.indexOfDisplayedRowAt(-9999)).isEqualTo(undefined);\n    assertThat(circuit.indexOfDisplayedRowAt(+9999)).isEqualTo(undefined);\n\n    assertThat(circuit.indexOfDisplayedRowAt(pts[0].y)).isEqualTo(0);\n    assertThat(circuit.indexOfDisplayedRowAt(pts[1].y)).isEqualTo(0);\n    assertThat(circuit.indexOfDisplayedRowAt(pts[2].y)).isEqualTo(1);\n    assertThat(circuit.indexOfDisplayedRowAt(pts[3].y)).isEqualTo(1);\n    assertThat(circuit.indexOfDisplayedRowAt(pts[4].y)).isEqualTo(undefined);\n});\n\nsuite.testUsingWebGL("drawCircuitCompletes_QuantumTeleportation", () => {\n    let teleportCircuit = CircuitDefinition.fromTextDiagram(\n        new Map([\n            [\'X\', Gates.HalfTurns.X],\n            [\'Z\', Gates.HalfTurns.Z],\n            [\'H\', Gates.HalfTurns.H],\n            [\'M\', Gates.Special.Measurement],\n            [\'•\', Gates.Controls.Control],\n            [\'@\', Gates.Displays.BlochSphereDisplay],\n            [\'t\', Gates.Powering.YForward],\n            [\'-\', undefined],\n            [\'=\', undefined],\n            [\'|\', undefined]\n        ]),\n        `------t@--•-H-M===•===\n         -H-•------X---M=•=|===\n         ---X------------X-Z-@-`);\n    let stats = CircuitStats.fromCircuitAtTime(teleportCircuit, 0.1);\n    let displayed = DisplayedCircuit.empty(0).withCircuit(teleportCircuit);\n    let canvas = /** @type {HTMLCanvasElement} */ document.createElement("canvas");\n    canvas.width = 1000;\n    canvas.height = 1000;\n    let painter = new Painter(canvas, new RestartableRng());\n\n    // We\'re just checking that this runs to completion without throwing an exception.\n    displayed.paint(painter, Hand.EMPTY, stats);\n\n    // And now a superfluous check to avoid the \'no assertions\' warning.\n    let inputState = stats.qubitDensityMatrix(7, 0);\n    let outputState = stats.qubitDensityMatrix(Infinity, 2);\n    assertThat(outputState).isApproximatelyEqualTo(inputState);\n});\n\nsuite.test("dragXIntoCNot", () => {\n    let drag = simulateDrag(`|\n                             |-H-•-X-\n                             |    0^\n                             |-+3421-\n                             |`);\n\n    assertThat(drag.beforeGrab.circuitDefinition).isEqualTo(circuit(`H•X\n                                                                     ---`));\n    assertThat(drag.afterGrab.circuitDefinition).isEqualTo(circuit(`H•-\n                                                                    ---`));\n    assertThat(drag.hovers.map(e => e.circuitDefinition)).isEqualTo([\n        circuit(`H•X\n                 ---`),\n        circuit(`H•-\n                 --X`),\n        circuit(`H•--\n                 --X-`),\n        circuit(`H-•-\n                 -X--`),\n        circuit(`H•-\n                 -X-`)]);\n    assertThat(drag.afterDrop.circuitDefinition).isEqualTo(circuit(`H•-\n                                                                    -X-`));\n    assertThat(drag.afterDropAndTidy.circuitDefinition).isEqualTo(circuit(`H•\n                                                                           -X`));\n});\n\nsuite.test("resizeQft", () => {\n    let drag = simulateDrag(`|\n                             |-Q-\n                             | 1\n                             |-/-\n                             | 0\n                             |-+-\n                             |\n                             |-+-\n                             | 2`);\n\n    assertThat(drag.beforeGrab.circuitDefinition).isEqualTo(circuit(`Q\n                                                                     /\n                                                                     -\n                                                                     -`));\n    assertThat(drag.afterGrab.circuitDefinition).isEqualTo(circuit(`Q\n                                                                    /\n                                                                    -\n                                                                    -`));\n    assertThat(drag.hovers.map(e => e.circuitDefinition)).isEqualTo([\n        circuit(`Q\n                 /\n                 -\n                 -`),\n        circuit(`Q\n                 -\n                 -\n                 -`),\n        circuit(`Q\n                 /\n                 /\n                 /`)]);\n    assertThat(drag.afterDrop.circuitDefinition).isEqualTo(circuit(`Q\n                                                                    /\n                                                                    /\n                                                                    /`));\n    assertThat(drag.afterDropAndTidy.circuitDefinition).isEqualTo(circuit(`Q\n                                                                           /\n                                                                           /\n                                                                           /`));\n});\n\nsuite.test("dragQft", () => {\n    let drag = simulateDrag(`|\n                             |-Q-\n                             | 0\n                             |-/-\n                             |\n                             |-+-\n                             | 1\n                             |-+-\n                             |`);\n\n    assertThat(drag.beforeGrab.circuitDefinition).isEqualTo(circuit(`Q\n                                                                     /\n                                                                     -\n                                                                     -`));\n    assertThat(drag.afterGrab.circuitDefinition).isEqualTo(circuit(`-\n                                                                    -\n                                                                    -\n                                                                    -`));\n    assertThat(drag.hovers.map(e => e.circuitDefinition)).isEqualTo([\n        circuit(`Q\n                 /\n                 -\n                 -`),\n        circuit(`-\n                 -\n                 Q\n                 /`)]);\n    assertThat(drag.afterDrop.circuitDefinition).isEqualTo(circuit(`-\n                                                                    -\n                                                                    Q\n                                                                    /`));\n    assertThat(drag.afterDropAndTidy.circuitDefinition).isEqualTo(circuit(`-\n                                                                           -\n                                                                           Q\n                                                                           /`));\n});\n', 'message': 'Pulled MysteryGate stuff out of AllGates\n', 'author_name': 'Craig Gidney', 'lang': 'test'}