From dc2daed0ebca05c3331d98311eed15465e1fbf33 Mon Sep 17 00:00:00 2001 From: Craig Gidney Date: Sun, 24 Mar 2019 12:13:19 -0700 Subject: [PATCH] Fix detect-control-reset gates not being able to toggle classical wires --- src/circuit/Gate.js | 21 ++++++++++++++++++++- src/circuit/GateColumn.js | 3 ++- src/gates/Detector.js | 2 +- test/circuit/CircuitDefinition.test.js | 6 ++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/circuit/Gate.js b/src/circuit/Gate.js index 9db006b3..9e50e93c 100644 --- a/src/circuit/Gate.js +++ b/src/circuit/Gate.js @@ -158,6 +158,14 @@ class Gate { * @private */ this._controlBit = undefined; + /** + * Determines if a controlled gate's control is guaranteed to be known classically. This is used by the + * combination detect-control-reset gates as a way to communicate that they can control permutation operations + * on classical wires. + * @type {boolean} + * @private + */ + this._isClassicalControl = false; /** * Indicates that this gate is guaranteed to preserve probability (as opposed to e.g. post-selection). * When gates with this property not set to true are present in a column, the simulator computes losses/gains. @@ -284,6 +292,7 @@ class Gate { g._effectCreatesSuperpositions = this._effectCreatesSuperpositions; g._affectsOtherWires = this._affectsOtherWires; g._controlBit = this._controlBit; + g._isClassicalControl = this._isClassicalControl; g.isControlWireSource = this.isControlWireSource; g._isDefinitelyUnitary = this._isDefinitelyUnitary; g.knownPhaseTurnsFunc = this.knownPhaseTurnsFunc; @@ -393,6 +402,13 @@ class Gate { return this._controlBit !== undefined; } + /** + * @returns {!boolean} + */ + isClassicalControl() { + return this._isClassicalControl; + } + /** * @returns {undefined|!boolean} */ @@ -809,12 +825,15 @@ class GateBuilder { /** * Sets meta-properties to indicate a gate is a control. * @param {!boolean} bit: Whether gate is a control or anti-control. Use before/after operations for flexibility. + * @param {!boolean} guaranteedClassical Whether or not the control can be used to control permutations of classical + * wires, even if placed on a coherent wire. * @returns {!GateBuilder} */ - markAsControlExpecting(bit) { + markAsControlExpecting(bit, guaranteedClassical=false) { this.gate._controlBit = bit; this.gate.isControlWireSource = true; this.gate.interestedInControls = false; + this.gate._isClassicalControl = guaranteedClassical; return this; } diff --git a/src/circuit/GateColumn.js b/src/circuit/GateColumn.js index f809ebb8..d7ecf18e 100644 --- a/src/circuit/GateColumn.js +++ b/src/circuit/GateColumn.js @@ -87,7 +87,8 @@ class GateColumn { for (let i = 0; i < this.gates.length; i++) { if ((inputMeasureMask & (1 << i)) === 0 && this.gates[i] !== undefined && - this.gates[i].isControl()) { + this.gates[i].isControl() && + !this.gates[i].isClassicalControl()) { return true; } } diff --git a/src/gates/Detector.js b/src/gates/Detector.js index 1f9bcf78..857a7926 100644 --- a/src/gates/Detector.js +++ b/src/gates/Detector.js @@ -370,7 +370,7 @@ function makeDetectControlClearGate(axis) { setTitle(`${axis} Detect-Control-Reset`). setBlurb(`Does a collapsing ${axis}-axis measurement.\nControls operations with the result.\nResets the target to |0⟩.`). setDrawer(args => drawDetectClearReset(args, axis)). - markAsControlExpecting(true). + markAsControlExpecting(true, true). markAsReachingOtherWires(). setActualEffectToUpdateFunc(() => {}). setStatTexturesMaker(withClearedControls(detectorStatTexture)). diff --git a/test/circuit/CircuitDefinition.test.js b/test/circuit/CircuitDefinition.test.js index 36d076c9..0b7d5cb6 100644 --- a/test/circuit/CircuitDefinition.test.js +++ b/test/circuit/CircuitDefinition.test.js @@ -901,6 +901,12 @@ suite.test("gateAtLocIsDisabledReason", () => { bad(1, 0, `MR`, ['R', Gates.Detectors.XDetectControlClear]); bad(1, 0, `MR`, ['R', Gates.Detectors.YDetectControlClear]); good(1, 0, `MR`, ['R', Gates.Detectors.ZDetectControlClear]); + good(3, 1, `---]- + -M-X-`, [']', Gates.Detectors.XDetectControlClear]); + good(3, 1, `---]- + -M-X-`, [']', Gates.Detectors.YDetectControlClear]); + good(3, 1, `---]- + -M-X-`, [']', Gates.Detectors.ZDetectControlClear]); // Permutation sub-groups. good(2, 0, `--P-