From 7e1817004c2eaeff3a3c801d03f112a016a26a36 Mon Sep 17 00:00:00 2001 From: Irina Yatsenko Date: Mon, 9 Nov 2020 12:50:02 -0800 Subject: [PATCH 1/6] Enable PrepareArbitraryState to use state injection on Quantum Simulator --- 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/Preparation/Arbitrary.cs | 66 +++++++++++++++++++ Standard/src/Standard.csproj | 4 +- Standard/tests/Standard.Tests.csproj | 2 +- Visualization/src/Visualization.csproj | 4 +- 11 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 Standard/src/Preparation/Arbitrary.cs diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index af4bcb22167..4e25d142fc0 100644 --- a/Chemistry/src/Runtime/Runtime.csproj +++ b/Chemistry/src/Runtime/Runtime.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -40,7 +40,7 @@ - + diff --git a/Chemistry/tests/ChemistryTests/QSharpTests.csproj b/Chemistry/tests/ChemistryTests/QSharpTests.csproj index 93341456f6e..a48a57480f5 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 fb9aaedeaac..49473ae5a9f 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 5017c5932ff..97287d23ee2 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 871614428cc..599160a1b17 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 ce9c826d092..cc8fc8c2079 100644 --- a/Numerics/src/Numerics.csproj +++ b/Numerics/src/Numerics.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -41,7 +41,7 @@ - + diff --git a/Numerics/tests/NumericsTests.csproj b/Numerics/tests/NumericsTests.csproj index cca28980f6a..8cec2face9a 100644 --- a/Numerics/tests/NumericsTests.csproj +++ b/Numerics/tests/NumericsTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Standard/src/Preparation/Arbitrary.cs b/Standard/src/Preparation/Arbitrary.cs new file mode 100644 index 00000000000..fcdc8a81efc --- /dev/null +++ b/Standard/src/Preparation/Arbitrary.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections; +using System.Runtime.InteropServices; +using Microsoft.Quantum.Simulation; +using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Simulation.Simulators; + + +namespace Microsoft.Quantum.Preparation +{ + public partial class PrepareArbitraryState + { + /// + /// Provides a native emulation of the PrepareArbitraryState operation when + /// the operation is executed using the full-state QuantumSimulator. + /// + public class Native : PrepareArbitraryState + { + [DllImport(QuantumSimulator.QSIM_DLL_NAME, ExactSpelling = true, + CallingConvention = CallingConvention.Cdecl, EntryPoint = "InjectState")] + private static extern double InjectState(uint sid, uint n, uint[] q, double[] re, double[] im); + + private QuantumSimulator Simulator { get; } + + public Native(IOperationFactory m) : base(m) + { + this.Simulator = m as QuantumSimulator; + } + + /// + /// Overrides the body to do the emulation when possible. If emulation is not possible, then + /// it just invokes the default Q# implementation. + /// + public override Func<(IQArray, Arithmetic.LittleEndian), QVoid>__Body__ => (_args) => + { + var (polar_amplitudes, qubits) = _args; + + if (this.Simulator == null) + { + return base.__Body__(_args); + } + + // calculate the norm as we might need to normalize the state + var norm = 0.0; + foreach (var pa in polar_amplitudes) { norm += pa.Magnitude * pa.Magnitude; } + norm = System.Math.Sqrt(norm); + + var state_size = polar_amplitudes.Length; + var re = new double[state_size]; + var im = new double[state_size]; + for (int i = 0; i < state_size; i++) + { + var pa = polar_amplitudes[i]; + re[i] = (System.Math.Abs(pa.Magnitude) * System.Math.Cos(pa.Argument))/norm; + im[i] = (System.Math.Abs(pa.Magnitude) * System.Math.Sin(pa.Argument))/norm; + } + + InjectState(Simulator.Id, (uint)qubits.Data.Length, qubits.Data.GetIds(), re, im); + return QVoid.Instance; + }; + } + } +} diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index 8407e189ef5..46ead3bcdb6 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -37,7 +37,7 @@ - + diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index 0e9be961006..83ee4b372e2 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Visualization/src/Visualization.csproj b/Visualization/src/Visualization.csproj index f148ebf7929..de6db06427b 100644 --- a/Visualization/src/Visualization.csproj +++ b/Visualization/src/Visualization.csproj @@ -32,9 +32,9 @@ - + - + From ed3c208570e3a462468cdd79035c9a1ffbbf82dd Mon Sep 17 00:00:00 2001 From: Irina Yatsenko Date: Mon, 9 Nov 2020 17:32:05 -0800 Subject: [PATCH 2/6] Some minor CR feedback --- Standard/src/Preparation/Arbitrary.cs | 34 ++++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/Standard/src/Preparation/Arbitrary.cs b/Standard/src/Preparation/Arbitrary.cs index fcdc8a81efc..b77df143de3 100644 --- a/Standard/src/Preparation/Arbitrary.cs +++ b/Standard/src/Preparation/Arbitrary.cs @@ -1,8 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#nullable enable + using System; -using System.Collections; using System.Runtime.InteropServices; using Microsoft.Quantum.Simulation; using Microsoft.Quantum.Simulation.Core; @@ -11,19 +12,19 @@ namespace Microsoft.Quantum.Preparation { - public partial class PrepareArbitraryState + public partial class ApproximatelyPrepareArbitraryState { /// - /// Provides a native emulation of the PrepareArbitraryState operation when + /// Provides a native emulation of the ApproximatelyPrepareArbitraryState operation when /// the operation is executed using the full-state QuantumSimulator. /// - public class Native : PrepareArbitraryState + public class Native : ApproximatelyPrepareArbitraryState { [DllImport(QuantumSimulator.QSIM_DLL_NAME, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "InjectState")] private static extern double InjectState(uint sid, uint n, uint[] q, double[] re, double[] im); - private QuantumSimulator Simulator { get; } + private QuantumSimulator? Simulator { get; } public Native(IOperationFactory m) : base(m) { @@ -34,10 +35,12 @@ public Native(IOperationFactory m) : base(m) /// Overrides the body to do the emulation when possible. If emulation is not possible, then /// it just invokes the default Q# implementation. /// - public override Func<(IQArray, Arithmetic.LittleEndian), QVoid>__Body__ => (_args) => + public override Func<(double, IQArray, Arithmetic.LittleEndian), QVoid>__Body__ => (_args) => { - var (polar_amplitudes, qubits) = _args; + var (tolerance, polarAmplitudes, qubits) = _args; + // TODO: benchmark for small `qubits` arrays to find out in which cases emulation is actually + // benefitial. if (this.Simulator == null) { return base.__Body__(_args); @@ -45,20 +48,29 @@ public Native(IOperationFactory m) : base(m) // calculate the norm as we might need to normalize the state var norm = 0.0; - foreach (var pa in polar_amplitudes) { norm += pa.Magnitude * pa.Magnitude; } + foreach (var pa in polarAmplitudes) { norm += pa.Magnitude * pa.Magnitude; } norm = System.Math.Sqrt(norm); - var state_size = polar_amplitudes.Length; + var state_size = polarAmplitudes.Length; var re = new double[state_size]; var im = new double[state_size]; for (int i = 0; i < state_size; i++) { - var pa = polar_amplitudes[i]; + var pa = polarAmplitudes[i]; re[i] = (System.Math.Abs(pa.Magnitude) * System.Math.Cos(pa.Argument))/norm; im[i] = (System.Math.Abs(pa.Magnitude) * System.Math.Sin(pa.Argument))/norm; } - InjectState(Simulator.Id, (uint)qubits.Data.Length, qubits.Data.GetIds(), re, im); + // Replace implementation in the library to stop throwing and return success/failure result instead. + try + { + // State injection is precise so tolerance isn't used. + InjectState(Simulator.Id, (uint)qubits.Data.Length, qubits.Data.GetIds(), re, im); + } + catch + { + return base.__Body__(_args); + } return QVoid.Instance; }; } From 705f6d8c632866ce3284d0b96e8c1cbf5581383c Mon Sep 17 00:00:00 2001 From: Irina Yatsenko Date: Fri, 13 Nov 2020 15:07:59 -0800 Subject: [PATCH 3/6] Add dedicated operation for state preparation w/o Adj/Ctrl --- Standard/src/Preparation/Arbitrary.cs | 36 +++++++++++++++------------ Standard/src/Preparation/Arbitrary.qs | 15 +++++++++++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Standard/src/Preparation/Arbitrary.cs b/Standard/src/Preparation/Arbitrary.cs index b77df143de3..93535b46d04 100644 --- a/Standard/src/Preparation/Arbitrary.cs +++ b/Standard/src/Preparation/Arbitrary.cs @@ -12,17 +12,17 @@ namespace Microsoft.Quantum.Preparation { - public partial class ApproximatelyPrepareArbitraryState + public partial class _PrepareAmplitudesFromZeroState { /// /// Provides a native emulation of the ApproximatelyPrepareArbitraryState operation when /// the operation is executed using the full-state QuantumSimulator. /// - public class Native : ApproximatelyPrepareArbitraryState + public class Native : _PrepareAmplitudesFromZeroState { [DllImport(QuantumSimulator.QSIM_DLL_NAME, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "InjectState")] - private static extern double InjectState(uint sid, uint n, uint[] q, double[] re, double[] im); + private static extern bool InjectState(uint sid, uint n, uint[] q, double[] re, double[] im); private QuantumSimulator? Simulator { get; } @@ -35,9 +35,9 @@ public Native(IOperationFactory m) : base(m) /// Overrides the body to do the emulation when possible. If emulation is not possible, then /// it just invokes the default Q# implementation. /// - public override Func<(double, IQArray, Arithmetic.LittleEndian), QVoid>__Body__ => (_args) => + public override Func<(IQArray, Arithmetic.LittleEndian), QVoid>__Body__ => (_args) => { - var (tolerance, polarAmplitudes, qubits) = _args; + var (polarAmplitudes, qubits) = _args; // TODO: benchmark for small `qubits` arrays to find out in which cases emulation is actually // benefitial. @@ -46,28 +46,32 @@ public Native(IOperationFactory m) : base(m) return base.__Body__(_args); } - // calculate the norm as we might need to normalize the state + // Calculate the norm as we might need to normalize the requsted state. var norm = 0.0; foreach (var pa in polarAmplitudes) { norm += pa.Magnitude * pa.Magnitude; } norm = System.Math.Sqrt(norm); - var state_size = polarAmplitudes.Length; - var re = new double[state_size]; - var im = new double[state_size]; - for (int i = 0; i < state_size; i++) + // Setup the amplitudes arrays for the call to native (it needs to translate from polar to cartesian and + // might need to pad the tail of an incomplete amplitudes' array with zeros). + var stateSize = (long)1 << (int)qubits.Data.Length; + var re = new double[stateSize]; + var im = new double[stateSize]; + for (long i = 0; i < polarAmplitudes.Length; i++) { var pa = polarAmplitudes[i]; re[i] = (System.Math.Abs(pa.Magnitude) * System.Math.Cos(pa.Argument))/norm; im[i] = (System.Math.Abs(pa.Magnitude) * System.Math.Sin(pa.Argument))/norm; } - - // Replace implementation in the library to stop throwing and return success/failure result instead. - try + for (long i = polarAmplitudes.Length; i < stateSize; i++) { - // State injection is precise so tolerance isn't used. - InjectState(Simulator.Id, (uint)qubits.Data.Length, qubits.Data.GetIds(), re, im); + re[i] = 0.0; + im[i] = 0.0; } - catch + + // Emulation might fail if the target qubits are entangled or not all in state |0>. In this case + // we should fallback to the quantum state preparation as it guarantees the operation to be a proper + // unitary no matter the state of the qubits. + if (!InjectState(Simulator.Id, (uint)qubits.Data.Length, qubits.Data.GetIds(), re, im)) { return base.__Body__(_args); } diff --git a/Standard/src/Preparation/Arbitrary.qs b/Standard/src/Preparation/Arbitrary.qs index c676003020e..093c8b1bf84 100644 --- a/Standard/src/Preparation/Arbitrary.qs +++ b/Standard/src/Preparation/Arbitrary.qs @@ -161,6 +161,21 @@ namespace Microsoft.Quantum.Preparation { ApproximatelyPrepareArbitraryState(0.0, coefficients, qubits); } + /// # Summary + /// Given a set of coefficients and a little-endian encoded quantum register + /// of unentangled qubits, all of which are in zero state, prepares a state + /// on that register described by the given coefficients. Uses state emulation + /// if supported by the target. + /// + /// # Notes + /// If the register isn't in zero state, the emulation will fail and fallback + /// to quantum state preparation. + /// This operation doesn't provide Adj/Ctr variants, because, in general, there + /// are no efficient emulation algorithms for those. + operation _PrepareAmplitudesFromZeroState(coefficients : ComplexPolar[], qubits : LittleEndian) : Unit { + ApproximatelyPrepareArbitraryState(0.0, coefficients, qubits); + } + /// # Summary /// Given a set of coefficients and a little-endian encoded quantum register, /// prepares an state on that register described by the given coefficients, From e4f308795968a3e70b743f3e8ed2b43193d18a3a Mon Sep 17 00:00:00 2001 From: Irina Yatsenko Date: Fri, 13 Nov 2020 15:25:34 -0800 Subject: [PATCH 4/6] move to 0.14.20111301-pull QDK --- 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 | 4 ++-- Standard/tests/Standard.Tests.csproj | 2 +- Visualization/src/Visualization.csproj | 4 ++-- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index 4e25d142fc0..d2c93b9b158 100644 --- a/Chemistry/src/Runtime/Runtime.csproj +++ b/Chemistry/src/Runtime/Runtime.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -40,7 +40,7 @@ - + diff --git a/Chemistry/tests/ChemistryTests/QSharpTests.csproj b/Chemistry/tests/ChemistryTests/QSharpTests.csproj index a48a57480f5..42bbb0ca3e2 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 49473ae5a9f..6b9b294fde2 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 97287d23ee2..daada5dfd12 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 599160a1b17..24b92a1a7ce 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 cc8fc8c2079..edfd36c4400 100644 --- a/Numerics/src/Numerics.csproj +++ b/Numerics/src/Numerics.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -41,7 +41,7 @@ - + diff --git a/Numerics/tests/NumericsTests.csproj b/Numerics/tests/NumericsTests.csproj index 8cec2face9a..5ac1acce08d 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 46ead3bcdb6..2ff6e559b7b 100644 --- a/Standard/src/Standard.csproj +++ b/Standard/src/Standard.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -37,7 +37,7 @@ - + diff --git a/Standard/tests/Standard.Tests.csproj b/Standard/tests/Standard.Tests.csproj index 83ee4b372e2..30a86ff68dd 100644 --- a/Standard/tests/Standard.Tests.csproj +++ b/Standard/tests/Standard.Tests.csproj @@ -1,4 +1,4 @@ - + diff --git a/Visualization/src/Visualization.csproj b/Visualization/src/Visualization.csproj index de6db06427b..7a0ba65039e 100644 --- a/Visualization/src/Visualization.csproj +++ b/Visualization/src/Visualization.csproj @@ -32,9 +32,9 @@ - + - + From 29847a6bfed62caf7c2f778f1584c2b14e47f79f Mon Sep 17 00:00:00 2001 From: Irina Yatsenko <36858951+irinayat-MS@users.noreply.github.com> Date: Tue, 17 Nov 2020 14:03:29 -0800 Subject: [PATCH 5/6] Update Standard/src/Preparation/Arbitrary.cs a typo in comment Co-authored-by: Chris Granade --- Standard/src/Preparation/Arbitrary.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Standard/src/Preparation/Arbitrary.cs b/Standard/src/Preparation/Arbitrary.cs index 93535b46d04..2066749f924 100644 --- a/Standard/src/Preparation/Arbitrary.cs +++ b/Standard/src/Preparation/Arbitrary.cs @@ -40,7 +40,7 @@ public Native(IOperationFactory m) : base(m) var (polarAmplitudes, qubits) = _args; // TODO: benchmark for small `qubits` arrays to find out in which cases emulation is actually - // benefitial. + // beneficial. if (this.Simulator == null) { return base.__Body__(_args); From 74ea9ee9e5bbc58288c4dd74c5aadf50da5bd5ef Mon Sep 17 00:00:00 2001 From: Irina Yatsenko <36858951+irinayat-MS@users.noreply.github.com> Date: Tue, 17 Nov 2020 14:53:09 -0800 Subject: [PATCH 6/6] Comment, that the new API is for internal use only --- Standard/src/Preparation/Arbitrary.qs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Standard/src/Preparation/Arbitrary.qs b/Standard/src/Preparation/Arbitrary.qs index 093c8b1bf84..0d5d83dd356 100644 --- a/Standard/src/Preparation/Arbitrary.qs +++ b/Standard/src/Preparation/Arbitrary.qs @@ -172,6 +172,9 @@ namespace Microsoft.Quantum.Preparation { /// to quantum state preparation. /// This operation doesn't provide Adj/Ctr variants, because, in general, there /// are no efficient emulation algorithms for those. + /// + /// For internal use only, until proposal https://github.com/microsoft/qsharp-language/pull/41 + /// is finalized and implemented. operation _PrepareAmplitudesFromZeroState(coefficients : ComplexPolar[], qubits : LittleEndian) : Unit { ApproximatelyPrepareArbitraryState(0.0, coefficients, qubits); }