diff --git a/src/Simulation/Common/IQuantumProcessor.cs b/src/Simulation/Common/IQuantumProcessor.cs
new file mode 100644
index 00000000000..565b44d0356
--- /dev/null
+++ b/src/Simulation/Common/IQuantumProcessor.cs
@@ -0,0 +1,640 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.Common
+{
+ ///
+ /// An interface for implementing QDK target quantum machines that work on a quantum circuit level.
+ ///
+ ///
+ /// To implement a target machine that executes quantum commands, implement this interface.
+ /// Consider using as a stub for easy impementation of this interface.
+ /// Implementors of interface do not manage qubits on their own.
+ /// All qubit management (allocation, dealocation, etc.) is done by the caller of this interface.
+ /// Implementors are notified when qubits are allocated, released, borrowed and returned allowing them to react to these events if necessary.
+ ///
+ public interface IQuantumProcessor
+ {
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.X is called in Q#.
+ /// When this is invoked, it is expected that the X gate gets applied to the given . The gate is given by matrix X=((0,1),(1,0)).
+ ///
+ ///
+ /// When adjoint of X is called in Q#, this same method is called because X is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void X(Qubit qubit);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.X is called in Q#.
+ /// When this is invoked, it is expected that the X gate gets applied to the given controlled on . The gate is given by matrix X=((0,1),(1,0)).
+ ///
+ ///
+ /// When adjoint of Controlled X is called in Q#, this same method is called because X is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Qubit to which the gate should be applied.
+ void ControlledX(IQArray controls, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.Y is called in Q#.
+ /// When this is invoked, it is expected that the Y gate gets applied to the given . The gate is given by matrix Y=((0,-𝑖),(𝑖,0)).
+ ///
+ ///
+ /// When adjoint of Y is called in Q#, this same method is called because Y is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void Y(Qubit qubit);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.Y is called in Q#.
+ /// When this is invoked, it is expected that the Y gate gets applied to the given controlled on . The gate is given by matrix Y=((0,-𝑖),(𝑖,0)).
+ ///
+ ///
+ /// When adjoint of Controlled Y is called in Q#, this same method is called because Y is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Qubit to which the gate should be applied.
+ void ControlledY(IQArray controls, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.Z is called in Q#.
+ /// When this is invoked, it is expected that the Z gate gets applied to the given . The gate is given by matrix Z=((1,0),(0,-1)).
+ ///
+ ///
+ /// When adjoint of Z is called in Q#, this same method is called because Z is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void Z(Qubit qubit);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.Z is called in Q#.
+ /// When this is invoked, it is expected that the Z gate gets applied to the given controlled on . The gate is given by matrix Z=((1,0),(0,-1)).
+ ///
+ ///
+ /// When adjoint of Controlled Z is called in Q#, this same method is called because Z is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Qubit to which the gate should be applied.
+ void ControlledZ(IQArray controls, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.SWAP is called in Q#.
+ /// When this is invoked, it is expected that the gate given by rule |ψ⟩⊗|ϕ⟩ ↦ |ϕ⟩⊗|ψ⟩ where |ϕ⟩,|ψ⟩ arbitrary one qubit states gets applied.
+ ///
+ ///
+ /// When adjoint of SWAP is called in Q#, this same method is called because SWAP is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// First qubit to be swapped.
+ /// Second qubit to be swapped.
+ void SWAP(Qubit qubit1, Qubit qubit2);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.SWAP is called in Q#.
+ /// When this is invoked, it is expected that the gate given by rule |ψ⟩⊗|ϕ⟩ ↦ |ϕ⟩⊗|ψ⟩ where |ϕ⟩,|ψ⟩ arbitrary one qubit states gets applied, controlled on .
+ ///
+ ///
+ /// When adjoint of Controlled SWAP is called in Q#, this same method is called because SWAP is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// First qubit to be swapped.
+ /// Second qubit to be swapped.
+ void ControlledSWAP(IQArray controls, Qubit qubit1, Qubit qubit2);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.H is called in Q#.
+ /// When this is invoked, it is expected that the Hadamard gate gets applied to . The gate is given by matrix H=((1,1),(1,-1))/√2.
+ ///
+ ///
+ /// When adjoint of H is called in Q#, this same method is called because Hadamard is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void H(Qubit qubit);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.H is called in Q#.
+ /// When this is invoked, it is expected that the Hadamard gate gets applied to controlled on . The gate is given by matrix H=((1,1),(1,-1))/√2.
+ ///
+ ///
+ /// When adjoint of Controlled H is called in Q#, this same method is called because Hadamard is self-adjoint.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Qubit to which the gate should be applied.
+ void ControlledH(IQArray controls, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.S is called in Q#.
+ /// When this is invoked, it is expected that the S gate gets applied to . The gate is given by matrix S=((1,0),(0,𝑖)).
+ ///
+ ///
+ /// When adjoint of S is called in Q#, is called.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void S(Qubit qubit);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.S is called in Q#.
+ /// When this is invoked, it is expected that the S gate gets applied to controlled on . The gate is given by matrix S=((1,0),(0,𝑖)).
+ ///
+ ///
+ /// When adjoint of Controlled S is called in Q#, is called.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Qubit to which the gate should be applied.
+ void ControlledS(IQArray controls, Qubit qubit);
+
+ ///
+ /// Called when adjoint Microsoft.Quantum.Intrinsic.S is called in Q#.
+ /// When this is invoked, it is expected that the S† gate gets applied to . The gate is given by matrix S†=((1,0),(0,-𝑖)).
+ ///
+ ///
+ /// When adjoint of Adjoint S is called in Q#, is called.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void SAdjoint(Qubit qubit);
+
+ ///
+ /// Called when controlled adjoint Microsoft.Quantum.Intrinsic.S is called in Q#.
+ /// When this is invoked, it is expected that the S† gate gets applied to controlled on . The gate is given by matrix S†=((1,0),(0,𝑖)).
+ ///
+ ///
+ /// When adjoint of Controlled S† is called in Q#, is called.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Qubit to which the gate should be applied.
+ void ControlledSAdjoint(IQArray controls, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.T is called in Q#.
+ /// When this is invoked, it is expected that the T gate gets applied to . The gate is given by matrix T=((1,0),(0,𝑒𝑥𝑝(𝑖⋅π/4))).
+ ///
+ ///
+ /// When adjoint of T is called in Q#, is called.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void T(Qubit qubit);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.T is called in Q#.
+ /// When this is invoked, it is expected that the T gate gets applied to controlled on . The gate is given by matrix T=((1,0),(0,𝑒𝑥𝑝(𝑖⋅π/4))).
+ ///
+ ///
+ /// When adjoint of Controlled T is called in Q#, is called.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Qubit to which the gate should be applied.
+ void ControlledT(IQArray controls, Qubit qubit);
+
+ ///
+ /// Called when adjoint Microsoft.Quantum.Intrinsic.T is called in Q#.
+ /// When this is invoked, it is expected that the T† gate gets applied to . The gate is given by matrix T†=((1,0),(0,𝑒𝑥𝑝(-𝑖⋅π/4))).
+ ///
+ ///
+ /// When adjoint of Adjoint T is called in Q#, is called.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void TAdjoint(Qubit qubit);
+
+ ///
+ /// Called when controlled adjoint Microsoft.Quantum.Intrinsic.T is called in Q#.
+ /// When this is invoked, it is expected that the T† gate gets applied to controlled on . The gate is given by matrix T†=((1,0),(0,𝑒𝑥𝑝(-𝑖⋅π/4))).
+ ///
+ ///
+ /// When adjoint of Controlled T† is called in Q#, is called.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Qubit to which the gate should be applied.
+ void ControlledTAdjoint(IQArray controls, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.R is called in Q#.
+ /// When this is invoked, it is expected that the 𝑒𝑥𝑝(-𝑖⋅⋅/2) gets applied to .
+ ///
+ ///
+ /// When adjoint of R is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Pauli operator to be exponentiated to form the rotation.
+ /// Angle about which the qubit is to be rotated.
+ /// Qubit to which the gate should be applied.
+ void R(Pauli axis, double theta, Qubit qubit);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.R is called in Q#.
+ /// When this is invoked, it is expected that the 𝑒𝑥𝑝(-𝑖⋅⋅/2) gets applied to controlled on .
+ ///
+ ///
+ /// When adjoint of Controlled R is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Pauli operator to be exponentiated to form the rotation.
+ /// Angle about which the qubit is to be rotated.
+ /// Qubit to which the gate should be applied.
+ void ControlledR(IQArray controls, Pauli axis, double theta, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.RFrac is called in Q#.
+ /// When this is invoked, it is expected that the 𝑒𝑥𝑝(𝑖⋅π⋅⋅/2^) gets applied to .
+ ///
+ ///
+ /// When adjoint of RFrac is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Pauli operator to be exponentiated to form the rotation.
+ /// Numerator in the dyadic fraction representation of the angle by which the qubit is to be rotated.
+ /// Power of two specifying the denominator of the angle by which the qubit is to be rotated.
+ /// Qubit to which the gate should be applied.
+ void RFrac(Pauli axis, long numerator, long power, Qubit qubit);
+
+ ///
+ /// Called when a controlled Microsoft.Quantum.Intrinsic.RFrac is called in Q#.
+ /// When this is invoked, it is expected that the 𝑒𝑥𝑝(𝑖⋅π⋅⋅/2^) gets applied to controlled on .
+ ///
+ ///
+ /// When adjoint of Controlled RFrac is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Pauli operator to be exponentiated to form the rotation.
+ /// Numerator in the dyadic fraction representation of the angle by which the qubit is to be rotated.
+ /// Power of two specifying the denominator of the angle by which the qubit is to be rotated.
+ /// Qubit to which the gate should be applied.
+ void ControlledRFrac(IQArray controls, Pauli axis, long numerator, long power, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.R1 is called in Q#.
+ /// When this is invoked, it is expected that the gate given by matrix ((1,0),(0,𝑒𝑥𝑝(𝑖⋅))) gets applied to .
+ ///
+ ///
+ /// When adjoint of R1 is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Angle about which the qubit is to be rotated.
+ /// Qubit to which the gate should be applied.
+ void R1(double theta, Qubit qubit);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.R is called in Q#.
+ /// When this is invoked, it is expected that the gate given by matrix ((1,0),(0,𝑒𝑥𝑝(𝑖⋅))) gets applied to controlled on .
+ ///
+ ///
+ /// When adjoint of Controlled R1 is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Angle about which the qubit is to be rotated.
+ /// Qubit to which the gate should be applied.
+ void ControlledR1(IQArray controls, double theta, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.R1Frac is called in Q#.
+ /// When this is invoked, it is expected that the gate given by matrix ((1,0),(0,𝑒𝑥𝑝(𝑖⋅π⋅/2^))) gets applied to .
+ ///
+ ///
+ /// When adjoint of R1Frac is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Numerator in the dyadic fraction representation of the angle by which the qubit is to be rotated.
+ /// Power of two specifying the denominator of the angle by which the qubit is to be rotated.
+ /// Qubit to which the gate should be applied.
+ void R1Frac(long numerator, long power, Qubit qubit);
+
+ ///
+ /// Called when a controlled Microsoft.Quantum.Intrinsic.R1Frac is called in Q#.
+ /// When this is invoked, it is expected that the gate given by matrix ((1,0),(0,𝑒𝑥𝑝(𝑖⋅π⋅/2^))) gets applied to controlled on .
+ ///
+ ///
+ /// When adjoint of Controlled RFrac is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Numerator in the dyadic fraction representation of the angle by which the qubit is to be rotated.
+ /// Power of two specifying the denominator of the angle by which the qubit is to be rotated.
+ /// Qubit to which the gate should be applied.
+ void ControlledR1Frac(IQArray controls, long numerator, long power, Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.Exp is called in Q#.
+ /// When this is invoked, it is expected that the 𝑒𝑥𝑝(𝑖⋅⋅) gets applied to .
+ ///
+ ///
+ /// When adjoint of Exp is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Array of single-qubit Pauli values representing a multi-qubit Pauli to be applied.
+ /// Angle about the given multi-qubit Pauli operator by which the target register is to be rotated.
+ /// Register to apply the exponent to.
+ void Exp(IQArray paulis, double theta, IQArray qubits);
+
+ ///
+ /// Called when a controlled Microsoft.Quantum.Intrinsic.Exp is called in Q#.
+ /// When this is invoked, it is expected that the 𝑒𝑥𝑝(𝑖⋅⋅) gets applied to controlled on .
+ ///
+ ///
+ /// When adjoint of Controlled Exp is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Array of single-qubit Pauli values representing a multi-qubit Pauli to be applied.
+ /// Angle about the given multi-qubit Pauli operator by which the target register is to be rotated.
+ /// Register to apply the exponent to.
+ void ControlledExp(IQArray controls, IQArray paulis, double theta, IQArray qubits);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.ExpFrac is called in Q#.
+ /// When this is invoked, it is expected that the 𝑒𝑥𝑝(𝑖⋅π⋅⋅/2^) gets applied to .
+ ///
+ ///
+ /// When adjoint of ExpFrac is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Array of single-qubit Pauli values representing a multi-qubit Pauli to be applied.
+ /// Numerator in the dyadic fraction representation of the angle by which the qubit register is to be rotated.
+ /// Power of two specifying the denominator of the angle by which the qubit register is to be rotated.
+ /// Register to apply the exponent to.
+ void ExpFrac(IQArray paulis, long numerator, long power, IQArray qubits);
+
+ ///
+ /// Called when controlled Microsoft.Quantum.Intrinsic.ExpFrac is called in Q#.
+ /// When this is invoked, it is expected that the 𝑒𝑥𝑝(𝑖⋅π⋅⋅/2^) gets applied to controlled on .
+ ///
+ ///
+ /// When adjoint of Controlled ExpFrac is called in Q#, is called with replaced by -.
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// The array of qubits on which the operation is controlled.
+ /// Array of single-qubit Pauli values representing a multi-qubit Pauli to be applied.
+ /// Numerator in the dyadic fraction representation of the angle by which the qubit register is to be rotated.
+ /// Power of two specifying the denominator of the angle by which the qubit register is to be rotated.
+ /// Register to apply the exponent to.
+ void ControlledExpFrac(IQArray controls, IQArray paulis, long numerator, long power, IQArray qubits);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.M is called in Q#.
+ /// When this is invoked, it is expected that the is measured in Z basis, in other words in the computational basis.
+ ///
+ ///
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ /// Class implementing interface can return any class derived from .
+ ///
+ /// Qubit to which the gate should be applied.
+ /// Zero if the +1 eigenvalue is observed, and One if the -1 eigenvalue is observed.
+ Result M(Qubit qubit);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.Measure is called in Q#.
+ /// When this is invoked, it is expected that the multi-qubit Pauli observable given by is measured on .
+ ///
+ ///
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ /// Class implementing interface can return any class derived from .
+ ///
+ /// Qubits to which the gate should be applied.
+ /// Array of single-qubit Pauli values describing multi-qubit Pauli observable.
+ /// Zero if the +1 eigenvalue is observed, and One if the -1 eigenvalue is observed.
+ Result Measure(IQArray bases, IQArray qubits);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.Reset is called in Q#.
+ /// When this is invoked, it is expected that the is measured and ensured to be in the |0⟩ state such that it can be safely released.
+ ///
+ ///
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// Qubit to which the gate should be applied.
+ void Reset(Qubit qubit);
+
+ ///
+ /// Intended for a limited support of branching upon measurement results on a target machine level.
+ /// Called when a conditional statement on measurement results is invoked.
+ ///
+ /// The actual results of the measurements of a number of qubits upon which branching is to be performed.
+ /// The expected values of results of the measurements of these qubits.
+ /// A value representing this conditional statement and encoding the result of condition.
+ ///
+ /// A typical implementation will compare all to and return the result of this comparison.
+ ///
+ long StartConditionalStatement(IQArray measurementResults, IQArray resultsValues);
+
+ ///
+ /// Intended for a limited support of branching upon measurement results on a target machine level.
+ /// Called when a conditional statement on a measurement result is invoked.
+ ///
+ /// The actual result of the measurement of a qubit upon which branching is to be performed.
+ /// The expected value of result of the measurement of this qubit.
+ /// A value representing this conditional statement and encoding the result of the condition. It will be passed through to the other branching related APIs such as RunThenClause.
+ ///
+ /// A typical implementation will compare to and return the result of this comparison.
+ ///
+ long StartConditionalStatement(Result measurementResult, Result resultValue);
+
+ ///
+ /// Intended for a limited support of branching upon measurement results on a target machine level.
+ /// Called when the "then" statement of a conditional statement is about to be executed.
+ ///
+ /// A value representing this conditional statement and encoding the result of condition.
+ /// If true is returned, the "then" statement will be executed, otherwise it will be skipped and RepeatThenClause will not be called.
+ ///
+ /// A typical implementation will use to return whether condition was evaluated to true.
+ ///
+ bool RunThenClause(long statement);
+
+ ///
+ /// Intended for a limited support of branching upon measurement results on a target machine level.
+ /// Called when the "then" statement of a conditional statement has finished executing.
+ ///
+ /// A value representing this conditional statement and encoding the result of the condition. This is the value returned from the StartConditionalStatement.
+ /// If true is returned, the "then" statement will be executed again (without calling RunThenClause), folowed by another call to RepeatThenClause.
+ ///
+ /// A typical implementation will return false.
+ ///
+ bool RepeatThenClause(long statement);
+
+ ///
+ /// Intended for a limited support of branching upon measurement results on a target machine level.
+ /// Called when the "else" statement of a conditional statement is about to be executed.
+ ///
+ /// A value representing this conditional statement and encoding the result of the condition. This is the value returned from the StartConditionalStatement.
+ /// If true is returned, the "else" statement will be executed, otherwise it will be skipped and RepeatElseClause will not be called.
+ ///
+ /// A typical implementation will use to return whether condition was evaluated to false.
+ ///
+ bool RunElseClause(long statement);
+
+ ///
+ /// Intended for a limited support of branching upon measurement results on a target machine level.
+ /// Called when the "else" statement of a conditional statement has finished executing.
+ ///
+ /// A value representing this conditional statement and encoding the result of the condition. This is the value returned from the StartConditionalStatement.
+ /// If true is returned, the "else" statement will be executed again (without calling RunElseClause), folowed by another call to RepeatElseClause.
+ ///
+ /// A typical implementation will return false.
+ ///
+ bool RepeatElseClause(long statement);
+
+ ///
+ /// Intended for a limited support of branching upon measurement results on a target machine level.
+ /// Called when a conditional statement on measurement results has finished executing.
+ ///
+ /// A value representing this conditional statement and encoding the result of the condition. This is the value returned from the StartConditionalStatement.
+ ///
+ /// A typical implementation will clean up any data structures associated with statement.
+ ///
+ void EndConditionalStatement(long statement);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.Assert is called in Q#.
+ ///
+ ///
+ /// The names and the order of the parameters are the same as for the corresponding Q# operation.
+ ///
+ /// A multi-qubit Pauli operator, for which the measurement outcome is asserted.
+ /// A register on which to make the assertion.
+ /// The expected result of Measure(bases, qubits)
+ /// A message to be reported if the assertion fails.
+ void Assert(IQArray bases, IQArray qubits, Result result, string msg);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.Assert is called in Q#.
+ ///
+ ///
+ /// The names and the order of the parameters is similar to the corresponding Q# operation./
+ ///
+ /// A multi-qubit Pauli operator, for which the measurement outcome is asserted.
+ /// A register on which to make the assertion.
+ /// The probability with which result Zero is expected.
+ /// A message to be reported if the assertion fails.
+ /// The precision with which the probability of Zero outcome is specified.
+ void AssertProb(IQArray bases, IQArray qubits, double probabilityOfZero, string msg, double tol);
+
+ ///
+ /// Called before a call to any Q# operation.
+ ///
+ /// Information about operation being called.
+ /// Information about the arguments passed to the operation.
+ ///
+ /// Implement this interface if you want to be notified every time a Q# operation starts.
+ /// To get the fully qualified Q# name of operation being called use .
+ /// For the variant of operation, that is to find if Adjoint, Controlled or Controlled Adjoint being called use .
+ /// To get a sequence of all qubits passed to the operation use .
+ ///
+ void OnOperationStart(ICallable operation, IApplyData arguments);
+
+ ///
+ /// Called when returning from a call to any Q# operation.
+ ///
+ /// Information about operation being called.
+ /// Information about the arguments passed to the operation.
+ ///
+ /// Implement this interface if you want to be notified every time a Q# operation ends.
+ /// To get the fully qualified Q# name of operation being called use .
+ /// For the variant of operation, that is to find if Adjoint, Controlled or Controlled Adjoint being called use .
+ /// To get a sequence of all qubits passed to the operation use .
+ ///
+ void OnOperationEnd(ICallable operation, IApplyData arguments);
+
+ ///
+ /// Called when an exception occurs. This could be Fail statement in Q#, or any other exception.
+ ///
+ /// Information about exception that was raised.
+ ///
+ ///
+ void OnFail(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo);
+
+ ///
+ /// Called when qubits are allocated by Q# using block.
+ ///
+ /// Qubits that are being allocated.
+ ///
+ /// Every qubit has a unique identifier .
+ /// All newly allocated qubits are in |0⟩ state.
+ ///
+ void OnAllocateQubits(IQArray qubits);
+
+ ///
+ /// Called when qubits are released in Q# in the end of using block.
+ ///
+ /// Qubits that are being released.
+ ///
+ /// Every qubit has a unique identifier .
+ /// All qubits are expected to be released in |0⟩ state.
+ ///
+ void OnReleaseQubits(IQArray qubits);
+
+ ///
+ /// Called when qubits are borrowed by Q# borrowing block.
+ ///
+ /// Qubits that are being borrowed.
+ ///
+ /// Every qubit has a unique identifier .
+ /// Borrowed qubits can be in any state.
+ ///
+ void OnBorrowQubits(IQArray qubits);
+
+ ///
+ /// Called when qubits are returned in the end of Q# borrowing block.
+ ///
+ /// Qubits that have been borrowed and are now being returned.
+ ///
+ /// Every qubit has a unique identifier .
+ /// Borrowed qubits are expected to be returned in the same state as the state they have been borrowed in.
+ ///
+ void OnReturnQubits(IQArray qubits);
+
+ ///
+ /// Called when
+ /// Microsoft.Quantum.Diagnostics.DumpMachine
+ /// is called in Q#.
+ ///
+ ///
+ /// The names and the order of the parameters are similar to corresponding Q# operation.
+ ///
+ ///
+ /// Provides information on where to generate the DumpMachine state.
+ void OnDumpMachine(T location);
+
+ ///
+ /// Called when
+ /// Microsoft.Quantum.Diagnostics.DumpRegister
+ /// is called in Q#.
+ ///
+ ///
+ /// The names and the order of the parameters are similar to corresponding Q# operation.
+ ///
+ ///
+ /// Provides information on where to generate the DumpRegister state.
+ /// The list of qubits to report.
+ void OnDumpRegister(T location, IQArray qubits);
+
+ ///
+ /// Called when Microsoft.Quantum.Intrinsic.Message is called in Q#.
+ ///
+ ///
+ /// The names and the order of the parameters are the same as corresponding Q# operations.
+ ///
+ /// The message to be reported.
+ void OnMessage(string msg);
+ }
+}
diff --git a/src/Simulation/Common/QuantumProcessorBase.cs b/src/Simulation/Common/QuantumProcessorBase.cs
new file mode 100644
index 00000000000..00ca208c33c
--- /dev/null
+++ b/src/Simulation/Common/QuantumProcessorBase.cs
@@ -0,0 +1,285 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+using System.Diagnostics;
+
+namespace Microsoft.Quantum.Simulation.Common
+{
+ ///
+ /// A class that implements IQuantumProcessor that does not do any logic, but is convenient to inherit from.
+ /// It throws for most APIs.
+ ///
+ public class QuantumProcessorBase : IQuantumProcessor
+ {
+ public virtual void X(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledX(IQArray controls, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void Y(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledY(IQArray controls, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void Z(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledZ(IQArray controls, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void SWAP(Qubit qubit1, Qubit qubit2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledSWAP(IQArray controls, Qubit qubit1, Qubit qubit2)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void H(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledH(IQArray controls, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void S(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledS(IQArray controls, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void SAdjoint(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledSAdjoint(IQArray controls, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void T(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledT(IQArray controls, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void TAdjoint(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledTAdjoint(IQArray controls, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void R(Pauli axis, double theta, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledR(IQArray controls, Pauli axis, double theta, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void RFrac(Pauli axis, long numerator, long power, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledRFrac(IQArray controls, Pauli axis, long numerator, long power, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void R1(double theta, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledR1(IQArray controls, double theta, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void R1Frac(long numerator, long power, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledR1Frac(IQArray controls, long numerator, long power, Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void Exp(IQArray paulis, double theta, IQArray qubits)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledExp(IQArray controls, IQArray paulis, double theta, IQArray qubits)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ExpFrac(IQArray paulis, long numerator, long power, IQArray qubits)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void ControlledExpFrac(IQArray controls, IQArray paulis, long numerator, long power, IQArray qubits)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Result M(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Result Measure(IQArray bases, IQArray qubits)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual void Reset(Qubit qubit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual long StartConditionalStatement(IQArray measurementResults, IQArray resultsValues)
+ {
+ Debug.Assert(measurementResults.Count == resultsValues.Count);
+
+ int equal = 1;
+
+ for (int i = 0; i < measurementResults.Count; i++)
+ {
+ if (measurementResults[i] != resultsValues[i])
+ {
+ equal = 0;
+ }
+ }
+
+ return equal;
+ }
+
+ public virtual long StartConditionalStatement(Result measurementResult, Result resultValue)
+ {
+
+ if (measurementResult == resultValue)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ public virtual bool RunThenClause(long statement)
+ {
+ return (statement != 0);
+ }
+
+ public virtual bool RepeatThenClause(long statement)
+ {
+ return false;
+ }
+
+ public virtual bool RunElseClause(long statement)
+ {
+ return (statement == 0);
+ }
+
+ public virtual bool RepeatElseClause(long statement)
+ {
+ return false;
+ }
+
+ public virtual void EndConditionalStatement(long id)
+ {
+
+ }
+
+ public virtual void Assert(IQArray bases, IQArray qubits, Result result, string msg)
+ {
+ }
+
+ public virtual void AssertProb(IQArray bases, IQArray qubits, double probabilityOfZero, string msg, double tol)
+ {
+ }
+
+ public virtual void OnOperationStart(ICallable operation, IApplyData arguments)
+ {
+ }
+
+ public virtual void OnOperationEnd(ICallable operation, IApplyData arguments)
+ {
+ }
+
+ public virtual void OnFail(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
+ {
+ }
+
+ public virtual void OnAllocateQubits(IQArray qubits)
+ {
+ }
+
+ public virtual void OnReleaseQubits(IQArray qubits)
+ {
+ }
+
+ public virtual void OnBorrowQubits(IQArray qubits)
+ {
+ }
+
+ public virtual void OnReturnQubits(IQArray qubits)
+ {
+ }
+
+ public virtual void OnDumpMachine(T location)
+ {
+ }
+
+ public virtual void OnDumpRegister(T location, IQArray qubits)
+ {
+ }
+
+ public virtual void OnMessage(string msg)
+ {
+ }
+
+ }
+}
diff --git a/src/Simulation/Common/Utils.cs b/src/Simulation/Common/Utils.cs
new file mode 100644
index 00000000000..752c4048dcd
--- /dev/null
+++ b/src/Simulation/Common/Utils.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Quantum.Simulation.Core;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Microsoft.Quantum.Simulation.Common
+{
+ public class CommonUtils
+ {
+ ///
+ /// Removes PauliI terms from observable and corresponding qubits from qubits.
+ /// Returns the observable description that is equivalent to the original one, but has no PauliI terms
+ ///
+ public static void PruneObservable(IQArray observable, IQArray qubits, out QArray prunedObservable, out QArray prunedQubits)
+ {
+ Debug.Assert(observable != null);
+ Debug.Assert(qubits != null);
+ Debug.Assert(observable.Length == qubits.Length);
+ prunedObservable = new QArray(PrunedSequence(observable, Pauli.PauliI, observable));
+ prunedQubits = new QArray(PrunedSequence(observable, Pauli.PauliI, qubits));
+ }
+
+ ///
+ /// Returns IEnumerable<T> that contains sub-sequence of [i], such that [i] is not equal to .
+ ///
+ public static IEnumerable PrunedSequence(IQArray sequence, U value, IQArray sequenceToPrune )
+ {
+ for (uint i = 0; i < sequence.Length; ++i)
+ {
+ if (!sequence[i].Equals(value))
+ {
+ yield return sequenceToPrune[i];
+ }
+ }
+ }
+
+ ///
+ /// Converts numbers of the form /2^ into canonical form where is odd or zero.
+ /// If is zero, must also be zero in the canonical form.
+ ///
+ public static (long, long) Reduce(long numerator, long denominatorPower)
+ {
+ if (numerator == 0)
+ {
+ return (0, 0);
+ }
+
+ if (numerator % 2 != 0)
+ {
+ return (numerator, denominatorPower);
+ }
+
+ long numNew = numerator;
+ long denomPowerNew = denominatorPower;
+
+ while (numNew % 2 == 0)
+ {
+ numNew /= 2;
+ denomPowerNew -= 1;
+ }
+
+ return (numNew, denomPowerNew);
+ }
+ }
+}
diff --git a/src/Simulation/Core/QArray.cs b/src/Simulation/Core/QArray.cs
index 450fb93253a..de9db576c88 100644
--- a/src/Simulation/Core/QArray.cs
+++ b/src/Simulation/Core/QArray.cs
@@ -329,6 +329,7 @@ IEnumerable IApplyData.Qubits
/// and ArgumentOutOfRangeException.
///
/// The long index of the element to access
+ /// New value of the element
/// The element
public QArray Modify(long index, T value)
{
@@ -351,7 +352,8 @@ public QArray Modify(long index, T value)
/// or if an index is outside the array bounds, it throws
/// and ArgumentOutOfRangeException.
///
- /// The long index of the element to access
+ /// The range of indices of the elements to access
+ /// New values of the elements
/// The element
public QArray Modify(QRange indices, IQArray values)
{
@@ -566,7 +568,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
}
///
- /// Reads the QArray<>
+ /// Reads the
///
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
diff --git a/src/Simulation/Simulators/QuantumProcessor/Allocate.cs b/src/Simulation/Simulators/QuantumProcessor/Allocate.cs
new file mode 100644
index 00000000000..ea176410f61
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Allocate.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherAllocate : Intrinsic.Allocate
+ {
+ private readonly QuantumProcessorDispatcher sim;
+ public QuantumProcessorDispatcherAllocate(QuantumProcessorDispatcher m) : base(m){
+ sim = m;
+ }
+
+ public override Qubit Apply()
+ {
+ IQArray qubits = sim.QubitManager.Allocate(1);
+ sim.QuantumProcessor.OnAllocateQubits(qubits);
+ return qubits[0];
+ }
+
+ public override IQArray Apply(long count)
+ {
+ IQArray qubits = sim.QubitManager.Allocate(count);
+ sim.QuantumProcessor.OnAllocateQubits(qubits);
+ return qubits;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Simulation/Simulators/QuantumProcessor/Assert.cs b/src/Simulation/Simulators/QuantumProcessor/Assert.cs
new file mode 100644
index 00000000000..d60f8bcef4e
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Assert.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Common;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherAssert : Quantum.Intrinsic.Assert
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherAssert(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(IQArray, IQArray, Result, string), QVoid> Body => (_args) =>
+ {
+ var (paulis, qubits, result, msg) = _args;
+ if (paulis.Length != qubits.Length)
+ {
+ IgnorableAssert.Assert((paulis.Length != qubits.Length), "Arrays length mismatch");
+ throw new InvalidOperationException($"Both input arrays for {this.GetType().Name} (paulis,qubits), must be of same size.");
+ }
+
+ CommonUtils.PruneObservable(paulis, qubits, out QArray newPaulis, out QArray newQubits);
+ Simulator.QuantumProcessor.Assert(newPaulis, newQubits, result, msg);
+
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, IQArray, Result, string), QVoid> AdjointBody => (_args) => { return QVoid.Instance; };
+
+ public override Func<(IQArray, (IQArray, IQArray, Result, string)), QVoid> ControlledBody => (_args) => { return QVoid.Instance; };
+
+ public override Func<(IQArray, (IQArray, IQArray, Result, string)), QVoid> ControlledAdjointBody => (_args) => { return QVoid.Instance; };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/AssertProb.cs b/src/Simulation/Simulators/QuantumProcessor/AssertProb.cs
new file mode 100644
index 00000000000..8d7d31eb8b3
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/AssertProb.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Common;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherAssertProb : Quantum.Intrinsic.AssertProb
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherAssertProb(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(IQArray, IQArray, Result, double, string, double), QVoid> Body => (_args) =>
+ {
+ var (paulis, qubits, result, expectedPr, msg, tol) = _args;
+ if (paulis.Length != qubits.Length)
+ {
+ IgnorableAssert.Assert((paulis.Length != qubits.Length), "Arrays length mismatch");
+ throw new InvalidOperationException($"Both input arrays for {this.GetType().Name} (paulis,qubits), must be of same size.");
+ }
+
+ double probabilityOfZero = result == Result.Zero ? expectedPr : 1.0 - expectedPr;
+ CommonUtils.PruneObservable(paulis, qubits, out QArray newPaulis, out QArray newQubits);
+ Simulator.QuantumProcessor.AssertProb(newPaulis, newQubits, probabilityOfZero, msg, tol );
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, IQArray, Result, double, string, double), QVoid> AdjointBody => (_args) => { return QVoid.Instance; };
+
+ public override Func<(IQArray, (IQArray, IQArray, Result, double, string, double)), QVoid> ControlledBody => (_args) => { return QVoid.Instance; };
+
+ public override Func<(IQArray, (IQArray, IQArray, Result, double, string, double)), QVoid> ControlledAdjointBody => (_args) => { return QVoid.Instance; };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/Borrow.cs b/src/Simulation/Simulators/QuantumProcessor/Borrow.cs
new file mode 100644
index 00000000000..bc68f6be23d
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Borrow.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherBorrow : Intrinsic.Borrow
+ {
+ private readonly QuantumProcessorDispatcher sim;
+ public QuantumProcessorDispatcherBorrow(QuantumProcessorDispatcher m) : base(m){
+ sim = m;
+ }
+
+ public override Qubit Apply()
+ {
+ IQArray qubits = sim.QubitManager.Borrow(1);
+ sim.QuantumProcessor.OnBorrowQubits(qubits);
+ return qubits[0];
+ }
+
+ public override IQArray Apply(long count)
+ {
+ IQArray qubits = sim.QubitManager.Borrow(count);
+ sim.QuantumProcessor.OnBorrowQubits(qubits);
+ return qubits;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs
new file mode 100644
index 00000000000..ded65c58b09
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs
@@ -0,0 +1,253 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+
+ private static void RunClause(ICallable op, OperationFunctor type, IQArray ctrls)
+ {
+ switch (type)
+ {
+ case OperationFunctor.Body: op.Apply(QVoid.Instance); break;
+ case OperationFunctor.Adjoint: ((IAdjointable)(op)).Adjoint.Apply(QVoid.Instance); break;
+ case OperationFunctor.Controlled: ((IControllable)(op)).Controlled.Apply(ctrls); break;
+ case OperationFunctor.ControlledAdjoint: ((IUnitary)(op)).Controlled.Adjoint.Apply(ctrls); break;
+ }
+ }
+
+ private static QVoid ExecuteConditionalStatementInternal(QuantumProcessorDispatcher Simulator,
+ long statement,
+ ICallable onEqualOp,
+ ICallable onNonEqualOp,
+ OperationFunctor type,
+ IQArray ctrls)
+ {
+ bool run;
+
+ run = Simulator.QuantumProcessor.RunThenClause(statement);
+ while (run)
+ {
+ RunClause(onEqualOp, type, ctrls);
+ run = Simulator.QuantumProcessor.RepeatThenClause(statement);
+ }
+
+ run = Simulator.QuantumProcessor.RunElseClause(statement);
+ while (run)
+ {
+ RunClause(onNonEqualOp, type, ctrls);
+ run = Simulator.QuantumProcessor.RepeatElseClause(statement);
+ }
+
+ Simulator.QuantumProcessor.EndConditionalStatement(statement);
+
+ return QVoid.Instance;
+ }
+
+ private static QVoid ExecuteConditionalStatement(QuantumProcessorDispatcher Simulator,
+ IQArray measurementResults,
+ IQArray resultsValues,
+ ICallable onEqualOp,
+ ICallable onNonEqualOp,
+ OperationFunctor type,
+ IQArray ctrls)
+ {
+ long statement = Simulator.QuantumProcessor.StartConditionalStatement(measurementResults, resultsValues);
+ return ExecuteConditionalStatementInternal(Simulator,
+ statement,
+ onEqualOp,
+ onNonEqualOp,
+ type,
+ ctrls);
+ }
+
+ private static QVoid ExecuteConditionalStatement(QuantumProcessorDispatcher Simulator,
+ Result measurementResult,
+ Result resultValue,
+ ICallable onEqualOp,
+ ICallable onNonEqualOp,
+ OperationFunctor type,
+ IQArray ctrls)
+ {
+ long statement = Simulator.QuantumProcessor.StartConditionalStatement(measurementResult, resultValue);
+ return ExecuteConditionalStatementInternal(Simulator,
+ statement,
+ onEqualOp,
+ onNonEqualOp,
+ type,
+ ctrls);
+ }
+
+
+ public class QuantumProcessorApplyIfElse : Extensions.ApplyIfElseIntrinsic
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorApplyIfElse(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(Result, ICallable, ICallable), QVoid> Body => (q) =>
+ {
+ var (measurementResult, onZero, onOne) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null);
+ };
+ }
+
+ public class QuantumProcessorApplyIfElseA : Extensions.ApplyIfElseIntrinsicA
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorApplyIfElseA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(Result, IAdjointable, IAdjointable), QVoid> Body => (q) =>
+ {
+ var (measurementResult, onZero, onOne) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null);
+ };
+
+ public override Func<(Result, IAdjointable, IAdjointable), QVoid> AdjointBody => (q) =>
+ {
+ var (measurementResult, onZero, onOne) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null);
+ };
+ }
+
+ public class QuantumProcessorApplyIfElseC : Extensions.ApplyIfElseIntrinsicC
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorApplyIfElseC(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(Result, IControllable, IControllable), QVoid> Body => (q) =>
+ {
+ var (measurementResult, onZero, onOne) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null);
+ };
+
+ public override Func<(IQArray, (Result, IControllable, IControllable)), QVoid> ControlledBody => (q) =>
+ {
+ var (ctrls, (measurementResult, onZero, onOne)) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls);
+ };
+ }
+
+ public class QuantumProcessorApplyIfElseCA : Extensions.ApplyIfElseIntrinsicCA
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorApplyIfElseCA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(Result, IUnitary, IUnitary), QVoid> Body => (q) =>
+ {
+ var (measurementResult, onZero, onOne) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null);
+ };
+
+ public override Func<(Result, IUnitary, IUnitary), QVoid> AdjointBody => (q) =>
+ {
+ var (measurementResult, onZero, onOne) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null);
+ };
+
+ public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> ControlledBody => (q) =>
+ {
+ var (ctrls, (measurementResult, onZero, onOne)) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls);
+ };
+
+ public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> ControlledAdjointBody => (q) =>
+ {
+ var (ctrls, (measurementResult, onZero, onOne)) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.ControlledAdjoint, ctrls);
+ };
+ }
+
+
+
+ public class QuantumProcessorApplyConditionally : Extensions.ApplyConditionallyIntrinsic
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorApplyConditionally(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(IQArray, IQArray, ICallable, ICallable), QVoid> Body => (q) =>
+ {
+ var (measurementResults, resultsValues, onEqualOp, onNonEqualOp) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null);
+ };
+ }
+
+ public class QuantumProcessorApplyConditionallyA : Extensions.ApplyConditionallyIntrinsicA
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorApplyConditionallyA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> Body => (q) =>
+ {
+ var (measurementResults, resultsValues, onEqualOp, onNonEqualOp) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null);
+ };
+
+ public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> AdjointBody => (q) =>
+ {
+ var (measurementResults, resultsValues, onEqualOp, onNonEqualOp) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null);
+ };
+ }
+
+ public class QuantumProcessorApplyConditionallyC : Extensions.ApplyConditionallyIntrinsicC
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorApplyConditionallyC(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(IQArray, IQArray, IControllable, IControllable), QVoid> Body => (q) =>
+ {
+ var (measurementResults, resultsValues, onEqualOp, onNonEqualOp) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null);
+ };
+
+ public override Func<(IQArray, (IQArray, IQArray, IControllable, IControllable)), QVoid> ControlledBody => (q) =>
+ {
+ var (ctrls, (measurementResults, resultsValues, onEqualOp, onNonEqualOp)) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls);
+ };
+ }
+
+ public class QuantumProcessorApplyConditionallyCA : Extensions.ApplyConditionallyIntrinsicCA
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorApplyConditionallyCA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> Body => (q) =>
+ {
+ var (measurementResults, resultsValues, onEqualOp, onNonEqualOp) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null);
+ };
+
+ public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> AdjointBody => (q) =>
+ {
+ var (measurementResults, resultsValues, onEqualOp, onNonEqualOp) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null);
+ };
+
+ public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> ControlledBody => (q) =>
+ {
+ var (ctrls, (measurementResults, resultsValues, onEqualOp, onNonEqualOp)) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls);
+ };
+
+ public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> ControlledAdjointBody => (q) =>
+ {
+ var (ctrls, (measurementResults, resultsValues, onEqualOp, onNonEqualOp)) = q;
+ return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.ControlledAdjoint, ctrls);
+ };
+ }
+
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.qs b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.qs
new file mode 100644
index 00000000000..f9bd481641d
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.qs
@@ -0,0 +1,185 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor.Extensions
+{
+ open Microsoft.Quantum.Intrinsic;
+
+ operation NoOp() : Unit is Ctl + Adj {}
+
+ // Private helper operations.
+ operation Delay<'T>(op : ('T => Unit), arg : 'T, aux : Unit) : Unit {
+ op(arg);
+ }
+
+ operation DelayC<'T>(op : ('T => Unit is Ctl), arg : 'T, aux : Unit) : Unit is Ctl {
+ op(arg);
+ }
+
+ operation DelayA<'T>(op : ('T => Unit is Adj), arg : 'T, aux : Unit) : Unit is Adj {
+ op(arg);
+ }
+
+ operation DelayCA<'T>(op : ('T => Unit is Ctl + Adj), arg : 'T, aux : Unit) : Unit is Ctl + Adj {
+ op(arg);
+ }
+
+
+ // Private helper operations.
+ operation ApplyIfElseIntrinsic(measurementResult : Result, onResultZeroOp : (Unit => Unit) , onResultOneOp : (Unit => Unit)) : Unit {
+ body intrinsic;
+ }
+
+ operation ApplyIfElseIntrinsicA(measurementResult : Result, onResultZeroOp : (Unit => Unit is Adj) , onResultOneOp : (Unit => Unit is Adj)) : Unit {
+ body intrinsic;
+ adjoint intrinsic;
+ }
+
+ operation ApplyIfElseIntrinsicC(measurementResult : Result, onResultZeroOp : (Unit => Unit is Ctl) , onResultOneOp : (Unit => Unit is Ctl)) : Unit {
+ body intrinsic;
+ controlled intrinsic;
+ }
+
+ operation ApplyIfElseIntrinsicCA(measurementResult : Result, onResultZeroOp : (Unit => Unit is Ctl + Adj) , onResultOneOp : (Unit => Unit is Ctl + Adj)) : Unit {
+ body intrinsic;
+ adjoint intrinsic;
+ controlled intrinsic;
+ controlled adjoint intrinsic;
+ }
+
+
+ // Private helper operations.
+ operation ApplyConditionallyIntrinsic(measurementResults : Result[], resultsValues : Result[], onEqualOp : (Unit => Unit) , onNonEqualOp : (Unit => Unit)) : Unit {
+ body intrinsic;
+ }
+
+ operation ApplyConditionallyIntrinsicA(measurementResults : Result[], resultsValues : Result[], onEqualOp : (Unit => Unit is Adj) , onNonEqualOp : (Unit => Unit is Adj)) : Unit is Adj {
+ body intrinsic;
+ adjoint intrinsic;
+ }
+
+ operation ApplyConditionallyIntrinsicC(measurementResults : Result[], resultsValues : Result[], onEqualOp : (Unit => Unit is Ctl) , onNonEqualOp : (Unit => Unit is Ctl)) : Unit is Ctl {
+ body intrinsic;
+ controlled intrinsic;
+ }
+
+ operation ApplyConditionallyIntrinsicCA(measurementResults : Result[], resultsValues : Result[], onEqualOp : (Unit => Unit is Ctl + Adj) , onNonEqualOp : (Unit => Unit is Ctl + Adj)) : Unit is Ctl + Adj {
+ body intrinsic;
+ adjoint intrinsic;
+ controlled intrinsic;
+ controlled adjoint intrinsic;
+ }
+
+
+ // Public operations that match Canon names.
+ // This corresponds to "if" statement of the following form in Q#:
+ // if (measurementResult == Zero) {onResultZeroOp(zeroArg);} else {onResultOneOp(oneArg);}
+ operation ApplyIfElseR<'T,'U>(measurementResult : Result, (onResultZeroOp : ('T => Unit), zeroArg : 'T) , (onResultOneOp : ('U => Unit), oneArg : 'U)) : Unit {
+ let zeroOp = Delay(onResultZeroOp, zeroArg, _);
+ let oneOp = Delay(onResultOneOp, oneArg, _);
+ ApplyIfElseIntrinsic(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfElseRA<'T,'U>(measurementResult : Result, (onResultZeroOp : ('T => Unit is Adj), zeroArg : 'T) , (onResultOneOp : ('U => Unit is Adj), oneArg : 'U)) : Unit is Adj {
+ let zeroOp = DelayA(onResultZeroOp, zeroArg, _);
+ let oneOp = DelayA(onResultOneOp, oneArg, _);
+ ApplyIfElseIntrinsicA(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfElseRC<'T,'U>(measurementResult : Result, (onResultZeroOp : ('T => Unit is Ctl), zeroArg : 'T) , (onResultOneOp : ('U => Unit is Ctl), oneArg : 'U)) : Unit is Ctl {
+ let zeroOp = DelayC(onResultZeroOp, zeroArg, _);
+ let oneOp = DelayC(onResultOneOp, oneArg, _);
+ ApplyIfElseIntrinsicC(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfElseCA<'T,'U>(measurementResult : Result, (onResultZeroOp : ('T => Unit is Adj + Ctl), zeroArg : 'T) , (onResultOneOp : ('U => Unit is Adj + Ctl), oneArg : 'U)) : Unit is Ctl + Adj {
+ let zeroOp = DelayCA(onResultZeroOp, zeroArg, _);
+ let oneOp = DelayCA(onResultOneOp, oneArg, _);
+ ApplyIfElseIntrinsicCA(measurementResult, zeroOp, oneOp);
+ }
+
+
+ // Public operations that match Canon names.
+ // This corresponds to "if" statement of the following form in Q#:
+ // if (measurementResult == Zero) {onResultZeroOp(zeroArg);}
+ operation ApplyIfZero<'T>(measurementResult : Result, (onResultZeroOp : ('T => Unit), zeroArg : 'T)) : Unit {
+ let zeroOp = Delay(onResultZeroOp, zeroArg, _);
+ let oneOp = Delay(NoOp, (), _);
+ ApplyIfElseIntrinsic(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfZeroA<'T>(measurementResult : Result, (onResultZeroOp : ('T => Unit is Adj), zeroArg : 'T)) : Unit is Adj{
+ let zeroOp = DelayA(onResultZeroOp, zeroArg, _);
+ let oneOp = DelayA(NoOp, (), _);
+ ApplyIfElseIntrinsicA(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfZeroC<'T>(measurementResult : Result, (onResultZeroOp : ('T => Unit is Ctl), zeroArg : 'T)) : Unit is Ctl {
+ let zeroOp = DelayC(onResultZeroOp, zeroArg, _);
+ let oneOp = DelayC(NoOp, (), _);
+ ApplyIfElseIntrinsicC(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfZeroCA<'T>(measurementResult : Result, (onResultZeroOp : ('T => Unit is Ctl + Adj), zeroArg : 'T)) : Unit is Ctl + Adj {
+ let zeroOp = DelayCA(onResultZeroOp, zeroArg, _);
+ let oneOp = DelayCA(NoOp, (), _);
+ ApplyIfElseIntrinsicCA(measurementResult, zeroOp, oneOp);
+ }
+
+
+ // Public operations that match Canon names.
+ // This corresponds to "if" statement of the following form in Q#:
+ // if (measurementResult == One) {onResultOneOp(oneArg);}
+ operation ApplyIfOne<'T>(measurementResult : Result, (onResultOneOp : ('T => Unit), oneArg : 'T)) : Unit {
+ let oneOp = Delay(onResultOneOp, oneArg, _);
+ let zeroOp = Delay(NoOp, (), _);
+ ApplyIfElseIntrinsic(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfOneA<'T>(measurementResult : Result, (onResultOneOp : ('T => Unit is Adj), oneArg : 'T)) : Unit is Adj {
+ let oneOp = DelayA(onResultOneOp, oneArg, _);
+ let zeroOp = DelayA(NoOp, (), _);
+ ApplyIfElseIntrinsicA(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfOneC<'T>(measurementResult : Result, (onResultOneOp : ('T => Unit is Ctl), oneArg : 'T)) : Unit is Ctl {
+ let oneOp = DelayC(onResultOneOp, oneArg, _);
+ let zeroOp = DelayC(NoOp, (), _);
+ ApplyIfElseIntrinsicC(measurementResult, zeroOp, oneOp);
+ }
+
+ operation ApplyIfOneCA<'T>(measurementResult : Result, (onResultOneOp : ('T => Unit is Ctl + Adj), oneArg : 'T)) : Unit is Ctl + Adj {
+ let oneOp = DelayCA(onResultOneOp, oneArg, _);
+ let zeroOp = DelayCA(NoOp, (), _);
+ ApplyIfElseIntrinsicCA(measurementResult, zeroOp, oneOp);
+ }
+
+
+ // Public operations that match Canon names.
+ // This corresponds to "if" statement of the following form in Q#:
+ // if ((measurementResults[0] == resultsValues[0]) && (measurementResults[1] == resultsValues[1])) {onEqualOp(equalArg);} else {onNonEqualOp(nonEqualArg);}
+ operation ApplyConditionally<'T,'U>(measurementResults : Result[], resultsValues : Result[], (onEqualOp : ('T => Unit), equalArg : 'T) , (onNonEqualOp : ('U => Unit), nonEqualArg : 'U)) : Unit {
+ let equalOp = Delay(onEqualOp,equalArg,_);
+ let nonEqualOp = Delay(onNonEqualOp,nonEqualArg,_);
+ ApplyConditionallyIntrinsic(measurementResults, resultsValues, equalOp, nonEqualOp);
+ }
+
+ operation ApplyConditionallyA<'T,'U>(measurementResults : Result[], resultsValues : Result[], (onEqualOp : ('T => Unit is Adj), equalArg : 'T) , (onNonEqualOp : ('U => Unit is Adj), nonEqualArg : 'U)) : Unit is Adj {
+ let equalOp = DelayA(onEqualOp, equalArg, _);
+ let nonEqualOp = DelayA(onNonEqualOp, nonEqualArg, _);
+ ApplyConditionallyIntrinsicA(measurementResults, resultsValues, equalOp, nonEqualOp);
+ }
+
+ operation ApplyConditionallyC<'T,'U>(measurementResults : Result[], resultsValues : Result[], (onEqualOp : ('T => Unit is Ctl), equalArg : 'T) , (onNonEqualOp : ('U => Unit is Ctl), nonEqualArg : 'U)) : Unit is Ctl {
+ let equalOp = DelayC(onEqualOp, equalArg, _);
+ let nonEqualOp = DelayC(onNonEqualOp, nonEqualArg, _);
+ ApplyConditionallyIntrinsicC(measurementResults, resultsValues, equalOp, nonEqualOp);
+ }
+
+ operation ApplyConditionallyCA<'T,'U>(measurementResults : Result[], resultsValues : Result[], (onEqualOp : ('T => Unit is Ctl + Adj), equalArg : 'T) , (onNonEqualOp : ('U => Unit is Ctl + Adj), nonEqualArg : 'U)) : Unit is Ctl + Adj {
+ let equalOp = DelayCA(onEqualOp, equalArg, _);
+ let nonEqualOp = DelayCA(onNonEqualOp, nonEqualArg, _);
+ ApplyConditionallyIntrinsicCA(measurementResults, resultsValues, equalOp, nonEqualOp);
+ }
+
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/Dump.cs b/src/Simulation/Simulators/QuantumProcessor/Dump.cs
new file mode 100644
index 00000000000..a0b2ce227f7
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Dump.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherDumpMachine : Quantum.Diagnostics.DumpMachine
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherDumpMachine(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (location) =>
+ {
+ if (location == null) { throw new ArgumentNullException(nameof(location)); }
+
+ this.Simulator.QuantumProcessor.OnDumpMachine(location);
+ return QVoid.Instance;
+ };
+ }
+
+ public class QuantumProcessorDispatcherDumpRegister : Quantum.Diagnostics.DumpRegister
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+
+ public QuantumProcessorDispatcherDumpRegister(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(T, IQArray), QVoid> Body => (__in) =>
+ {
+ var (location, qubits) = __in;
+
+ if (location == null) { throw new ArgumentNullException(nameof(location)); }
+ this.Simulator.QuantumProcessor.OnDumpRegister(location, qubits);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/Exp.cs b/src/Simulation/Simulators/QuantumProcessor/Exp.cs
new file mode 100644
index 00000000000..90f981a996b
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Exp.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Common;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherExp : Quantum.Intrinsic.Exp
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherExp(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(IQArray, double, IQArray), QVoid> Body => (_args) =>
+ {
+ var (paulis, theta, qubits) = _args;
+
+ if (paulis.Length != qubits.Length)
+ {
+ throw new InvalidOperationException($"Both input arrays for {this.GetType().Name} (paulis,qubits), must be of same size.");
+ }
+
+ CommonUtils.PruneObservable(paulis, qubits, out QArray newPaulis, out QArray newQubits);
+ Simulator.QuantumProcessor.Exp(newPaulis, theta, newQubits);
+
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, double, IQArray), QVoid> AdjointBody => (_args) =>
+ {
+ var (paulis, angle, qubits) = _args;
+ return this.Body.Invoke((paulis, -angle, qubits));
+ };
+
+ public override Func<(IQArray, (IQArray, double, IQArray)), QVoid> ControlledBody => (_args) =>
+ {
+ var (ctrls, (paulis, theta, qubits)) = _args;
+
+ CommonUtils.PruneObservable(paulis, qubits, out QArray newPaulis, out QArray newQubits);
+ Simulator.QuantumProcessor.ControlledExp(ctrls, newPaulis, theta, newQubits);
+
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, (IQArray, double, IQArray)), QVoid> ControlledAdjointBody => (_args) =>
+ {
+ var (ctrls, (paulis, angle, qubits)) = _args;
+
+ return this.ControlledBody.Invoke((ctrls, (paulis, -angle, qubits)));
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/ExpFrac.cs b/src/Simulation/Simulators/QuantumProcessor/ExpFrac.cs
new file mode 100644
index 00000000000..5d9eda03e5a
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/ExpFrac.cs
@@ -0,0 +1,65 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Quantum.Simulation.Common;
+using Microsoft.Quantum.Simulation.Core;
+using System;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherExpFrac : Quantum.Intrinsic.ExpFrac
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherExpFrac(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; }
+
+ public override Func<(IQArray, long, long, IQArray), QVoid> Body => (_args) =>
+ {
+ var (paulis, nom, den, qubits) = _args;
+
+ if (paulis.Length != qubits.Length)
+ {
+ throw new InvalidOperationException(
+ $"Both input arrays for {this.GetType().Name} (paulis,qubits), must be of same size.");
+ }
+
+ CommonUtils.PruneObservable(paulis, qubits, out QArray newPaulis, out QArray newQubits);
+
+ Simulator.QuantumProcessor.ExpFrac(newPaulis, nom, den, newQubits);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, long, long, IQArray), QVoid> AdjointBody => (_args) =>
+ {
+ var (paulis, nom, den, qubits) = _args;
+ return this.Body.Invoke((paulis, -nom, den, qubits));
+ };
+
+ public override Func<(IQArray, (IQArray, long, long, IQArray)), QVoid>
+ ControlledBody => (_args) =>
+ {
+ var (ctrls, (paulis, nom, den, qubits)) = _args;
+
+ if (paulis.Length != qubits.Length)
+ {
+ throw new InvalidOperationException(
+ $"Both input arrays for {this.GetType().Name} (paulis,qubits), must be of same size.");
+ }
+ CommonUtils.PruneObservable(paulis, qubits, out QArray newPaulis, out QArray newQubits);
+ Simulator.QuantumProcessor.ControlledExpFrac(ctrls, newPaulis, nom, den, newQubits);
+
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, (IQArray, long, long, IQArray)), QVoid>
+ ControlledAdjointBody => (_args) =>
+ {
+ var (ctrls, (paulis, nom, den, qubits)) = _args;
+
+ return this.ControlledBody.Invoke((ctrls, (paulis, -nom, den, qubits)));
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/H.cs b/src/Simulation/Simulators/QuantumProcessor/H.cs
new file mode 100644
index 00000000000..e92bb13f6e2
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/H.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherH : Quantum.Intrinsic.H
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherH(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (q1) =>
+ {
+ Simulator.QuantumProcessor.H(q1);
+ return QVoid.Instance;
+ };
+
+
+ public override Func<(IQArray, Qubit), QVoid> ControlledBody => (args) =>
+ {
+ var (ctrls, q1) = args;
+ Simulator.QuantumProcessor.ControlledH(ctrls, q1);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/M.cs b/src/Simulation/Simulators/QuantumProcessor/M.cs
new file mode 100644
index 00000000000..adf46ea18ef
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/M.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherM : Quantum.Intrinsic.M
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherM(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (q) =>
+ {
+ return Simulator.QuantumProcessor.M(q);
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/Measure.cs b/src/Simulation/Simulators/QuantumProcessor/Measure.cs
new file mode 100644
index 00000000000..04b93b71162
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Measure.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Common;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherMeasure : Quantum.Intrinsic.Measure
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherMeasure(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(IQArray, IQArray), Result> Body => (_args) =>
+ {
+ var (paulis, qubits) = _args;
+
+ if (paulis.Length != qubits.Length)
+ {
+ throw new InvalidOperationException($"Both input arrays for {this.GetType().Name} (paulis,qubits), must be of same size");
+ }
+
+ CommonUtils.PruneObservable(paulis, qubits, out QArray newPaulis, out QArray newQubits);
+ return Simulator.QuantumProcessor.Measure( newPaulis, newQubits);
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/QuantumProcessorDispatcher.cs b/src/Simulation/Simulators/QuantumProcessor/QuantumProcessorDispatcher.cs
new file mode 100644
index 00000000000..54d937add40
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/QuantumProcessorDispatcher.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Common;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ ///
+ /// Dispatcher (Simulator) that redirects all the calls to a class implementing interface.
+ ///
+ public partial class QuantumProcessorDispatcher : SimulatorBase
+ {
+ private const int PreallocatedQubitCount = 256;
+ ///
+ /// Random number generator used for Microsoft.Quantum.Intrinsic.Random
+ ///
+ public readonly System.Random random;
+
+ public override string Name => "QuantumProcessorDispatcher";
+
+ ///
+ /// An instance of a class implementing interface that this simulator wraps.
+ ///
+ public IQuantumProcessor QuantumProcessor
+ {
+ get;
+ private set;
+ }
+
+ ///
+ ///
+ ///
+ /// An instance of a class implementing interface to be wrapped. If the parameter is null is used.
+ /// An instance of a class implementing interface. If the parameter is null is used.
+ /// A seed to be used by Q# Microsoft.Quantum.Intrinsic.Random operation.
+ public QuantumProcessorDispatcher(IQuantumProcessor quantumProcessor = null, IQubitManager qubitManager = null, int? randomSeed = null)
+ : base(qubitManager ?? new QubitManagerTrackingScope(PreallocatedQubitCount, mayExtendCapacity:true, disableBorrowing:false))
+ {
+ random = new System.Random(randomSeed == null ? DateTime.Now.Millisecond : randomSeed.Value);
+ QuantumProcessor = quantumProcessor ?? new QuantumProcessorBase();
+ OnOperationStart += QuantumProcessor.OnOperationStart;
+ OnOperationEnd += QuantumProcessor.OnOperationEnd;
+ OnFail += QuantumProcessor.OnFail;
+ OnLog += QuantumProcessor.OnMessage;
+ }
+
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/R.cs b/src/Simulation/Simulators/QuantumProcessor/R.cs
new file mode 100644
index 00000000000..cd3307d2acf
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/R.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherR : Quantum.Intrinsic.R
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+
+ public QuantumProcessorDispatcherR(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(Pauli, double, Qubit), QVoid> Body => (_args) =>
+ {
+ var (basis, angle, q1) = _args;
+ if (basis != Pauli.PauliI)
+ {
+ Simulator.QuantumProcessor.R(basis, angle,q1);
+ }
+ return QVoid.Instance;
+ };
+
+ public override Func<(Pauli, double, Qubit), QVoid> AdjointBody => (_args) =>
+ {
+ var (basis, angle, q1) = _args;
+ return this.Body.Invoke((basis, -angle, q1));
+ };
+
+ public override Func<(IQArray, (Pauli, double, Qubit)), QVoid> ControlledBody => (_args) =>
+ {
+ var (ctrls, (basis, angle, q1)) = _args;
+ Simulator.QuantumProcessor.ControlledR(ctrls, basis, angle, q1);
+ return QVoid.Instance;
+ };
+
+
+ public override Func<(IQArray, (Pauli, double, Qubit)), QVoid> ControlledAdjointBody => (_args) =>
+ {
+ var (ctrls, (basis, angle, q1)) = _args;
+ return this.ControlledBody.Invoke((ctrls, (basis, -angle, q1)));
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/R1.cs b/src/Simulation/Simulators/QuantumProcessor/R1.cs
new file mode 100644
index 00000000000..401caf9f380
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/R1.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherR1 : Quantum.Intrinsic.R1
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherR1(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(double, Qubit), QVoid> Body => (_args) =>
+ {
+ var (angle, q1) = _args;
+ Simulator.QuantumProcessor.R1(angle, q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(double, Qubit), QVoid> AdjointBody => (_args) =>
+ {
+ var (angle, q1) = _args;
+ return this.Body.Invoke((-angle, q1));
+ };
+
+ public override Func<(IQArray, ( double, Qubit)), QVoid> ControlledBody => (_args) =>
+ {
+ var (ctrls, (angle, q1)) = _args;
+ Simulator.QuantumProcessor.ControlledR1(ctrls, angle, q1);
+ return QVoid.Instance;
+ };
+
+
+ public override Func<(IQArray, (double, Qubit)), QVoid> ControlledAdjointBody => (_args) =>
+ {
+ var (ctrls, (angle, q1)) = _args;
+ return this.ControlledBody.Invoke((ctrls, (-angle, q1)));
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/R1Frac.cs b/src/Simulation/Simulators/QuantumProcessor/R1Frac.cs
new file mode 100644
index 00000000000..64808e823ad
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/R1Frac.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Common;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherR1Frac : Quantum.Intrinsic.R1Frac
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherR1Frac(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(long, long, Qubit), QVoid> Body => (_args) =>
+ {
+ var (num, denom , q1) = _args;
+ var (numNew, denomNew) = CommonUtils.Reduce(num, denom);
+ Simulator.QuantumProcessor.R1Frac(numNew, denomNew, q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(long, long, Qubit), QVoid> AdjointBody => (_args) =>
+ {
+ var (num, denom, q1) = _args;
+ return this.Body.Invoke((-num, denom, q1));
+ };
+
+ public override Func<(IQArray, (long, long, Qubit)), QVoid> ControlledBody => (_args) =>
+ {
+ var (ctrls, (num, denom, q1)) = _args;
+ var (numNew, denomNew) = CommonUtils.Reduce(num, denom);
+ Simulator.QuantumProcessor.ControlledR1Frac(ctrls, numNew, denomNew, q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, (long, long, Qubit)), QVoid> ControlledAdjointBody => (_args) =>
+ {
+ var (ctrls, (num, denom, q1)) = _args;
+ return this.ControlledBody.Invoke((ctrls, (-num, denom, q1)));
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/RFrac.cs b/src/Simulation/Simulators/QuantumProcessor/RFrac.cs
new file mode 100644
index 00000000000..6164863b740
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/RFrac.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Common;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherRFrac : Quantum.Intrinsic.RFrac
+ {
+
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherRFrac(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(Pauli, long, long, Qubit), QVoid> Body => (_args) =>
+ {
+ var (basis, num, denom , q1) = _args;
+ if (basis != Pauli.PauliI)
+ {
+ var (numNew, denomNew) = CommonUtils.Reduce(num, denom);
+ Simulator.QuantumProcessor.RFrac(basis, numNew, denomNew, q1);
+ }
+ return QVoid.Instance;
+ };
+
+ public override Func<(Pauli, long, long, Qubit), QVoid> AdjointBody => (_args) =>
+ {
+ var (basis, num, denom, q1) = _args;
+ return this.Body.Invoke((basis, -num, denom, q1));
+ };
+
+ public override Func<(IQArray, (Pauli, long, long, Qubit)), QVoid> ControlledBody => (_args) =>
+ {
+ var (ctrls, (basis, num, denom, q1)) = _args;
+ var (numNew, denomNew) = CommonUtils.Reduce(num, denom);
+ Simulator.QuantumProcessor.ControlledRFrac(ctrls, basis, numNew, denomNew, q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, (Pauli, long, long, Qubit)), QVoid> ControlledAdjointBody => (_args) =>
+ {
+ var (ctrls, (basis, num, denom, q1)) = _args;
+ return this.ControlledBody.Invoke((ctrls, (basis, -num, denom, q1)));
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/Release.cs b/src/Simulation/Simulators/QuantumProcessor/Release.cs
new file mode 100644
index 00000000000..84424d3daa0
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Release.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherRelease : Intrinsic.Release
+ {
+ private readonly QuantumProcessorDispatcher sim;
+ public QuantumProcessorDispatcherRelease(QuantumProcessorDispatcher m) : base(m){
+ sim = m;
+ }
+
+ public override void Apply(Qubit q)
+ {
+ sim.QuantumProcessor.OnReleaseQubits(new QArray(q));
+ sim.QubitManager.Release(q);
+ }
+
+ public override void Apply(IQArray qubits)
+ {
+ sim.QuantumProcessor.OnReleaseQubits(qubits);
+ sim.QubitManager.Release(qubits);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Simulation/Simulators/QuantumProcessor/Reset.cs b/src/Simulation/Simulators/QuantumProcessor/Reset.cs
new file mode 100644
index 00000000000..4ebee59437a
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Reset.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherReset : Quantum.Intrinsic.Reset
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherReset(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (q1) =>
+ {
+ Simulator.QuantumProcessor.Reset(q1);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/Return.cs b/src/Simulation/Simulators/QuantumProcessor/Return.cs
new file mode 100644
index 00000000000..db541624ef3
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Return.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ using Microsoft.Quantum.Simulation.Core;
+
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherReturn : Intrinsic.Return
+ {
+ private readonly QuantumProcessorDispatcher sim;
+ public QuantumProcessorDispatcherReturn(QuantumProcessorDispatcher m) : base(m){
+ sim = m;
+ }
+
+ public override void Apply(Qubit q)
+ {
+ sim.QuantumProcessor.OnReturnQubits(new QArray(q));
+ sim.QubitManager.Return(q);
+ }
+
+ public override void Apply(IQArray qubits)
+ {
+ sim.QuantumProcessor.OnReturnQubits(qubits);
+ sim.QubitManager.Return(qubits);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Simulation/Simulators/QuantumProcessor/S.cs b/src/Simulation/Simulators/QuantumProcessor/S.cs
new file mode 100644
index 00000000000..84bac1a1ed9
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/S.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherS : Quantum.Intrinsic.S
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherS(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (q1) =>
+ {
+ Simulator.QuantumProcessor.S(q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, Qubit), QVoid> ControlledBody => (_args) =>
+ {
+ (IQArray ctrls, Qubit q1) = _args;
+ Simulator.QuantumProcessor.ControlledS(ctrls, q1);
+ return QVoid.Instance;
+ };
+
+ public override Func AdjointBody => (q1) =>
+ {
+ Simulator.QuantumProcessor.SAdjoint(q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, Qubit), QVoid> ControlledAdjointBody => (_args) =>
+ {
+ (IQArray ctrls, Qubit q1) = _args;
+ Simulator.QuantumProcessor.ControlledSAdjoint(ctrls, q1);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/SWAP.cs b/src/Simulation/Simulators/QuantumProcessor/SWAP.cs
new file mode 100644
index 00000000000..edb95bf4c63
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/SWAP.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherSWAP : Quantum.Intrinsic.SWAP
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherSWAP(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func<(Qubit,Qubit), QVoid> Body => (q1) =>
+ {
+ Simulator.QuantumProcessor.SWAP(q1.Item1, q1.Item2);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, (Qubit, Qubit)), QVoid> ControlledBody => (args) =>
+ {
+ var (ctrls, q1) = args;
+ Simulator.QuantumProcessor.ControlledSWAP(ctrls, q1.Item1, q1.Item2);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/T.cs b/src/Simulation/Simulators/QuantumProcessor/T.cs
new file mode 100644
index 00000000000..e7d7e295ac4
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/T.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherT : Quantum.Intrinsic.T
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherT(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (q1) =>
+ {
+ Simulator.QuantumProcessor.T(q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, Qubit), QVoid> ControlledBody => (_args) =>
+ {
+ (IQArray ctrls, Qubit q1) = _args;
+
+ Simulator.QuantumProcessor.ControlledT(ctrls, q1);
+
+ return QVoid.Instance;
+ };
+
+ public override Func AdjointBody => (q1) =>
+ {
+ Simulator.QuantumProcessor.TAdjoint(q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, Qubit), QVoid> ControlledAdjointBody => (_args) =>
+ {
+ (IQArray ctrls, Qubit q1) = _args;
+ Simulator.QuantumProcessor.ControlledTAdjoint(ctrls, q1);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/X.cs b/src/Simulation/Simulators/QuantumProcessor/X.cs
new file mode 100644
index 00000000000..1de39069395
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/X.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherX : Quantum.Intrinsic.X
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherX(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (q1) =>
+ {
+ Simulator.QuantumProcessor.X(q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, Qubit), QVoid> ControlledBody => (args) =>
+ {
+ var (ctrls, q1) = args;
+ Simulator.QuantumProcessor.ControlledX(ctrls, q1);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/Y.cs b/src/Simulation/Simulators/QuantumProcessor/Y.cs
new file mode 100644
index 00000000000..e4a7836c7d5
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Y.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherY : Quantum.Intrinsic.Y
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherY(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (q1) =>
+ {
+ Simulator.QuantumProcessor.Y(q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, Qubit), QVoid> ControlledBody => (_args) =>
+ {
+ (IQArray ctrls, Qubit q1) = _args;
+ Simulator.QuantumProcessor.ControlledY(ctrls, q1);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/Z.cs b/src/Simulation/Simulators/QuantumProcessor/Z.cs
new file mode 100644
index 00000000000..b939d1373ef
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/Z.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Quantum.Simulation.Core;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public class QuantumProcessorDispatcherZ : Quantum.Intrinsic.Z
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+
+ public QuantumProcessorDispatcherZ(QuantumProcessorDispatcher m) : base(m)
+ {
+ this.Simulator = m;
+ }
+
+ public override Func Body => (q1) =>
+ {
+ Simulator.QuantumProcessor.Z(q1);
+ return QVoid.Instance;
+ };
+
+ public override Func<(IQArray, Qubit), QVoid> ControlledBody => (_args) =>
+ {
+ (IQArray ctrls, Qubit q1) = _args;
+ Simulator.QuantumProcessor.ControlledZ(ctrls, q1);
+ return QVoid.Instance;
+ };
+ }
+ }
+}
diff --git a/src/Simulation/Simulators/QuantumProcessor/random.cs b/src/Simulation/Simulators/QuantumProcessor/random.cs
new file mode 100644
index 00000000000..d9c51cfa202
--- /dev/null
+++ b/src/Simulation/Simulators/QuantumProcessor/random.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.Quantum.Simulation.Core;
+using System;
+
+namespace Microsoft.Quantum.Simulation.QuantumProcessor
+{
+ public partial class QuantumProcessorDispatcher
+ {
+ public static long SampleDistribution(IQArray unnormalizedDistribution, double uniformZeroOneSample)
+ {
+ double total = 0.0;
+ foreach (double prob in unnormalizedDistribution)
+ {
+ if (prob < 0)
+ {
+ throw new ExecutionFailException("Random expects array of non-negative doubles.");
+ }
+ total += prob;
+ }
+
+ if (total == 0)
+ {
+ throw new ExecutionFailException("Random expects array of non-negative doubles with positive sum.");
+ }
+
+ double sample = uniformZeroOneSample * total;
+ double sum = unnormalizedDistribution[0];
+ for (int i = 0; i < unnormalizedDistribution.Length - 1; ++i)
+ {
+ if (sum >= sample)
+ {
+ return i;
+ }
+ sum += unnormalizedDistribution[i];
+ }
+ return unnormalizedDistribution.Length;
+ }
+
+ public class QuantumProcessorDispatcherRandom : Quantum.Intrinsic.Random
+ {
+ private QuantumProcessorDispatcher Simulator { get; }
+ public QuantumProcessorDispatcherRandom(QuantumProcessorDispatcher m) : base(m)
+ {
+ Simulator = m;
+ }
+
+ public override Func, Int64> Body => (p) =>
+ {
+ return SampleDistribution(p, Simulator.random.NextDouble());
+ };
+ }
+ }
+}