From e7115ebe3427fe191d6939f14bc24ea5a3b5cdf0 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 09:55:05 -0700 Subject: [PATCH 01/32] Initial version of diagnostic plumbing. --- .../Diagnostics/{Quantum.qs => Asserts.qs} | 13 ++-- Standard/src/Diagnostics/Deprecated.qs | 11 ++++ .../src/Diagnostics/Emulation/Internal.cs | 45 +++++++++++++ .../Diagnostics/Emulation/Visualization.cs | 63 +++++++++++++++++++ Standard/src/Diagnostics/Facts.qs | 51 +++++++++------ Standard/src/Diagnostics/Internal.qs | 17 +++++ Standard/src/Standard.csproj | 1 + Standard/tests/AssertTests.qs | 22 +++---- Standard/tests/MultiplexerTests.qs | 36 +++++------ 9 files changed, 205 insertions(+), 54 deletions(-) rename Standard/src/Diagnostics/{Quantum.qs => Asserts.qs} (67%) create mode 100644 Standard/src/Diagnostics/Deprecated.qs create mode 100644 Standard/src/Diagnostics/Emulation/Internal.cs create mode 100644 Standard/src/Diagnostics/Emulation/Visualization.cs create mode 100644 Standard/src/Diagnostics/Internal.qs diff --git a/Standard/src/Diagnostics/Quantum.qs b/Standard/src/Diagnostics/Asserts.qs similarity index 67% rename from Standard/src/Diagnostics/Quantum.qs rename to Standard/src/Diagnostics/Asserts.qs index 3cd4fcebe83..5ef775ee372 100644 --- a/Standard/src/Diagnostics/Quantum.qs +++ b/Standard/src/Diagnostics/Asserts.qs @@ -1,7 +1,7 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -namespace Microsoft.Quantum.Canon { +namespace Microsoft.Quantum.Diagnostics { open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Math; @@ -9,6 +9,7 @@ namespace Microsoft.Quantum.Canon { /// # Summary /// Asserts that the phase of an equal superposition state has the expected value. /// + /// # Description /// Specifically, asserts that the phase $\phi$ of a quantum state /// that may be expressed as /// $\frac{e^{i t}}{\sqrt{2}}(e^{i\phi}\ket{0} + e^{-i\phi}\ket{1})$ @@ -35,12 +36,12 @@ namespace Microsoft.Quantum.Canon { /// /// `qubit` is in state $\ket{\psi}=e^{-i 2.2}\sqrt{1/2}\ket{0}+e^{i 0.2}\sqrt{1/2}\ket{1}$; /// - `AssertPhase(-1.2,qubit,10e-10);` - operation AssertPhase (expected : Double, qubit : Qubit, tolerance : Double) : Unit { + operation AssertPhase(expected : Double, qubit : Qubit, tolerance : Double) : Unit { let exptectedProbX = Cos(expected) * Cos(expected); let exptectedProbY = Sin(-1.0 * expected + PI() / 4.0) * Sin(-1.0 * expected + PI() / 4.0); - AssertProb([PauliZ], [qubit], Zero, 0.5, $"AssertPhase failed. Was not given a uniform superposition.", tolerance); - AssertProb([PauliY], [qubit], Zero, exptectedProbY, $"AssertPhase failed. PauliY Zero basis did not give probability {exptectedProbY}.", tolerance); - AssertProb([PauliX], [qubit], Zero, exptectedProbX, $"AssertPhase failed. PauliX Zero basis did not give probability {exptectedProbX}.", tolerance); + AssertMeasurementProbability([PauliZ], [qubit], Zero, 0.5, $"AssertPhase failed. Was not given a uniform superposition.", tolerance); + AssertMeasurementProbability([PauliY], [qubit], Zero, exptectedProbY, $"AssertPhase failed. PauliY Zero basis did not give probability {exptectedProbY}.", tolerance); + AssertMeasurementProbability([PauliX], [qubit], Zero, exptectedProbX, $"AssertPhase failed. PauliX Zero basis did not give probability {exptectedProbX}.", tolerance); } } diff --git a/Standard/src/Diagnostics/Deprecated.qs b/Standard/src/Diagnostics/Deprecated.qs new file mode 100644 index 00000000000..7a0b7ae6720 --- /dev/null +++ b/Standard/src/Diagnostics/Deprecated.qs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Canon { + + @Deprecated("Microsoft.Quantum.Diagnostics.AssertPhase") + operation AssertPhase(expected : Double, qubit : Qubit, tolerance : Double) : Unit { + Microsoft.Quantum.Diagnostics.AssertPhase(expected, qubit, tolerance); + } + +} diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs new file mode 100644 index 00000000000..8c3091ea46e --- /dev/null +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +using Microsoft.Quantum.Simulation.Common; +using Microsoft.Quantum.Simulation.Core; + +namespace Microsoft.Quantum.Diagnostics +{ + + internal partial class FormattedFailure<__T__> + { + + public class Native : FormattedFailure<__T__> + { + private SimulatorBase? Simulator; + + public Native(IOperationFactory m) : base(m) + { + Simulator = m as SimulatorBase; + } + + public override Func<(__T__,__T__,String), QVoid> Body => (__in__) => + { + if (Simulator != null) + { + var (actual, expected, message) = __in__; + Simulator.MaybeDisplayDiagnostic( + new FailureRecord<__T__> + { + Message = message, + Actual = actual, + Expected = expected + } + ); + } + return base.Body(__in__); + }; + } + + } + +} \ No newline at end of file diff --git a/Standard/src/Diagnostics/Emulation/Visualization.cs b/Standard/src/Diagnostics/Emulation/Visualization.cs new file mode 100644 index 00000000000..fddc3182efa --- /dev/null +++ b/Standard/src/Diagnostics/Emulation/Visualization.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using Microsoft.Jupyter.Core; +using Newtonsoft.Json; + +namespace Microsoft.Quantum.Diagnostics +{ + + internal class FailureRecord + { + [JsonProperty("actual")] + public T Actual { get; set; } + + [JsonProperty("expected")] + public T Expected { get; set; } + + [JsonProperty("message")] + public string Message { get; set; } = ""; + } + + + public class FailureRecordToHtmlEncoder : IResultEncoder + { + public string MimeType => MimeTypes.Html; + + public EncodedData? Encode(object displayable) => + displayable is FailureRecord record + ? $@" +
+

+ Contradiction reached: {record.Message} +

+ + + + + + + + + + +
Actual{record.Actual}
Expected{record.Expected}
+
+ ".ToEncodedData() + : (EncodedData?)null; + } + + public class FailureRecordToTextEncoder : IResultEncoder + { + public string MimeType => MimeTypes.PlainText; + + public EncodedData? Encode(object displayable) => + displayable is FailureRecord record + ? $"{record.Message}\n\tExpected:\t{record.Expected}\n\tActual:\t{record.Actual}".ToEncodedData() + : (EncodedData?)null; + } + + +} diff --git a/Standard/src/Diagnostics/Facts.qs b/Standard/src/Diagnostics/Facts.qs index fe6f830d919..06caa0c5de8 100644 --- a/Standard/src/Diagnostics/Facts.qs +++ b/Standard/src/Diagnostics/Facts.qs @@ -7,12 +7,6 @@ namespace Microsoft.Quantum.Diagnostics { open Microsoft.Quantum.Arrays; open Microsoft.Quantum.Logical; - /// # Summary - /// Internal function used to generate meaningful error messages. - internal function FormattedExpectation<'T>(actual : 'T, expected : 'T) : String { - return $"Expected: '{expected}'. Actual: '{actual}'"; - } - /// # Summary /// Declares that a classical condition is true. /// @@ -26,7 +20,9 @@ namespace Microsoft.Quantum.Diagnostics { /// # See Also /// - Microsoft.Quantum.Diagnostics.Contradiction function Fact(actual : Bool, message : String) : Unit { - if (not actual) { fail message; } + if (not actual) { + FormattedFailure(actual, true, message); + } } /// # Summary @@ -49,7 +45,9 @@ namespace Microsoft.Quantum.Diagnostics { /// Message("Hello, world."); /// ``` function Contradiction(actual : Bool, message : String) : Unit { - if (actual) { fail message; } + if (actual) { + FormattedFailure(actual, false, message); + } } /// # Summary @@ -67,7 +65,7 @@ namespace Microsoft.Quantum.Diagnostics { function EqualityWithinToleranceFact(actual : Double, expected : Double, tolerance : Double) : Unit { let delta = actual - expected; if (delta > tolerance or delta < -tolerance) { - fail FormattedExpectation(actual, expected); + FormattedFailure(actual, expected, "Values were not equal within tolerance."); } } @@ -102,7 +100,7 @@ namespace Microsoft.Quantum.Diagnostics { // conditions. let ((reA, imA), (reE, imE)) = (actual!, expected!); if (AbsD(reA - reE) >= 1e-10 or AbsD(imA - imE) >= 1e-10) { - fail FormattedExpectation(actual, expected); + FormattedFailure(actual, expected, "Values were not equal within tolerance."); } } @@ -134,7 +132,9 @@ namespace Microsoft.Quantum.Diagnostics { /// ## message /// Failure message string to be used when the assertion is triggered. function EqualityFactI(actual : Int, expected : Int, message : String) : Unit { - Fact(actual == expected, $"{actual} ≠ {expected}: {message}"); + if (actual != expected) { + FormattedFailure(actual, expected, message); + } } /// # Summary @@ -149,7 +149,9 @@ namespace Microsoft.Quantum.Diagnostics { /// ## message /// Failure message string to be used when the assertion is triggered. function EqualityFactL(actual : BigInt, expected : BigInt, message : String) : Unit { - Fact(actual == expected, $"{actual} ≠ {expected}: {message}"); + if (actual != expected) { + FormattedFailure(actual, expected, message); + } } /// # Summary @@ -165,7 +167,9 @@ namespace Microsoft.Quantum.Diagnostics { /// ## message /// Failure message string to be used when the assertion is triggered. function EqualityFactB(actual : Bool, expected : Bool, message : String) : Unit { - Fact(actual == expected, $"{actual} ≠ {expected}: {message}"); + if (actual != expected) { + FormattedFailure(actual, expected, message); + } } /// # Summary @@ -181,7 +185,9 @@ namespace Microsoft.Quantum.Diagnostics { /// ## message /// Failure message string to be used when the assertion is triggered. function EqualityFactR (actual : Result, expected : Result, message : String) : Unit { - Fact(actual == expected, $"{actual} ≠ {expected}: {message}"); + if (actual != expected) { + FormattedFailure(actual, expected, message); + } } /// # Summary @@ -197,7 +203,9 @@ namespace Microsoft.Quantum.Diagnostics { /// ## message /// Failure message string to be used when the assertion is triggered. function EqualityFactC(actual : Complex, expected : Complex, message : String) : Unit { - Fact(EqualC(actual, expected), $"{actual} ≠ {expected}: {message}"); + if (actual::Real != expected::Real or actual::Imag != expected::Imag) { + FormattedFailure(actual, expected, message); + } } /// # Summary @@ -213,7 +221,14 @@ namespace Microsoft.Quantum.Diagnostics { /// ## message /// Failure message string to be used when the assertion is triggered. function EqualityFactCP(actual : ComplexPolar, expected : ComplexPolar, message : String) : Unit { - Fact(EqualCP(actual, expected), $"{actual} ≠ {expected}: {message}"); + let actualCartesian = ComplexPolarAsComplex(actual); + let expectedCartesian = ComplexPolarAsComplex(expected); + if ( + actualCartesian::Real != expectedCartesian::Real or + actualCartesian::Imag != expectedCartesian::Imag + ) { + FormattedFailure(actual, expected, message); + } } /// # Summary @@ -232,7 +247,7 @@ namespace Microsoft.Quantum.Diagnostics { function AllEqualityFactB(actual : Bool[], expected : Bool[], message : String) : Unit { let n = Length(actual); if (n != Length(expected)) { - fail message; + FormattedFailure(actual, expected, message); } Ignore(Mapped(EqualityFactB(_, _, message), Zip(actual, expected))); @@ -254,7 +269,7 @@ namespace Microsoft.Quantum.Diagnostics { function AllEqualityFactI(actual : Int[], expected : Int[], message : String) : Unit { let n = Length(actual); if (n != Length(expected)) { - fail message; + FormattedFailure(actual, expected, message); } Ignore(Mapped(EqualityFactI(_, _, message), Zip(actual, expected))); diff --git a/Standard/src/Diagnostics/Internal.qs b/Standard/src/Diagnostics/Internal.qs new file mode 100644 index 00000000000..3c66aa1dc40 --- /dev/null +++ b/Standard/src/Diagnostics/Internal.qs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Diagnostics { + open Microsoft.Quantum.Intrinsic; + + /// # Summary + /// Internal function used to fail with meaningful error messages. + /// + /// # Remarks + /// This function is intended to be emulated by simulation runtimes, so as + /// to allow forwarding formatted contradictions. + internal function FormattedFailure<'T>(actual : 'T, expected : 'T, message : String) : Unit { + fail $"{message}\n\tExpected:\t{expected}\n\tActual:\t{actual}"; + } + +} diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index d0cbc8cc426..f295ba5b11e 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -32,6 +32,7 @@ + diff --git a/Standard/tests/AssertTests.qs b/Standard/tests/AssertTests.qs index 1d35be2a51b..a74151265e2 100644 --- a/Standard/tests/AssertTests.qs +++ b/Standard/tests/AssertTests.qs @@ -4,7 +4,7 @@ namespace Microsoft.Quantum.Tests { open Microsoft.Quantum.Arithmetic; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; - open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Diagnostics as Diag; open Microsoft.Quantum.Arrays; @@ -14,7 +14,7 @@ namespace Microsoft.Quantum.Tests { operation PreparationTest () : Unit { using (qubit = Qubit()) { - AssertProb([PauliZ], [qubit], Zero, 1.0, $"Freshly prepared qubit was not in |0〉 state.", 1E-10); + Diag.AssertMeasurementProbability([PauliZ], [qubit], Zero, 1.0, $"Freshly prepared qubit was not in |0〉 state.", 1E-10); } } @@ -27,29 +27,27 @@ namespace Microsoft.Quantum.Tests { } function AssertEqualTestShouldFail () : Unit { - NearEqualityFactD(1.0, 0.0); + Diag.NearEqualityFactD(1.0, 0.0); } function AssertBoolArrayEqualTestShouldFail () : Unit { - - AllEqualityFactB([true, false], [false, true], $"OK"); + Diag.AllEqualityFactB([true, false], [false, true], $"OK"); } function AssertBoolEqualTestShouldFail () : Unit { - EqualityFactB(true, false, $"OK"); + Diag.EqualityFactB(true, false, $"OK"); } function EqualityFactRTestShouldFail () : Unit { - EqualityFactR(Zero, One, $"OK"); + Diag.EqualityFactR(Zero, One, $"OK"); } function EqualityFactITestShouldFail () : Unit { - - EqualityFactI(12, 42, $"OK"); + Diag.EqualityFactI(12, 42, $"OK"); } @@ -60,7 +58,7 @@ namespace Microsoft.Quantum.Tests { /// operation equality assertions. operation SelfAdjointOperationsTest () : Unit { for (op in [I, X, Y, Z, H]) { - AssertOperationsEqualReferenced(3, ApplyToEach(op, _), ApplyToEachA(op, _)); + Diag.AssertOperationsEqualReferenced(3, ApplyToEach(op, _), ApplyToEachA(op, _)); } } @@ -75,7 +73,7 @@ namespace Microsoft.Quantum.Tests { for (op in [I, X, Y, Z, H]) { let arr = [op, Adjoint op]; let bound = BoundCA(arr); - AssertOperationsEqualReferenced(3, ApplyToEachCA(BoundCA(arr), _), ApplyToEachA(I, _)); + Diag.AssertOperationsEqualReferenced(3, ApplyToEachCA(BoundCA(arr), _), ApplyToEachA(I, _)); } } @@ -105,7 +103,7 @@ namespace Microsoft.Quantum.Tests { using (qubits = Qubit[1]) { H(qubits[0]); Exp([PauliZ], phase, qubits); - AssertPhase(phase, qubits[0], tolerance); + Diag.AssertPhase(phase, qubits[0], tolerance); ResetAll(qubits); } } diff --git a/Standard/tests/MultiplexerTests.qs b/Standard/tests/MultiplexerTests.qs index 0f53c7f43e0..f081bc3b680 100644 --- a/Standard/tests/MultiplexerTests.qs +++ b/Standard/tests/MultiplexerTests.qs @@ -5,11 +5,12 @@ namespace Microsoft.Quantum.Tests { open Microsoft.Quantum.Canon; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Convert; - open Microsoft.Quantum.Diagnostics; + // Needed to avoid colliding with deprecation stubs in Canon. + open Microsoft.Quantum.Diagnostics as Diag; open Microsoft.Quantum.Measurement; open Microsoft.Quantum.Arrays; - operation MultiplexZTestHelper (coefficients : Double[], multiplexerControl : LittleEndian, additionalControl : Qubit[], target : Qubit, tolerance : Double) : Unit { + operation MultiplexZTestHelper(coefficients : Double[], multiplexerControl : LittleEndian, additionalControl : Qubit[], target : Qubit, tolerance : Double) : Unit { let nCoefficients = Length(coefficients); let nQubits = (Length(multiplexerControl!) + Length(additionalControl)) + 1; @@ -46,7 +47,7 @@ namespace Microsoft.Quantum.Tests { // Case where Identity operation is performed. Message($"Controlled MultiplexZ test. coefficient {multiplexerControlInteger} of {nCoefficients-1}."); - AssertPhase(0.0, target, tolerance); + Diag.AssertPhase(0.0, target, tolerance); } else { mutable coeff = 0.0; @@ -57,13 +58,12 @@ namespace Microsoft.Quantum.Tests { if (Length(additionalControl) == 0) { Message($"MultiplexZ test. Qubits: {nQubits}; coefficient {multiplexerControlInteger} of {nCoefficients-1}."); - AssertPhase(coeff, target, tolerance); + Diag.AssertPhase(coeff, target, tolerance); } else { Message($"Controlled MultiplexZ test. Qubits: {nQubits}; coefficient {multiplexerControlInteger} of {nCoefficients-1}."); - AssertPhase(coeff, target, tolerance); + Diag.AssertPhase(coeff, target, tolerance); } - //AssertPhase(coeff, target, tolerance); } // Note that MeasureInteger has the effect of resetting its target, so @@ -71,8 +71,8 @@ namespace Microsoft.Quantum.Tests { Reset(target); } - - operation MultiplexZTest () : Unit { + @Diag.Test("QuantumSimulator") + operation TestMultiplexZ() : Unit { let maxQubits = 6; @@ -375,7 +375,7 @@ namespace Microsoft.Quantum.Tests { if (result == One) { Message($"MultiplexOperations test. Qubits: {nQubits}; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); } } } @@ -388,28 +388,28 @@ namespace Microsoft.Quantum.Tests { if (result == One) { Message($"Controlled MultiplexOperations test. Qubits: {nQubits}; idxControl = 0; nControls = 1; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); } set result = MultiplexOperationsTestHelper(idxTest, idxTarget, nQubits, 1, 1); if (result == One) { Message($"Controlled MultiplexOperations test. Qubits: {nQubits}; idxControl = 1; nControls = 1; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); } set result = MultiplexOperationsTestHelper(idxTest, idxTarget, nQubits, 1, 2); if (result == One) { Message($"Controlled MultiplexOperations test. Qubits: {nQubits}; idxControl = 1; nControls = 2; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); } set result = MultiplexOperationsTestHelper(idxTest, idxTarget, nQubits, 3, 2); if (result == One) { Message($"Controlled MultiplexOperations test. Qubits: {nQubits}; idxControl = 3; nControls = 2; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, $"MultiplexOperations failed."); } } } @@ -518,7 +518,7 @@ namespace Microsoft.Quantum.Tests { set result = MultiplexOperationsFromGeneratorTestHelper(idxTest, idxTarget, nQubits, 0, 0); if(result == One){ Message($"MultiplexOperations test. Qubits: {nQubits}; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); } } } @@ -529,25 +529,25 @@ namespace Microsoft.Quantum.Tests { set result = MultiplexOperationsFromGeneratorTestHelper(idxTest, idxTarget, nQubits, 0, 1); if(result == One){ Message($"Controlled MultiplexOperations test. Qubits: {nQubits}; idxControl = 0; nControls = 1; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); } set result = MultiplexOperationsFromGeneratorTestHelper(idxTest, idxTarget, nQubits, 1, 1); if(result == One){ Message($"Controlled MultiplexOperations test. Qubits: {nQubits}; idxControl = 1; nControls = 1; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); } set result = MultiplexOperationsFromGeneratorTestHelper(idxTest, idxTarget, nQubits, 1, 2); if(result == One){ Message($"Controlled MultiplexOperations test. Qubits: {nQubits}; idxControl = 1; nControls = 2; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); } set result = MultiplexOperationsFromGeneratorTestHelper(idxTest, idxTarget, nQubits, 3, 2); if(result == One){ Message($"Controlled MultiplexOperations test. Qubits: {nQubits}; idxControl = 3; nControls = 2; idxTest {idxTest} of idxTarget {idxTarget} result {result}."); - EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); + Diag.EqualityFactI(idxTarget, idxTest, "MultiplexOperations failed."); } } } From 96710091ff786a137f49de516964403bd44dbdaf Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 11:33:41 -0700 Subject: [PATCH 02/32] Update to 0.12.20072120-beta. --- Chemistry/src/Runtime/Runtime.csproj | 4 ++-- Chemistry/tests/ChemistryTests/QSharpTests.csproj | 2 +- Chemistry/tests/SystemTests/SystemTests.csproj | 2 +- MachineLearning/src/MachineLearning.csproj | 2 +- MachineLearning/tests/MachineLearningTests.csproj | 2 +- Numerics/src/Numerics.csproj | 4 ++-- Numerics/tests/NumericsTests.csproj | 2 +- Standard/src/Standard.csproj | 5 +++-- Standard/tests/Standard.Tests.csproj | 2 +- 9 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index 5582c4bbbfb..943a71a62d5 100644 --- a/Chemistry/src/Runtime/Runtime.csproj +++ b/Chemistry/src/Runtime/Runtime.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -36,7 +36,7 @@ - + diff --git a/Chemistry/tests/ChemistryTests/QSharpTests.csproj b/Chemistry/tests/ChemistryTests/QSharpTests.csproj index 5f67d6eabb3..b19ee076038 100644 --- a/Chemistry/tests/ChemistryTests/QSharpTests.csproj +++ b/Chemistry/tests/ChemistryTests/QSharpTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Chemistry/tests/SystemTests/SystemTests.csproj b/Chemistry/tests/SystemTests/SystemTests.csproj index e639c70d365..71cde622e64 100644 --- a/Chemistry/tests/SystemTests/SystemTests.csproj +++ b/Chemistry/tests/SystemTests/SystemTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/MachineLearning/src/MachineLearning.csproj b/MachineLearning/src/MachineLearning.csproj index c3c610ce7d5..3d79009df20 100644 --- a/MachineLearning/src/MachineLearning.csproj +++ b/MachineLearning/src/MachineLearning.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 Microsoft.Quantum.MachineLearning diff --git a/MachineLearning/tests/MachineLearningTests.csproj b/MachineLearning/tests/MachineLearningTests.csproj index 24e796bf78b..e7302da55ec 100644 --- a/MachineLearning/tests/MachineLearningTests.csproj +++ b/MachineLearning/tests/MachineLearningTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Numerics/src/Numerics.csproj b/Numerics/src/Numerics.csproj index 356da38b794..5a76a55d8f5 100644 --- a/Numerics/src/Numerics.csproj +++ b/Numerics/src/Numerics.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -40,7 +40,7 @@ - + diff --git a/Numerics/tests/NumericsTests.csproj b/Numerics/tests/NumericsTests.csproj index ed5dc9199c6..1f182e8c9f5 100644 --- a/Numerics/tests/NumericsTests.csproj +++ b/Numerics/tests/NumericsTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index f295ba5b11e..148e09be5ad 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -30,9 +30,10 @@ - + + diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index 1a4ded18c16..2f57cf901a6 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -1,4 +1,4 @@ - + From 91393d42d9c7220ce95626844ab9f35474860f45 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 11:34:08 -0700 Subject: [PATCH 03/32] Started porting dump operation to new visualization. --- Standard/src/Diagnostics/Dump.qs | 17 ++++ .../src/Diagnostics/Emulation/Internal.cs | 78 +++++++++++++++++++ .../Diagnostics/Emulation/Visualization.cs | 18 +++++ Standard/src/Diagnostics/Internal.qs | 9 +++ 4 files changed, 122 insertions(+) create mode 100644 Standard/src/Diagnostics/Dump.qs diff --git a/Standard/src/Diagnostics/Dump.qs b/Standard/src/Diagnostics/Dump.qs new file mode 100644 index 00000000000..e268cca0b54 --- /dev/null +++ b/Standard/src/Diagnostics/Dump.qs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Diagnostics { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Characterization; + open Microsoft.Quantum.Preparation; + + operation DumpOperation(nQubits : Int, op : (Qubit[] => Unit)) : Unit { + using ((reference, target) = (Qubit[nQubits], Qubit[nQubits])) { + PrepareChoiState(op, reference, target); + DumpReferenceAndTarget(reference, target); + ResetAll(reference + target); + } + } + +} diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index 8c3091ea46e..bd07770b5b8 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -4,8 +4,12 @@ #nullable enable using System; +using System.Linq; using Microsoft.Quantum.Simulation.Common; using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Simulation.Simulators; +using NumSharp; +using static NumSharp.Slice; namespace Microsoft.Quantum.Diagnostics { @@ -42,4 +46,78 @@ public Native(IOperationFactory m) : base(m) } + internal class ArrayDumper : QuantumSimulator.StateDumper + { + // NB: NumSharp does not yet support complex numbers, so we store data + // as an array with a trailing index of length 2. + internal NumSharp.NDArray? Data = null; + public ArrayDumper(QuantumSimulator sim) : base(sim) + { + + } + + public override bool Callback(uint idx, double real, double img) + { + if (Data as object == null) throw new Exception("Expected data buffer to be initialized before callback, but it was null."); + Data[(int)idx, 0] = real; + Data[(int)idx, 1] = img; + return true; + } + + public override bool Dump(IQArray? qubits = null) + { + var count = qubits == null + ? this.Simulator.QubitManager!.GetAllocatedQubitsCount() + : qubits.Length; + var nQubitsPerRegister = ((int) count / 2); + Data = np.empty(new Shape(1 << ((int)count), 2)); + var result = base.Dump(qubits); + + // At this point, _data should be filled with the full state + // vector, so let's display it, counting on the right display + // encoder to be there to pack it into a table. + var scaleFactor = System.Math.Sqrt(1 << nQubitsPerRegister); + Data = scaleFactor * Data.reshape(1 << nQubitsPerRegister, 1 << nQubitsPerRegister, 2); + + // Clean up the state vector buffer. + Data = null; + + return result; + } + } + + internal partial class DumpReferenceAndTarget + { + public class Native : DumpReferenceAndTarget + { + private SimulatorBase? Simulator; + + public Native(IOperationFactory m) : base(m) + { + Simulator = m as SimulatorBase; + } + + private QVoid DumpUnitary(QuantumSimulator simulator, IQArray reference, IQArray target) + { + var arrayDumper = new ArrayDumper(simulator); + arrayDumper.Dump(new QArray(reference.Concat(target))); + // TODO: do something to get state of the two registers out from simulator. + // TODO: write operation out as unitary. + return QVoid.Instance; + } + + public override Func<(IQArray, IQArray), QVoid> Body => (__in__) => + { + var (reference, target) = __in__; + return Simulator switch + { + QuantumSimulator sim => DumpUnitary(sim, reference, target), + // TODO: Add Toffoli simulator here. + _ => base.Body(__in__) + }; + }; + + } + } + } \ No newline at end of file diff --git a/Standard/src/Diagnostics/Emulation/Visualization.cs b/Standard/src/Diagnostics/Emulation/Visualization.cs index fddc3182efa..3c694e8b34b 100644 --- a/Standard/src/Diagnostics/Emulation/Visualization.cs +++ b/Standard/src/Diagnostics/Emulation/Visualization.cs @@ -5,6 +5,7 @@ using Microsoft.Jupyter.Core; using Newtonsoft.Json; +using static NumSharp.Slice; namespace Microsoft.Quantum.Diagnostics { @@ -59,5 +60,22 @@ displayable is FailureRecord record : (EncodedData?)null; } + internal class DisplayableUnitaryOperator + { + public NumSharp.NDArray? Data { get; set; } + } + + public class DisplayableUnitaryOperatorToTextEncoder : IResultEncoder + { + public string MimeType => MimeTypes.PlainText; + + public EncodedData? Encode(object displayable) => + displayable is DisplayableUnitaryOperator op + ? op.Data != null + ? $"Real:\n{op.Data[Ellipsis, 0]}\nImag:\n{op.Data[Ellipsis, 1]}".ToEncodedData() + : (EncodedData?)null + : (EncodedData?)null; + + } } diff --git a/Standard/src/Diagnostics/Internal.qs b/Standard/src/Diagnostics/Internal.qs index 3c66aa1dc40..80dfaafcce6 100644 --- a/Standard/src/Diagnostics/Internal.qs +++ b/Standard/src/Diagnostics/Internal.qs @@ -14,4 +14,13 @@ namespace Microsoft.Quantum.Diagnostics { fail $"{message}\n\tExpected:\t{expected}\n\tActual:\t{actual}"; } + /// # Summary + /// Uses DumpRegister to provide diagnostics on the state of a reference and + /// target register. Written as separate operation to allow overriding and + /// interpreting as separate registers, rather than as a single combined + /// register. + internal operation DumpReferenceAndTarget(reference : Qubit[], target : Qubit[]) : Unit { + DumpRegister((), reference + target); + } + } From e4e0f0f7dbee64f930db556a65d9c77bf33b26ab Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 13:06:10 -0700 Subject: [PATCH 04/32] Update M.J.Core. --- Chemistry/src/Jupyter/Jupyter.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Chemistry/src/Jupyter/Jupyter.csproj b/Chemistry/src/Jupyter/Jupyter.csproj index 0dbefaadc74..833b8769531 100644 --- a/Chemistry/src/Jupyter/Jupyter.csproj +++ b/Chemistry/src/Jupyter/Jupyter.csproj @@ -25,7 +25,7 @@ - + From ded9c5f826fe14692c635479086f5fac8dbd3e5c Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 14:41:17 -0700 Subject: [PATCH 05/32] Started working on Allow* diagnostics. --- Standard/src/Diagnostics/Allows.qs | 15 +++ Standard/src/Diagnostics/Dump.qs | 32 ++++- Standard/src/Diagnostics/Emulation/Allows.cs | 112 ++++++++++++++++++ .../src/Diagnostics/Emulation/Extensions.cs | 55 +++++++++ .../src/Diagnostics/Emulation/Internal.cs | 1 + .../Diagnostics/Emulation/Visualization.cs | 2 +- 6 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 Standard/src/Diagnostics/Allows.qs create mode 100644 Standard/src/Diagnostics/Emulation/Allows.cs create mode 100644 Standard/src/Diagnostics/Emulation/Extensions.cs diff --git a/Standard/src/Diagnostics/Allows.qs b/Standard/src/Diagnostics/Allows.qs new file mode 100644 index 00000000000..2bed6cdace5 --- /dev/null +++ b/Standard/src/Diagnostics/Allows.qs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Diagnostics { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Canon; + + + operation AllowAtMostNCallsCA<'TInput, 'TOutput>( + nTimes : Int, op : ('TInput => 'TOutput is Adj + Ctl) + ) + : Unit is Adj { + } + +} diff --git a/Standard/src/Diagnostics/Dump.qs b/Standard/src/Diagnostics/Dump.qs index e268cca0b54..9f612743e1f 100644 --- a/Standard/src/Diagnostics/Dump.qs +++ b/Standard/src/Diagnostics/Dump.qs @@ -6,11 +6,35 @@ namespace Microsoft.Quantum.Diagnostics { open Microsoft.Quantum.Characterization; open Microsoft.Quantum.Preparation; - operation DumpOperation(nQubits : Int, op : (Qubit[] => Unit)) : Unit { + /// # Summary + /// Given an operation, displays diagnostics about + /// the operation that are made available by the current + /// execution target. + /// + /// # Input + /// ## nQubits + /// The number of qubits on which the given operation acts. + /// ## op + /// The operation that is to be diagnosed. + /// + /// # Remarks + /// Calling this operation has no observable effect from within + /// Q#. The exact diagnostics that are displayed, if any, are + /// dependent on the current execution target and editor environment. + /// For example, when used on the full-state quantum simulator, + /// a unitary matrix used to represent `op` is displayed. + operation DumpOperation(nQubits : Int, op : (Qubit[] => Unit is Adj)) + : Unit { using ((reference, target) = (Qubit[nQubits], Qubit[nQubits])) { - PrepareChoiState(op, reference, target); - DumpReferenceAndTarget(reference, target); - ResetAll(reference + target); + // The operation provided could be a partial application of + // another operation, such that there could be an observable + // effect of dumping this operation unless we undo preparing the + // Choi state. + within { + PrepareChoiStateA(op, reference, target); + } apply { + DumpReferenceAndTarget(reference, target); + } } } diff --git a/Standard/src/Diagnostics/Emulation/Allows.cs b/Standard/src/Diagnostics/Emulation/Allows.cs new file mode 100644 index 00000000000..1a078f37be4 --- /dev/null +++ b/Standard/src/Diagnostics/Emulation/Allows.cs @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Quantum.Diagnostics.Emulation; +using Microsoft.Quantum.Simulation.Common; +using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Simulation.Simulators; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Quantum.Diagnostics +{ + + internal struct CallSites + { + public string Subject { get; set; } + public ImmutableList> Sites { get; set; } + } + + public partial class AllowAtMostNCallsCA<__TInput__, __TOutput__> + { + public class Native : AllowAtMostNCallsCA<__TInput__, __TOutput__> + { + private SimulatorBase? Simulator; + + private static Dictionary<(Type, Type), Stack> Handlers = + new Dictionary<(Type, Type), Stack>(); + + private readonly (Type, Type) Key = (typeof(__TInput__), typeof(__TOutput__)); + + public Native(IOperationFactory m) : base(m) + { + Simulator = m as SimulatorBase; + } + + public override Func<(long, IUnitary), QVoid> Body => (_args) => + { + if (Simulator == null) return QVoid.Instance; + + (var nTimes, var op) = _args; + var callStack = ImmutableStack.Empty; + var callSites = ImmutableList>.Empty; + + if (!Handlers.ContainsKey(Key)) + { + Handlers[Key] = new Stack(); + } + + bool IsSelf(ICallable callable) => + callable.FullName == "Microsoft.Quantum.Diagnostics.AllowAtMostNCallsCA"; + + var failed = false; + + Handlers[Key].Push(Simulator.RegisterOperationHandlers( + startOperation: (callable, data) => + { + if (IsSelf(callable)) return; + callStack = callStack.Push(callable.FullName); + if (callable.FullName == op.FullName) + { + callSites = callSites.Add(callStack); + if (callSites.Count > nTimes) + { + Simulator?.MaybeDisplayDiagnostic(new CallSites + { + Sites = callSites, + Subject = op.FullName + }); + failed = true; + throw new ExecutionFailException( + $"Operation {op.FullName} was called more than the allowed {nTimes} times." + ); + } + } + }, + + endOperation: (callable, data) => + { + if (failed || IsSelf(callable)) return; + try + { + callStack = callStack.Pop(); + } + catch (InvalidOperationException ex) + { + System.Console.WriteLine($"Call stack was empty when popped:\n{ex}"); + } + } + )); + return QVoid.Instance; + }; + + public override Func<(long, IUnitary), QVoid> AdjointBody => (_args) => + { + if (Simulator == null) return QVoid.Instance; + + Handlers[Key].Pop().Dispose(); + + return QVoid.Instance; + }; + } + + } + +} diff --git a/Standard/src/Diagnostics/Emulation/Extensions.cs b/Standard/src/Diagnostics/Emulation/Extensions.cs new file mode 100644 index 00000000000..198a4c2ca06 --- /dev/null +++ b/Standard/src/Diagnostics/Emulation/Extensions.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +using Microsoft.Quantum.Simulation.Common; +using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Simulation.Simulators; + +namespace Microsoft.Quantum.Diagnostics.Emulation +{ + + internal class SimulatorEventDisposer : IDisposable + { + private SimulatorBase Simulator; + private Action StartOperation, EndOperation; + + public SimulatorEventDisposer( + SimulatorBase simulator, + Action startOperation, + Action endOperation + ) + { + Simulator = simulator; + StartOperation = startOperation; + EndOperation = endOperation; + + Simulator.OnOperationStart += startOperation; + Simulator.OnOperationEnd += endOperation; + } + + public void Dispose() + { + System.Console.WriteLine("Removing events."); + Simulator.OnOperationStart -= StartOperation; + Simulator.OnOperationEnd -= EndOperation; + } + } + + internal static class Extensions + { + internal static SimulatorEventDisposer RegisterOperationHandlers( + this SimulatorBase simulator, + Action startOperation, + Action? endOperation = null + ) => new SimulatorEventDisposer( + simulator, + startOperation, + endOperation == null + ? (callable, data) => {} + : endOperation + ); + } +} diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index bd07770b5b8..33c84ada3bb 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -5,6 +5,7 @@ using System; using System.Linq; +using Microsoft.Quantum.Diagnostics.Emulation; using Microsoft.Quantum.Simulation.Common; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Simulation.Simulators; diff --git a/Standard/src/Diagnostics/Emulation/Visualization.cs b/Standard/src/Diagnostics/Emulation/Visualization.cs index 3c694e8b34b..b64201b5ac3 100644 --- a/Standard/src/Diagnostics/Emulation/Visualization.cs +++ b/Standard/src/Diagnostics/Emulation/Visualization.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json; using static NumSharp.Slice; -namespace Microsoft.Quantum.Diagnostics +namespace Microsoft.Quantum.Diagnostics.Emulation { internal class FailureRecord From 9a1af8f463c8ec437c346175bc49e2438d020d16 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 15:00:34 -0700 Subject: [PATCH 06/32] Connect DumpUnitary method. --- Standard/src/Diagnostics/Emulation/Internal.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index 33c84ada3bb..a2fae913c40 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -102,8 +102,12 @@ private QVoid DumpUnitary(QuantumSimulator simulator, IQArray reference, { var arrayDumper = new ArrayDumper(simulator); arrayDumper.Dump(new QArray(reference.Concat(target))); - // TODO: do something to get state of the two registers out from simulator. - // TODO: write operation out as unitary. + Simulator?.MaybeDisplayDiagnostic( + new DisplayableUnitaryOperator + { + Data = arrayDumper.Data + } + ); return QVoid.Instance; } From 5111d80ddd8d29dcca69e0bdc0d69b221f43c830 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 16:17:24 -0700 Subject: [PATCH 07/32] Update to newest logging package. --- Chemistry/src/DataModel/DataModel.csproj | 6 +-- Chemistry/src/DataModel/Logging.cs | 52 ------------------------ 2 files changed, 3 insertions(+), 55 deletions(-) delete mode 100644 Chemistry/src/DataModel/Logging.cs diff --git a/Chemistry/src/DataModel/DataModel.csproj b/Chemistry/src/DataModel/DataModel.csproj index 06934c7b3a1..47f07491b0d 100644 --- a/Chemistry/src/DataModel/DataModel.csproj +++ b/Chemistry/src/DataModel/DataModel.csproj @@ -31,9 +31,9 @@ - - - + + + diff --git a/Chemistry/src/DataModel/Logging.cs b/Chemistry/src/DataModel/Logging.cs deleted file mode 100644 index 945491f3b06..00000000000 --- a/Chemistry/src/DataModel/Logging.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Microsoft.Extensions.Logging; - -namespace Microsoft.Quantum.Chemistry -{ - public static class Logging - { - private static ILoggerFactory loggerFactory = null; - - public static string LogPath - { - get => logPath; - set { - if (loggerFactory != null) - { - loggerFactory.Dispose(); - loggerFactory = null; - } - else - { - logPath = value; - } - } - } - private static string logPath; - - public static ILoggerFactory LoggerFactory - { - get - { - if (loggerFactory == null) - { - loggerFactory = new LoggerFactory() - .AddDebug() - .AddConsole(true); - - if (LogPath != null) - { - System.Console.WriteLine($"Logging to {LogPath}."); - loggerFactory - .AddFile(LogPath); - } - } - - return loggerFactory; - } - } - } -} From 4ec7f20a80302dd94cb2d24f0bf8cf0d77e0496b Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 17:11:10 -0700 Subject: [PATCH 08/32] Fixing deprecated operation names. --- .../ChemistryTests/InitialStatePrepTests.qs | 7 +- .../ChemistryTests/MajoranaOperatorTests.qs | 72 +++++++++---------- .../src/Diagnostics/Emulation/Internal.cs | 2 +- 3 files changed, 36 insertions(+), 45 deletions(-) diff --git a/Chemistry/tests/ChemistryTests/InitialStatePrepTests.qs b/Chemistry/tests/ChemistryTests/InitialStatePrepTests.qs index 1527f1f974d..7ffa9a950cd 100644 --- a/Chemistry/tests/ChemistryTests/InitialStatePrepTests.qs +++ b/Chemistry/tests/ChemistryTests/InitialStatePrepTests.qs @@ -5,7 +5,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { open Microsoft.Quantum.Arithmetic; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; - open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Diagnostics as Diag; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Chemistry.JordanWigner; open Microsoft.Quantum.Arrays; @@ -109,8 +109,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { // Prepare multiple excitations with complex weights - operation PrepareSparseMultiConfigurationalState4Test () : Unit { - + operation PrepareSparseMultiConfigurationalState4Test () : Unit { let nQubits = 1; let intTest = [39, 21, 10]; let phase = 2.453; @@ -118,7 +117,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { using (qubits = Qubit[nQubits]) { PrepareSparseMultiConfigurationalState(NoOp, excitations, qubits); - AssertPhase(-phase / 2.0, qubits[0], 1E-09); + Diag.AssertPhase(-phase / 2.0, qubits[0], 1E-09); ResetAll(qubits); } } diff --git a/Chemistry/tests/ChemistryTests/MajoranaOperatorTests.qs b/Chemistry/tests/ChemistryTests/MajoranaOperatorTests.qs index bf10be29e29..b7c0abd6cf2 100644 --- a/Chemistry/tests/ChemistryTests/MajoranaOperatorTests.qs +++ b/Chemistry/tests/ChemistryTests/MajoranaOperatorTests.qs @@ -5,7 +5,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { open Microsoft.Quantum.Arithmetic; open Microsoft.Quantum.Intrinsic; open Microsoft.Quantum.Canon; - open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Diagnostics as Diag; open Microsoft.Quantum.Convert; open Microsoft.Quantum.Chemistry.JordanWigner; open Microsoft.Quantum.Math; @@ -41,7 +41,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { // |0> -> |0> // |+> -> |-> Message($"Test Z Pauli on qubit {idxTest}"); - AssertProb([PauliZ], [testQubit], Zero, 1.0, $"Error: Test {idxTest} {idxTest} Z Pauli |0>", 1E-10); + Diag.AssertMeasurementProbability([PauliZ], [testQubit], Zero, 1.0, $"Error: Test {idxTest} {idxTest} Z Pauli |0>", 1E-10); } elif (targetIndex == idxTest) { @@ -53,7 +53,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { // |0> -> i|1> // |+> -> -i|-> Message($"Test X or Y Pauli on qubit {idxTest}"); - AssertProb([PauliZ], [testQubit], One, 1.0, $"Error: Test {idxTest} X or Y Pauli |0>", 1E-10); + Diag.AssertMeasurementProbability([PauliZ], [testQubit], One, 1.0, $"Error: Test {idxTest} X or Y Pauli |0>", 1E-10); } else { @@ -61,7 +61,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { // |0> -> |0> // |+> -> |+> Message($"Test ZI Pauli on qubit {idxTest}"); - AssertProb([PauliZ], [testQubit], Zero, 1.0, $"Error: Test {idxTest} I Pauli |0>", 1E-10); + Diag.AssertMeasurementProbability([PauliZ], [testQubit], Zero, 1.0, $"Error: Test {idxTest} I Pauli |0>", 1E-10); } } @@ -109,7 +109,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { // |0> -> |0> // |+> -> |-> Message($"Test Z Pauli on qubit {idxTest}"); - AssertProb([PauliX], [testQubit], One, 1.0, $"Error: Test {idxTest} Z Pauli |+>", 1e-10); + Diag.AssertMeasurementProbability([PauliX], [testQubit], One, 1.0, $"Error: Test {idxTest} Z Pauli |+>", 1e-10); } elif(targetIndex == idxTest){ // Test X Pauli @@ -117,7 +117,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { // |+> -> |+> if(pauliBasis == PauliX){ Message($"Test X Pauli on qubit {idxTest}"); - AssertProb([PauliX], [testQubit], Zero, 1.0, $"Error: Test {idxTest} X Pauli |+>", 1e-10); + Diag.AssertMeasurementProbability([PauliX], [testQubit], Zero, 1.0, $"Error: Test {idxTest} X Pauli |+>", 1e-10); } // Test Y Pauli @@ -125,7 +125,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { // |+> -> -i|-> if(pauliBasis == PauliY){ Message($"Test Y Pauli on qubit {idxTest}"); - AssertProb([PauliX], [testQubit], One, 1.0, $"Error: Test {idxTest} Y Pauli |+>", 1e-10); + Diag.AssertMeasurementProbability([PauliX], [testQubit], One, 1.0, $"Error: Test {idxTest} Y Pauli |+>", 1e-10); } } @@ -134,7 +134,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { // |0> -> |0> // |+> -> |+> Message($"Test I Pauli on qubit {idxTest}"); - AssertProb([PauliX], [testQubit], Zero, 1.0, $"Error: Test {idxTest} I Pauli |+>", 1e-10); + Diag.AssertMeasurementProbability([PauliX], [testQubit], Zero, 1.0, $"Error: Test {idxTest} I Pauli |+>", 1e-10); } } OptimizedBEXY(pauliBasisQubit[0], LittleEndian(indexRegister), targetRegister); @@ -188,8 +188,10 @@ namespace Microsoft.Quantum.Chemistry.Tests { // Test phase of controlled OptimizedBEXY operator. - operation ControlledOptimizedBEOperatorTestHelper (pauliBasis : Pauli, targetRegisterSize : Int, targetIndex : Int) : Unit { - + operation ControlledOptimizedBEOperatorTestHelper( + pauliBasis : Pauli, targetRegisterSize : Int, targetIndex : Int + ) + : Unit { let indexRegisterSize = Ceiling(Lg(IntAsDouble(targetRegisterSize))); using (pauliBasisQubit = Qubit[1]) { @@ -202,37 +204,27 @@ namespace Microsoft.Quantum.Chemistry.Tests { let testQubit = targetRegister[targetIndex]; // Create indexRegister state. - ApplyXorInPlace(targetIndex, LittleEndian(indexRegister)); - - // Initialize control in |+> state. - H(controlRegister[0]); + within { + ApplyXorInPlace(targetIndex, LittleEndian(indexRegister)); - // Choose X or Y operator. - if (pauliBasis == PauliX) { - - // Initialize testQubit state in X +1 eigenstate - H(testQubit); - Controlled OptimizedBEXY(controlRegister, (pauliBasisQubit[0], LittleEndian(indexRegister), targetRegister)); - AssertPhase(0.0, controlRegister[0], 1E-10); - Adjoint Controlled OptimizedBEXY(controlRegister, (pauliBasisQubit[0], LittleEndian(indexRegister), targetRegister)); - H(testQubit); - } - elif (pauliBasis == PauliY) { - X(pauliBasisQubit[0]); - - // Initialize testQubit state Y +1 eigenstate - H(testQubit); - S(testQubit); - Controlled OptimizedBEXY(controlRegister, (pauliBasisQubit[0], LittleEndian(indexRegister), targetRegister)); - AssertPhase(0.0, controlRegister[0], 1E-10); - Adjoint Controlled OptimizedBEXY(controlRegister, (pauliBasisQubit[0], LittleEndian(indexRegister), targetRegister)); - Adjoint S(testQubit); - H(testQubit); - X(pauliBasisQubit[0]); + // Initialize control in |+> state. + H(controlRegister[0]); + + // Choose X or Y operator. + if (pauliBasis == PauliX) { + // Initialize testQubit state in X +1 eigenstate + H(testQubit); + Controlled OptimizedBEXY(controlRegister, (pauliBasisQubit[0], LittleEndian(indexRegister), targetRegister)); + } elif (pauliBasis == PauliY) { + // Initialize testQubit state Y +1 eigenstate + X(pauliBasisQubit[0]); + H(testQubit); + S(testQubit); + Controlled OptimizedBEXY(controlRegister, (pauliBasisQubit[0], LittleEndian(indexRegister), targetRegister)); + } + } apply { + Diag.AssertPhase(0.0, controlRegister[0], 1E-10); } - - H(controlRegister[0]); - Adjoint ApplyXorInPlace(targetIndex, LittleEndian(indexRegister)); } } } @@ -265,7 +257,7 @@ namespace Microsoft.Quantum.Chemistry.Tests { H(targetRegister[idxTest]); ApplyXorInPlace(idxTest, LittleEndian(indexRegister)); SelectZ(LittleEndian(indexRegister), targetRegister); - AssertProb([PauliX], [targetRegister[idxTest]], One, 1.0, $"Error: Test {idxTest} X Pauli |+>", 1E-10); + Diag.AssertMeasurementProbability([PauliX], [targetRegister[idxTest]], One, 1.0, $"Error: Test {idxTest} X Pauli |+>", 1E-10); Z(targetRegister[idxTest]); Adjoint ApplyXorInPlace(idxTest, LittleEndian(indexRegister)); H(targetRegister[idxTest]); diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index a2fae913c40..9a6c3781a76 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -116,7 +116,7 @@ private QVoid DumpUnitary(QuantumSimulator simulator, IQArray reference, var (reference, target) = __in__; return Simulator switch { - QuantumSimulator sim => DumpUnitary(sim, reference, target), + QuantumSimulator sim => this.DumpUnitary(sim, reference, target), // TODO: Add Toffoli simulator here. _ => base.Body(__in__) }; From 3b34b98d26814a301a835330a17c19ae7201060d Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 18:36:59 -0700 Subject: [PATCH 09/32] Split visualization into new package. --- Build/manifest.ps1 | 1 + Build/pack.ps1 | 3 ++ Standard.sln | 11 +++++ .../Diagnostics/Emulation/DataStructures.cs | 26 ++++++++++++ Standard/src/Standard.csproj | 1 - Visualization/Common/DelaySign.cs | 24 +++++++++++ .../src/DisplayEncoders.cs | 18 -------- Visualization/src/Visualization.csproj | 41 +++++++++++++++++++ 8 files changed, 106 insertions(+), 19 deletions(-) create mode 100644 Standard/src/Diagnostics/Emulation/DataStructures.cs create mode 100644 Visualization/Common/DelaySign.cs rename Standard/src/Diagnostics/Emulation/Visualization.cs => Visualization/src/DisplayEncoders.cs (83%) create mode 100644 Visualization/src/Visualization.csproj diff --git a/Build/manifest.ps1 b/Build/manifest.ps1 index f4b4ab285ed..4fad664f64a 100644 --- a/Build/manifest.ps1 +++ b/Build/manifest.ps1 @@ -12,6 +12,7 @@ ); Assemblies = @( ".\Standard\src\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Standard.dll", + ".\Visualization\src\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Standard.Visualization.dll", ".\Numerics\src\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Numerics.dll", ".\MachineLearning\src\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.MachineLearning.dll", ".\Chemistry\src\DataModel\bin\$Env:BUILD_CONFIGURATION\netstandard2.1\Microsoft.Quantum.Chemistry.DataModel.dll", diff --git a/Build/pack.ps1 b/Build/pack.ps1 index ec9563561f9..f329a766e4e 100644 --- a/Build/pack.ps1 +++ b/Build/pack.ps1 @@ -25,6 +25,9 @@ function Pack-One() { Write-Host "##[info]Pack Standard library" Pack-One '../Standard/src/Standard.csproj' +Write-Host "##[info]Pack Standard visualization library" +Pack-One '../Visualization/src/Visualization.csproj' + Write-Host "##[info]Pack Chemistry library" Pack-One '../Chemistry/src/Runtime/Runtime.csproj' Pack-One '../Chemistry/src/DataModel/DataModel.csproj' diff --git a/Standard.sln b/Standard.sln index 6706dfe09f3..b8cbaa04b26 100644 --- a/Standard.sln +++ b/Standard.sln @@ -12,6 +12,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Standard", "Standard\src\St EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Standard.Tests", "Standard\tests\Standard.Tests.csproj", "{DEDA9681-2C11-492F-B1C9-D772BB45730A}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Visualization", "Visualization", "{2C5BF171-7D32-4DEC-BD08-9667A55A36FF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Visualization", "Visualization\src\Visualization.csproj", "{AC5462CC-F249-48E4-BFBE-93FC5AAC0D4E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -26,6 +30,10 @@ Global {DEDA9681-2C11-492F-B1C9-D772BB45730A}.Debug|Any CPU.Build.0 = Debug|Any CPU {DEDA9681-2C11-492F-B1C9-D772BB45730A}.Release|Any CPU.ActiveCfg = Release|Any CPU {DEDA9681-2C11-492F-B1C9-D772BB45730A}.Release|Any CPU.Build.0 = Release|Any CPU + {AC5462CC-F249-48E4-BFBE-93FC5AAC0D4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC5462CC-F249-48E4-BFBE-93FC5AAC0D4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC5462CC-F249-48E4-BFBE-93FC5AAC0D4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC5462CC-F249-48E4-BFBE-93FC5AAC0D4E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -39,4 +47,7 @@ Global GlobalSection(Performance) = preSolution HasPerformanceSessions = true EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {AC5462CC-F249-48E4-BFBE-93FC5AAC0D4E} = {2C5BF171-7D32-4DEC-BD08-9667A55A36FF} + EndGlobalSection EndGlobal diff --git a/Standard/src/Diagnostics/Emulation/DataStructures.cs b/Standard/src/Diagnostics/Emulation/DataStructures.cs new file mode 100644 index 00000000000..9e7736a355f --- /dev/null +++ b/Standard/src/Diagnostics/Emulation/DataStructures.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using Newtonsoft.Json; + +namespace Microsoft.Quantum.Diagnostics.Emulation +{ + public class FailureRecord + { + [JsonProperty("actual")] + public T Actual { get; set; } + + [JsonProperty("expected")] + public T Expected { get; set; } + + [JsonProperty("message")] + public string Message { get; set; } = ""; + } + + public class DisplayableUnitaryOperator + { + public NumSharp.NDArray? Data { get; set; } + } +} diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index 148e09be5ad..fa9ed681e89 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -32,7 +32,6 @@ - diff --git a/Visualization/Common/DelaySign.cs b/Visualization/Common/DelaySign.cs new file mode 100644 index 00000000000..a2e08c82e45 --- /dev/null +++ b/Visualization/Common/DelaySign.cs @@ -0,0 +1,24 @@ +using System.Reflection; + +// Attributes for delay-signing +#if SIGNED +[assembly:AssemblyKeyFile("..\\..\\Build\\267DevDivSNKey2048.snk")] +[assembly:AssemblyDelaySign(true)] +#endif + +internal static class SigningConstants +{ +#if SIGNED + public const string PUBLIC_KEY = ", PublicKey=" + + "002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1" + + "a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a2" + + "35e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b" + + "5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c" + + "8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f" + + "9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f3" + + "02d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd9" + + "11f0571aaf3d54da12b11ddec375b3"; +#else + public const string PUBLIC_KEY = ""; +#endif +} diff --git a/Standard/src/Diagnostics/Emulation/Visualization.cs b/Visualization/src/DisplayEncoders.cs similarity index 83% rename from Standard/src/Diagnostics/Emulation/Visualization.cs rename to Visualization/src/DisplayEncoders.cs index b64201b5ac3..6521066d15e 100644 --- a/Standard/src/Diagnostics/Emulation/Visualization.cs +++ b/Visualization/src/DisplayEncoders.cs @@ -9,19 +9,6 @@ namespace Microsoft.Quantum.Diagnostics.Emulation { - - internal class FailureRecord - { - [JsonProperty("actual")] - public T Actual { get; set; } - - [JsonProperty("expected")] - public T Expected { get; set; } - - [JsonProperty("message")] - public string Message { get; set; } = ""; - } - public class FailureRecordToHtmlEncoder : IResultEncoder { @@ -60,11 +47,6 @@ displayable is FailureRecord record : (EncodedData?)null; } - internal class DisplayableUnitaryOperator - { - public NumSharp.NDArray? Data { get; set; } - } - public class DisplayableUnitaryOperatorToTextEncoder : IResultEncoder { public string MimeType => MimeTypes.PlainText; diff --git a/Visualization/src/Visualization.csproj b/Visualization/src/Visualization.csproj new file mode 100644 index 00000000000..f4d5d64cd44 --- /dev/null +++ b/Visualization/src/Visualization.csproj @@ -0,0 +1,41 @@ + + + + netstandard2.1 + Microsoft.Quantum.Standard.Visualization + 1591 + + + + Microsoft + Provides IQ# visualization support for Microsoft's Q# standard libraries. + © Microsoft Corporation. All rights reserved. + See: https://docs.microsoft.com/en-us/quantum/relnotes/ + MIT + https://github.com/Microsoft/Quantum + qdk-nuget-icon.png + Quantum Q# Qsharp + false + true + true + true + snupkg + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb;.xml + + + + + + + + + + + + + + + + + + From e8e8d90b9ed0f3536ca1ec703e20bd7b0e56e7ea Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 21 Jul 2020 21:52:38 -0700 Subject: [PATCH 10/32] Fix project reference to standard. --- Visualization/src/Visualization.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Visualization/src/Visualization.csproj b/Visualization/src/Visualization.csproj index f4d5d64cd44..17a5a06a771 100644 --- a/Visualization/src/Visualization.csproj +++ b/Visualization/src/Visualization.csproj @@ -27,6 +27,10 @@ + + + + From 8fa9d6bd77a4964e88c1b480ae1a590ceae8b69f Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 28 Jul 2020 20:34:49 -0700 Subject: [PATCH 11/32] Fix dump = null. --- .../src/Diagnostics/Emulation/Internal.cs | 3 --- Visualization/src/DisplayEncoders.cs | 25 ++++++++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index 9a6c3781a76..e6702868431 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -80,9 +80,6 @@ public override bool Dump(IQArray? qubits = null) var scaleFactor = System.Math.Sqrt(1 << nQubitsPerRegister); Data = scaleFactor * Data.reshape(1 << nQubitsPerRegister, 1 << nQubitsPerRegister, 2); - // Clean up the state vector buffer. - Data = null; - return result; } } diff --git a/Visualization/src/DisplayEncoders.cs b/Visualization/src/DisplayEncoders.cs index 6521066d15e..328577f01c0 100644 --- a/Visualization/src/DisplayEncoders.cs +++ b/Visualization/src/DisplayEncoders.cs @@ -4,6 +4,7 @@ #nullable enable using Microsoft.Jupyter.Core; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using static NumSharp.Slice; @@ -49,14 +50,26 @@ displayable is FailureRecord record public class DisplayableUnitaryOperatorToTextEncoder : IResultEncoder { + private ILogger logger; public string MimeType => MimeTypes.PlainText; - public EncodedData? Encode(object displayable) => - displayable is DisplayableUnitaryOperator op - ? op.Data != null - ? $"Real:\n{op.Data[Ellipsis, 0]}\nImag:\n{op.Data[Ellipsis, 1]}".ToEncodedData() - : (EncodedData?)null - : (EncodedData?)null; + public DisplayableUnitaryOperatorToTextEncoder(ILogger logger) + { + this.logger = logger; + } + + public EncodedData? Encode(object displayable) + { + if (displayable is DisplayableUnitaryOperator op) + { + if (op?.Data is null) + { + logger.LogError("Asked to encode a displayable unitary operator, but its data was null. This should not happen."); + } + return $"Real:\n{op.Data[Ellipsis, 0]}\nImag:\n{op.Data[Ellipsis, 1]}".ToEncodedData(); + } + else return null; + } } From eb3f389930db3ffb187a4c76bb3965679c6b506b Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Wed, 29 Jul 2020 14:14:00 -0700 Subject: [PATCH 12/32] Got DumpOperation working through IQ#. --- Chemistry/src/Runtime/Runtime.csproj | 4 +- .../tests/ChemistryTests/QSharpTests.csproj | 2 +- .../tests/SystemTests/SystemTests.csproj | 2 +- MachineLearning/src/MachineLearning.csproj | 2 +- .../tests/MachineLearningTests.csproj | 2 +- Numerics/src/Numerics.csproj | 4 +- Numerics/tests/NumericsTests.csproj | 2 +- .../Diagnostics/Emulation/DataStructures.cs | 4 ++ .../src/Diagnostics/Emulation/Internal.cs | 9 +-- Standard/src/Standard.csproj | 4 +- Standard/tests/Standard.Tests.csproj | 2 +- Visualization/src/DisplayEncoders.cs | 63 +++++++++++++++++++ Visualization/src/Extensions.cs | 35 +++++++++++ Visualization/src/Visualization.csproj | 4 +- 14 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 Visualization/src/Extensions.cs diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index 943a71a62d5..d7c6acb27d2 100644 --- a/Chemistry/src/Runtime/Runtime.csproj +++ b/Chemistry/src/Runtime/Runtime.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -36,7 +36,7 @@ - + diff --git a/Chemistry/tests/ChemistryTests/QSharpTests.csproj b/Chemistry/tests/ChemistryTests/QSharpTests.csproj index b19ee076038..0866d134fe7 100644 --- a/Chemistry/tests/ChemistryTests/QSharpTests.csproj +++ b/Chemistry/tests/ChemistryTests/QSharpTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Chemistry/tests/SystemTests/SystemTests.csproj b/Chemistry/tests/SystemTests/SystemTests.csproj index 71cde622e64..12c76775cf0 100644 --- a/Chemistry/tests/SystemTests/SystemTests.csproj +++ b/Chemistry/tests/SystemTests/SystemTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/MachineLearning/src/MachineLearning.csproj b/MachineLearning/src/MachineLearning.csproj index 3d79009df20..2490d5d08ec 100644 --- a/MachineLearning/src/MachineLearning.csproj +++ b/MachineLearning/src/MachineLearning.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 Microsoft.Quantum.MachineLearning diff --git a/MachineLearning/tests/MachineLearningTests.csproj b/MachineLearning/tests/MachineLearningTests.csproj index e7302da55ec..d119b5d392e 100644 --- a/MachineLearning/tests/MachineLearningTests.csproj +++ b/MachineLearning/tests/MachineLearningTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Numerics/src/Numerics.csproj b/Numerics/src/Numerics.csproj index 5a76a55d8f5..c1e11cb3de7 100644 --- a/Numerics/src/Numerics.csproj +++ b/Numerics/src/Numerics.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -40,7 +40,7 @@ - + diff --git a/Numerics/tests/NumericsTests.csproj b/Numerics/tests/NumericsTests.csproj index 1f182e8c9f5..b45979ffbe7 100644 --- a/Numerics/tests/NumericsTests.csproj +++ b/Numerics/tests/NumericsTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Standard/src/Diagnostics/Emulation/DataStructures.cs b/Standard/src/Diagnostics/Emulation/DataStructures.cs index 9e7736a355f..8fabf5dc772 100644 --- a/Standard/src/Diagnostics/Emulation/DataStructures.cs +++ b/Standard/src/Diagnostics/Emulation/DataStructures.cs @@ -3,6 +3,9 @@ #nullable enable +using System.Collections.Generic; +using Microsoft.Quantum.Simulation.Common; +using Microsoft.Quantum.Simulation.Core; using Newtonsoft.Json; namespace Microsoft.Quantum.Diagnostics.Emulation @@ -21,6 +24,7 @@ public class FailureRecord public class DisplayableUnitaryOperator { + public IList? Qubits { get; set; } public NumSharp.NDArray? Data { get; set; } } } diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index e6702868431..e343a6aaee3 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -95,14 +95,15 @@ public Native(IOperationFactory m) : base(m) Simulator = m as SimulatorBase; } - private QVoid DumpUnitary(QuantumSimulator simulator, IQArray reference, IQArray target) + private QVoid DumpUnitaryFromChoiState(QuantumSimulator simulator, IQArray reference, IQArray target) { var arrayDumper = new ArrayDumper(simulator); arrayDumper.Dump(new QArray(reference.Concat(target))); Simulator?.MaybeDisplayDiagnostic( new DisplayableUnitaryOperator { - Data = arrayDumper.Data + Data = arrayDumper.Data, + Qubits = target.ToList() } ); return QVoid.Instance; @@ -113,8 +114,8 @@ private QVoid DumpUnitary(QuantumSimulator simulator, IQArray reference, var (reference, target) = __in__; return Simulator switch { - QuantumSimulator sim => this.DumpUnitary(sim, reference, target), - // TODO: Add Toffoli simulator here. + QuantumSimulator sim => this.DumpUnitaryFromChoiState(sim, reference, target), + // TODO: Add other simulators here as appropriate. _ => base.Body(__in__) }; }; diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index fa9ed681e89..b313a73adc0 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -30,7 +30,7 @@ - + diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index 2f57cf901a6..0c45defdefb 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Visualization/src/DisplayEncoders.cs b/Visualization/src/DisplayEncoders.cs index 328577f01c0..9dd5f7b1355 100644 --- a/Visualization/src/DisplayEncoders.cs +++ b/Visualization/src/DisplayEncoders.cs @@ -3,10 +3,14 @@ #nullable enable +using System.Text; using Microsoft.Jupyter.Core; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using static NumSharp.Slice; +using Microsoft.Quantum.IQSharp.Jupyter; +using System.Linq; +using System; namespace Microsoft.Quantum.Diagnostics.Emulation { @@ -65,6 +69,7 @@ public DisplayableUnitaryOperatorToTextEncoder(ILogger logger; + private readonly IConfigurationSource configurationSource; + public string MimeType => MimeTypes.Html; + + public DisplayableUnitaryOperatorToHtmlEncoder( + ILogger logger, + IConfigurationSource configurationSource + ) + { + this.logger = logger; + this.configurationSource = configurationSource; + } + + public EncodedData? Encode(object displayable) + { + if (displayable is DisplayableUnitaryOperator op) + { + if (op?.Data is null) + { + logger.LogError("Asked to encode a displayable unitary operator, but its data was null. This should not happen."); + return null; + } + var outputMatrix = String.Join( + " \\\\\n", + op.Data.EnumerateOverAxis().Cast().Select( + row => + String.Join(" & ", + row.EnumerateOverAxis() + .Cast() + .Select(element => $"{element[0]} {(((double)element[1]) < 0 ? "-" : "+")} {System.Math.Abs((double)element[1])}i") + ) + ) + ); + return $@" + + + + + + + + + +
Qubit IDs{String.Join(", ", op.Qubits.Select(q => q.Id))} +
Unitary representation$$ + \left(\begin{{matrix}} + {outputMatrix} + \end{{matrix}}\right) + $$
+ ".ToEncodedData(); + } + else return null; + } + + } + } diff --git a/Visualization/src/Extensions.cs b/Visualization/src/Extensions.cs new file mode 100644 index 00000000000..771051da4e8 --- /dev/null +++ b/Visualization/src/Extensions.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Text; +using Microsoft.Jupyter.Core; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using NumSharp; +using static NumSharp.Slice; +using Microsoft.Quantum.IQSharp.Jupyter; +using System.Linq; +using System; +using System.Collections.Generic; + +namespace Microsoft.Quantum.Diagnostics.Emulation +{ + + internal static class Extensions + { + internal static IEnumerable EnumerateOverAxis(this NumSharp.NDArray array, int axis = 0) + { + var prefix = Enumerable.Repeat(All, axis).ToArray(); + foreach (var idx in Enumerable.Range(0, array.Shape[axis])) + { + Slice[] slice = prefix.Concat(new Slice[] { idx, Ellipsis }).ToArray(); + yield return array[slice]; + } + } + + + } + +} diff --git a/Visualization/src/Visualization.csproj b/Visualization/src/Visualization.csproj index 17a5a06a771..d0281235a7b 100644 --- a/Visualization/src/Visualization.csproj +++ b/Visualization/src/Visualization.csproj @@ -32,9 +32,9 @@ - + - + From e8dd1bbfa501cc3e5000aed49fbe07d62168405a Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Thu, 30 Jul 2020 14:11:30 -0700 Subject: [PATCH 13/32] Got DumpOperation working. --- Chemistry/src/Runtime/Runtime.csproj | 4 +- .../tests/ChemistryTests/QSharpTests.csproj | 2 +- .../tests/SystemTests/SystemTests.csproj | 2 +- MachineLearning/src/MachineLearning.csproj | 2 +- .../tests/MachineLearningTests.csproj | 2 +- Numerics/src/Numerics.csproj | 4 +- Numerics/tests/NumericsTests.csproj | 2 +- Standard/src/Diagnostics/Allows.qs | 28 ++++++ Standard/src/Diagnostics/Dump.qs | 17 ++++ Standard/src/Diagnostics/Emulation/Allows.cs | 6 -- .../Diagnostics/Emulation/DataStructures.cs | 21 ++--- .../src/Diagnostics/Emulation/Internal.cs | 33 ------- Standard/src/Standard.csproj | 4 +- Standard/tests/Standard.Tests.csproj | 2 +- Visualization/src/CallSiteEncoders.cs | 91 +++++++++++++++++++ ...oders.cs => DisplayableUnitaryEncoders.cs} | 72 +++++++-------- Visualization/src/Extensions.cs | 9 +- Visualization/src/Visualization.csproj | 4 +- 18 files changed, 199 insertions(+), 106 deletions(-) create mode 100644 Visualization/src/CallSiteEncoders.cs rename Visualization/src/{DisplayEncoders.cs => DisplayableUnitaryEncoders.cs} (67%) diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index d7c6acb27d2..92dc5f2710d 100644 --- a/Chemistry/src/Runtime/Runtime.csproj +++ b/Chemistry/src/Runtime/Runtime.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -36,7 +36,7 @@ - + diff --git a/Chemistry/tests/ChemistryTests/QSharpTests.csproj b/Chemistry/tests/ChemistryTests/QSharpTests.csproj index 0866d134fe7..297fb4d601d 100644 --- a/Chemistry/tests/ChemistryTests/QSharpTests.csproj +++ b/Chemistry/tests/ChemistryTests/QSharpTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Chemistry/tests/SystemTests/SystemTests.csproj b/Chemistry/tests/SystemTests/SystemTests.csproj index 12c76775cf0..02e769293d5 100644 --- a/Chemistry/tests/SystemTests/SystemTests.csproj +++ b/Chemistry/tests/SystemTests/SystemTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/MachineLearning/src/MachineLearning.csproj b/MachineLearning/src/MachineLearning.csproj index 2490d5d08ec..3034629c8df 100644 --- a/MachineLearning/src/MachineLearning.csproj +++ b/MachineLearning/src/MachineLearning.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 Microsoft.Quantum.MachineLearning diff --git a/MachineLearning/tests/MachineLearningTests.csproj b/MachineLearning/tests/MachineLearningTests.csproj index d119b5d392e..efda9c28acb 100644 --- a/MachineLearning/tests/MachineLearningTests.csproj +++ b/MachineLearning/tests/MachineLearningTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Numerics/src/Numerics.csproj b/Numerics/src/Numerics.csproj index c1e11cb3de7..c7c75fd281c 100644 --- a/Numerics/src/Numerics.csproj +++ b/Numerics/src/Numerics.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -40,7 +40,7 @@ - + diff --git a/Numerics/tests/NumericsTests.csproj b/Numerics/tests/NumericsTests.csproj index b45979ffbe7..10f1e0fbb3b 100644 --- a/Numerics/tests/NumericsTests.csproj +++ b/Numerics/tests/NumericsTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Standard/src/Diagnostics/Allows.qs b/Standard/src/Diagnostics/Allows.qs index 2bed6cdace5..d934caa50b2 100644 --- a/Standard/src/Diagnostics/Allows.qs +++ b/Standard/src/Diagnostics/Allows.qs @@ -6,6 +6,34 @@ namespace Microsoft.Quantum.Diagnostics { open Microsoft.Quantum.Canon; + /// # Summary + /// Between a call to this operation and its adjoint, asserts that + /// a given operation is called at most a certain number of times. + /// + /// # Input + /// ## nTimes + /// The maximum number of times that `op` may be called. + /// ## op + /// An operation whose calls are to be restricted. + /// + /// # Example + /// The following snippet will fail when executed on machines which + /// support this diagnostic: + /// ```Q# + /// using (register = Qubit[4]) { + /// within { + /// AllowAtMostNCallsCA(3, H); + /// } apply { + /// // Fails since this calls H four times, rather than the + /// // allowed maximum of three. + /// ApplyToEach(H, register); + /// } + /// } + /// ``` + /// + /// # Remarks + /// This operation may be replaced by a no-op on targets which do not + /// support it. operation AllowAtMostNCallsCA<'TInput, 'TOutput>( nTimes : Int, op : ('TInput => 'TOutput is Adj + Ctl) ) diff --git a/Standard/src/Diagnostics/Dump.qs b/Standard/src/Diagnostics/Dump.qs index 9f612743e1f..597ff7c7a33 100644 --- a/Standard/src/Diagnostics/Dump.qs +++ b/Standard/src/Diagnostics/Dump.qs @@ -17,6 +17,23 @@ namespace Microsoft.Quantum.Diagnostics { /// ## op /// The operation that is to be diagnosed. /// + /// # Example + /// When run on the quantum simulator target, the following snippet + /// will output the matrix + /// $\left(\begin{matrix} 0.0 & 0.707 \\\\ 0.707 & 0.0\end{matrix}\right)$: + /// + /// ```Q# + /// open Microsoft.Quantum.Arrays as Arrays; + /// + /// operation ApplyH(register : Qubit[]) : Unit is Adj + Ctl { + /// H(Head(register)); + /// } + /// + /// operation DumpH() : Unit { + /// DumpOperation(1, ApplyH); + /// } + /// ``` + /// /// # Remarks /// Calling this operation has no observable effect from within /// Q#. The exact diagnostics that are displayed, if any, are diff --git a/Standard/src/Diagnostics/Emulation/Allows.cs b/Standard/src/Diagnostics/Emulation/Allows.cs index 1a078f37be4..7574104628a 100644 --- a/Standard/src/Diagnostics/Emulation/Allows.cs +++ b/Standard/src/Diagnostics/Emulation/Allows.cs @@ -18,12 +18,6 @@ namespace Microsoft.Quantum.Diagnostics { - internal struct CallSites - { - public string Subject { get; set; } - public ImmutableList> Sites { get; set; } - } - public partial class AllowAtMostNCallsCA<__TInput__, __TOutput__> { public class Native : AllowAtMostNCallsCA<__TInput__, __TOutput__> diff --git a/Standard/src/Diagnostics/Emulation/DataStructures.cs b/Standard/src/Diagnostics/Emulation/DataStructures.cs index 8fabf5dc772..6606671de0b 100644 --- a/Standard/src/Diagnostics/Emulation/DataStructures.cs +++ b/Standard/src/Diagnostics/Emulation/DataStructures.cs @@ -4,27 +4,22 @@ #nullable enable using System.Collections.Generic; +using System.Collections.Immutable; using Microsoft.Quantum.Simulation.Common; using Microsoft.Quantum.Simulation.Core; using Newtonsoft.Json; namespace Microsoft.Quantum.Diagnostics.Emulation -{ - public class FailureRecord - { - [JsonProperty("actual")] - public T Actual { get; set; } - - [JsonProperty("expected")] - public T Expected { get; set; } - - [JsonProperty("message")] - public string Message { get; set; } = ""; - } - +{ public class DisplayableUnitaryOperator { public IList? Qubits { get; set; } public NumSharp.NDArray? Data { get; set; } } + + public struct CallSites + { + public string Subject { get; set; } + public ImmutableList> Sites { get; set; } + } } diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index e343a6aaee3..afcd8eec534 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -14,39 +14,6 @@ namespace Microsoft.Quantum.Diagnostics { - - internal partial class FormattedFailure<__T__> - { - - public class Native : FormattedFailure<__T__> - { - private SimulatorBase? Simulator; - - public Native(IOperationFactory m) : base(m) - { - Simulator = m as SimulatorBase; - } - - public override Func<(__T__,__T__,String), QVoid> Body => (__in__) => - { - if (Simulator != null) - { - var (actual, expected, message) = __in__; - Simulator.MaybeDisplayDiagnostic( - new FailureRecord<__T__> - { - Message = message, - Actual = actual, - Expected = expected - } - ); - } - return base.Body(__in__); - }; - } - - } - internal class ArrayDumper : QuantumSimulator.StateDumper { // NB: NumSharp does not yet support complex numbers, so we store data diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index b313a73adc0..a5481519982 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -30,7 +30,7 @@ - + diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index 0c45defdefb..ec83cb33df2 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Visualization/src/CallSiteEncoders.cs b/Visualization/src/CallSiteEncoders.cs new file mode 100644 index 00000000000..6520d2aa3ed --- /dev/null +++ b/Visualization/src/CallSiteEncoders.cs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System.Text; +using Microsoft.Jupyter.Core; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using static NumSharp.Slice; +using Microsoft.Quantum.IQSharp.Jupyter; +using System.Linq; +using System; + +namespace Microsoft.Quantum.Diagnostics.Emulation +{ + public class CallSitesToTextEncoder : IResultEncoder + { + private ILogger logger; + public string MimeType => MimeTypes.PlainText; + + public CallSitesToTextEncoder(ILogger logger) + { + this.logger = logger; + } + + public EncodedData? Encode(object displayable) + { + if (displayable is CallSites sites) + { + var list = String.Join("\n---\n", + sites.Sites.Select( + call => String.Join("\n", + call.Select( + frame => $"- {frame}" + ) + ) + ) + ); + return $"Calls to {sites.Subject}:\n\n{list}".ToEncodedData(); + } + else return null; + } + + } + + public class CallSitesToHtmlEncoder : IResultEncoder + { + private readonly ILogger logger; + private readonly IConfigurationSource configurationSource; + public string MimeType => MimeTypes.Html; + + public CallSitesToHtmlEncoder( + ILogger logger, + IConfigurationSource configurationSource + ) + { + this.logger = logger; + this.configurationSource = configurationSource; + } + + public EncodedData? Encode(object displayable) + { + if (displayable is CallSites sites) + { + logger.LogDebug("Using HTML encoder to output call site record."); + return $@" +
+ Calls to {sites.Subject}: +
    { + String.Join("\n", + sites.Sites.Select( + call => $@" +
    • { + String.Join("\n", call.Select( + frame => $"
    • {frame}
    • " + )) + }
  • + " + ) + ) + }
+
+ ".ToEncodedData(); + } + else return null; + } + + } + +} diff --git a/Visualization/src/DisplayEncoders.cs b/Visualization/src/DisplayableUnitaryEncoders.cs similarity index 67% rename from Visualization/src/DisplayEncoders.cs rename to Visualization/src/DisplayableUnitaryEncoders.cs index 9dd5f7b1355..a9652bc6b82 100644 --- a/Visualization/src/DisplayEncoders.cs +++ b/Visualization/src/DisplayableUnitaryEncoders.cs @@ -14,44 +14,6 @@ namespace Microsoft.Quantum.Diagnostics.Emulation { - - public class FailureRecordToHtmlEncoder : IResultEncoder - { - public string MimeType => MimeTypes.Html; - - public EncodedData? Encode(object displayable) => - displayable is FailureRecord record - ? $@" -
-

- Contradiction reached: {record.Message} -

- - - - - - - - - - -
Actual{record.Actual}
Expected{record.Expected}
-
- ".ToEncodedData() - : (EncodedData?)null; - } - - public class FailureRecordToTextEncoder : IResultEncoder - { - public string MimeType => MimeTypes.PlainText; - - public EncodedData? Encode(object displayable) => - displayable is FailureRecord record - ? $"{record.Message}\n\tExpected:\t{record.Expected}\n\tActual:\t{record.Actual}".ToEncodedData() - : (EncodedData?)null; - } - public class DisplayableUnitaryOperatorToTextEncoder : IResultEncoder { private ILogger logger; @@ -95,6 +57,9 @@ IConfigurationSource configurationSource public EncodedData? Encode(object displayable) { + bool IsNearZero(double value) => + System.Math.Abs(value) <= configurationSource.TruncationThreshold; + if (displayable is DisplayableUnitaryOperator op) { if (op?.Data is null) @@ -102,6 +67,12 @@ IConfigurationSource configurationSource logger.LogError("Asked to encode a displayable unitary operator, but its data was null. This should not happen."); return null; } + + var precision = configurationSource.GetOptionOrDefault( + "dump.unitaryPrecision", + 3 + ); + var outputMatrix = String.Join( " \\\\\n", op.Data.EnumerateOverAxis().Cast().Select( @@ -109,7 +80,30 @@ IConfigurationSource configurationSource String.Join(" & ", row.EnumerateOverAxis() .Cast() - .Select(element => $"{element[0]} {(((double)element[1]) < 0 ? "-" : "+")} {System.Math.Abs((double)element[1])}i") + .Select(element => + { + var format = $"{{0:G{precision}}}"; + var re = (double)element[0]; + var im = (double)element[1]; + var reFmt = String.Format(format, re); + var imFmt = String.Format(format, System.Math.Abs(im)) + "i"; + if (IsNearZero(re) && IsNearZero(im)) + { + return "0"; + } + else if (IsNearZero(im)) + { + return reFmt; + } + else if (IsNearZero(re)) + { + return im < 0.0 ? $"-{imFmt}" : imFmt; + } + else + { + return $"{reFmt} {(im < 0.0 ? "-" : "+")} {imFmt}"; + } + }) ) ) ); diff --git a/Visualization/src/Extensions.cs b/Visualization/src/Extensions.cs index 771051da4e8..52ee8a793a4 100644 --- a/Visualization/src/Extensions.cs +++ b/Visualization/src/Extensions.cs @@ -29,7 +29,14 @@ internal static IEnumerable EnumerateOverAxis(this NumSharp.NDArray arra } } - + // TODO: remove once https://github.com/microsoft/iqsharp/pull/239 is + // resolved. + internal static T GetOptionOrDefault( + this IConfigurationSource configurationSource, string optionName, T defaultValue + ) => + configurationSource.Configuration.TryGetValue(optionName, out var token) + ? token.ToObject() ?? defaultValue + : defaultValue; } } diff --git a/Visualization/src/Visualization.csproj b/Visualization/src/Visualization.csproj index d0281235a7b..3aced349035 100644 --- a/Visualization/src/Visualization.csproj +++ b/Visualization/src/Visualization.csproj @@ -32,9 +32,9 @@ - + - + From c53349804e694705ee70c148217a45cdede58037 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Thu, 30 Jul 2020 14:52:58 -0700 Subject: [PATCH 14/32] Added new AllowAtMostNQubits. --- Standard/src/Diagnostics/Allows.qs | 31 ++++++- .../{Allows.cs => AllowOperationCalls.cs} | 0 .../Emulation/AllowQubitAllocations.cs | 85 +++++++++++++++++++ .../src/Diagnostics/Emulation/Extensions.cs | 15 ++++ 4 files changed, 128 insertions(+), 3 deletions(-) rename Standard/src/Diagnostics/Emulation/{Allows.cs => AllowOperationCalls.cs} (100%) create mode 100644 Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs diff --git a/Standard/src/Diagnostics/Allows.qs b/Standard/src/Diagnostics/Allows.qs index d934caa50b2..9c32d1ac688 100644 --- a/Standard/src/Diagnostics/Allows.qs +++ b/Standard/src/Diagnostics/Allows.qs @@ -2,9 +2,6 @@ // Licensed under the MIT License. namespace Microsoft.Quantum.Diagnostics { - open Microsoft.Quantum.Intrinsic; - open Microsoft.Quantum.Canon; - /// # Summary /// Between a call to this operation and its adjoint, asserts that @@ -40,4 +37,32 @@ namespace Microsoft.Quantum.Diagnostics { : Unit is Adj { } + /// # Summary + /// Between a call to this operation and its adjoint, asserts that + /// at most a given number of additional qubits are allocated with + /// using statements. + /// + /// # Input + /// ## nQubits + /// The maximum number of qubits that may be allocated. + /// + /// # Example + /// The following snippet will fail when executed on machines which + /// support this diagnostic: + /// ```Q# + /// within { + /// AllowAtMostNQubits(3); + /// } apply { + /// // Fails since this allocates four qubits. + /// using (register = Qubit[4]) { + /// } + /// } + /// ``` + /// + /// # Remarks + /// This operation may be replaced by a no-op on targets which do not + /// support it. + operation AllowAtMostNQubits(nQubits : Int) : Unit is Adj { + } + } diff --git a/Standard/src/Diagnostics/Emulation/Allows.cs b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs similarity index 100% rename from Standard/src/Diagnostics/Emulation/Allows.cs rename to Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs diff --git a/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs b/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs new file mode 100644 index 00000000000..11365ef0022 --- /dev/null +++ b/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Quantum.Diagnostics.Emulation; +using Microsoft.Quantum.Simulation.Common; +using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Simulation.Simulators; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Quantum.Diagnostics +{ + + public partial class AllowAtMostNQubits + { + public class Native : AllowAtMostNQubits + { + private SimulatorBase? Simulator; + + private static Stack<(IDisposable, IDisposable)> Handlers = + new Stack<(IDisposable, IDisposable)>(); + + public Native(IOperationFactory m) : base(m) + { + Simulator = m as SimulatorBase; + } + + public override Func Body => (_args) => + { + if (Simulator == null) return QVoid.Instance; + + var nQubitsAllowed = _args; + var nQubitsAllocated = 0L; + + Handlers.Push(( + new ActionDisposer>( + nQubits => + { + nQubitsAllocated += nQubits; + if (nQubitsAllocated > nQubitsAllowed) + { + throw new ExecutionFailException( + $"{nQubitsAllocated} were allocated, but at most {nQubitsAllowed} are allowed." + ); + } + }, + setup: handler => Simulator.OnAllocateQubits += handler, + cleanup: handler => Simulator.OnAllocateQubits -= handler + ), + + new ActionDisposer>>( + register => + { + nQubitsAllocated -= register.Length; + }, + setup: handler => Simulator.OnReleaseQubits += handler, + cleanup: handler => Simulator.OnReleaseQubits -= handler + ) + )); + + return QVoid.Instance; + }; + + public override Func AdjointBody => (_args) => + { + if (Simulator == null) return QVoid.Instance; + + var (start, end) = Handlers.Pop(); + start.Dispose(); + end.Dispose(); + + return QVoid.Instance; + }; + } + + } + +} diff --git a/Standard/src/Diagnostics/Emulation/Extensions.cs b/Standard/src/Diagnostics/Emulation/Extensions.cs index 198a4c2ca06..c0b146fdb9c 100644 --- a/Standard/src/Diagnostics/Emulation/Extensions.cs +++ b/Standard/src/Diagnostics/Emulation/Extensions.cs @@ -38,6 +38,21 @@ public void Dispose() } } + internal class ActionDisposer : IDisposable + { + private Action cleanup; + private TData data; + public ActionDisposer(TData data, Action setup, Action cleanup) + { + this.data = data; + this.cleanup = cleanup; + setup(data); + } + + public void Dispose() => + cleanup(data); + } + internal static class Extensions { internal static SimulatorEventDisposer RegisterOperationHandlers( From 43b2c60b5faef547cd2f4c037ba06fa20bf3b020 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Thu, 30 Jul 2020 16:07:22 -0700 Subject: [PATCH 15/32] Added note about global phase. --- Standard/src/Diagnostics/Dump.qs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Standard/src/Diagnostics/Dump.qs b/Standard/src/Diagnostics/Dump.qs index 597ff7c7a33..f19eedb6499 100644 --- a/Standard/src/Diagnostics/Dump.qs +++ b/Standard/src/Diagnostics/Dump.qs @@ -40,6 +40,10 @@ namespace Microsoft.Quantum.Diagnostics { /// dependent on the current execution target and editor environment. /// For example, when used on the full-state quantum simulator, /// a unitary matrix used to represent `op` is displayed. + /// + /// Note that, when run on simulators that admit a global phase ambiguity + /// (e.g.: the full-state simulator), returned representations may vary + /// up to a global phase. operation DumpOperation(nQubits : Int, op : (Qubit[] => Unit is Adj)) : Unit { using ((reference, target) = (Qubit[nQubits], Qubit[nQubits])) { From e816dc8172841ae540256c45dd5d50c46ebf686e Mon Sep 17 00:00:00 2001 From: Chris Granade Date: Fri, 31 Jul 2020 09:21:24 -0700 Subject: [PATCH 16/32] Apply suggestions from code review Co-authored-by: Mathias Soeken --- Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs | 6 +++--- Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs | 4 ++-- Standard/src/Diagnostics/Emulation/Internal.cs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs index 7574104628a..36f5d39471f 100644 --- a/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs +++ b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs @@ -34,11 +34,11 @@ public Native(IOperationFactory m) : base(m) Simulator = m as SimulatorBase; } - public override Func<(long, IUnitary), QVoid> Body => (_args) => + public override Func<(long, IUnitary), QVoid> Body => _args => { if (Simulator == null) return QVoid.Instance; - (var nTimes, var op) = _args; + var (nTimes, op) = _args; var callStack = ImmutableStack.Empty; var callSites = ImmutableList>.Empty; @@ -91,7 +91,7 @@ bool IsSelf(ICallable callable) => return QVoid.Instance; }; - public override Func<(long, IUnitary), QVoid> AdjointBody => (_args) => + public override Func<(long, IUnitary), QVoid> AdjointBody => _args => { if (Simulator == null) return QVoid.Instance; diff --git a/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs b/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs index 11365ef0022..971b7661687 100644 --- a/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs +++ b/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs @@ -32,7 +32,7 @@ public Native(IOperationFactory m) : base(m) Simulator = m as SimulatorBase; } - public override Func Body => (_args) => + public override Func Body => _args => { if (Simulator == null) return QVoid.Instance; @@ -68,7 +68,7 @@ public Native(IOperationFactory m) : base(m) return QVoid.Instance; }; - public override Func AdjointBody => (_args) => + public override Func AdjointBody => _args => { if (Simulator == null) return QVoid.Instance; diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index afcd8eec534..b21375af4b2 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -37,7 +37,7 @@ public override bool Dump(IQArray? qubits = null) var count = qubits == null ? this.Simulator.QubitManager!.GetAllocatedQubitsCount() : qubits.Length; - var nQubitsPerRegister = ((int) count / 2); + var nQubitsPerRegister = ((int)count / 2); Data = np.empty(new Shape(1 << ((int)count), 2)); var result = base.Dump(qubits); @@ -90,4 +90,4 @@ private QVoid DumpUnitaryFromChoiState(QuantumSimulator simulator, IQArray Date: Wed, 5 Aug 2020 14:48:53 -0700 Subject: [PATCH 17/32] More C# doc comments. --- .../Diagnostics/Emulation/DataStructures.cs | 34 +++++++++++++++++++ .../src/Diagnostics/Emulation/Extensions.cs | 9 ++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Standard/src/Diagnostics/Emulation/DataStructures.cs b/Standard/src/Diagnostics/Emulation/DataStructures.cs index 6606671de0b..3661e7e1f22 100644 --- a/Standard/src/Diagnostics/Emulation/DataStructures.cs +++ b/Standard/src/Diagnostics/Emulation/DataStructures.cs @@ -11,15 +11,49 @@ namespace Microsoft.Quantum.Diagnostics.Emulation { + /// + /// Represents a unitary operator intended for use as a diagnostic + /// display. + /// public class DisplayableUnitaryOperator { + /// + /// The qubits on which the represented operator acts, or + /// null if there is no specific register associated with + /// this operator. + /// public IList? Qubits { get; set; } + + /// + /// An array of matrix elements for the given unitary operator. + /// + /// + /// For ease of use, this array has a dtype of double, and + /// shape (dim, dim, 2), where dim is the dimension + /// of the represented unitary operator (i.e.: 2^nQubits), and + /// where the last axis represents the real (index 0) and + /// imaginary parts, respectively. + /// public NumSharp.NDArray? Data { get; set; } } + /// + /// A diagnostic record of sites where a given operation or function + /// was called. + /// public struct CallSites { + /// + /// The name of the operation or function whose calls are + /// represented by this record. + /// public string Subject { get; set; } + + /// + /// A collection of calls to the given operation or function, each + /// represented as a call stack at the point where the subject was + /// called. + /// public ImmutableList> Sites { get; set; } } } diff --git a/Standard/src/Diagnostics/Emulation/Extensions.cs b/Standard/src/Diagnostics/Emulation/Extensions.cs index c0b146fdb9c..003894815ee 100644 --- a/Standard/src/Diagnostics/Emulation/Extensions.cs +++ b/Standard/src/Diagnostics/Emulation/Extensions.cs @@ -11,6 +11,10 @@ namespace Microsoft.Quantum.Diagnostics.Emulation { + /// + /// Attaches events to a + /// instance, allowing for events to be removed with a disposable pattern. + /// internal class SimulatorEventDisposer : IDisposable { private SimulatorBase Simulator; @@ -32,7 +36,6 @@ Action endOperation public void Dispose() { - System.Console.WriteLine("Removing events."); Simulator.OnOperationStart -= StartOperation; Simulator.OnOperationEnd -= EndOperation; } @@ -55,6 +58,10 @@ public void Dispose() => internal static class Extensions { + /// + /// Attaches given event handlers to a simulator, returning a + /// disposable object that removes handlers when disposed. + /// internal static SimulatorEventDisposer RegisterOperationHandlers( this SimulatorBase simulator, Action startOperation, From 92ece3c151df648647c46f749ba39ec80a621ba0 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Wed, 5 Aug 2020 15:15:17 -0700 Subject: [PATCH 18/32] Q# API documentation improvements. --- Standard/src/Diagnostics/Asserts.qs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Standard/src/Diagnostics/Asserts.qs b/Standard/src/Diagnostics/Asserts.qs index 2484c0f5dc6..acf699987f8 100644 --- a/Standard/src/Diagnostics/Asserts.qs +++ b/Standard/src/Diagnostics/Asserts.qs @@ -9,10 +9,11 @@ namespace Microsoft.Quantum.Diagnostics { /// # Summary /// Asserts that the phase of an equal superposition state has the expected value. /// - /// Specifically, asserts that the phase $\phi$ of a quantum state + /// # Description + /// This operation asserts that the phase $\phi$ of a quantum state /// that may be expressed as /// $\frac{e^{i t}}{\sqrt{2}}(e^{i\phi}\ket{0} + e^{-i\phi}\ket{1})$ - /// for some arbitrary real t has the expected value. + /// for some arbitrary real $t$ has the expected value. /// /// # Input /// ## expected From 91427f8a2f8026ce6e71c99a42d7b3dfcdbe7e52 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Thu, 6 Aug 2020 11:21:40 -0700 Subject: [PATCH 19/32] Add unit tests. --- Standard/tests/AssertTests.qs | 28 ++++++----- Standard/tests/Diagnostics/AllowTests.qs | 57 +++++++++++++++++++++++ Standard/tests/Diagnostics/DumpTests.cs | 59 ++++++++++++++++++++++++ Standard/tests/Diagnostics/DumpTests.qs | 13 ++++++ Standard/tests/QcvvTests.cs | 5 +- Standard/tests/SimulatorTestTargets.cs | 2 +- 6 files changed, 147 insertions(+), 17 deletions(-) create mode 100644 Standard/tests/Diagnostics/AllowTests.qs create mode 100644 Standard/tests/Diagnostics/DumpTests.cs create mode 100644 Standard/tests/Diagnostics/DumpTests.qs diff --git a/Standard/tests/AssertTests.qs b/Standard/tests/AssertTests.qs index a74151265e2..30e8eb2ea76 100644 --- a/Standard/tests/AssertTests.qs +++ b/Standard/tests/AssertTests.qs @@ -10,43 +10,43 @@ namespace Microsoft.Quantum.Tests { // This file contains very simple tests that should trivially pass // with the intent of testing the assert and testing harness mechanisms themselves. - operation EmptyTest () : Unit { } + operation EmptyTest() : Unit { } - operation PreparationTest () : Unit { + operation PreparationTest() : Unit { using (qubit = Qubit()) { Diag.AssertMeasurementProbability([PauliZ], [qubit], Zero, 1.0, $"Freshly prepared qubit was not in |0〉 state.", 1E-10); } } - operation OperationTestShouldFail () : Unit { + operation OperationTestShouldFail() : Unit { fail $"OK"; } - function FunctionTestShouldFail () : Unit { + function FunctionTestShouldFail() : Unit { fail $"OK"; } - function AssertEqualTestShouldFail () : Unit { + function AssertEqualTestShouldFail() : Unit { Diag.NearEqualityFactD(1.0, 0.0); } - function AssertBoolArrayEqualTestShouldFail () : Unit { + function AssertBoolArrayEqualTestShouldFail() : Unit { Diag.AllEqualityFactB([true, false], [false, true], $"OK"); } - function AssertBoolEqualTestShouldFail () : Unit { + function AssertBoolEqualTestShouldFail() : Unit { Diag.EqualityFactB(true, false, $"OK"); } - function EqualityFactRTestShouldFail () : Unit { + function EqualityFactRTestShouldFail() : Unit { Diag.EqualityFactR(Zero, One, $"OK"); } - function EqualityFactITestShouldFail () : Unit { + function EqualityFactITestShouldFail() : Unit { Diag.EqualityFactI(12, 42, $"OK"); } @@ -56,7 +56,7 @@ namespace Microsoft.Quantum.Tests { /// These tests are already performed in Solid itself, such that /// this operation tests whether we can reproduce that using our /// operation equality assertions. - operation SelfAdjointOperationsTest () : Unit { + operation SelfAdjointOperationsTest() : Unit { for (op in [I, X, Y, Z, H]) { Diag.AssertOperationsEqualReferenced(3, ApplyToEach(op, _), ApplyToEachA(op, _)); } @@ -69,7 +69,7 @@ namespace Microsoft.Quantum.Tests { /// /// # Remarks /// Marked as ex-fail due to known issues with Bound. - operation BindSelfAdjointOperationsTestExFail () : Unit { + operation BindSelfAdjointOperationsTestExFail() : Unit { for (op in [I, X, Y, Z, H]) { let arr = [op, Adjoint op]; let bound = BoundCA(arr); @@ -78,8 +78,7 @@ namespace Microsoft.Quantum.Tests { } - operation AssertProbIntTest () : Unit { - + operation AssertProbIntTest() : Unit { let theta = 0.123; let prob = 0.015052858190174602; let tolerance = 1E-09; @@ -95,8 +94,7 @@ namespace Microsoft.Quantum.Tests { } - operation AssertPhaseTest () : Unit { - + operation AssertPhaseTest() : Unit { let phase = 0.456; let tolerance = 1E-09; diff --git a/Standard/tests/Diagnostics/AllowTests.qs b/Standard/tests/Diagnostics/AllowTests.qs new file mode 100644 index 00000000000..71f007c090a --- /dev/null +++ b/Standard/tests/Diagnostics/AllowTests.qs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Diagnostics as Diag; + + operation CheckAllowNCallsTestShouldFail() : Unit { + within { + Diag.AllowAtMostNCallsCA(3, X); + } apply { + using (q = Qubit()) { + // Should run four times, one more + // than the three allowed. + for (idx in 0..3) { + X(q); + } + } + } + } + + @Diag.Test("QuantumSimulator") + operation CheckAllowNCalls() : Unit { + within { + Diag.AllowAtMostNCallsCA(4, X); + } apply { + using (q = Qubit()) { + // Should run four times, exactly as + // many times as allowed. + for (idx in 0..3) { + X(q); + } + } + } + } + + operation CheckAllowNQubitsTestShouldFail() : Unit { + within { + Diag.AllowAtMostNQubits(3); + } apply { + using (qs = Qubit[2]) { + using (qs2 = Qubit[1]) { } + using (qs2 = Qubit[2]) { } + } + } + } + + @Diag.Test("QuantumSimulator") + operation CheckAllowNQubits() : Unit { + within { + Diag.AllowAtMostNQubits(3); + } apply { + using (qs = Qubit[3]) { } + } + } + +} diff --git a/Standard/tests/Diagnostics/DumpTests.cs b/Standard/tests/Diagnostics/DumpTests.cs new file mode 100644 index 00000000000..eae7f6cecfe --- /dev/null +++ b/Standard/tests/Diagnostics/DumpTests.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.Quantum.Diagnostics.Emulation; +using Microsoft.Quantum.Intrinsic; +using Microsoft.Quantum.Simulation; +using Microsoft.Quantum.Simulation.Common; +using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Simulation.Simulators; +using Microsoft.Quantum.Standard.Emulation; +using Xunit; +using Assert = Xunit.Assert; + +namespace Microsoft.Quantum.Tests +{ + public class DumpOperation + { + [Fact] + public void DumpSReturnsCorrectMatrix() + { + using var sim = new QuantumSimulator(); + var diagnostics = new List(); + sim.OnDisplayableDiagnostic += diagnostic => + { + diagnostics.Add(diagnostic); + }; + sim.DisableLogToConsole(); + + DumpS.Run(sim).Wait(); + + Assert.Equal(diagnostics.Count, 1); + var diagnostic = diagnostics.Single(); + + Assert.IsType(diagnostic); + var unitary = diagnostic as DisplayableUnitaryOperator; + + Assert.NotNull(unitary); + Assert.Equal(1, unitary.Qubits?.Count); + Assert.NotNull(unitary.Data); + Assert.Equal(3, unitary.Data.ndim); + Assert.Equal(2, unitary.Data.shape[0]); + Assert.Equal(2, unitary.Data.shape[1]); + Assert.Equal(2, unitary.Data.shape[2]); + // Check that the matrix is [1 0; 0 𝑖]. + Assert.Equal(1.0, (double)unitary.Data[0, 0, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 1, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 0, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 1, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 0, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 1, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 0, 1], precision: 6); + Assert.Equal(1.0, (double)unitary.Data[1, 1, 1], precision: 6); + } + } +} diff --git a/Standard/tests/Diagnostics/DumpTests.qs b/Standard/tests/Diagnostics/DumpTests.qs new file mode 100644 index 00000000000..0b30169969b --- /dev/null +++ b/Standard/tests/Diagnostics/DumpTests.qs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Tests { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Diagnostics as Diag; + + operation DumpS() : Unit { + Diag.DumpOperation(1, ApplyToEachCA(S, _)); + } + +} diff --git a/Standard/tests/QcvvTests.cs b/Standard/tests/QcvvTests.cs index fc36a0857af..f3ce3386779 100644 --- a/Standard/tests/QcvvTests.cs +++ b/Standard/tests/QcvvTests.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; using System.Linq; using System.Runtime.InteropServices; diff --git a/Standard/tests/SimulatorTestTargets.cs b/Standard/tests/SimulatorTestTargets.cs index 0ed1d8d3f5e..c49bea1de67 100644 --- a/Standard/tests/SimulatorTestTargets.cs +++ b/Standard/tests/SimulatorTestTargets.cs @@ -58,7 +58,7 @@ public void QuantumSimulatorTarget(TestOperation opData) opData.TestOperationRunner(sim); } } - catch( System.BadImageFormatException e ) + catch (System.BadImageFormatException e) { throw new System.BadImageFormatException($"Could not load Quantum Simulator. If you are running tests using Visual Studio 2017, " + $"this problem can be fixed by using menu Test > Test Settings > Default Processor Architecture " + From cd70b4be4cab01cb65d7d150c1eaefa1d6cc2d53 Mon Sep 17 00:00:00 2001 From: Chris Granade Date: Mon, 10 Aug 2020 08:25:04 -0700 Subject: [PATCH 20/32] Apply suggestions from code review Co-authored-by: Mathias Soeken --- Standard/src/Diagnostics/Emulation/Internal.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Standard/src/Diagnostics/Emulation/Internal.cs b/Standard/src/Diagnostics/Emulation/Internal.cs index b21375af4b2..04f30c91316 100644 --- a/Standard/src/Diagnostics/Emulation/Internal.cs +++ b/Standard/src/Diagnostics/Emulation/Internal.cs @@ -21,7 +21,6 @@ internal class ArrayDumper : QuantumSimulator.StateDumper internal NumSharp.NDArray? Data = null; public ArrayDumper(QuantumSimulator sim) : base(sim) { - } public override bool Callback(uint idx, double real, double img) @@ -34,9 +33,7 @@ public override bool Callback(uint idx, double real, double img) public override bool Dump(IQArray? qubits = null) { - var count = qubits == null - ? this.Simulator.QubitManager!.GetAllocatedQubitsCount() - : qubits.Length; + var count = qubits?.Length ?? Simulator.QubitManager!.GetAllocatedQubitsCount(); var nQubitsPerRegister = ((int)count / 2); Data = np.empty(new Shape(1 << ((int)count), 2)); var result = base.Dump(qubits); @@ -76,7 +73,7 @@ private QVoid DumpUnitaryFromChoiState(QuantumSimulator simulator, IQArray, IQArray), QVoid> Body => (__in__) => + public override Func<(IQArray, IQArray), QVoid> Body => __in__ => { var (reference, target) = __in__; return Simulator switch From 133bc3e6db109afaa2b84dcca799d41ada5b4172 Mon Sep 17 00:00:00 2001 From: Chris Granade Date: Mon, 10 Aug 2020 08:25:31 -0700 Subject: [PATCH 21/32] Update Standard/src/Diagnostics/Emulation/Extensions.cs Co-authored-by: Mathias Soeken --- Standard/src/Diagnostics/Emulation/Extensions.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Standard/src/Diagnostics/Emulation/Extensions.cs b/Standard/src/Diagnostics/Emulation/Extensions.cs index 003894815ee..867bc7395ca 100644 --- a/Standard/src/Diagnostics/Emulation/Extensions.cs +++ b/Standard/src/Diagnostics/Emulation/Extensions.cs @@ -69,9 +69,7 @@ internal static SimulatorEventDisposer RegisterOperationHandlers( ) => new SimulatorEventDisposer( simulator, startOperation, - endOperation == null - ? (callable, data) => {} - : endOperation + endOperation ?? (callable, data) => {} ); } } From 8378de409e8ca5d05143d8f1eb149cc5d219dfef Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Mon, 10 Aug 2020 10:52:08 -0700 Subject: [PATCH 22/32] Fix syntax error. --- Standard/src/Diagnostics/Emulation/Extensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Standard/src/Diagnostics/Emulation/Extensions.cs b/Standard/src/Diagnostics/Emulation/Extensions.cs index 867bc7395ca..d02525b5e46 100644 --- a/Standard/src/Diagnostics/Emulation/Extensions.cs +++ b/Standard/src/Diagnostics/Emulation/Extensions.cs @@ -69,7 +69,7 @@ internal static SimulatorEventDisposer RegisterOperationHandlers( ) => new SimulatorEventDisposer( simulator, startOperation, - endOperation ?? (callable, data) => {} + endOperation ?? ((callable, data) => {}) ); } } From 081d7485b24dfeddccd4b6bfadee25c91249b0d3 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Mon, 10 Aug 2020 10:52:24 -0700 Subject: [PATCH 23/32] Make Key static readonly. --- Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs index 36f5d39471f..62461d1e1de 100644 --- a/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs +++ b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs @@ -27,7 +27,7 @@ public class Native : AllowAtMostNCallsCA<__TInput__, __TOutput__> private static Dictionary<(Type, Type), Stack> Handlers = new Dictionary<(Type, Type), Stack>(); - private readonly (Type, Type) Key = (typeof(__TInput__), typeof(__TOutput__)); + private static readonly (Type, Type) Key = (typeof(__TInput__), typeof(__TOutput__)); public Native(IOperationFactory m) : base(m) { From b7742fa1fe22d7d44a1e09745ecb48cc4eb2edf5 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Mon, 10 Aug 2020 10:55:16 -0700 Subject: [PATCH 24/32] More C# docs. --- Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs index 62461d1e1de..2bdb4681a27 100644 --- a/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs +++ b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs @@ -50,6 +50,9 @@ public Native(IOperationFactory m) : base(m) bool IsSelf(ICallable callable) => callable.FullName == "Microsoft.Quantum.Diagnostics.AllowAtMostNCallsCA"; + // Record whether or not the condition checked by this allow + // has failed, so that we can property unwind in the endOperation + // handler below. var failed = false; Handlers[Key].Push(Simulator.RegisterOperationHandlers( @@ -77,6 +80,9 @@ bool IsSelf(ICallable callable) => endOperation: (callable, data) => { + // Ignore call stack entries that happen after we've + // failed, or that are generated by ending the + // condition itself. if (failed || IsSelf(callable)) return; try { From e8f09c5c9d1a3c9623cfd5939c9ff11e9be706d9 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Mon, 10 Aug 2020 10:58:02 -0700 Subject: [PATCH 25/32] Modify to use switch expressions. --- Visualization/src/CallSiteEncoders.cs | 39 +++++++++++---------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/Visualization/src/CallSiteEncoders.cs b/Visualization/src/CallSiteEncoders.cs index 6520d2aa3ed..35b3f246e36 100644 --- a/Visualization/src/CallSiteEncoders.cs +++ b/Visualization/src/CallSiteEncoders.cs @@ -24,24 +24,21 @@ public CallSitesToTextEncoder(ILogger logger) this.logger = logger; } - public EncodedData? Encode(object displayable) + public EncodedData? Encode(object displayable) => displayable switch { - if (displayable is CallSites sites) - { - var list = String.Join("\n---\n", - sites.Sites.Select( - call => String.Join("\n", - call.Select( - frame => $"- {frame}" + CallSites sites => $@"Calls to {sites.Subject}:\n\n{ + String.Join("\n---\n", + sites.Sites.Select( + call => String.Join("\n", + call.Select( + frame => $"- {frame}" + ) ) ) ) - ); - return $"Calls to {sites.Subject}:\n\n{list}".ToEncodedData(); - } - else return null; - } - + }".ToEncodedData(), + _ => null + }; } public class CallSitesToHtmlEncoder : IResultEncoder @@ -59,12 +56,9 @@ IConfigurationSource configurationSource this.configurationSource = configurationSource; } - public EncodedData? Encode(object displayable) + public EncodedData? Encode(object displayable) => displayable switch { - if (displayable is CallSites sites) - { - logger.LogDebug("Using HTML encoder to output call site record."); - return $@" + CallSites sites => $@"
Calls to {sites.Subject}:
    { @@ -81,10 +75,9 @@ IConfigurationSource configurationSource ) }
- ".ToEncodedData(); - } - else return null; - } + ".ToEncodedData(), + _ => null + }; } From 3b5551908f85baac35584982248d334c12bb2b43 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Mon, 17 Aug 2020 21:58:03 -0700 Subject: [PATCH 26/32] Addressing feedback. --- Chemistry/src/Runtime/Runtime.csproj | 4 +- .../tests/ChemistryTests/QSharpTests.csproj | 2 +- .../tests/SystemTests/SystemTests.csproj | 2 +- MachineLearning/src/MachineLearning.csproj | 2 +- .../tests/MachineLearningTests.csproj | 2 +- Numerics/src/Numerics.csproj | 4 +- Numerics/tests/NumericsTests.csproj | 2 +- Standard/src/Standard.csproj | 4 +- Standard/tests/Diagnostics/DumpTests.cs | 65 +++++++++++++++++++ Standard/tests/Diagnostics/DumpTests.qs | 8 +++ Standard/tests/Standard.Tests.csproj | 2 +- Visualization/src/Extensions.cs | 9 --- Visualization/src/Visualization.csproj | 4 +- 13 files changed, 87 insertions(+), 23 deletions(-) diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index 92dc5f2710d..6373a3bff3e 100644 --- a/Chemistry/src/Runtime/Runtime.csproj +++ b/Chemistry/src/Runtime/Runtime.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -36,7 +36,7 @@ - + diff --git a/Chemistry/tests/ChemistryTests/QSharpTests.csproj b/Chemistry/tests/ChemistryTests/QSharpTests.csproj index cd318f77261..258662bd8e1 100644 --- a/Chemistry/tests/ChemistryTests/QSharpTests.csproj +++ b/Chemistry/tests/ChemistryTests/QSharpTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Chemistry/tests/SystemTests/SystemTests.csproj b/Chemistry/tests/SystemTests/SystemTests.csproj index d3a188dbb4e..42c31e5964b 100644 --- a/Chemistry/tests/SystemTests/SystemTests.csproj +++ b/Chemistry/tests/SystemTests/SystemTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/MachineLearning/src/MachineLearning.csproj b/MachineLearning/src/MachineLearning.csproj index 3034629c8df..351e9615ea5 100644 --- a/MachineLearning/src/MachineLearning.csproj +++ b/MachineLearning/src/MachineLearning.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 Microsoft.Quantum.MachineLearning diff --git a/MachineLearning/tests/MachineLearningTests.csproj b/MachineLearning/tests/MachineLearningTests.csproj index efda9c28acb..37a2f9c7fa6 100644 --- a/MachineLearning/tests/MachineLearningTests.csproj +++ b/MachineLearning/tests/MachineLearningTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Numerics/src/Numerics.csproj b/Numerics/src/Numerics.csproj index c7c75fd281c..d18dd45bb63 100644 --- a/Numerics/src/Numerics.csproj +++ b/Numerics/src/Numerics.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -40,7 +40,7 @@ - + diff --git a/Numerics/tests/NumericsTests.csproj b/Numerics/tests/NumericsTests.csproj index 750cba665be..06bf7b26d1d 100644 --- a/Numerics/tests/NumericsTests.csproj +++ b/Numerics/tests/NumericsTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index a5481519982..93d78493975 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -30,7 +30,7 @@ - + diff --git a/Standard/tests/Diagnostics/DumpTests.cs b/Standard/tests/Diagnostics/DumpTests.cs index eae7f6cecfe..11827dccae5 100644 --- a/Standard/tests/Diagnostics/DumpTests.cs +++ b/Standard/tests/Diagnostics/DumpTests.cs @@ -55,5 +55,70 @@ public void DumpSReturnsCorrectMatrix() Assert.Equal(0.0, (double)unitary.Data[1, 0, 1], precision: 6); Assert.Equal(1.0, (double)unitary.Data[1, 1, 1], precision: 6); } + + + [Fact] + public void DumpCnotReturnsCorrectMatrix() + { + using var sim = new QuantumSimulator(); + var diagnostics = new List(); + sim.OnDisplayableDiagnostic += diagnostic => + { + diagnostics.Add(diagnostic); + }; + sim.DisableLogToConsole(); + + DumpCnot.Run(sim).Wait(); + + Assert.Equal(diagnostics.Count, 1); + var diagnostic = diagnostics.Single(); + + Assert.IsType(diagnostic); + var unitary = diagnostic as DisplayableUnitaryOperator; + + Assert.NotNull(unitary); + Assert.Equal(2, unitary.Qubits?.Count); + Assert.NotNull(unitary.Data); + Assert.Equal(3, unitary.Data.ndim); + Assert.Equal(4, unitary.Data.shape[0]); + Assert.Equal(4, unitary.Data.shape[1]); + Assert.Equal(2, unitary.Data.shape[2]); + // Check that the matrix is [1 0 0 0; 0 0 0 1; 0 0 1 0; 0 1 0 0]. + // real + Assert.Equal(1.0, (double)unitary.Data[0, 0, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 1, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 2, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 3, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 0, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 1, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 2, 0], precision: 6); + Assert.Equal(1.0, (double)unitary.Data[1, 3, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[2, 0, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[2, 1, 0], precision: 6); + Assert.Equal(1.0, (double)unitary.Data[2, 2, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[2, 3, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[3, 0, 0], precision: 6); + Assert.Equal(1.0, (double)unitary.Data[3, 1, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[3, 2, 0], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[3, 3, 0], precision: 6); + + // imaginary + Assert.Equal(0.0, (double)unitary.Data[0, 0, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 1, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 2, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[0, 3, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 0, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 1, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 2, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[1, 3, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[2, 0, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[2, 1, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[2, 2, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[2, 3, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[3, 0, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[3, 1, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[3, 2, 1], precision: 6); + Assert.Equal(0.0, (double)unitary.Data[3, 3, 1], precision: 6); + } } } diff --git a/Standard/tests/Diagnostics/DumpTests.qs b/Standard/tests/Diagnostics/DumpTests.qs index 0b30169969b..4940b04ca26 100644 --- a/Standard/tests/Diagnostics/DumpTests.qs +++ b/Standard/tests/Diagnostics/DumpTests.qs @@ -10,4 +10,12 @@ namespace Microsoft.Quantum.Tests { Diag.DumpOperation(1, ApplyToEachCA(S, _)); } + operation ApplyCnotToRegister(register : Qubit[]) : Unit is Adj + Ctl { + CNOT(register[0], register[1]); + } + + operation DumpCnot() : Unit { + Diag.DumpOperation(2, ApplyCnotToRegister); + } + } diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index ec83cb33df2..56b6a84ad56 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Visualization/src/Extensions.cs b/Visualization/src/Extensions.cs index 52ee8a793a4..5bacbdd3c3a 100644 --- a/Visualization/src/Extensions.cs +++ b/Visualization/src/Extensions.cs @@ -28,15 +28,6 @@ internal static IEnumerable EnumerateOverAxis(this NumSharp.NDArray arra yield return array[slice]; } } - - // TODO: remove once https://github.com/microsoft/iqsharp/pull/239 is - // resolved. - internal static T GetOptionOrDefault( - this IConfigurationSource configurationSource, string optionName, T defaultValue - ) => - configurationSource.Configuration.TryGetValue(optionName, out var token) - ? token.ToObject() ?? defaultValue - : defaultValue; } } diff --git a/Visualization/src/Visualization.csproj b/Visualization/src/Visualization.csproj index 3aced349035..c9250f4e0c5 100644 --- a/Visualization/src/Visualization.csproj +++ b/Visualization/src/Visualization.csproj @@ -32,9 +32,9 @@ - + - + From 004805b0b2918d624c1c526455a546a3b3d6cb96 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Mon, 17 Aug 2020 22:48:23 -0700 Subject: [PATCH 27/32] Add override for ToString. --- Standard/src/Diagnostics/Emulation/DataStructures.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Standard/src/Diagnostics/Emulation/DataStructures.cs b/Standard/src/Diagnostics/Emulation/DataStructures.cs index 3661e7e1f22..b0d06b997ec 100644 --- a/Standard/src/Diagnostics/Emulation/DataStructures.cs +++ b/Standard/src/Diagnostics/Emulation/DataStructures.cs @@ -35,6 +35,11 @@ public class DisplayableUnitaryOperator /// imaginary parts, respectively. /// public NumSharp.NDArray? Data { get; set; } + + public override ToString() => + Data == null + ? "" + : $"Real:\n{Data[Ellipsis, 0]}\nImag:\n{Data[Ellipsis, 1]}"; } /// From 263c496bce704a3e9064c3818efffd33633916b9 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 18 Aug 2020 09:29:19 -0700 Subject: [PATCH 28/32] Fix ToString. --- Standard/src/Diagnostics/Emulation/DataStructures.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Standard/src/Diagnostics/Emulation/DataStructures.cs b/Standard/src/Diagnostics/Emulation/DataStructures.cs index b0d06b997ec..ec16fa62fe3 100644 --- a/Standard/src/Diagnostics/Emulation/DataStructures.cs +++ b/Standard/src/Diagnostics/Emulation/DataStructures.cs @@ -36,7 +36,7 @@ public class DisplayableUnitaryOperator /// public NumSharp.NDArray? Data { get; set; } - public override ToString() => + public override string ToString() => Data == null ? "" : $"Real:\n{Data[Ellipsis, 0]}\nImag:\n{Data[Ellipsis, 1]}"; From 807e46ce7e9a43bfc0d6a7a4fe70aae97960a6a0 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 18 Aug 2020 09:40:28 -0700 Subject: [PATCH 29/32] Expanded doccomment. --- Standard/src/Diagnostics/Dump.qs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Standard/src/Diagnostics/Dump.qs b/Standard/src/Diagnostics/Dump.qs index f19eedb6499..0bb9e13ddd9 100644 --- a/Standard/src/Diagnostics/Dump.qs +++ b/Standard/src/Diagnostics/Dump.qs @@ -34,6 +34,30 @@ namespace Microsoft.Quantum.Diagnostics { /// } /// ``` /// + /// # Example + /// When run on the quantum simulator target, the following snippet will + /// output the matrix + /// $$ + /// \begin{aligned} + /// \left(\begin{matrix} + /// 1 & 0 & 0 & 0 \\\\ + /// 0 & 0 & 0 & 1 \\\\ + /// 0 & 0 & 1 & 0 \\\\ + /// 0 & 1 & 0 & 0 + /// \end{matrix}\right) + /// \end{aligned}. + /// $$ + /// + /// ```Q# + /// operation ApplyCnotToRegister(register : Qubit[]) : Unit is Adj + Ctl { + /// CNOT(register[0], register[1]); + /// } + /// + /// operation DumpCnot() : Unit { + /// Diag.DumpOperation(2, ApplyCnotToRegister); + /// } + /// ``` + /// /// # Remarks /// Calling this operation has no observable effect from within /// Q#. The exact diagnostics that are displayed, if any, are @@ -44,6 +68,10 @@ namespace Microsoft.Quantum.Diagnostics { /// Note that, when run on simulators that admit a global phase ambiguity /// (e.g.: the full-state simulator), returned representations may vary /// up to a global phase. + /// + /// Similarly, the ordering of rows and columns matrix representations + /// may vary with the conventions used by each simulator supporting this + /// operation. operation DumpOperation(nQubits : Int, op : (Qubit[] => Unit is Adj)) : Unit { using ((reference, target) = (Qubit[nQubits], Qubit[nQubits])) { From f840bde178892d8ca14dc11227e096018a411205 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 18 Aug 2020 10:02:31 -0700 Subject: [PATCH 30/32] Add message input. --- Standard/src/Diagnostics/Allows.qs | 13 +++++++--- .../Emulation/AllowOperationCalls.cs | 8 +++--- .../Emulation/AllowQubitAllocations.cs | 8 +++--- .../Diagnostics/Emulation/DataStructures.cs | 1 + Standard/tests/Diagnostics/AllowTests.qs | 25 ++++++++++++++++--- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Standard/src/Diagnostics/Allows.qs b/Standard/src/Diagnostics/Allows.qs index 9c32d1ac688..201c86114e8 100644 --- a/Standard/src/Diagnostics/Allows.qs +++ b/Standard/src/Diagnostics/Allows.qs @@ -12,6 +12,8 @@ namespace Microsoft.Quantum.Diagnostics { /// The maximum number of times that `op` may be called. /// ## op /// An operation whose calls are to be restricted. + /// ## message + /// A message to be displayed upon failure. /// /// # Example /// The following snippet will fail when executed on machines which @@ -19,7 +21,7 @@ namespace Microsoft.Quantum.Diagnostics { /// ```Q# /// using (register = Qubit[4]) { /// within { - /// AllowAtMostNCallsCA(3, H); + /// AllowAtMostNCallsCA(3, H, "Too many calls to H."); /// } apply { /// // Fails since this calls H four times, rather than the /// // allowed maximum of three. @@ -32,7 +34,8 @@ namespace Microsoft.Quantum.Diagnostics { /// This operation may be replaced by a no-op on targets which do not /// support it. operation AllowAtMostNCallsCA<'TInput, 'TOutput>( - nTimes : Int, op : ('TInput => 'TOutput is Adj + Ctl) + nTimes : Int, op : ('TInput => 'TOutput is Adj + Ctl), + message : String ) : Unit is Adj { } @@ -45,13 +48,15 @@ namespace Microsoft.Quantum.Diagnostics { /// # Input /// ## nQubits /// The maximum number of qubits that may be allocated. + /// ## message + /// A message to be displayed upon failure. /// /// # Example /// The following snippet will fail when executed on machines which /// support this diagnostic: /// ```Q# /// within { - /// AllowAtMostNQubits(3); + /// AllowAtMostNQubits(3, "Too many qubits allocated."); /// } apply { /// // Fails since this allocates four qubits. /// using (register = Qubit[4]) { @@ -62,7 +67,7 @@ namespace Microsoft.Quantum.Diagnostics { /// # Remarks /// This operation may be replaced by a no-op on targets which do not /// support it. - operation AllowAtMostNQubits(nQubits : Int) : Unit is Adj { + operation AllowAtMostNQubits(nQubits : Int, message : String) : Unit is Adj { } } diff --git a/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs index 2bdb4681a27..f7c0b4509ef 100644 --- a/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs +++ b/Standard/src/Diagnostics/Emulation/AllowOperationCalls.cs @@ -34,11 +34,11 @@ public Native(IOperationFactory m) : base(m) Simulator = m as SimulatorBase; } - public override Func<(long, IUnitary), QVoid> Body => _args => + public override Func<(long, IUnitary, string), QVoid> Body => _args => { if (Simulator == null) return QVoid.Instance; - var (nTimes, op) = _args; + var (nTimes, op, message) = _args; var callStack = ImmutableStack.Empty; var callSites = ImmutableList>.Empty; @@ -72,7 +72,7 @@ bool IsSelf(ICallable callable) => }); failed = true; throw new ExecutionFailException( - $"Operation {op.FullName} was called more than the allowed {nTimes} times." + $"Operation {op.FullName} was called more than the allowed {nTimes} times:\n{message}" ); } } @@ -97,7 +97,7 @@ bool IsSelf(ICallable callable) => return QVoid.Instance; }; - public override Func<(long, IUnitary), QVoid> AdjointBody => _args => + public override Func<(long, IUnitary, string), QVoid> AdjointBody => _args => { if (Simulator == null) return QVoid.Instance; diff --git a/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs b/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs index 971b7661687..66c247dc5e3 100644 --- a/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs +++ b/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs @@ -32,11 +32,11 @@ public Native(IOperationFactory m) : base(m) Simulator = m as SimulatorBase; } - public override Func Body => _args => + public override Func<(long, string), QVoid> Body => _args => { if (Simulator == null) return QVoid.Instance; - var nQubitsAllowed = _args; + var (nQubitsAllowed, message) = _args; var nQubitsAllocated = 0L; Handlers.Push(( @@ -47,7 +47,7 @@ public Native(IOperationFactory m) : base(m) if (nQubitsAllocated > nQubitsAllowed) { throw new ExecutionFailException( - $"{nQubitsAllocated} were allocated, but at most {nQubitsAllowed} are allowed." + $"{nQubitsAllocated} were allocated, but at most {nQubitsAllowed} are allowed:\n{message}." ); } }, @@ -68,7 +68,7 @@ public Native(IOperationFactory m) : base(m) return QVoid.Instance; }; - public override Func AdjointBody => _args => + public override Func<(long, string), QVoid> AdjointBody => _args => { if (Simulator == null) return QVoid.Instance; diff --git a/Standard/src/Diagnostics/Emulation/DataStructures.cs b/Standard/src/Diagnostics/Emulation/DataStructures.cs index ec16fa62fe3..f0524045fe6 100644 --- a/Standard/src/Diagnostics/Emulation/DataStructures.cs +++ b/Standard/src/Diagnostics/Emulation/DataStructures.cs @@ -8,6 +8,7 @@ using Microsoft.Quantum.Simulation.Common; using Microsoft.Quantum.Simulation.Core; using Newtonsoft.Json; +using static NumSharp.Slice; namespace Microsoft.Quantum.Diagnostics.Emulation { diff --git a/Standard/tests/Diagnostics/AllowTests.qs b/Standard/tests/Diagnostics/AllowTests.qs index 71f007c090a..d91648257bd 100644 --- a/Standard/tests/Diagnostics/AllowTests.qs +++ b/Standard/tests/Diagnostics/AllowTests.qs @@ -7,7 +7,7 @@ namespace Microsoft.Quantum.Tests { operation CheckAllowNCallsTestShouldFail() : Unit { within { - Diag.AllowAtMostNCallsCA(3, X); + Diag.AllowAtMostNCallsCA(3, X, "Too many calls to X."); } apply { using (q = Qubit()) { // Should run four times, one more @@ -22,7 +22,7 @@ namespace Microsoft.Quantum.Tests { @Diag.Test("QuantumSimulator") operation CheckAllowNCalls() : Unit { within { - Diag.AllowAtMostNCallsCA(4, X); + Diag.AllowAtMostNCallsCA(4, X, "Too many calls to X."); } apply { using (q = Qubit()) { // Should run four times, exactly as @@ -34,9 +34,26 @@ namespace Microsoft.Quantum.Tests { } } + @Diag.Test("ToffoliSimulator") + operation CheckAllowNQubitsWithNestedCalls() : Unit { + // Here, the total number of allocated qubits exceeds our policy, + // but the number of thosse qubits allocated inside the policy + // condition is still OK such that this should pass. + using (outer = Qubit[4]) { + within { + Diag.AllowAtMostNQubits(5, "Too many additional qubit allocations."); + } apply { + using (qs = Qubit[2]) { + using (qs2 = Qubit[1]) { } + using (qs2 = Qubit[2]) { } + } + } + } + } + operation CheckAllowNQubitsTestShouldFail() : Unit { within { - Diag.AllowAtMostNQubits(3); + Diag.AllowAtMostNQubits(3, "Too many additional qubit allocations."); } apply { using (qs = Qubit[2]) { using (qs2 = Qubit[1]) { } @@ -48,7 +65,7 @@ namespace Microsoft.Quantum.Tests { @Diag.Test("QuantumSimulator") operation CheckAllowNQubits() : Unit { within { - Diag.AllowAtMostNQubits(3); + Diag.AllowAtMostNQubits(3, "Too many additional qubit allocations."); } apply { using (qs = Qubit[3]) { } } From 1b2bb12f319662ded5bd7a2f28f9f9229b0b4bb2 Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Tue, 18 Aug 2020 10:06:58 -0700 Subject: [PATCH 31/32] Addressing feedback. --- Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs b/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs index 66c247dc5e3..910ac6223c0 100644 --- a/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs +++ b/Standard/src/Diagnostics/Emulation/AllowQubitAllocations.cs @@ -47,7 +47,7 @@ public Native(IOperationFactory m) : base(m) if (nQubitsAllocated > nQubitsAllowed) { throw new ExecutionFailException( - $"{nQubitsAllocated} were allocated, but at most {nQubitsAllowed} are allowed:\n{message}." + $"{nQubitsAllocated} qubit(s) were allocated, but at most {nQubitsAllowed} qubit(s) are allowed:\n{message}." ); } }, From 0b6747886f5bb4c29fcc6fa5623c259f3c477ead Mon Sep 17 00:00:00 2001 From: Christopher Granade Date: Wed, 19 Aug 2020 09:55:43 -0700 Subject: [PATCH 32/32] Addressing feedback. --- Standard/src/Diagnostics/Dump.qs | 6 +----- Standard/tests/Diagnostics/DumpTests.qs | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/Standard/src/Diagnostics/Dump.qs b/Standard/src/Diagnostics/Dump.qs index 0bb9e13ddd9..e84959a6da6 100644 --- a/Standard/src/Diagnostics/Dump.qs +++ b/Standard/src/Diagnostics/Dump.qs @@ -49,12 +49,8 @@ namespace Microsoft.Quantum.Diagnostics { /// $$ /// /// ```Q# - /// operation ApplyCnotToRegister(register : Qubit[]) : Unit is Adj + Ctl { - /// CNOT(register[0], register[1]); - /// } - /// /// operation DumpCnot() : Unit { - /// Diag.DumpOperation(2, ApplyCnotToRegister); + /// DumpOperation(2, ApplyToFirstTwoQubitsCA(CNOT, _)); /// } /// ``` /// diff --git a/Standard/tests/Diagnostics/DumpTests.qs b/Standard/tests/Diagnostics/DumpTests.qs index 4940b04ca26..29bf24cfa79 100644 --- a/Standard/tests/Diagnostics/DumpTests.qs +++ b/Standard/tests/Diagnostics/DumpTests.qs @@ -10,12 +10,8 @@ namespace Microsoft.Quantum.Tests { Diag.DumpOperation(1, ApplyToEachCA(S, _)); } - operation ApplyCnotToRegister(register : Qubit[]) : Unit is Adj + Ctl { - CNOT(register[0], register[1]); - } - operation DumpCnot() : Unit { - Diag.DumpOperation(2, ApplyCnotToRegister); + Diag.DumpOperation(2, ApplyToFirstTwoQubitsCA(CNOT, _)); } }