diff --git a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs index b20864f09ee..f3556f08b3d 100644 --- a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs +++ b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs @@ -3685,10 +3685,21 @@ namespace Microsoft.Quantum.Tests.UnitTests baseSim.OnLog += this.Output.WriteLine; } - sim.Run(QVoid.Instance).Wait(); - if (sim is IDisposable disposeSim) + try + { + sim.Execute(QVoid.Instance); + } + catch (Exception e) + { +#line 22 "%%" + Xunit.Assert.True(false, "Q# Test failed. For details see the Standard output below."); + } + finally { - disposeSim.Dispose(); + if (sim is IDisposable disposeSim) + { + disposeSim.Dispose(); + } } } } @@ -3717,10 +3728,21 @@ namespace Microsoft.Quantum.Tests.UnitTests baseSim.OnLog += this.Output.WriteLine; } - sim.Run(QVoid.Instance).Wait(); - if (sim is IDisposable disposeSim) + try { - disposeSim.Dispose(); + sim.Execute(QVoid.Instance); + } + catch (Exception e) + { +#line 22 "%%" + Xunit.Assert.True(false, "Q# Test failed. For details see the Standard output below."); + } + finally + { + if (sim is IDisposable disposeSim) + { + disposeSim.Dispose(); + } } } } @@ -3778,10 +3800,21 @@ namespace Microsoft.Quantum.Tests.UnitTests baseSim.OnLog += this.Output.WriteLine; } - sim.Run(QVoid.Instance).Wait(); - if (sim is IDisposable disposeSim) + try + { + sim.Execute(QVoid.Instance); + } + catch (Exception e) { - disposeSim.Dispose(); +#line 26 "%%" + Xunit.Assert.True(false, "Q# Test failed. For details see the Standard output below."); + } + finally + { + if (sim is IDisposable disposeSim) + { + disposeSim.Dispose(); + } } } } diff --git a/src/Simulation/CsharpGeneration/SimulationCode.fs b/src/Simulation/CsharpGeneration/SimulationCode.fs index d1dafb7b4bf..16000eb6ad3 100644 --- a/src/Simulation/CsharpGeneration/SimulationCode.fs +++ b/src/Simulation/CsharpGeneration/SimulationCode.fs @@ -1240,7 +1240,7 @@ module SimulationCode = let disposeSim = ``ident`` "disposeSim" let ``this.Output`` = ``ident`` "this" <|.|> ``ident`` "Output" let ``sim.OnLog`` = baseSim <|.|> ``ident`` "OnLog" - let Run = generic "Run" ``<<`` [opName; "QVoid"; "QVoid"] ``>>`` + let Execute = generic "Execute" ``<<`` [opName; "QVoid"; "QVoid"] ``>>`` let simCond = sim |> ``is assign`` "Microsoft.Quantum.Simulation.Common.SimulatorBase" baseSim .&&. ``this.Output`` .!=. ``null`` @@ -1248,11 +1248,29 @@ module SimulationCode = let assignLogEvent = ``if`` ``(`` simCond ``)`` [ ``sim.OnLog`` <+=> (``this.Output`` <|.|> ``ident`` "WriteLine") ] None - let ``sim.Run.Wait`` = sim <.> (Run, [ ``ident`` "QVoid" <|.|> ``ident`` "Instance"]) <.> ((``ident`` "Wait"), []) |> statement + let ``sim.Execute`` = sim <.> (Execute, [ ``ident`` "QVoid" <|.|> ``ident`` "Instance"]) |> statement let disposeOfRun = ``if`` ``(`` (sim |> ``is assign`` "IDisposable" disposeSim) ``)`` [ disposeSim <.> ((``ident`` "Dispose"), []) |> statement ] None + let errMsg = ``literal`` "Q# Test failed. For details see the Standard output below." + + let tryRunCatch = + ``try`` + [ + ``sim.Execute`` + ] + [ + ``catch`` (Some ("Exception", "e")) + [ + (``ident`` "Xunit.Assert") <.> ((``ident`` "True"), [``false`` :> ExpressionSyntax; errMsg]) |> (statement >> ``#line`` (opStart + 1) opSourceFile) + ] + ] + (Some (``finally`` + [ + ``disposeOfRun`` + ])) + ``attributes`` [ ``attribute`` None (``ident`` "Xunit.Fact") []; @@ -1261,7 +1279,7 @@ module SimulationCode = ] (``method`` "void" opName ``<<`` [] ``>>`` ``(`` [] ``)`` [``public``] ``{`` - [getSimulator; assignLogEvent; ``sim.Run.Wait``; disposeOfRun] + [getSimulator; assignLogEvent; tryRunCatch] ``}`` |> ``with trivia`` (``#lineNr`` (opStart + 1) opSourceFile) // we need 1-based line numbers here, and opStart is zero-based ) diff --git a/src/Simulation/QCTraceSimulator/DepthCounter.cs b/src/Simulation/QCTraceSimulator/DepthCounter.cs index db02a56fb8b..8cd0c58cc71 100644 --- a/src/Simulation/QCTraceSimulator/DepthCounter.cs +++ b/src/Simulation/QCTraceSimulator/DepthCounter.cs @@ -87,8 +87,8 @@ public void OnOperationEnd(object[] returnedQubitsTraceData) OperationCallRecord caller = operationCallStack.Peek(); HashedString callerName = caller.OperationName; - caller.ReleasedQubitsAvailableTime = Max(opRec.ReleasedQubitsAvailableTime, caller.ReleasedQubitsAvailableTime ); - caller.ReleasedQubitsAvailableTime = Max(opRec.ReleasedQubitsAvailableTime, caller.ReleasedQubitsAvailableTime ); + caller.ReleasedQubitsAvailableTime = Max(opRec.ReleasedQubitsAvailableTime, caller.ReleasedQubitsAvailableTime); + caller.ReturnedQubitsAvailableTime = Max(opRec.ReturnedQubitsAvailableTime, caller.ReturnedQubitsAvailableTime); double[] metrics = StatisticsRecord( diff --git a/src/Simulation/QCTraceSimulator/DistinctInputsChecker.cs b/src/Simulation/QCTraceSimulator/DistinctInputsChecker.cs index bd795995e1d..f5ae0e99851 100644 --- a/src/Simulation/QCTraceSimulator/DistinctInputsChecker.cs +++ b/src/Simulation/QCTraceSimulator/DistinctInputsChecker.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Diagnostics; using Microsoft.Quantum.Simulation.Core; -using Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators; namespace Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime { diff --git a/src/Simulation/QCTraceSimulator/Exceptions.cs b/src/Simulation/QCTraceSimulator/Exceptions.cs index 938921ba2af..0d4e31be8c5 100644 --- a/src/Simulation/QCTraceSimulator/Exceptions.cs +++ b/src/Simulation/QCTraceSimulator/Exceptions.cs @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -namespace Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators +namespace Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime { /// /// This exception is thrown when the input to an diff --git a/src/Simulation/QCTraceSimulator/InvalidatedQubitsUseChecker.cs b/src/Simulation/QCTraceSimulator/InvalidatedQubitsUseChecker.cs index d6a7ebb550c..d08db1bfd6c 100644 --- a/src/Simulation/QCTraceSimulator/InvalidatedQubitsUseChecker.cs +++ b/src/Simulation/QCTraceSimulator/InvalidatedQubitsUseChecker.cs @@ -8,7 +8,6 @@ using System.Text; using System.Threading.Tasks; using Microsoft.Quantum.Simulation.Core; -using Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators; namespace Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime { diff --git a/src/Simulation/QCTraceSimulator/QCTraceSimulatorCore.cs b/src/Simulation/QCTraceSimulator/QCTraceSimulatorCore.cs index 87c56594945..d89fae497ca 100644 --- a/src/Simulation/QCTraceSimulator/QCTraceSimulatorCore.cs +++ b/src/Simulation/QCTraceSimulator/QCTraceSimulatorCore.cs @@ -8,7 +8,6 @@ namespace Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime using System.Collections.Generic; using System.Diagnostics; using Microsoft.Quantum.Simulation.Common; - using Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators; using System.Linq; [Serializable] diff --git a/src/Simulation/QCTraceSimulator/QubitMetrics.cs b/src/Simulation/QCTraceSimulator/QubitMetrics.cs index 397d9c1003b..ca7b1a0bd9c 100644 --- a/src/Simulation/QCTraceSimulator/QubitMetrics.cs +++ b/src/Simulation/QCTraceSimulator/QubitMetrics.cs @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators; - namespace Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime { /// diff --git a/src/Simulation/QsharpCore/Targeting.qs b/src/Simulation/QsharpCore/Targeting.qs new file mode 100644 index 00000000000..989a5eb7ec9 --- /dev/null +++ b/src/Simulation/QsharpCore/Targeting.qs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/// # Summary +/// This namespace provides functionality for targeting specific quantum processors. +namespace Microsoft.Quantum.Targeting { + /// # Summary + /// Compiler-recognized attribute used to mark a callable with the runtime capabilities it + /// requires. + /// + /// # Named Items + /// ## Level + /// The name of the runtime capability level required by the callable. + /// + /// ## Reason + /// A description of why the callable requires this runtime capability. + /// + /// # Remarks + /// This attribute is automatically added to callables by the compiler, unless an instance of + /// this attribute already exists on the callable. It should not be used except in rare cases + /// where the compiler does not infer the required capability correctly. + /// + /// Below is the list of capability level names, in order of increasing capabilities or + /// decreasing restrictions: + /// + /// ## `"BasicQuantumFunctionality"` + /// Measurement results cannot be compared for equality. + /// + /// ## `"BasicMeasurementFeedback"` + /// Measurement results can be compared for equality only in if-statement conditional + /// expressions in operations. The block of an if-statement that depends on a result cannot + /// contain set statements for mutable variables declared outside the block, or return + /// statements. + /// + /// ## `"FullComputation"` + /// No runtime restrictions. Any Q# program can be executed. + @Attribute() + newtype RequiresCapability = (Level : String, Reason : String); +} diff --git a/src/Simulation/QsharpFoundation/Core.qs b/src/Simulation/QsharpFoundation/Core.qs index 69d3287f5ee..fe4a5d02e50 100644 --- a/src/Simulation/QsharpFoundation/Core.qs +++ b/src/Simulation/QsharpFoundation/Core.qs @@ -22,7 +22,7 @@ namespace Microsoft.Quantum.Core { /// # Summary /// Compiler-recognized attribute used to mark a type or callable as deprecated. /// - /// # Input + /// # Named Items /// ## NewName /// The full name of the type or callable to use instead. /// Is set to the empty String if a type or callable has been deprecated without substitution. @@ -30,7 +30,6 @@ namespace Microsoft.Quantum.Core { @Attribute() newtype Deprecated = (NewName : String); - /// # Summary /// Returns a default instance of the specified type. /// @@ -136,5 +135,3 @@ namespace Microsoft.Quantum.Core { } } - - diff --git a/src/Simulation/Simulators.Impl/QCTraceSimulator/QCTraceSimulatorImpl.cs b/src/Simulation/Simulators.Impl/QCTraceSimulator/QCTraceSimulatorImpl.cs index c3bd7f2de57..83a978f8461 100644 --- a/src/Simulation/Simulators.Impl/QCTraceSimulator/QCTraceSimulatorImpl.cs +++ b/src/Simulation/Simulators.Impl/QCTraceSimulator/QCTraceSimulatorImpl.cs @@ -177,32 +177,6 @@ from op in primitiveOperationAsCircuits } } - #region Helpers - static private (long, long) Reduce(long numerator, long denominatorPower) - { - if (numerator == 0) - { - return (0, 0); - } - - if (numerator % 2 != 0) - { - return (numerator, denominatorPower); - } - - long numNew = numerator; - long denomPowerNew = denominatorPower; - - while (numNew % 2 == 0) - { - numNew /= 2; - denomPowerNew -= 1; - } - - return (numNew, denomPowerNew); - } - #endregion - #region Primitive operations logic private void DoPrimitiveOperation(PrimitiveOperationsGroups operation, IQArray target, bool invalidateConstraints = true) @@ -228,7 +202,7 @@ private void RFrac(Pauli pauli, long numerator, long denominatorPower, Qubit tar return; // global phase case } - (long numNew, long denomPowerNew) = Reduce(numerator, denominatorPower); + (long numNew, long denomPowerNew) = CommonUtils.Reduce(numerator, denominatorPower); switch (denomPowerNew) { case 3: diff --git a/src/Simulation/Simulators.Impl/QuantumSimulator/Measure.cs b/src/Simulation/Simulators.Impl/QuantumSimulator/Measure.cs index 25eb5caed95..6931709f194 100644 --- a/src/Simulation/Simulators.Impl/QuantumSimulator/Measure.cs +++ b/src/Simulation/Simulators.Impl/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(); }; 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/Microsoft.Quantum.Simulators.nuspec.template b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.nuspec.template index a6b1ee3819e..6c9f9181b5b 100644 --- a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.nuspec.template +++ b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.nuspec.template @@ -20,6 +20,10 @@ + + + + diff --git a/src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualReferenced.qs b/src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualReferenced.qs index 72e0deb95d9..eed629789a1 100644 --- a/src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualReferenced.qs +++ b/src/Simulation/TargetDefinitions/Decompositions/AssertOperationsEqualReferenced.qs @@ -31,7 +31,7 @@ namespace Microsoft.Quantum.Diagnostics { /// # Summary /// Given two operations, asserts that they act identically for all input states. /// - /// This assertion is implemented by using the Choi–Jamiłkowski isomorphism to reduce + /// This assertion is implemented by using the Choi–Jamiołkowski isomorphism to reduce /// the assertion to one of a qubit state assertion on two entangled registers. /// Thus, this operation needs only a single call to each operation being tested, /// but requires twice as many qubits to be allocated. diff --git a/src/Simulation/TargetDefinitions/TargetPackages/Common.Package.props b/src/Simulation/TargetDefinitions/TargetPackages/Common.Package.props index a53c8f9abbe..3f0557d6b92 100644 --- a/src/Simulation/TargetDefinitions/TargetPackages/Common.Package.props +++ b/src/Simulation/TargetDefinitions/TargetPackages/Common.Package.props @@ -26,7 +26,6 @@ -