diff --git a/Chemistry/src/Runtime/Runtime.csproj b/Chemistry/src/Runtime/Runtime.csproj index af4bcb22167..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 93341456f6e..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 fb9aaedeaac..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 5017c5932ff..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 871614428cc..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 ce9c826d092..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 cca28980f6a..5ac1acce08d 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..2066749f924 --- /dev/null +++ b/Standard/src/Preparation/Arbitrary.cs @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#nullable enable + +using System; +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 _PrepareAmplitudesFromZeroState + { + /// + /// Provides a native emulation of the ApproximatelyPrepareArbitraryState operation when + /// the operation is executed using the full-state QuantumSimulator. + /// + public class Native : _PrepareAmplitudesFromZeroState + { + [DllImport(QuantumSimulator.QSIM_DLL_NAME, ExactSpelling = true, + CallingConvention = CallingConvention.Cdecl, EntryPoint = "InjectState")] + private static extern bool 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 (polarAmplitudes, qubits) = _args; + + // TODO: benchmark for small `qubits` arrays to find out in which cases emulation is actually + // beneficial. + if (this.Simulator == null) + { + return base.__Body__(_args); + } + + // 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); + + // 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; + } + for (long i = polarAmplitudes.Length; i < stateSize; i++) + { + re[i] = 0.0; + im[i] = 0.0; + } + + // 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); + } + return QVoid.Instance; + }; + } + } +} diff --git a/Standard/src/Preparation/Arbitrary.qs b/Standard/src/Preparation/Arbitrary.qs index c676003020e..0d5d83dd356 100644 --- a/Standard/src/Preparation/Arbitrary.qs +++ b/Standard/src/Preparation/Arbitrary.qs @@ -161,6 +161,24 @@ 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. + /// + /// 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); + } + /// # Summary /// Given a set of coefficients and a little-endian encoded quantum register, /// prepares an state on that register described by the given coefficients, diff --git a/Standard/src/Standard.csproj b/Standard/src/Standard.csproj index 8407e189ef5..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 0e9be961006..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 f148ebf7929..7a0ba65039e 100644 --- a/Visualization/src/Visualization.csproj +++ b/Visualization/src/Visualization.csproj @@ -32,9 +32,9 @@ - + - +