From cbab4d02dc28b75ae42654782c05db5fe8bfe0d0 Mon Sep 17 00:00:00 2001 From: "Stefan J. Wernli" Date: Wed, 7 Oct 2020 17:13:44 -0700 Subject: [PATCH 1/2] Fix bug in logic for releasing qubits after joint measurement To allow release of qubits that have been collapsed by measurement, we mark them with `IsMeasured` equal to true (see #206). However, joint measurement does not collapse the states of the input qubits and might actually create additional entanglement, so those qubits should not be marked as valid for release. This change fixes the logic by only marking the input to `Measure` when it is a single qubit, and adds a test that validates the exception that should be thrown when trying to release qubits after joint measurement. --- .../Simulators.Tests/Circuits/CoreOperations.qs | 9 +++++++++ .../QuantumSimulatorTests/QubitReleaseTest.cs | 9 +++++++++ .../Simulators.Tests/TestProjects/TargetedExe/Program.qs | 1 + src/Simulation/Simulators/QuantumSimulator/Measure.cs | 7 ++++--- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/Simulation/Simulators.Tests/Circuits/CoreOperations.qs b/src/Simulation/Simulators.Tests/Circuits/CoreOperations.qs index 75898a27657..fcb36aa4c8b 100644 --- a/src/Simulation/Simulators.Tests/Circuits/CoreOperations.qs +++ b/src/Simulation/Simulators.Tests/Circuits/CoreOperations.qs @@ -342,6 +342,7 @@ namespace Microsoft.Quantum.Tests.CoreOperations { // Using a different namespace, so tests can be auto-discovered. namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits { + open Microsoft.Quantum.Simulation.Simulators.Tests.Circuits.Generics; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Diagnostics; @@ -559,6 +560,14 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits { } } + operation ReleaseMeasureMultipleQubitCheck() : Unit { + using (qs = Qubit[2]) { + ApplyToEach(H, qs); + let r = Measure([PauliZ, PauliZ], qs); + // Should raise an exception + } + } + operation BorrowingQubitCheck () : Unit { using (q = Qubit()) diff --git a/src/Simulation/Simulators.Tests/QuantumSimulatorTests/QubitReleaseTest.cs b/src/Simulation/Simulators.Tests/QuantumSimulatorTests/QubitReleaseTest.cs index a267a719274..3e2d78ddf7d 100644 --- a/src/Simulation/Simulators.Tests/QuantumSimulatorTests/QubitReleaseTest.cs +++ b/src/Simulation/Simulators.Tests/QuantumSimulatorTests/QubitReleaseTest.cs @@ -33,6 +33,15 @@ public async Task MeasuredQubitReleaseTest() await ReleaseMeasuredQubitCheck.Run(sim); } + //test to check that qubits cannot be released after multiple qubit measure + [Fact] + public async Task MeasuredMultipleQubitsReleaseTest() + { + var sim = new QuantumSimulator(); + + await Assert.ThrowsAsync(() => ReleaseMeasureMultipleQubitCheck.Run(sim)); + } + //test to check that qubit that is released and reallocated is in state |0> [Fact] public async Task ReallocateQubitInGroundStateTest() diff --git a/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/Program.qs b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/Program.qs index c08b6d4188b..47a26f9d403 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/Program.qs +++ b/src/Simulation/Simulators.Tests/TestProjects/TargetedExe/Program.qs @@ -10,6 +10,7 @@ let arr = Default(); using (qs = Qubit[2]) { Ignore(Measure([PauliX, PauliX], qs)); + ResetAll(qs); return "TargetedExe"; } } diff --git a/src/Simulation/Simulators/QuantumSimulator/Measure.cs b/src/Simulation/Simulators/QuantumSimulator/Measure.cs index 25eb5caed95..6931709f194 100644 --- a/src/Simulation/Simulators/QuantumSimulator/Measure.cs +++ b/src/Simulation/Simulators/QuantumSimulator/Measure.cs @@ -31,10 +31,11 @@ public QSimMeasure(QuantumSimulator m) : base(m) { throw new InvalidOperationException($"Both input arrays for {this.GetType().Name} (paulis,qubits), must be of same size"); } - foreach (Qubit q in qubits) + if (qubits.Length == 1) { - //setting qubit as measured to allow for release - q.IsMeasured = true; + // When we are operating on a single qubit we will collapse the state, so mark + // that qubit as measured. + qubits[0].IsMeasured = true; } return Measure(Simulator.Id, (uint)paulis.Length, paulis.ToArray(), qubits.GetIds()).ToResult(); }; From a8edddf133ca79297d7d50263cfe299f6b67bebd Mon Sep 17 00:00:00 2001 From: "Stefan J. Wernli" Date: Thu, 8 Oct 2020 10:43:28 -0700 Subject: [PATCH 2/2] Empty commit to force pipeline rerun...