diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..a2fb9f977b6 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# Automatically tag in libraries maintainers on Q# API changes. +*.qs @microsoft/quantumlibraries diff --git a/Simulation.sln b/Simulation.sln index bfe0e7c6315..0abbff54fdc 100644 --- a/Simulation.sln +++ b/Simulation.sln @@ -47,6 +47,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Library1", "src\Simulation\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Library2", "src\Simulation\Simulators.Tests\TestProjects\Library2\Library2.csproj", "{A85277B3-4E07-4E15-8F0C-07CC855A3BCB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Library with Spaces", "src\Simulation\Simulators.Tests\TestProjects\Library with Spaces\Library with Spaces.csproj", "{418E79F7-9FCF-4128-AA35-1334A685377D}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "src\Simulation\Simulators.Tests\TestProjects\UnitTests\UnitTests.csproj", "{46278108-D247-4EFC-AC34-23D4A676F62F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure", "Azure", "{37CDC768-16D4-4574-8553-07D99D0A72F7}" @@ -355,6 +357,22 @@ Global {46278108-D247-4EFC-AC34-23D4A676F62F}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {46278108-D247-4EFC-AC34-23D4A676F62F}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {46278108-D247-4EFC-AC34-23D4A676F62F}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.Debug|x64.ActiveCfg = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.Debug|x64.Build.0 = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.Release|Any CPU.Build.0 = Release|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.Release|x64.ActiveCfg = Release|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.Release|x64.Build.0 = Release|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU + {418E79F7-9FCF-4128-AA35-1334A685377D}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU {7F05FD87-A2FB-4915-A988-4EF92AB82179}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7F05FD87-A2FB-4915-A988-4EF92AB82179}.Debug|Any CPU.Build.0 = Debug|Any CPU {7F05FD87-A2FB-4915-A988-4EF92AB82179}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -411,6 +429,7 @@ Global {7256B986-6705-42FC-9F57-485D72D9DE51} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} {A85277B3-4E07-4E15-8F0C-07CC855A3BCB} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} {46278108-D247-4EFC-AC34-23D4A676F62F} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} + {418E79F7-9FCF-4128-AA35-1334A685377D} = {09C842CB-930C-4C7D-AD5F-E30DE4A55820} {7F05FD87-A2FB-4915-A988-4EF92AB82179} = {37CDC768-16D4-4574-8553-07D99D0A72F7} {4858E5E3-23FA-4928-B99A-54065875A2B9} = {37CDC768-16D4-4574-8553-07D99D0A72F7} EndGlobalSection diff --git a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs index e3ee0787da2..2d4f80b713c 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs @@ -62,7 +62,7 @@ public async Task UploadBlobAsync( try { // Ensure container is created - await containerClient.CreateIfNotExistsAsync(PublicAccessType.Blob, cancellationToken: cancellationToken); + await containerClient.CreateIfNotExistsAsync(PublicAccessType.None, cancellationToken: cancellationToken); // Upload blob BlobClient blob = containerClient.GetBlobClient(blobName); diff --git a/src/Simulation/Common/IQuantumProcessor.cs b/src/Simulation/Common/IQuantumProcessor.cs index 4152249b139..dd61aed3bdd 100644 --- a/src/Simulation/Common/IQuantumProcessor.cs +++ b/src/Simulation/Common/IQuantumProcessor.cs @@ -517,7 +517,7 @@ public interface IQuantumProcessor void Assert(IQArray bases, IQArray qubits, Result result, string msg); /// - /// Called when Microsoft.Quantum.Intrinsic.Assert is called in Q#. + /// Called when Microsoft.Quantum.Intrinsic.AssertProb is called in Q#. /// /// /// The names and the order of the parameters is similar to the corresponding Q# operation./ diff --git a/src/Simulation/Common/SimulatorBase.cs b/src/Simulation/Common/SimulatorBase.cs index 1440e2112db..41f566ea641 100644 --- a/src/Simulation/Common/SimulatorBase.cs +++ b/src/Simulation/Common/SimulatorBase.cs @@ -31,6 +31,14 @@ public abstract class SimulatorBase : AbstractFactory, IOperat public event Action? OnLog = null; public event Action>? OnException = null; + + /// + /// An event fired whenever a simulator has additional diagnostic data + /// available for display (e.g. state information, assertion details, + /// execution traces). + /// + public event Action? OnDisplayableDiagnostic = null; + public IQubitManager? QubitManager { get; } public abstract string Name { get; } @@ -182,6 +190,17 @@ public void EnableExceptionPrinting() OnException += WriteStackTraceToLog; } + /// + /// Sends diagnostic data to any listening display handlers. + /// Display handlers may discard any unrecognized data, such that + /// no guarantee is made as to any particular action taken as a result + /// of calling this method. + /// + protected void MaybeDisplayDiagnostic(object data) + { + OnDisplayableDiagnostic?.Invoke(data); + } + /// /// Disables default handling of stack traces, such that stack diff --git a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs index 31fb2e62e04..90416d37e9e 100644 --- a/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs +++ b/src/Simulation/CsharpGeneration.Tests/SimulationCodeTests.fs @@ -7,6 +7,7 @@ open System open System.Collections.Immutable open System.IO open System.Globalization +open System.Web open Microsoft.CodeAnalysis open Microsoft.CodeAnalysis.CSharp @@ -218,9 +219,13 @@ namespace N1 let testOneFile fileName (expected:string) = - let expected = expected.Replace("%%%", (Uri(Path.GetFullPath fileName)).AbsolutePath) - let expected = expected.Replace("%%", (Path.GetFullPath fileName).Replace("\\", "\\\\")) - let tree = parse [(Path.Combine("Circuits","Intrinsic.qs")); fileName] + let fullPath = Path.GetFullPath fileName + let escapeCSharpString (s : string) = SymbolDisplay.FormatLiteral (s, false) + let expected = + expected + |> (fun s -> s.Replace("%%%", fullPath |> HttpUtility.JavaScriptStringEncode |> escapeCSharpString)) + |> (fun s -> s.Replace("%%", fullPath |> escapeCSharpString)) + let tree = parse [Path.Combine ("Circuits", "Intrinsic.qs"); fileName] let actual = CodegenContext.Create (tree, ImmutableDictionary.Empty) |> generate (Path.GetFullPath fileName |> NonNullable.New) @@ -2307,7 +2312,7 @@ namespace N1 false |> testOne randomOperation let testOneClass (_,op : QsCallable) executionTarget (expected : string) = - let expected = expected.Replace("%%%", op.SourceFile.Value) + let expected = expected.Replace("%%%", HttpUtility.JavaScriptStringEncode op.SourceFile.Value) let assemblyConstants = new System.Collections.Generic.KeyValuePair<_,_> (AssemblyConstants.ExecutionTarget, executionTarget) |> Seq.singleton @@ -3397,7 +3402,7 @@ using Microsoft.Quantum.Simulation.Core; #line hidden namespace Microsoft.Quantum.Tests.Inline { - [SourceLocation("%%%", OperationFunctor.Body, 7, -1)] + [SourceLocation("%%", OperationFunctor.Body, 7, -1)] public partial class HelloWorld : Operation, ICallable { public HelloWorld(IOperationFactory m) : base(m) @@ -3454,7 +3459,7 @@ using Microsoft.Quantum.Simulation.Core; #line hidden namespace Microsoft.Quantum.Tests.LineNumbers { - [SourceLocation("%%%", OperationFunctor.Body, 9, -1)] + [SourceLocation("%%", OperationFunctor.Body, 9, -1)] public partial class TestLineInBlocks : Operation, ICallable { public TestLineInBlocks(IOperationFactory m) : base(m) @@ -3628,7 +3633,7 @@ namespace Microsoft.Quantum.Diagnostics #line hidden namespace Microsoft.Quantum.Tests.UnitTests { - [SourceLocation("%%%", OperationFunctor.Body, 22, 26)] + [SourceLocation("%%", OperationFunctor.Body, 22, 26)] public partial class UnitTest1 : Operation, ICallable { public UnitTest1(IOperationFactory m) : base(m) @@ -3651,7 +3656,7 @@ namespace Microsoft.Quantum.Tests.UnitTests [Xunit.Trait("Target", "QuantumSimulator")] [Xunit.Trait("Name", "UnitTest1")] public void UnitTest1() -#line 22 "%%%" +#line 22 "%%" { var sim = new Microsoft.Quantum.Simulation.Simulators.QuantumSimulator(); if (sim is Microsoft.Quantum.Simulation.Common.SimulatorBase baseSim && this.Output != null) @@ -3683,7 +3688,7 @@ namespace Microsoft.Quantum.Tests.UnitTests [Xunit.Trait("Target", "ToffoliSimulator")] [Xunit.Trait("Name", "UnitTest1")] public void UnitTest1() -#line 22 "%%%" +#line 22 "%%" { var sim = new Microsoft.Quantum.Simulation.Simulators.ToffoliSimulator(); if (sim is Microsoft.Quantum.Simulation.Common.SimulatorBase baseSim && this.Output != null) @@ -3721,7 +3726,7 @@ namespace Microsoft.Quantum.Tests.UnitTests } } - [SourceLocation("%%%", OperationFunctor.Body, 26, -1)] + [SourceLocation("%%", OperationFunctor.Body, 26, -1)] public partial class UnitTest2 : Operation, ICallable { public UnitTest2(IOperationFactory m) : base(m) @@ -3744,7 +3749,7 @@ namespace Microsoft.Quantum.Tests.UnitTests [Xunit.Trait("Target", "CustomSimulator")] [Xunit.Trait("Name", "UnitTest2")] public void UnitTest2() -#line 26 "%%%" +#line 26 "%%" { var sim = new SomeNamespace.CustomSimulator(); if (sim is Microsoft.Quantum.Simulation.Common.SimulatorBase baseSim && this.Output != null) diff --git a/src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj b/src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj index 1bc1a267e83..03679c61a32 100644 --- a/src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj +++ b/src/Simulation/CsharpGeneration/Microsoft.Quantum.CsharpGeneration.fsproj @@ -21,7 +21,7 @@ - + diff --git a/src/Simulation/CsharpGeneration/SimulationCode.fs b/src/Simulation/CsharpGeneration/SimulationCode.fs index e0c6b0c0810..30e83926c90 100644 --- a/src/Simulation/CsharpGeneration/SimulationCode.fs +++ b/src/Simulation/CsharpGeneration/SimulationCode.fs @@ -1573,13 +1573,10 @@ module SimulationCode = generator.Apply elements // Returns only those namespaces and their elements that are defined for the given file. - let findLocalElements selector fileName syntaxTree = - let path = - match CompilationBuilder.CompilationUnitManager.TryGetUri fileName with - | true, uri -> uri.AbsolutePath |> NonNullable.New - | false, _ -> NonNullable.New "" + let findLocalElements selector (fileName : NonNullable) syntaxTree = syntaxTree - |> Seq.map (fun ns -> (ns.Name, (FilterBySourceFile.Apply (ns, path)).Elements |> Seq.choose selector |> Seq.toList)) + |> Seq.map (fun ns -> + (ns.Name, (FilterBySourceFile.Apply (ns, fileName)).Elements |> Seq.choose selector |> Seq.toList)) |> Seq.sortBy fst |> Seq.filter (fun (_,elements) -> not elements.IsEmpty) |> Seq.toList diff --git a/src/Simulation/EntryPointDriver.Tests/Tests.fs b/src/Simulation/EntryPointDriver.Tests/Tests.fs index 7f242fdc5a0..9d3c9c5d0aa 100644 --- a/src/Simulation/EntryPointDriver.Tests/Tests.fs +++ b/src/Simulation/EntryPointDriver.Tests/Tests.fs @@ -474,15 +474,15 @@ let ``Shadows --shots`` () = // The expected output from the resources estimator. let private resourceSummary = - "Metric Sum - CNOT 0 - QubitClifford 1 - R 0 - Measure 1 - T 0 - Depth 0 - Width 1 - BorrowedWidth 0" + "Metric Sum Max + CNOT 0 0 + QubitClifford 1 1 + R 0 0 + Measure 1 1 + T 0 0 + Depth 0 0 + Width 1 1 + BorrowedWidth 0 0" [] let ``Supports QuantumSimulator`` () = diff --git a/src/Simulation/QCTraceSimulator.Tests/Circuits/RandomTests.qs b/src/Simulation/QCTraceSimulator.Tests/Circuits/RandomTests.qs new file mode 100644 index 00000000000..b37c8c0c33f --- /dev/null +++ b/src/Simulation/QCTraceSimulator.Tests/Circuits/RandomTests.qs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + + +namespace Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.Tests { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Diagnostics; + + internal function Fact(condition : Bool, message : String) : Unit { + if (not condition) { + fail message; + } + } + + @Test("ResourcesEstimator") + /// # Summary + /// Checks for regression against microsoft/qsharp-runtime#256. + operation CheckRandomInCorrectRange() : Unit { + for (idxTrial in 0..99) { + let sample = Random([1.0, 2.0, 2.0]); + + Fact(0 <= sample and sample <= 2, $"sample was {sample}, not in range [0, 2]"); + } + } +} diff --git a/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj b/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj index 93d81f193bb..ce03e2cb766 100644 --- a/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj +++ b/src/Simulation/QCTraceSimulator.Tests/Tests.Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/QsharpCore/Arrays/Enumeration.qs b/src/Simulation/QsharpCore/Arrays/Enumeration.qs new file mode 100644 index 00000000000..a90383b1ab5 --- /dev/null +++ b/src/Simulation/QsharpCore/Arrays/Enumeration.qs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Arrays { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Canon; + + /// # Summary + /// Given an array, returns a range over the indices of that array, suitable + /// for use in a for loop. + /// + /// # Type Parameters + /// ## 'TElement + /// The type of elements of the array. + /// + /// # Input + /// ## array + /// An array for which a range of indices should be returned. + /// + /// # Output + /// A range over all indices of the array. + /// + /// # Example + /// The following `for` loops are equivalent: + /// ```Q# + /// for (idx in IndexRange(array)) { ... } + /// for (idx in IndexRange(array)) { ... } + /// ``` + function IndexRange<'TElement>(array : 'TElement[]) : Range { + return 0..(Length(array) - 1); + } + +} diff --git a/src/Simulation/QsharpCore/Canon/NoOp.qs b/src/Simulation/QsharpCore/Canon/NoOp.qs new file mode 100644 index 00000000000..b9a778f6e26 --- /dev/null +++ b/src/Simulation/QsharpCore/Canon/NoOp.qs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Canon { + + /// # Summary + /// Performs the identity operation (no-op) on an argument. + /// + /// # Description + /// This operation takes a value of any type and does nothing to it. + /// This can be useful whenever an input of an operation type is expected, + /// but no action should be taken. + /// For instance, if a particular error correction syndrome indicates that + /// no error has occurred, `NoOp` may be the correct recovery + /// procedure. + /// Similarly, if an operation expects a state preparation procedure as + /// input, `NoOp` can be used to prepare the state + /// $\ket{0 \cdots 0}$. + /// + /// # Input + /// ## input + /// A value to be ignored. + /// + /// # Remarks + /// In almost all cases, the type parameter for `NoOp` needs to be specified + /// explicitly. For instance, `NoOp` is identical to + /// . + /// + /// # See Also + /// - Microsoft.Quantum.Intrinsic.I + operation NoOp<'T>(input : 'T) : Unit is Adj + Ctl { + } + + + /// # Summary + /// Ignores the output of an operation or function. + /// + /// # Input + /// ## value + /// A value to be ignored. + function Ignore<'T> (value : 'T) : Unit { + return (); + } + +} diff --git a/src/Simulation/QsharpCore/Diagnostics/Assert.qs b/src/Simulation/QsharpCore/Diagnostics/Assert.qs new file mode 100644 index 00000000000..6f5cb339633 --- /dev/null +++ b/src/Simulation/QsharpCore/Diagnostics/Assert.qs @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Diagnostics { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Canon; + + /// # Summary + /// Asserts that measuring the given qubits in the given Pauli basis will + /// always have the given result. + /// + /// # Input + /// ## bases + /// A measurement effect to assert the probability of, expressed as a + /// multi-qubit Pauli operator. + /// ## qubits + /// A register on which to make the assertion. + /// ## result + /// The expected result of `Measure(bases, qubits)`. + /// ## msg + /// A message to be reported if the assertion fails. + /// + /// # Remarks + /// Note that the Adjoint and Controlled versions of this operation will not + /// check the condition. + /// + /// # See Also + /// - Microsoft.Quantum.Diagnostics.AssertMeasurementProbability + operation AssertMeasurement(bases : Pauli[], qubits : Qubit[], result : Result, msg : String) : Unit + is Adj + Ctl { + body intrinsic; + } + + + /// # Summary + /// Asserts that measuring the given qubits in the given Pauli basis will have the given result + /// with the given probability, within some tolerance. + /// + /// # Input + /// ## bases + /// A measurement effect to assert the probability of, expressed as a + /// multi-qubit Pauli operator. + /// ## qubits + /// A register on which to make the assertion. + /// ## result + /// An expected result of `Measure(bases, qubits)`. + /// ## prob + /// The probability with which the given result is expected. + /// ## msg + /// A message to be reported if the assertion fails. + /// + /// # Example + /// ```qsharp + /// using (register = Qubit()) { + /// H(register); + /// AssertProb([PauliZ], [register], One, 0.5, + /// "Measuring in conjugate basis did not give 50/50 results.", 1e-5); + /// } + /// ``` + /// + /// # Remarks + /// Note that the Adjoint and Controlled versions of this operation will not + /// check the condition. + /// + /// # See Also + /// - Microsoft.Quantum.Diagnostics.AssertMeasurement + operation AssertMeasurementProbability(bases : Pauli[], qubits : Qubit[], result : Result, prob : Double, msg : String, tol : Double) : Unit + is Adj + Ctl { + body intrinsic; + } + +} diff --git a/src/Simulation/QsharpCore/Intrinsic.qs b/src/Simulation/QsharpCore/Intrinsic.qs index 28f0353dd86..92980459031 100644 --- a/src/Simulation/QsharpCore/Intrinsic.qs +++ b/src/Simulation/QsharpCore/Intrinsic.qs @@ -27,68 +27,16 @@ namespace Microsoft.Quantum.Intrinsic { } - /// # Summary - /// Asserts that measuring the given qubits in the given Pauli basis will - /// always have the given result. - /// - /// # Input - /// ## bases - /// A measurement effect to assert the probability of, expressed as a - /// multi-qubit Pauli operator. - /// ## qubits - /// A register on which to make the assertion. - /// ## result - /// The expected result of `Measure(bases, qubits)`. - /// ## msg - /// A message to be reported if the assertion fails. - /// - /// # Remarks - /// Note that the Adjoint and Controlled versions of this operation will not - /// check the condition. - /// - /// # See Also - /// - AssertProb + @Deprecated("Microsoft.Quantum.Diagnostics.AssertMeasurement") operation Assert (bases : Pauli[], qubits : Qubit[], result : Result, msg : String) : Unit is Adj + Ctl { - body intrinsic; + Microsoft.Quantum.Diagnostics.AssertMeasurement(bases, qubits, result, msg); } - - /// # Summary - /// Asserts that measuring the given qubits in the given Pauli basis will have the given result - /// with the given probability, within some tolerance. - /// - /// # Input - /// ## bases - /// A measurement effect to assert the probability of, expressed as a - /// multi-qubit Pauli operator. - /// ## qubits - /// A register on which to make the assertion. - /// ## result - /// An expected result of `Measure(bases, qubits)`. - /// ## prob - /// The probability with which the given result is expected. - /// ## msg - /// A message to be reported if the assertion fails. - /// - /// # Example - /// ```qsharp - /// using (register = Qubit()) { - /// H(register); - /// AssertProb([PauliZ], [register], One, 0.5, - /// "Measuring in conjugate basis did not give 50/50 results.", 1e-5); - /// } - /// ``` - /// - /// # Remarks - /// Note that the Adjoint and Controlled versions of this operation will not - /// check the condition. - /// - /// # See Also - /// - Assert + @Deprecated("Microsoft.Quantum.Diagnostics.AssertMeasurementProbability") operation AssertProb (bases : Pauli[], qubits : Qubit[], result : Result, prob : Double, msg : String, tol : Double) : Unit is Adj + Ctl { - body intrinsic; + Microsoft.Quantum.Diagnostics.AssertMeasurementProbability(bases, qubits, result, prob, msg, tol); } @@ -209,8 +157,10 @@ namespace Microsoft.Quantum.Intrinsic { /// # Summary - /// Applies the π/4 phase gate to a single qubit. + /// Applies the S gate to a single qubit. /// + /// # Description + /// This operation can be simulated by the unitary matrix /// \begin{align} /// S \mathrel{:=} /// \begin{bmatrix} @@ -222,15 +172,17 @@ namespace Microsoft.Quantum.Intrinsic { /// # Input /// ## qubit /// Qubit to which the gate should be applied. - operation S (qubit : Qubit) : Unit + operation S(qubit : Qubit) : Unit is Adj + Ctl { body intrinsic; } /// # Summary - /// Applies the π/8 gate to a single qubit. + /// Applies the T gate to a single qubit. /// + /// # Description + /// This operation can be simulated by the unitary matrix /// \begin{align} /// T \mathrel{:=} /// \begin{bmatrix} @@ -242,7 +194,7 @@ namespace Microsoft.Quantum.Intrinsic { /// # Input /// ## qubit /// Qubit to which the gate should be applied. - operation T (qubit : Qubit) : Unit + operation T(qubit : Qubit) : Unit is Adj + Ctl { body intrinsic; } @@ -277,8 +229,7 @@ namespace Microsoft.Quantum.Intrinsic { operation CNOT (control : Qubit, target : Qubit) : Unit is Adj + Ctl { - body (...) - { + body (...) { Controlled X([control], target); } @@ -304,8 +255,7 @@ namespace Microsoft.Quantum.Intrinsic { /// ``` operation CCNOT (control1 : Qubit, control2 : Qubit, target : Qubit) : Unit is Adj + Ctl { - body (...) - { + body (...) { Controlled X([control1, control2], target); } diff --git a/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj b/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj index 03556c866bd..d5553a8964a 100644 --- a/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj +++ b/src/Simulation/QsharpCore/Microsoft.Quantum.QSharp.Core.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/QsharpCore/Primitive.qs b/src/Simulation/QsharpCore/Primitive.qs deleted file mode 100644 index 85fb806872d..00000000000 --- a/src/Simulation/QsharpCore/Primitive.qs +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.Quantum.Primitive { - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.random". - @Deprecated("Microsoft.Quantum.Intrinsic.Random") - operation Random (probs : Double[]) : Int { - return Microsoft.Quantum.Intrinsic.Random(probs); - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.assert". - @Deprecated("Microsoft.Quantum.Intrinsic.Assert") - operation Assert (bases : Pauli[], qubits : Qubit[], result : Result, msg : String) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.Assert(bases, qubits, result, msg); - } - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.assertprob". - @Deprecated("Microsoft.Quantum.Intrinsic.AssertProb") - operation AssertProb (bases : Pauli[], qubits : Qubit[], result : Result, prob : Double, msg : String, tol : Double) : Unit - { - body (...) { - Microsoft.Quantum.Intrinsic.AssertProb(bases, qubits, result, prob, msg, tol); - } - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.message". - @Deprecated("Microsoft.Quantum.Intrinsic.Message") - function Message (msg : String) : Unit { - return Microsoft.Quantum.Intrinsic.Message(msg); - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.i". - @Deprecated("Microsoft.Quantum.Intrinsic.I") - operation I (qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.I(qubit); - } - adjoint self; - controlled auto; - controlled adjoint self; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.x". - @Deprecated("Microsoft.Quantum.Intrinsic.X") - operation X (qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.X(qubit); - } - adjoint self; - controlled auto; - controlled adjoint self; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.y". - @Deprecated("Microsoft.Quantum.Intrinsic.Y") - operation Y (qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.Y(qubit); - } - adjoint self; - controlled auto; - controlled adjoint self; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.z". - @Deprecated("Microsoft.Quantum.Intrinsic.Z") - operation Z (qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.Z(qubit); - } - adjoint self; - controlled auto; - controlled adjoint self; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.h". - @Deprecated("Microsoft.Quantum.Intrinsic.H") - operation H (qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.H(qubit); - } - adjoint self; - controlled auto; - controlled adjoint self; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.s". - @Deprecated("Microsoft.Quantum.Intrinsic.S") - operation S (qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.S(qubit); - } - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.t". - @Deprecated("Microsoft.Quantum.Intrinsic.T") - operation T (qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.T(qubit); - } - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.cnot". - @Deprecated("Microsoft.Quantum.Intrinsic.CNOT") - operation CNOT (control : Qubit, target : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.CNOT(control, target); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.ccnot". - @Deprecated("Microsoft.Quantum.Intrinsic.CCNOT") - operation CCNOT (control1 : Qubit, control2 : Qubit, target : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.CCNOT(control1, control2, target); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.swap". - @Deprecated("Microsoft.Quantum.Intrinsic.SWAP") - operation SWAP (qubit1 : Qubit, qubit2 : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.SWAP(qubit1, qubit2); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.canon.applytoeachca". - @Deprecated("ApplyToEachCA(X, _)") - operation MultiX (qubits : Qubit[]) : Unit { - body (...) { - for (index in 0 .. Length(qubits) - 1) { - Microsoft.Quantum.Intrinsic.X(qubits[index]); - } - } - - adjoint self; - controlled distribute; - controlled adjoint self; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.r". - @Deprecated("Microsoft.Quantum.Intrinsic.R") - operation R(pauli : Pauli, theta : Double, qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.R(pauli, theta, qubit); - } - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.rfrac". - @Deprecated("Microsoft.Quantum.Intrinsic.RFrac") - operation RFrac(pauli : Pauli, numerator : Int, power : Int, qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.RFrac(pauli, numerator, power, qubit); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.rx". - @Deprecated("Microsoft.Quantum.Intrinsic.Rx") - operation Rx (theta : Double, qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.Rx(theta, qubit); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.ry". - @Deprecated("Microsoft.Quantum.Intrinsic.Ry") - operation Ry (theta : Double, qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.Ry(theta, qubit); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.rz". - @Deprecated("Microsoft.Quantum.Intrinsic.Rz") - operation Rz (theta : Double, qubit : Qubit) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.Rz(theta, qubit); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.r1". - @Deprecated("Microsoft.Quantum.Intrinsic.R1") - operation R1 (theta : Double, qubit : Qubit) : Unit - { - body (...) { - Microsoft.Quantum.Intrinsic.R1(theta, qubit); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.r1frac". - @Deprecated("Microsoft.Quantum.Intrinsic.R1Frac") - operation R1Frac (numerator : Int, power : Int, qubit : Qubit) : Unit - { - body (...) { - Microsoft.Quantum.Intrinsic.R1Frac(numerator, power, qubit); - } - - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.exp". - @Deprecated("Microsoft.Quantum.Intrinsic.Exp") - operation Exp (paulis : Pauli[], theta : Double, qubits : Qubit[]) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.Exp(paulis, theta, qubits); - } - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.expfrac". - @Deprecated("Microsoft.Quantum.Intrinsic.ExpFrac") - operation ExpFrac (paulis : Pauli[], numerator : Int, power : Int, qubits : Qubit[]) : Unit { - body (...) { - Microsoft.Quantum.Intrinsic.ExpFrac(paulis, numerator, power, qubits); - } - adjoint auto; - controlled auto; - controlled adjoint auto; - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.measure". - @Deprecated("Microsoft.Quantum.Intrinsic.Measure") - operation Measure(bases : Pauli[], qubits : Qubit[]) : Result { - return Microsoft.Quantum.Intrinsic.Measure(bases, qubits); - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.m". - @Deprecated("Microsoft.Quantum.Intrinsic.M") - operation M (qubit : Qubit) : Result { - return Microsoft.Quantum.Intrinsic.M(qubit); - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.reset". - @Deprecated("Microsoft.Quantum.Intrinsic.Reset") - operation Reset (target : Qubit) : Unit { - return Microsoft.Quantum.Intrinsic.Reset(target); - } - - /// # Deprecated - /// Please use @"microsoft.quantum.intrinsic.resetall". - @Deprecated("Microsoft.Quantum.Intrinsic.ResetAll") - operation ResetAll (qubits : Qubit[]) : Unit { - return Microsoft.Quantum.Intrinsic.ResetAll(qubits); - } - -} - diff --git a/src/Simulation/Simulators.Tests/Circuits/Bug3758.qs b/src/Simulation/Simulators.Tests/Circuits/Bug3758.qs index 894c45cac3e..e65347a39e1 100644 --- a/src/Simulation/Simulators.Tests/Circuits/Bug3758.qs +++ b/src/Simulation/Simulators.Tests/Circuits/Bug3758.qs @@ -1,12 +1,10 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -namespace Bug3758 -{ - open Microsoft.Quantum.Primitive; +namespace Bug3758 { + open Microsoft.Quantum.Intrinsic; - function Reverse<'T> (array : 'T[]) : 'T[] - { + function Reverse<'T> (array : 'T[]) : 'T[] { let nElements = Length(array); return array[nElements-1..-1..0]; } @@ -22,43 +20,31 @@ namespace Bug3758 /// # Summary /// An example operation used for testing input transformations. - operation TransformationReferenceForward(register : Qubit[]) : Unit { - body (...) { - X(register[0]); - H(register[1]); - X(register[2]); - } - adjoint auto; - controlled auto; - controlled adjoint auto; + operation TransformationReferenceForward(register : Qubit[]) : Unit is Adj + Ctl { + X(register[0]); + H(register[1]); + X(register[2]); } /// # Summary /// An example operation used for testing input transformations. - operation TransformationReferenceReverse(register : Qubit[]) : Unit { - body (...) { - X(register[2]); - H(register[1]); - X(register[0]); - } - adjoint auto; - controlled auto; - controlled adjoint auto; + operation TransformationReferenceReverse(register : Qubit[]) : Unit is Adj + Ctl { + X(register[2]); + H(register[1]); + X(register[0]); } } -namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits -{ +namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits { open Bug3758; - open Microsoft.Quantum.Extensions.Testing; + open Microsoft.Quantum.Diagnostics; operation TransformedOperationTest() : Unit { - AssertOperationsEqualReferenced( + AssertOperationsEqualReferenced(3, TransformedOperation(Reverse, TransformationReferenceReverse), - TransformationReferenceForward, - 3 + TransformationReferenceForward ); } } diff --git a/src/Simulation/Simulators.Tests/Circuits/Fail.qs b/src/Simulation/Simulators.Tests/Circuits/Fail.qs index fc6aa685f76..1f079c005eb 100644 --- a/src/Simulation/Simulators.Tests/Circuits/Fail.qs +++ b/src/Simulation/Simulators.Tests/Circuits/Fail.qs @@ -89,9 +89,11 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits { } operation AllocateQubit2 () : Unit { - using( q = Qubit() ) { + using (q = Qubit()) { Microsoft.Quantum.Intrinsic.H(q); - Microsoft.Quantum.Intrinsic.Assert([PauliZ],[q],One,""); + Microsoft.Quantum.Diagnostics.AssertMeasurement( + [PauliZ], [q], One, "" + ); } } -} \ No newline at end of file +} diff --git a/src/Simulation/Simulators.Tests/Circuits/ResourcesEstimator.qs b/src/Simulation/Simulators.Tests/Circuits/ResourcesEstimator.qs index 8d34b42448c..dd3e52fc884 100644 --- a/src/Simulation/Simulators.Tests/Circuits/ResourcesEstimator.qs +++ b/src/Simulation/Simulators.Tests/Circuits/ResourcesEstimator.qs @@ -16,4 +16,45 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests ResetAll([q[1], q[0]]); } } + + // When multiple operations are traced by resource estimator, + // it should report cumulative statistics in the end. + operation Operation_1_of_2() : Unit + { + using ((a, b) = (Qubit(), Qubit())) { + H(a); + CNOT(a, b); + T(b); + } + } + operation Operation_2_of_2() : Result + { + using ((a, b, c) = (Qubit(), Qubit(), Qubit())) { + X(a); + CNOT(a, b); + Rx(0.42, b); + CNOT(b, c); + return M(c); + } + } + + // Tests for Depth and Width lower bounds + operation DepthDifferentQubits () : Unit + { + using(q = Qubit[3]) { + T(q[0]); + T(q[1]); + T(q[2]); + T(q[0]); + } + } + operation DepthVersusWidth () : Unit + { + using(q = Qubit()) { + T(q); + } + using(q = Qubit()) { + T(q); + } + } } diff --git a/src/Simulation/Simulators.Tests/DebuggingToolsTests.cs b/src/Simulation/Simulators.Tests/DebuggingToolsTests.cs index 4885cb14d54..279a6185f00 100644 --- a/src/Simulation/Simulators.Tests/DebuggingToolsTests.cs +++ b/src/Simulation/Simulators.Tests/DebuggingToolsTests.cs @@ -2,8 +2,8 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; -using System.Text; +using System.Globalization; +using System.Threading; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Tests.CoreOperations; @@ -18,36 +18,35 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests /// public class DebuggingToolsTests { - [Fact] - public void ToStringTests() + public void ToStringTests() => Helper.RunWithMultipleSimulators(qsim => { - Helper.RunWithMultipleSimulators((qsim) => + var _ = AbstractCallable._; + + var dump = qsim.Get(typeof(Microsoft.Quantum.Extensions.Diagnostics.DumpMachine<>)); + var trace = qsim.Get(typeof(Circuits.Generics.Trace<>)); + var x = qsim.Get(); + var q2 = new FreeQubit(2) as Qubit; + var Q = new Q(q2); + var Qs = new QArray(q2); + var qs = new Qs(Qs); + var udtOp = new U3(x); + var udtQ = new Q(q2); + var t1 = new QTuple<(long, QRange, (Qubit, IUnitary))>((1L, new QRange(10, -2, 4), (q2, x))); + var t4 = new T4((3L, (1.1, false, Result.One))); + var t5 = new T5((Pauli.PauliX, Qs, qs, Q)); + + var d_1 = dump.Partial(_); + var d_2 = d_1.Partial(_); + var x_1 = x.Partial(new Func(q => q)); + var x_2 = x_1.Partial(new Func(q => q)); + var x_3 = x.Partial>(_); + + var t_1 = trace.Adjoint.Partial(_); + var t_2 = t_1.Controlled.Partial(_); + + WithInvariantCulture(() => { - var _ = AbstractCallable._; - - var dump = qsim.Get(typeof(Microsoft.Quantum.Extensions.Diagnostics.DumpMachine<>)); - var trace = qsim.Get(typeof(Circuits.Generics.Trace<>)); - var x = qsim.Get(); - var q2 = new FreeQubit(2) as Qubit; - var Q = new Q(q2); - var Qs = new QArray(q2); - var qs = new Qs(Qs); - var udtOp = new U3(x); - var udtQ = new Q(q2); - var t1 = new QTuple<(long, QRange, (Qubit, IUnitary))>((1L, new QRange(10, -2, 4), (q2, x))); - var t4 = new T4((3L, (1.1, false, Result.One))); - var t5 = new T5((Pauli.PauliX, Qs, qs, Q)); - - var d_1 = dump.Partial(_); - var d_2 = d_1.Partial(_); - var x_1 = x.Partial(new Func(q => q)); - var x_2 = x_1.Partial(new Func(q => q)); - var x_3 = x.Partial>(_); - - var t_1 = trace.Adjoint.Partial(_); - var t_2 = t_1.Controlled.Partial(_); - Assert.Equal("()", QVoid.Instance.ToString()); Assert.Equal("_", _.ToString()); Assert.Equal("U3(X)", udtOp.ToString()); @@ -75,7 +74,7 @@ public void ToStringTests() Assert.Equal("(Adjoint Trace){_}", t_1.ToString()); Assert.Equal("(Adjoint (Controlled (Adjoint Trace){_}){_})", t_2.Adjoint.ToString()); }); - } + }); [Fact] public void QSharpTypeTests() @@ -277,5 +276,18 @@ public void GenericPartialDebuggerProxy() TestOneProxy("", g_3); }); } + + /// + /// Changes the current thread culture to the invariant culture, runs the action, and then restores the original + /// thread culture. + /// + /// The action to run within the invariant culture. + private static void WithInvariantCulture(System.Action action) + { + var culture = Thread.CurrentThread.CurrentCulture; + Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + action(); + Thread.CurrentThread.CurrentCulture = culture; + } } } diff --git a/src/Simulation/Simulators.Tests/ResourcesEstimatorTests.cs b/src/Simulation/Simulators.Tests/ResourcesEstimatorTests.cs index 5fa9728a0d0..0a60328484d 100644 --- a/src/Simulation/Simulators.Tests/ResourcesEstimatorTests.cs +++ b/src/Simulation/Simulators.Tests/ResourcesEstimatorTests.cs @@ -2,9 +2,8 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; using System.Linq; -using System.Text; +using System.Data; using Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime; using Xunit; @@ -95,11 +94,86 @@ public void ToTSVTest() var cols = rows[0].Split('\t'); Assert.Equal("Metric", cols[0].Trim()); - Assert.Equal(2, cols.Length); + Assert.Equal(3, cols.Length); var cliffords = rows.First(r => r.StartsWith("QubitClifford")).Split('\t'); - Assert.Equal(2, cliffords.Length); + Assert.Equal(3, cliffords.Length); Assert.Equal("2", cliffords[1]); + } + + /// + /// Shows that T gates on different qubits are counted for depth purposes as + /// executing in parallel. + /// + [Fact] + public void DepthDifferentQubitsTest() + { + var sim = new ResourcesEstimator(); + + // using(q = Qubit[3]) { T(q[0]); T(q[1]); T(q[3]); T(q[0]); } + DepthDifferentQubits.Run(sim).Wait(); + var data = sim.Data; + + Assert.Equal(4.0, data.Rows.Find("T")["Sum"]); + Assert.Equal(3.0, data.Rows.Find("Width")["Sum"]); + Assert.Equal(2.0, data.Rows.Find("Depth")["Sum"]); + } + + /// + /// Documents that the width and depth statistics reflect independent lower + /// bounds for each (two T gates cannot be combined into a circuit of depth + /// one and width one). + /// + [Fact] + public void DepthVersusWidthTest() + { + var sim = new ResourcesEstimator(); + + // using(q = Qubit()) { T(q); } using(q = Qubit()) { T(q); } (yes, twice) + DepthVersusWidth.Run(sim).Wait(); + var data = sim.Data; + + Assert.Equal(2.0, data.Rows.Find("T")["Sum"]); + Assert.Equal(1.0, data.Rows.Find("Width")["Sum"]); + Assert.Equal(1.0, data.Rows.Find("Depth")["Sum"]); + } + + /// + /// Verifies that for multiple separately traced operations, the final + /// statistics are cumulative. + /// + [Fact] + public void VerifyTracingMultipleOperationsTest() + { + ResourcesEstimator sim = new ResourcesEstimator(); + + Operation_1_of_2.Run(sim).Wait(); + DataTable data1 = sim.Data; + + Assert.Equal(1.0, data1.Rows.Find("CNOT")["Sum"]); + Assert.Equal(1.0, data1.Rows.Find("QubitClifford")["Sum"]); + Assert.Equal(1.0, data1.Rows.Find("T")["Sum"]); + Assert.Equal(0.0, data1.Rows.Find("R")["Sum"]); + Assert.Equal(0.0, data1.Rows.Find("Measure")["Sum"]); + Assert.Equal(2.0, data1.Rows.Find("Width")["Sum"]); + + Operation_2_of_2.Run(sim).Wait(); + DataTable data2 = sim.Data; + + // Aggregated stats for both operations. + Assert.Equal(1.0 + 2.0, data2.Rows.Find("CNOT")["Sum"]); + Assert.Equal(1.0 + 1.0, data2.Rows.Find("QubitClifford")["Sum"]); + Assert.Equal(1.0 + 0.0, data2.Rows.Find("T")["Sum"]); + Assert.Equal(0.0 + 1.0, data2.Rows.Find("R")["Sum"]); + Assert.Equal(0.0 + 1.0, data2.Rows.Find("Measure")["Sum"]); + Assert.Equal(2.0 + 3.0, data2.Rows.Find("Width")["Sum"]); + Assert.Equal(System.Math.Max(2.0, 3.0), data2.Rows.Find("Width")["Max"]); + + // Run again to confirm two operations isn't the limit! + VerySimpleEstimate.Run(sim).Wait(); + DataTable data3 = sim.Data; + Assert.Equal(2.0 + 3.0 + 3.0, data3.Rows.Find("Width")["Sum"]); + Assert.Equal(3.0, data3.Rows.Find("Width")["Max"]); } } } diff --git a/src/Simulation/Simulators.Tests/StackTraceTests.cs b/src/Simulation/Simulators.Tests/StackTraceTests.cs index 48c142d7e2b..c3fead7b586 100644 --- a/src/Simulation/Simulators.Tests/StackTraceTests.cs +++ b/src/Simulation/Simulators.Tests/StackTraceTests.cs @@ -1,6 +1,8 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable + using Xunit; using System; @@ -29,32 +31,33 @@ public StackTraceTests(ITestOutputHelper output) [Fact] public void AllocateQubit2Test() { - using (var sim = new QuantumSimulator()) + using var sim = new QuantumSimulator(); + try { - try - { - IgnorableAssert.Disable(); - QVoid res = sim.Execute(QVoid.Instance); - } - catch (ExecutionFailException) - { - StackFrame[] stackFrames = sim.CallStack; + IgnorableAssert.Disable(); + QVoid res = sim.Execute(QVoid.Instance); + } + catch (ExecutionFailException) + { + var stackFrames = sim.CallStack; - // The following assumes that Assert is on Q# stack. - Assert.Equal(2, stackFrames.Length); + // Make sure that the call stack isn't null before proceeding. + Assert.NotNull(stackFrames); - Assert.Equal("Microsoft.Quantum.Intrinsic.Assert", stackFrames[0].Callable.FullName); - Assert.Equal(namespacePrefix + "AllocateQubit2", stackFrames[1].Callable.FullName); + // The following assumes that Assert is on Q# stack. + Assert.Equal(2, stackFrames!.Length); - Assert.Equal(OperationFunctor.Body, stackFrames[0].Callable.Variant); - Assert.Equal(OperationFunctor.Body, stackFrames[1].Callable.Variant); + Assert.Equal("Microsoft.Quantum.Diagnostics.AssertMeasurement", stackFrames[0].Callable.FullName); + Assert.Equal(namespacePrefix + "AllocateQubit2", stackFrames[1].Callable.FullName); - Assert.Equal(94, stackFrames[1].FailedLineNumber); - } - finally - { - IgnorableAssert.Enable(); - } + Assert.Equal(OperationFunctor.Body, stackFrames[0].Callable.Variant); + Assert.Equal(OperationFunctor.Body, stackFrames[1].Callable.Variant); + + Assert.Equal(94, stackFrames[1].FailedLineNumber); + } + finally + { + IgnorableAssert.Enable(); } } diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj new file mode 100644 index 00000000000..abfb0b57f2f --- /dev/null +++ b/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library with Spaces.csproj @@ -0,0 +1,25 @@ + + + netstandard2.1 + false + false + + + true + + + + + + + + + + + + + diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library.qs b/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library.qs new file mode 100644 index 00000000000..eebe352cb30 --- /dev/null +++ b/src/Simulation/Simulators.Tests/TestProjects/Library with Spaces/Library.qs @@ -0,0 +1,5 @@ +namespace LibraryWithSpaces { + function HelloQ() : String { + return "Hello quantum world!"; + } +} diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj index 8e69c0a388d..b195d6d4eb0 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/Library1/Library1.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj b/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj index 8e69c0a388d..b195d6d4eb0 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/Library2/Library2.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 diff --git a/src/Simulation/Simulators.Tests/TestProjects/QsharpExe/QsharpExe.csproj b/src/Simulation/Simulators.Tests/TestProjects/QsharpExe/QsharpExe.csproj index 9326805e5a9..15a9579387e 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/QsharpExe/QsharpExe.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/QsharpExe/QsharpExe.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/Facts.qs b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/Facts.qs new file mode 100644 index 00000000000..880bdf81a85 --- /dev/null +++ b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/Facts.qs @@ -0,0 +1,37 @@ +namespace Microsoft.Quantum.Testing { + internal function FactI(expected : Int, got : Int) : Unit { + if (expected != got) { + fail $"Expected: {expected}, got: {got}"; + } + } + + internal function FactS(expected : String, got : String) : Unit { + if (expected != got) { + fail $"Expected: {expected}, got: {got}"; + } + } + + internal function FactMyInt1(expected : Int, got : Library1.MyInt) : Unit { + if (expected != got::Value1) { + fail $"Expected: {expected}, got: {got::Value1}"; + } + } + + internal function FactMyInt2(expected : Int, got : Library2.MyInt) : Unit { + if (expected != got::Value2) { + fail $"Expected: {expected}, got: {got::Value2}"; + } + } + + internal function FactMyString1(expected : String, got : Microsoft.Quantum.Library.MyString) : Unit { + if (expected != got::Text) { + fail $"Expected: {expected}, got: {got::Text}"; + } + } + + internal function FactMyString2(expected : String, got : Library2.MyString) : Unit { + if (expected != got::Text) { + fail $"Expected: {expected}, got: {got::Text}"; + } + } +} diff --git a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/SpaceTests.qs b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/SpaceTests.qs new file mode 100644 index 00000000000..2faa5616e2b --- /dev/null +++ b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/SpaceTests.qs @@ -0,0 +1,9 @@ +namespace Microsoft.Quantum.Testing.SpacesInFileName { + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Testing; + + @Test("QuantumSimulator") + function LibraryWithSpacesTest() : Unit { + FactS("Hello quantum world!", LibraryWithSpaces.HelloQ()); + } +} diff --git a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/Tests.qs b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/TestNameTests.qs similarity index 52% rename from src/Simulation/Simulators.Tests/TestProjects/UnitTests/Tests.qs rename to src/Simulation/Simulators.Tests/TestProjects/UnitTests/TestNameTests.qs index 008f2c9f646..68a3ee38845 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/Tests.qs +++ b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/TestNameTests.qs @@ -2,43 +2,7 @@ open Microsoft.Quantum.Diagnostics; open Microsoft.Quantum.Intrinsic; - - internal function FactI(expected : Int, got : Int) : Unit { - if (expected != got) { - fail $"Expected: {expected}, got: {got}"; - } - } - - internal function FactS(expected : String, got : String) : Unit { - if (expected != got) { - fail $"Expected: {expected}, got: {got}"; - } - } - - internal function FactMyInt1(expected : Int, got : Library1.MyInt) : Unit { - if (expected != got::Value1) { - fail $"Expected: {expected}, got: {got::Value1}"; - } - } - - internal function FactMyInt2(expected : Int, got : Library2.MyInt) : Unit { - if (expected != got::Value2) { - fail $"Expected: {expected}, got: {got::Value2}"; - } - } - - internal function FactMyString1(expected : String, got : Microsoft.Quantum.Library.MyString) : Unit { - if (expected != got::Text) { - fail $"Expected: {expected}, got: {got::Text}"; - } - } - - internal function FactMyString2(expected : String, got : Library2.MyString) : Unit { - if (expected != got::Text) { - fail $"Expected: {expected}, got: {got::Text}"; - } - } - + open Microsoft.Quantum.Testing; @Test("QuantumSimulator") operation BothCallables () : Unit { diff --git a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj index 73c103678c0..8ac7acf29f7 100644 --- a/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj +++ b/src/Simulation/Simulators.Tests/TestProjects/UnitTests/UnitTests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 @@ -15,6 +15,7 @@ + diff --git a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj index cc6001ef292..88591686fa8 100644 --- a/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators.Tests/Tests.Microsoft.Quantum.Simulators.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj index 167a6619277..3ae4043c9c0 100644 --- a/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj +++ b/src/Simulation/Simulators/Microsoft.Quantum.Simulators.csproj @@ -1,4 +1,4 @@ - + diff --git a/src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs b/src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs index 79395f62ec6..f3beba01330 100644 --- a/src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs +++ b/src/Simulation/Simulators/QCTraceSimulator/InterfaceUtils.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.Diagnostics; using Microsoft.Quantum.Simulation.Core; @@ -73,5 +74,19 @@ public static partial class Extensions { return InterfaceType(t, typeof(IControllable<>)); } + + internal static IEnumerable SelectAggregates( + this IEnumerable source, + Func aggregate, + TResult initial = default + ) + { + var acc = initial; + foreach (var element in source) + { + acc = aggregate(acc, element); + yield return acc; + } + } } } \ No newline at end of file diff --git a/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.Assert.cs b/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.Assert.cs index bcbd49b948a..71357de0bd7 100644 --- a/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.Assert.cs +++ b/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.Assert.cs @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators.Implementati public partial class QCTraceSimulatorImpl { - public class TracerAssert : Intrinsic.Assert + public class TracerAssert : Microsoft.Quantum.Diagnostics.AssertMeasurement { private readonly QCTraceSimulatorCore core; public TracerAssert(QCTraceSimulatorImpl m) : base(m) diff --git a/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.AssertProb.cs b/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.AssertProb.cs index 511682661ed..705d5d3ae1d 100644 --- a/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.AssertProb.cs +++ b/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.Primitive.AssertProb.cs @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators.Implementati public partial class QCTraceSimulatorImpl { - public class TracerAssertProb : Intrinsic.AssertProb + public class TracerAssertProb : Microsoft.Quantum.Diagnostics.AssertMeasurementProbability { private readonly QCTraceSimulatorCore core; public TracerAssertProb(QCTraceSimulatorImpl m) : base(m){ diff --git a/src/Simulation/Simulators/QCTraceSimulator/Utils.cs b/src/Simulation/Simulators/QCTraceSimulator/Utils.cs index 203173c3137..9f991e7ed0c 100644 --- a/src/Simulation/Simulators/QCTraceSimulator/Utils.cs +++ b/src/Simulation/Simulators/QCTraceSimulator/Utils.cs @@ -1,7 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.Collections.Generic; +using System.Linq; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime; @@ -214,32 +216,36 @@ static class SimulatorsUtils /// Number between Zero and one, uniformly distributed public static long SampleDistribution(IQArray unnormalizedDistribution, double uniformZeroOneSample) { - double total = 0.0; - foreach (double prob in unnormalizedDistribution) + if (unnormalizedDistribution.Any(prob => prob < 0.0)) { - if (prob < 0) - { - throw new ExecutionFailException("Random expects array of non-negative doubles."); - } - total += prob; + throw new ExecutionFailException("Random expects array of non-negative doubles."); } + var total = unnormalizedDistribution.Sum(); if (total == 0) { throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum."); } - double sample = uniformZeroOneSample * total; - double sum = unnormalizedDistribution[0]; - for (int i = 0; i < unnormalizedDistribution.Length - 1; ++i) - { - if (sum >= sample) - { - return i; - } - sum += unnormalizedDistribution[i]; - } - return unnormalizedDistribution.Length; + var sample = uniformZeroOneSample * total; + + return unnormalizedDistribution + // Get the unnormalized CDF of the distribution. + .SelectAggregates((double acc, double x) => acc + x) + // Look for the first index at which the CDF is bigger + // than the random sample of 𝑈(0, 1) that we were given + // as a parameter. + .Select((cumulativeProb, idx) => (cumulativeProb, idx)) + .Where(item => item.cumulativeProb >= sample) + // Cast that index to long, and default to returning + // the last item. + .Select( + item => (long)item.idx + ) + .DefaultIfEmpty( + unnormalizedDistribution.Length - 1 + ) + .First(); } } } diff --git a/src/Simulation/Simulators/QuantumProcessor/Assert.cs b/src/Simulation/Simulators/QuantumProcessor/Assert.cs index 50f230e89ee..a0badd62007 100644 --- a/src/Simulation/Simulators/QuantumProcessor/Assert.cs +++ b/src/Simulation/Simulators/QuantumProcessor/Assert.cs @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Simulation.QuantumProcessor { public partial class QuantumProcessorDispatcher { - public class QuantumProcessorDispatcherAssert : Quantum.Intrinsic.Assert + public class QuantumProcessorDispatcherAssert : Microsoft.Quantum.Diagnostics.AssertMeasurement { private QuantumProcessorDispatcher Simulator { get; } diff --git a/src/Simulation/Simulators/QuantumProcessor/AssertProb.cs b/src/Simulation/Simulators/QuantumProcessor/AssertProb.cs index 9a86fb29fca..9f4d87e085e 100644 --- a/src/Simulation/Simulators/QuantumProcessor/AssertProb.cs +++ b/src/Simulation/Simulators/QuantumProcessor/AssertProb.cs @@ -9,7 +9,7 @@ namespace Microsoft.Quantum.Simulation.QuantumProcessor { public partial class QuantumProcessorDispatcher { - public class QuantumProcessorDispatcherAssertProb : Quantum.Intrinsic.AssertProb + public class QuantumProcessorDispatcherAssertProb : Microsoft.Quantum.Diagnostics.AssertMeasurementProbability { private QuantumProcessorDispatcher Simulator { get; } diff --git a/src/Simulation/Simulators/QuantumSimulator/Assert.cs b/src/Simulation/Simulators/QuantumSimulator/Assert.cs index d0936509470..69d1b035d69 100644 --- a/src/Simulation/Simulators/QuantumSimulator/Assert.cs +++ b/src/Simulation/Simulators/QuantumSimulator/Assert.cs @@ -12,7 +12,7 @@ namespace Microsoft.Quantum.Simulation.Simulators { public partial class QuantumSimulator { - public class QSimAssert : Quantum.Intrinsic.Assert + public class QSimAssert : Microsoft.Quantum.Diagnostics.AssertMeasurement { [DllImport(QSIM_DLL_NAME, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "JointEnsembleProbability")] private static extern double JointEnsembleProbability(uint id, uint n, Pauli[] b, uint[] q); diff --git a/src/Simulation/Simulators/QuantumSimulator/AssertProb.cs b/src/Simulation/Simulators/QuantumSimulator/AssertProb.cs index 8f93eea3b31..39e3901e592 100644 --- a/src/Simulation/Simulators/QuantumSimulator/AssertProb.cs +++ b/src/Simulation/Simulators/QuantumSimulator/AssertProb.cs @@ -12,7 +12,7 @@ namespace Microsoft.Quantum.Simulation.Simulators { public partial class QuantumSimulator { - public class QSimAssertProb : Quantum.Intrinsic.AssertProb + public class QSimAssertProb : Microsoft.Quantum.Diagnostics.AssertMeasurementProbability { [DllImport(QSIM_DLL_NAME, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "JointEnsembleProbability")] private static extern double JointEnsembleProbability(uint id, uint n, Pauli[] b, uint[] q); diff --git a/src/Simulation/Simulators/ResourcesEstimator/ResourcesEstimator.cs b/src/Simulation/Simulators/ResourcesEstimator/ResourcesEstimator.cs index ec0e80ddef1..d08847898cf 100644 --- a/src/Simulation/Simulators/ResourcesEstimator/ResourcesEstimator.cs +++ b/src/Simulation/Simulators/ResourcesEstimator/ResourcesEstimator.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Linq; @@ -113,6 +112,7 @@ public virtual DataTable Data table.Columns.Add(new DataColumn { DataType = typeof(string), ColumnName = "Metric" }); table.Columns.Add(new DataColumn { DataType = typeof(double), ColumnName = "Sum" }); + table.Columns.Add(new DataColumn { DataType = typeof(double), ColumnName = "Max" }); table.PrimaryKey = new DataColumn[] { table.Columns[0] }; foreach (var l in CoreConfig.Listeners) @@ -121,11 +121,9 @@ public virtual DataTable Data if (l is ICallGraphStatistics collector) { var results = collector.Results.ToTable(); - Debug.Assert(results.rows.Count() == 1); Debug.Assert(results.keyColumnNames.Length > 2 && results.keyColumnNames[2] == "Caller"); - var root = results.rows.FirstOrDefault(r => r.KeyRow[2] == CallGraphEdge.CallGraphRootHashed); - + var roots = results.rows.Where(r => r.KeyRow[2] == CallGraphEdge.CallGraphRootHashed); var s_idx = Array.FindIndex(results.statisticsNames, n => n == "Sum"); for (var m_idx = 0; m_idx < results.metricNames.Length; m_idx++) @@ -133,12 +131,21 @@ public virtual DataTable Data var label = GetMetricLabel(results.metricNames[m_idx]); if (label == null) continue; - var row = table.NewRow(); + DataRow row = table.NewRow(); row["Metric"] = label; if (m_idx >= 0 && s_idx >= 0) - { - row["Sum"] = root.DataRow[m_idx, s_idx]; + { + Double sum = 0; + Double max = 0; // all our metrics are positive + foreach (var r in roots) + { + Double metric_value = r.DataRow[m_idx, s_idx]; + sum += metric_value; + max = System.Math.Max(max, metric_value); + } + row["Sum"] = sum; + row["Max"] = max; } table.Rows.Add(row); diff --git a/src/Simulation/Simulators/ToffoliSimulator/Assert.cs b/src/Simulation/Simulators/ToffoliSimulator/Assert.cs index 1d00d159ea1..13c71ead4d9 100644 --- a/src/Simulation/Simulators/ToffoliSimulator/Assert.cs +++ b/src/Simulation/Simulators/ToffoliSimulator/Assert.cs @@ -12,7 +12,7 @@ public partial class ToffoliSimulator /// /// Implementation of the Assert operation for the Toffoli simulator. /// - public class Assert : Intrinsic.Assert + public class Assert : Microsoft.Quantum.Diagnostics.AssertMeasurement { private ToffoliSimulator simulator; diff --git a/src/Simulation/Simulators/ToffoliSimulator/AssertProb.cs b/src/Simulation/Simulators/ToffoliSimulator/AssertProb.cs index 29228e9b604..3ed31f98369 100644 --- a/src/Simulation/Simulators/ToffoliSimulator/AssertProb.cs +++ b/src/Simulation/Simulators/ToffoliSimulator/AssertProb.cs @@ -13,7 +13,7 @@ public partial class ToffoliSimulator /// /// Implementation of the AssertProb operation for the Toffoli simulator. /// - public class AssertProb : Intrinsic.AssertProb + public class AssertProb : Microsoft.Quantum.Diagnostics.AssertMeasurementProbability { private ToffoliSimulator simulator;