From 8f632a9101f0195e8753833fd97d928ba77c90cf Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Fri, 4 Sep 2020 17:11:33 -0700 Subject: [PATCH 1/6] simulator base api --- src/Simulation/Common/AbstractFactory.cs | 7 +- ...onException.cs => TranslationException.cs} | 0 src/Simulation/Common/QuantumProcessorBase.cs | 40 +---- src/Simulation/Common/SimulatorBase.cs | 142 +++++++++--------- 4 files changed, 82 insertions(+), 107 deletions(-) rename src/Simulation/Common/Exceptions/{QuantumProcessorTranslationException.cs => TranslationException.cs} (100%) diff --git a/src/Simulation/Common/AbstractFactory.cs b/src/Simulation/Common/AbstractFactory.cs index 204936002ee..fc5430288d4 100644 --- a/src/Simulation/Common/AbstractFactory.cs +++ b/src/Simulation/Common/AbstractFactory.cs @@ -3,9 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; - -using Microsoft.Quantum.Simulation.Core; namespace Microsoft.Quantum.Simulation.Common { @@ -18,8 +15,8 @@ namespace Microsoft.Quantum.Simulation.Common /// public abstract class AbstractFactory { - private Dictionary opsOverrides = new Dictionary(); - private Dictionary opsCache = new Dictionary(); + protected Dictionary opsOverrides = new Dictionary(); + protected Dictionary opsCache = new Dictionary(); /// /// Register an override for the given operation. diff --git a/src/Simulation/Common/Exceptions/QuantumProcessorTranslationException.cs b/src/Simulation/Common/Exceptions/TranslationException.cs similarity index 100% rename from src/Simulation/Common/Exceptions/QuantumProcessorTranslationException.cs rename to src/Simulation/Common/Exceptions/TranslationException.cs diff --git a/src/Simulation/Common/QuantumProcessorBase.cs b/src/Simulation/Common/QuantumProcessorBase.cs index 26783f7fdea..d24c5324677 100644 --- a/src/Simulation/Common/QuantumProcessorBase.cs +++ b/src/Simulation/Common/QuantumProcessorBase.cs @@ -3,8 +3,6 @@ using System; using Microsoft.Quantum.Simulation.Core; -using System.Diagnostics; -using System.Runtime.CompilerServices; namespace Microsoft.Quantum.Simulation.Common { @@ -12,6 +10,7 @@ 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. /// + [Obsolete] public class QuantumProcessorBase : IQuantumProcessor { public virtual void X(Qubit qubit) @@ -181,35 +180,23 @@ public virtual void Reset(Qubit qubit) public virtual long StartConditionalStatement(IQArray measurementResults, IQArray resultsValues) { - if (measurementResults == null) { return 1; }; - if (resultsValues == null) { return 1; }; - Debug.Assert(measurementResults.Count == resultsValues.Count); - if (measurementResults.Count != resultsValues.Count) { return 1; }; - - int equal = 1; + if (measurementResults == null) { return resultsValues == null ? 1 : 0; }; + if (measurementResults.Count != resultsValues?.Count) { return 0; }; for (int i = 0; i < measurementResults.Count; i++) { if (measurementResults[i] != resultsValues[i]) { - equal = 0; + return 0; } } - return equal; + return 1; } public virtual long StartConditionalStatement(Result measurementResult, Result resultValue) { - - if (measurementResult == resultValue) - { - return 1; - } - else - { - return 0; - } + return measurementResult == resultValue ? 1 : 0; } public virtual bool RunThenClause(long statement) @@ -234,7 +221,6 @@ public virtual bool RepeatElseClause(long statement) public virtual void EndConditionalStatement(long id) { - } public virtual void Assert(IQArray bases, IQArray qubits, Result result, string msg) @@ -286,18 +272,4 @@ public virtual void OnMessage(string msg) } } - - /// - /// A class that implements exception to be thrown when Operation is not supported by a QuantumProcessor. - /// - public class UnsupportedOperationException : PlatformNotSupportedException - { - public UnsupportedOperationException(string text = "", - [CallerFilePath] string file = "", - [CallerMemberName] string member = "", - [CallerLineNumber] int line = 0) - : base($"{file}::{line}::[{member}]:{text}") - { - } - } } diff --git a/src/Simulation/Common/SimulatorBase.cs b/src/Simulation/Common/SimulatorBase.cs index ffb9aef7f0c..bd90ea6bead 100644 --- a/src/Simulation/Common/SimulatorBase.cs +++ b/src/Simulation/Common/SimulatorBase.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.Quantum.Simulation.Core; @@ -12,6 +13,20 @@ namespace Microsoft.Quantum.Simulation.Common { + /// + /// A class that implements exception to be thrown when Operation is not supported by a QuantumProcessor. + /// + public class UnsupportedOperationException : PlatformNotSupportedException + { + public UnsupportedOperationException(string text = "", + [CallerFilePath] string file = "", + [CallerMemberName] string member = "", + [CallerLineNumber] int line = 0) + : base($"{file}::{line}::[{member}]:{text}") + { + } + } + /// /// A Base class for Simulators. /// It provides the infrastructure that makes it easy for a Simulator @@ -31,14 +46,11 @@ public abstract class SimulatorBase : AbstractFactory, IOperat public event Action? OnLog = null; public event Action>? OnException = null; - protected readonly int randomSeed; protected readonly Lazy randomGenerator; public int Seed => randomSeed; protected System.Random RandomGenerator => randomGenerator.Value; - - /// /// An event fired whenever a simulator has additional diagnostic data /// available for display (e.g. state information, assertion details, @@ -50,7 +62,6 @@ public abstract class SimulatorBase : AbstractFactory, IOperat public abstract string Name { get; } - /// /// If the execution finishes in failure, this method returns the call-stack of the Q# operations /// executed up to the point when the failure happened. @@ -82,7 +93,7 @@ public SimulatorBase(IQubitManager? qubitManager = null, int? seed = null) } } - public virtual I Get(Type T) + public I Get(Type T) { return (I)this.GetInstance(T); } @@ -97,7 +108,7 @@ public virtual I Get(Type T) /// If the operation has no body in the Q# file, and no override has been defined in the Simulator, /// this method will throw an InvalidOperationException. /// - public virtual I Get() where T : AbstractCallable, I + public I Get() where T : AbstractCallable, I { var key = typeof(T); return (I)this.GetInstance(key); @@ -271,8 +282,8 @@ public void CheckQubits(IQArray qubits, string arrayName) /// public class Allocate : Intrinsic.Allocate { - private SimulatorBase sim; - private IQubitManager? manager; + protected readonly SimulatorBase sim; + protected readonly IQubitManager manager; public Allocate(SimulatorBase m) : base(m) { @@ -282,26 +293,16 @@ public Allocate(SimulatorBase m) : base(m) public override Qubit Apply() { + Qubit qubit = manager.Allocate(); sim.OnAllocateQubits?.Invoke(1); - return manager.Allocate(); + return qubit; } public override IQArray Apply(long count) { - if (count < 0) - { - throw new InvalidOperationException($"Trying to allocate {count} qubits."); - } - else if (count == 0) - { - sim.OnAllocateQubits?.Invoke(count); - return new QArray(); - } - else - { - sim.OnAllocateQubits?.Invoke(count); - return manager.Allocate(count); - } + IQArray qubits = manager.Allocate(count); + sim.OnAllocateQubits?.Invoke(count); + return qubits; } } @@ -311,8 +312,8 @@ public override IQArray Apply(long count) /// public class Release : Intrinsic.Release { - private SimulatorBase sim; - private IQubitManager manager; + protected readonly SimulatorBase sim; + protected readonly IQubitManager manager; public Release(SimulatorBase m) : base(m) { @@ -339,22 +340,27 @@ public override void Apply(IQArray qubits) /// public class Borrow : Intrinsic.Borrow { - SimulatorBase sim; + protected readonly SimulatorBase sim; + protected readonly IQubitManager manager; public Borrow(SimulatorBase m) : base(m) { - sim = m; + this.sim = m; + this.manager = m.QubitManager; } public override Qubit Apply() { - return sim.QubitManager.Allocate(); + Qubit qubit = manager.Borrow(); + sim.OnBorrowQubits?.Invoke(1); + return qubit; } public override IQArray Apply(long count) { + IQArray qubits = manager.Borrow(count); sim.OnBorrowQubits?.Invoke(count); - return sim.QubitManager.Borrow(count); + return qubits; } } @@ -364,57 +370,44 @@ public override IQArray Apply(long count) /// public class Return : Intrinsic.Return { - SimulatorBase sim; + protected readonly SimulatorBase sim; + protected readonly IQubitManager manager; public Return(SimulatorBase m) : base(m) { - sim = m; + this.sim = m; + this.manager = m.QubitManager; } public override void Apply(Qubit q) { sim.OnReturnQubits?.Invoke(new QArray(new[] { q })); - sim.QubitManager.Return(q); + manager.Return(q); } public override void Apply(IQArray qubits) { sim.OnReturnQubits?.Invoke(qubits); - sim.QubitManager.Return(qubits); + manager.Return(qubits); } } - /// - /// Implements the Log statement as an operation. It just calls Console.WriteLine. - /// - public class Message : Intrinsic.Message - { - private SimulatorBase sim; - public Message(SimulatorBase m) : base(m) - { - sim = m; - } - - public override Func __Body__ => (msg) => - { - sim.OnLog?.Invoke(msg); - return QVoid.Instance; - }; - } - /// /// Implements the GetQubitsAvailableToUse extension function. /// public class GetQubitsAvailableToUse : Environment.GetQubitsAvailableToUse { - private SimulatorBase sim; + protected readonly SimulatorBase sim; + protected readonly IQubitManager manager; public GetQubitsAvailableToUse(SimulatorBase m) : base(m) { - sim = m; + this.sim = m; + this.manager = m.QubitManager; } - public override Func __Body__ => (arg) => sim.QubitManager.GetFreeQubitsCount(); + public override Func __Body__ => (arg) => + manager.GetFreeQubitsCount(); } /// @@ -422,15 +415,34 @@ public GetQubitsAvailableToUse(SimulatorBase m) : base(m) /// public class GetQubitsAvailableToBorrow : Environment.GetQubitsAvailableToBorrow { - private SimulatorBase sim; + protected readonly SimulatorBase sim; + protected readonly IQubitManager manager; public GetQubitsAvailableToBorrow(SimulatorBase m) : base(m) { - sim = m; + this.sim = m; + this.manager = m.QubitManager; } - public override Func __Body__ => (arg) => sim.QubitManager.GetParentQubitsAvailableToBorrowCount() + - sim.QubitManager.GetFreeQubitsCount(); + public override Func __Body__ => (arg) => + manager.GetParentQubitsAvailableToBorrowCount() + manager.GetFreeQubitsCount(); + } + + + /// + /// Implements the Log statement as an operation. It just calls Console.WriteLine. + /// + public class Message : Intrinsic.Message + { + protected readonly SimulatorBase sim; + public Message(SimulatorBase m) : base(m) => + sim = m; + + public override Func __Body__ => (msg) => + { + sim.OnLog?.Invoke(msg); + return QVoid.Instance; + }; } /// @@ -439,12 +451,9 @@ public GetQubitsAvailableToBorrow(SimulatorBase m) : base(m) /// public class DrawRandomInt : Random.DrawRandomInt { - private SimulatorBase sim; - - public DrawRandomInt(SimulatorBase m) : base(m) - { + protected readonly SimulatorBase sim; + public DrawRandomInt(SimulatorBase m) : base(m) => sim = m; - } public override Func<(long, long), long> __Body__ => arg => { @@ -463,12 +472,9 @@ public DrawRandomInt(SimulatorBase m) : base(m) /// public class DrawRandomDouble : Random.DrawRandomDouble { - private SimulatorBase sim; - - public DrawRandomDouble(SimulatorBase m) : base(m) - { + protected readonly SimulatorBase sim; + public DrawRandomDouble(SimulatorBase m) : base(m) => sim = m; - } public override Func<(double, double), double> __Body__ => arg => { From ac35b5e700e1664e036c0cf0b5ef1a1b756af116 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 7 Sep 2020 09:02:44 -0700 Subject: [PATCH 2/6] some classical control refactoring --- src/Simulation/Common/SimulatorBase.cs | 2 +- .../QuantumProcessor/ClassicalControl.cs | 129 ++++++++---------- 2 files changed, 59 insertions(+), 72 deletions(-) diff --git a/src/Simulation/Common/SimulatorBase.cs b/src/Simulation/Common/SimulatorBase.cs index bd90ea6bead..0f27e2d0057 100644 --- a/src/Simulation/Common/SimulatorBase.cs +++ b/src/Simulation/Common/SimulatorBase.cs @@ -498,7 +498,7 @@ public virtual void EndOperation(ICallable operation, IApplyData resultValue) OnOperationEnd?.Invoke(operation, resultValue); } - public virtual void Fail(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionInfo ) + public virtual void Fail(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionInfo) { OnFail?.Invoke(exceptionInfo); } diff --git a/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs index 8b19da839c7..2e4698388f4 100644 --- a/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs +++ b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs @@ -14,72 +14,41 @@ private static void RunClause(ICallable op, OperationFunctor type, IQArray? ctrls) + private void ExecuteConditionalStatementInternal(long statement, ICallable onEqualOp, ICallable onNonEqualOp, OperationFunctor type, IQArray? ctrls) { - bool run; - - run = Simulator.QuantumProcessor.RunThenClause(statement); + bool run = this.QuantumProcessor.RunThenClause(statement); while (run) { RunClause(onEqualOp, type, ctrls); - run = Simulator.QuantumProcessor.RepeatThenClause(statement); + run = this.QuantumProcessor.RepeatThenClause(statement); } - run = Simulator.QuantumProcessor.RunElseClause(statement); + run = this.QuantumProcessor.RunElseClause(statement); while (run) { RunClause(onNonEqualOp, type, ctrls); - run = Simulator.QuantumProcessor.RepeatElseClause(statement); + run = this.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) + private void ExecuteConditionalStatement(IQArray results1, IQArray results2, ICallable onEqual, ICallable onNonEqual, OperationFunctor type, IQArray? ctrls) { - long statement = Simulator.QuantumProcessor.StartConditionalStatement(measurementResults, resultsValues); - return ExecuteConditionalStatementInternal(Simulator, - statement, - onEqualOp, - onNonEqualOp, - type, - ctrls); + long statement = this.QuantumProcessor.StartConditionalStatement(results1, results2); + ExecuteConditionalStatementInternal(statement, onEqual, onNonEqual, type, ctrls); + this.QuantumProcessor.EndConditionalStatement(statement); } - private static QVoid ExecuteConditionalStatement(QuantumProcessorDispatcher Simulator, - Result measurementResult, - Result resultValue, - ICallable onEqualOp, - ICallable onNonEqualOp, - OperationFunctor type, - IQArray? ctrls) + private void ExecuteConditionalStatement(Result result1, Result result2, ICallable onEqualOp, ICallable onNonEqualOp, OperationFunctor type, IQArray? ctrls) { - long statement = Simulator.QuantumProcessor.StartConditionalStatement(measurementResult, resultValue); - return ExecuteConditionalStatementInternal(Simulator, - statement, - onEqualOp, - onNonEqualOp, - type, - ctrls); + long statement = this.QuantumProcessor.StartConditionalStatement(result1, result2); + ExecuteConditionalStatementInternal(statement, onEqualOp, onNonEqualOp, type, ctrls); + this.QuantumProcessor.EndConditionalStatement(statement); } @@ -92,7 +61,8 @@ public class QuantumProcessorApplyIfElse : Extensions.ApplyIfElseIntrinsic public override Func<(Result, ICallable, ICallable), QVoid> __Body__ => (q) => { (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + return QVoid.Instance; }; } @@ -105,13 +75,15 @@ public class QuantumProcessorApplyIfElseA : Extensions.ApplyIfElseIntrinsicA public override Func<(Result, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => { (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + return QVoid.Instance; }; public override Func<(Result, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => { (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); + return QVoid.Instance; }; } @@ -124,7 +96,8 @@ public class QuantumProcessorApplyIfElseC : Extensions.ApplyIfElseIntrinsicC public override Func<(Result, IControllable, IControllable), QVoid> __Body__ => (q) => { (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + return QVoid.Instance; }; public override Func<(IQArray, (Result, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => @@ -132,12 +105,13 @@ public class QuantumProcessorApplyIfElseC : Extensions.ApplyIfElseIntrinsicC (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; if ((ctrls == null) || (ctrls.Count == 0)) { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); } else { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); } + return QVoid.Instance; }; } @@ -150,13 +124,15 @@ public class QuantumProcessorApplyIfElseCA : Extensions.ApplyIfElseIntrinsicCA public override Func<(Result, IUnitary, IUnitary), QVoid> __Body__ => (q) => { (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + return QVoid.Instance; }; public override Func<(Result, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => { (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); + return QVoid.Instance; }; public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => @@ -165,12 +141,13 @@ public class QuantumProcessorApplyIfElseCA : Extensions.ApplyIfElseIntrinsicCA if ((ctrls == null) || (ctrls.Count == 0)) { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); } else { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); } + return QVoid.Instance; }; public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => @@ -179,12 +156,13 @@ public class QuantumProcessorApplyIfElseCA : Extensions.ApplyIfElseIntrinsicCA if ((ctrls == null) || (ctrls.Count == 0)) { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); } else { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.ControlledAdjoint, ctrls); + Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.ControlledAdjoint, ctrls); } + return QVoid.Instance; }; } @@ -199,7 +177,8 @@ public class QuantumProcessorApplyConditionally : Extensions.ApplyConditionallyI public override Func<(IQArray, IQArray, ICallable, ICallable), QVoid> __Body__ => (q) => { (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + return QVoid.Instance; }; } @@ -212,13 +191,15 @@ public class QuantumProcessorApplyConditionallyA : Extensions.ApplyConditionally public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => { (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + return QVoid.Instance; }; public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => { (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); + return QVoid.Instance; }; } @@ -231,7 +212,8 @@ public class QuantumProcessorApplyConditionallyC : Extensions.ApplyConditionally public override Func<(IQArray, IQArray, IControllable, IControllable), QVoid> __Body__ => (q) => { (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + return QVoid.Instance; }; public override Func<(IQArray, (IQArray, IQArray, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => @@ -240,12 +222,13 @@ public class QuantumProcessorApplyConditionallyC : Extensions.ApplyConditionally if ((ctrls == null) || (ctrls.Count == 0)) { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); } else { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); } + return QVoid.Instance; }; } @@ -258,13 +241,15 @@ public class QuantumProcessorApplyConditionallyCA : Extensions.ApplyConditionall public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __Body__ => (q) => { (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + return QVoid.Instance; }; public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => { (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); + return QVoid.Instance; }; public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => @@ -273,12 +258,13 @@ public class QuantumProcessorApplyConditionallyCA : Extensions.ApplyConditionall if ((ctrls == null) || (ctrls.Count == 0)) { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); } else { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); } + return QVoid.Instance; }; public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => @@ -287,12 +273,13 @@ public class QuantumProcessorApplyConditionallyCA : Extensions.ApplyConditionall if ((ctrls == null) || (ctrls.Count == 0)) { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); } else { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.ControlledAdjoint, ctrls); + Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.ControlledAdjoint, ctrls); } + return QVoid.Instance; }; } From 5efe596f3d827ccff588cbf9e760e4d4e72ce426 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 7 Sep 2020 11:09:03 -0700 Subject: [PATCH 3/6] migrated the classical control handling into the simulator --- src/Simulation/Common/SimulatorBase.cs | 294 +++++++++++++++++- .../QuantumProcessor/ClassicalControl.cs | 270 +--------------- 2 files changed, 306 insertions(+), 258 deletions(-) diff --git a/src/Simulation/Common/SimulatorBase.cs b/src/Simulation/Common/SimulatorBase.cs index 0f27e2d0057..eec83363f3c 100644 --- a/src/Simulation/Common/SimulatorBase.cs +++ b/src/Simulation/Common/SimulatorBase.cs @@ -8,13 +8,14 @@ using System.Threading.Tasks; using Microsoft.Quantum.Simulation.Core; +using Microsoft.Quantum.Simulation.QuantumProcessor.Extensions; #nullable enable namespace Microsoft.Quantum.Simulation.Common { /// - /// A class that implements exception to be thrown when Operation is not supported by a QuantumProcessor. + /// A class that implements exception to be thrown when Operation is not supported. /// public class UnsupportedOperationException : PlatformNotSupportedException { @@ -488,6 +489,297 @@ public DrawRandomDouble(SimulatorBase m) : base(m) => }; } + #region Branching based on measurement + + public class ApplyIfElse : ApplyIfElseIntrinsic + { + protected readonly SimulatorBase sim; + public ApplyIfElse(SimulatorBase m) : base(m) => + sim = m; + + public override Func<(Result, ICallable, ICallable), QVoid> __Body__ => (q) => + { + (Result measurementResult, ICallable onZero, ICallable onOne) = q; + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + return QVoid.Instance; + }; + } + + public class ApplyIfElseA : ApplyIfElseIntrinsicA + { + protected readonly SimulatorBase sim; + public ApplyIfElseA(SimulatorBase m) : base(m) => + sim = m; + + public override Func<(Result, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => + { + (Result measurementResult, ICallable onZero, ICallable onOne) = q; + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + return QVoid.Instance; + }; + + public override Func<(Result, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => + { + (Result measurementResult, ICallable onZero, ICallable onOne) = q; + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); + return QVoid.Instance; + }; + } + + public class ApplyIfElseC : ApplyIfElseIntrinsicC + { + protected readonly SimulatorBase sim; + public ApplyIfElseC(SimulatorBase m) : base(m) => + sim = m; + + public override Func<(Result, IControllable, IControllable), QVoid> __Body__ => (q) => + { + (Result measurementResult, ICallable onZero, ICallable onOne) = q; + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + return QVoid.Instance; + }; + + public override Func<(IQArray, (Result, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => + { + (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; + if ((ctrls == null) || (ctrls.Count == 0)) + { + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + } + else + { + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); + } + return QVoid.Instance; + }; + } + + public class ApplyIfElseCA : ApplyIfElseIntrinsicCA + { + protected readonly SimulatorBase sim; + public ApplyIfElseCA(SimulatorBase m) : base(m) => + sim = m; + + public override Func<(Result, IUnitary, IUnitary), QVoid> __Body__ => (q) => + { + (Result measurementResult, ICallable onZero, ICallable onOne) = q; + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + return QVoid.Instance; + }; + + public override Func<(Result, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => + { + (Result measurementResult, ICallable onZero, ICallable onOne) = q; + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); + return QVoid.Instance; + }; + + public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => + { + (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; + + if ((ctrls == null) || (ctrls.Count == 0)) + { + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); + } + else + { + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); + } + return QVoid.Instance; + }; + + public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => + { + (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; + + if ((ctrls == null) || (ctrls.Count == 0)) + { + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); + } + else + { + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.ControlledAdjoint, ctrls); + } + return QVoid.Instance; + }; + } + + public class ApplyConditionally : ApplyConditionallyIntrinsic + { + protected readonly SimulatorBase sim; + public ApplyConditionally(SimulatorBase m) : base(m) => + sim = m; + + public override Func<(IQArray, IQArray, ICallable, ICallable), QVoid> __Body__ => (q) => + { + (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + return QVoid.Instance; + }; + } + + public class ApplyConditionallyA : ApplyConditionallyIntrinsicA + { + protected readonly SimulatorBase sim; + public ApplyConditionallyA(SimulatorBase m) : base(m) => + sim = m; + + public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => + { + (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + return QVoid.Instance; + }; + + public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => + { + (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); + return QVoid.Instance; + }; + } + + public class ApplyConditionallyC : ApplyConditionallyIntrinsicC + { + protected readonly SimulatorBase sim; + public ApplyConditionallyC(SimulatorBase m) : base(m) => + sim = m; + + public override Func<(IQArray, IQArray, IControllable, IControllable), QVoid> __Body__ => (q) => + { + (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + return QVoid.Instance; + }; + + public override Func<(IQArray, (IQArray, IQArray, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => + { + (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; + + if ((ctrls == null) || (ctrls.Count == 0)) + { + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + } + else + { + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); + } + return QVoid.Instance; + }; + } + + public class ApplyConditionallyCA : ApplyConditionallyIntrinsicCA + { + protected readonly SimulatorBase sim; + public ApplyConditionallyCA(SimulatorBase m) : base(m) => + sim = m; + + public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __Body__ => (q) => + { + (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + return QVoid.Instance; + }; + + public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => + { + (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); + return QVoid.Instance; + }; + + public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => + { + (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; + + if ((ctrls == null) || (ctrls.Count == 0)) + { + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); + } + else + { + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); + } + return QVoid.Instance; + }; + + public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => + { + (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; + + if ((ctrls == null) || (ctrls.Count == 0)) + { + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); + } + else + { + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.ControlledAdjoint, ctrls); + } + return QVoid.Instance; + }; + } + + private Action BuildClause(ICallable op, OperationFunctor type, IQArray? ctrls) => + type switch + { + OperationFunctor.Body => () => op.Apply(QVoid.Instance), + OperationFunctor.Adjoint => () => ((IAdjointable)op).Adjoint.Apply(QVoid.Instance), + OperationFunctor.Controlled => () => ((IControllable)op).Controlled.Apply((ctrls, QVoid.Instance)), + OperationFunctor.ControlledAdjoint => () => ((IUnitary)op).Controlled.Adjoint.Apply((ctrls, QVoid.Instance)), + _ => throw new NotImplementedException("unknown specialization"), + }; + + private void BranchingBasedOnMeasurement(IQArray results1, IQArray results2, ICallable onEqual, ICallable onNonEqual, OperationFunctor type, IQArray? ctrls) + { + long statement = this.StartBranchingBasedOnMeasurement(results1, results2); + ExecuteBranchingBasedOnMeasurement(statement, BuildClause(onEqual, type, ctrls), BuildClause(onNonEqual, type, ctrls)); + this.EndBranchingBasedOnMeasurement(statement); + } + + private void BranchingBasedOnMeasurement(Result result1, Result result2, ICallable onEqual, ICallable onNonEqual, OperationFunctor type, IQArray? ctrls) + { + long statement = this.StartBranchingBasedOnMeasurement(result1, result2); + ExecuteBranchingBasedOnMeasurement(statement, BuildClause(onEqual, type, ctrls), BuildClause(onNonEqual, type, ctrls)); + this.EndBranchingBasedOnMeasurement(statement); + } + + public virtual void ExecuteBranchingBasedOnMeasurement(long condition, Action onEqual, Action onNonEqual) + { + switch (condition) + { + case 1: onEqual?.Invoke(); break; + case 0: onNonEqual?.Invoke(); break; + default: throw new NotImplementedException("value for condition was expected to be either 0 (when the condition is false) or 1 (when the condition is true)"); + } + } + + /// + /// By default, 1 indicates that all results are equal, i.e. the statement is to enter the then-clause, + /// and 0 indicates that they are not, i.e. the statement is to enter then else-clause. + /// If both arrays are null, then 1 is returned. + /// + public virtual long StartBranchingBasedOnMeasurement(IQArray results1, IQArray results2) + { + if (results1 == null) { return results2 == null ? 1 : 0; }; + if (results1.Count != results2?.Count) { return 0; }; + return results1.Zip(results2, (r1, r2) => (r1, r2)).Any(pair => pair.r1 != pair.r2) ? 0 : 1; + } + + /// + /// By default, 1 indicates that both results are equal, i.e. the statement is to enter the then-clause. + /// and 0 indicates that they are not, i.e. the statement is to enter then else-clause. + /// + public virtual long StartBranchingBasedOnMeasurement(Result result1, Result result2) + { + return result1 == result2 ? 1 : 0; + } + + public virtual void EndBranchingBasedOnMeasurement(long statement) + { } + + #endregion + public virtual void StartOperation(ICallable operation, IApplyData inputValue) { OnOperationStart?.Invoke(operation, inputValue); diff --git a/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs index 2e4698388f4..c9f8b4bb8e5 100644 --- a/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs +++ b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs @@ -8,280 +8,36 @@ 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, QVoid.Instance)); break; - case OperationFunctor.ControlledAdjoint: ((IUnitary)op).Controlled.Adjoint.Apply((ctrls, QVoid.Instance)); break; - } - } - - private void ExecuteConditionalStatementInternal(long statement, ICallable onEqualOp, ICallable onNonEqualOp, OperationFunctor type, IQArray? ctrls) + public override void ExecuteBranchingBasedOnMeasurement(long condition, Action onEqual, Action onNonEqual) { - bool run = this.QuantumProcessor.RunThenClause(statement); + bool run = this.QuantumProcessor.RunThenClause(condition); while (run) { - RunClause(onEqualOp, type, ctrls); - run = this.QuantumProcessor.RepeatThenClause(statement); + onEqual?.Invoke(); + run = this.QuantumProcessor.RepeatThenClause(condition); } - run = this.QuantumProcessor.RunElseClause(statement); + run = this.QuantumProcessor.RunElseClause(condition); while (run) { - RunClause(onNonEqualOp, type, ctrls); - run = this.QuantumProcessor.RepeatElseClause(statement); + onNonEqual?.Invoke(); + run = this.QuantumProcessor.RepeatElseClause(condition); } } - private void ExecuteConditionalStatement(IQArray results1, IQArray results2, ICallable onEqual, ICallable onNonEqual, OperationFunctor type, IQArray? ctrls) - { - long statement = this.QuantumProcessor.StartConditionalStatement(results1, results2); - ExecuteConditionalStatementInternal(statement, onEqual, onNonEqual, type, ctrls); - this.QuantumProcessor.EndConditionalStatement(statement); - } - - private void ExecuteConditionalStatement(Result result1, Result result2, ICallable onEqualOp, ICallable onNonEqualOp, OperationFunctor type, IQArray? ctrls) - { - long statement = this.QuantumProcessor.StartConditionalStatement(result1, result2); - ExecuteConditionalStatementInternal(statement, onEqualOp, onNonEqualOp, type, ctrls); - this.QuantumProcessor.EndConditionalStatement(statement); - } - - - 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) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - return QVoid.Instance; - }; - } - - public class QuantumProcessorApplyIfElseA : Extensions.ApplyIfElseIntrinsicA + public override long StartBranchingBasedOnMeasurement(Result result1, Result result2) { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyIfElseA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(Result, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - return QVoid.Instance; - }; - - public override Func<(Result, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); - return QVoid.Instance; - }; + return this.QuantumProcessor.StartConditionalStatement(result1, result2); } - public class QuantumProcessorApplyIfElseC : Extensions.ApplyIfElseIntrinsicC + public override long StartBranchingBasedOnMeasurement(IQArray results1, IQArray results2) { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyIfElseC(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(Result, IControllable, IControllable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - return QVoid.Instance; - }; - - public override Func<(IQArray, (Result, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - if ((ctrls == null) || (ctrls.Count == 0)) - { - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - } - else - { - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); - } - return QVoid.Instance; - }; + return this.QuantumProcessor.StartConditionalStatement(results1, results2); } - public class QuantumProcessorApplyIfElseCA : Extensions.ApplyIfElseIntrinsicCA + public override void EndBranchingBasedOnMeasurement(long statement) { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyIfElseCA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(Result, IUnitary, IUnitary), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - return QVoid.Instance; - }; - - public override Func<(Result, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); - return QVoid.Instance; - }; - - public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - } - else - { - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); - } - return QVoid.Instance; - }; - - public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); - } - else - { - Simulator.ExecuteConditionalStatement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.ControlledAdjoint, ctrls); - } - return QVoid.Instance; - }; - } - - - - 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) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - return QVoid.Instance; - }; - } - - 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) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - return QVoid.Instance; - }; - - public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - return QVoid.Instance; - }; - } - - 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) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - return QVoid.Instance; - }; - - public override Func<(IQArray, (IQArray, IQArray, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - } - else - { - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); - } - return QVoid.Instance; - }; - } - - 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) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - return QVoid.Instance; - }; - - public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - return QVoid.Instance; - }; - - public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - } - else - { - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); - } - return QVoid.Instance; - }; - - public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - } - else - { - Simulator.ExecuteConditionalStatement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.ControlledAdjoint, ctrls); - } - return QVoid.Instance; - }; + this.QuantumProcessor.EndConditionalStatement(statement); } - } } From 43da02af078fafd3e117d7668d13c3eb852f95a6 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 7 Sep 2020 11:49:26 -0700 Subject: [PATCH 4/6] minor things --- src/Simulation/Common/QuantumProcessorBase.cs | 23 ++----- src/Simulation/Common/SimulatorBase.cs | 65 ++++--------------- 2 files changed, 19 insertions(+), 69 deletions(-) diff --git a/src/Simulation/Common/QuantumProcessorBase.cs b/src/Simulation/Common/QuantumProcessorBase.cs index d24c5324677..fd9043f8a12 100644 --- a/src/Simulation/Common/QuantumProcessorBase.cs +++ b/src/Simulation/Common/QuantumProcessorBase.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Linq; using Microsoft.Quantum.Simulation.Core; namespace Microsoft.Quantum.Simulation.Common @@ -10,7 +11,6 @@ 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. /// - [Obsolete] public class QuantumProcessorBase : IQuantumProcessor { public virtual void X(Qubit qubit) @@ -178,25 +178,16 @@ public virtual void Reset(Qubit qubit) throw new UnsupportedOperationException(); } - public virtual long StartConditionalStatement(IQArray measurementResults, IQArray resultsValues) + public virtual long StartConditionalStatement(IQArray results1, IQArray results2) { - if (measurementResults == null) { return resultsValues == null ? 1 : 0; }; - if (measurementResults.Count != resultsValues?.Count) { return 0; }; - - for (int i = 0; i < measurementResults.Count; i++) - { - if (measurementResults[i] != resultsValues[i]) - { - return 0; - } - } - - return 1; + if (results1 == null) { return results2 == null ? 1 : 0; }; + if (results1.Count != results2?.Count) { return 0; }; + return results1.Zip(results2, (r1, r2) => (r1, r2)).Any(pair => pair.r1 != pair.r2) ? 0 : 1; } - public virtual long StartConditionalStatement(Result measurementResult, Result resultValue) + public virtual long StartConditionalStatement(Result result1, Result result2) { - return measurementResult == resultValue ? 1 : 0; + return result1 == result2 ? 1 : 0; } public virtual bool RunThenClause(long statement) diff --git a/src/Simulation/Common/SimulatorBase.cs b/src/Simulation/Common/SimulatorBase.cs index eec83363f3c..e2529cf75c7 100644 --- a/src/Simulation/Common/SimulatorBase.cs +++ b/src/Simulation/Common/SimulatorBase.cs @@ -542,14 +542,8 @@ public ApplyIfElseC(SimulatorBase m) : base(m) => public override Func<(IQArray, (Result, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => { (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - if ((ctrls == null) || (ctrls.Count == 0)) - { - this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - } - else - { - this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); - } + (var specKind, IQArray? controls) = ctrls?.Count == 0 ? (OperationFunctor.Body, null) : (OperationFunctor.Controlled, ctrls); + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, specKind, controls); return QVoid.Instance; }; } @@ -577,30 +571,16 @@ public ApplyIfElseCA(SimulatorBase m) : base(m) => public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => { (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - } - else - { - this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); - } + (var specKind, IQArray? controls) = ctrls?.Count == 0 ? (OperationFunctor.Body, null) : (OperationFunctor.Controlled, ctrls); + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, specKind, controls); return QVoid.Instance; }; public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => { (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); - } - else - { - this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, OperationFunctor.ControlledAdjoint, ctrls); - } + (var specKind, IQArray? controls) = ctrls?.Count == 0 ? (OperationFunctor.Adjoint, null) : (OperationFunctor.ControlledAdjoint, ctrls); + this.sim.BranchingBasedOnMeasurement(measurementResult, Result.Zero, onZero, onOne, specKind, controls); return QVoid.Instance; }; } @@ -656,15 +636,8 @@ public ApplyConditionallyC(SimulatorBase m) : base(m) => public override Func<(IQArray, (IQArray, IQArray, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => { (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - } - else - { - this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); - } + (var specKind, IQArray? controls) = ctrls?.Count == 0 ? (OperationFunctor.Body, null) : (OperationFunctor.Controlled, ctrls); + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, specKind, controls); return QVoid.Instance; }; } @@ -692,30 +665,16 @@ public ApplyConditionallyCA(SimulatorBase m) : base(m) => public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => { (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - } - else - { - this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); - } + (var specKind, IQArray? controls) = ctrls?.Count == 0 ? (OperationFunctor.Body, null) : (OperationFunctor.Controlled, ctrls); + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, specKind, controls); return QVoid.Instance; }; public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => { (IQArray ctrls, (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - - if ((ctrls == null) || (ctrls.Count == 0)) - { - this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - } - else - { - this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.ControlledAdjoint, ctrls); - } + (var specKind, IQArray? controls) = ctrls?.Count == 0 ? (OperationFunctor.Adjoint, null) : (OperationFunctor.ControlledAdjoint, ctrls); + this.sim.BranchingBasedOnMeasurement(measurementResults, resultsValues, onEqualOp, onNonEqualOp, specKind, controls); return QVoid.Instance; }; } From 85a33fdeb5a626091096ebafccbbd7472422022a Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 7 Sep 2020 16:18:01 -0700 Subject: [PATCH 5/6] removing classical control handling from tracer --- .../Circuits/ClassicalControl.qs | 43 --- .../QCTraceSimulator/Circuits/Interface.qs | 259 +++++--------- .../QCTraceSimulator.ClassicalControl.cs | 317 ------------------ 3 files changed, 78 insertions(+), 541 deletions(-) delete mode 100644 src/Simulation/Simulators/QCTraceSimulator/Circuits/ClassicalControl.qs delete mode 100644 src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.ClassicalControl.cs diff --git a/src/Simulation/Simulators/QCTraceSimulator/Circuits/ClassicalControl.qs b/src/Simulation/Simulators/QCTraceSimulator/Circuits/ClassicalControl.qs deleted file mode 100644 index 5ea025c9b56..00000000000 --- a/src/Simulation/Simulators/QCTraceSimulator/Circuits/ClassicalControl.qs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators.Circuits -{ - open Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators.Implementation; - - // Private helper operations. - operation ApplyIfElseIntrinsic(measurementResult : Result, onResultZeroOp : (Unit => Unit) , onResultOneOp : (Unit => Unit)) : Unit { - Interface_ApplyIfElse(measurementResult, onResultZeroOp, onResultOneOp); - } - - operation ApplyIfElseIntrinsicA(measurementResult : Result, onResultZeroOp : (Unit => Unit is Adj) , onResultOneOp : (Unit => Unit is Adj)) : Unit is Adj { - Interface_ApplyIfElseA(measurementResult, onResultZeroOp, onResultOneOp); - } - - operation ApplyIfElseIntrinsicC(measurementResult : Result, onResultZeroOp : (Unit => Unit is Ctl) , onResultOneOp : (Unit => Unit is Ctl)) : Unit is Ctl { - Interface_ApplyIfElseC(measurementResult, onResultZeroOp, onResultOneOp); - } - - operation ApplyIfElseIntrinsicCA(measurementResult : Result, onResultZeroOp : (Unit => Unit is Ctl + Adj) , onResultOneOp : (Unit => Unit is Ctl + Adj)) : Unit is Ctl + Adj { - Interface_ApplyIfElseCA(measurementResult, onResultZeroOp, onResultOneOp); - } - - - // Private helper operations. - operation ApplyConditionallyIntrinsic(measurementResults : Result[], resultsValues : Result[], onEqualOp : (Unit => Unit) , onNonEqualOp : (Unit => Unit)) : Unit { - Interface_ApplyConditionally(measurementResults, resultsValues, onEqualOp, onNonEqualOp); - } - - operation ApplyConditionallyIntrinsicA(measurementResults : Result[], resultsValues : Result[], onEqualOp : (Unit => Unit is Adj) , onNonEqualOp : (Unit => Unit is Adj)) : Unit is Adj { - Interface_ApplyConditionallyA(measurementResults, resultsValues, onEqualOp, onNonEqualOp); - } - - operation ApplyConditionallyIntrinsicC(measurementResults : Result[], resultsValues : Result[], onEqualOp : (Unit => Unit is Ctl) , onNonEqualOp : (Unit => Unit is Ctl)) : Unit is Ctl { - Interface_ApplyConditionallyC(measurementResults, resultsValues, onEqualOp, onNonEqualOp); - } - - operation ApplyConditionallyIntrinsicCA(measurementResults : Result[], resultsValues : Result[], onEqualOp : (Unit => Unit is Ctl + Adj) , onNonEqualOp : (Unit => Unit is Ctl + Adj)) : Unit is Ctl + Adj { - Interface_ApplyConditionallyCA(measurementResults, resultsValues, onEqualOp, onNonEqualOp); - } - -} diff --git a/src/Simulation/Simulators/QCTraceSimulator/Circuits/Interface.qs b/src/Simulation/Simulators/QCTraceSimulator/Circuits/Interface.qs index 3f69a55bd11..b3a4884303c 100644 --- a/src/Simulation/Simulators/QCTraceSimulator/Circuits/Interface.qs +++ b/src/Simulation/Simulators/QCTraceSimulator/Circuits/Interface.qs @@ -1,183 +1,80 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -namespace Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators.Implementation { - - /// # Summary - /// Controlled-X gate natively supported by the machine - /// - /// # Input - /// ## control - /// the qubit used to control the application of X gate - /// ## target - /// the qubit to which Pauli X is applied when control qubit is in state |1⟩ - /// - /// # Remarks - /// Controlled-X gate with target on qubit 2 and control on qubit 1 - /// is C₁X₂ = [ [1,0,0,0], [0,1,0,0], [0,0,0,1], [0,0,1,0] ] - operation Interface_CX (control : Qubit, target : Qubit) : Unit { - body intrinsic; - } - - /// # Summary - /// R gate natively supported by the machine. It is exp(-iφP/2) where P is the Pauli matrix - /// - /// # Input - /// ## axis - /// Pauli matrix, P - /// ## angle - /// Rotation angle, φ - /// ## target - /// the qubit operation is acting on - operation Interface_R (axis : Pauli, angle : Double, target : Qubit) : Unit { - body intrinsic; - } - - /// # Summary - /// RzFrac gate natively supported by the machine. It is exp(iπkP/2ⁿ) where P is the Pauli matrix - /// - /// # Input - /// ## axis - /// Pauli matrix, P - /// ## numerator - /// k - /// ## power - /// n - /// ## target - /// the qubit operation is acting on - /// - /// # Remarks - /// When power is 3 or less the operation is guaranteed to use S and T and Z gates to perform rotation - operation Interface_RFrac (axis : Pauli, numerator : Int, power : Int, target : Qubit) : Unit { - body intrinsic; - } - - /// # Summary - /// Applies Clifford multiplied by a pauli matrix - /// given by 'pauli' to the qubit given by 'target' - /// - /// # Input - /// ## cliffordId - /// Id of the single qubit unitary to apply. See remarks - /// - /// # Remarks - /// The list of id's corresponding to Cliffords is given by: - /// Identity - 0 - /// H - 1 - /// S - 2 - /// H followed by S ( as circuit ) - 3 - /// S followed by H ( as circuit ) - 4 - /// H S H - 5 - operation Interface_Clifford (cliffordId : Int, pauli : Pauli, target : Qubit) : Unit { - body intrinsic; - } - - - /// Forces the future measurement of a given observable to give specified result - operation ForceMeasure (observable : Pauli[], target : Qubit[], result : Result) : Unit { - body intrinsic; - } - - /// - /// Performs the onResultZeroOp when measurementResult is Zero, else performs the onResultOneOp. - /// - operation Interface_ApplyIfElse ( - measurementResult : Result, - onResultZeroOp : (Unit => Unit), - onResultOneOp : (Unit => Unit) - ) : Unit { +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators.Implementation { + + /// # Summary + /// Controlled-X gate natively supported by the machine + /// + /// # Input + /// ## control + /// the qubit used to control the application of X gate + /// ## target + /// the qubit to which Pauli X is applied when control qubit is in state |1⟩ + /// + /// # Remarks + /// Controlled-X gate with target on qubit 2 and control on qubit 1 + /// is C₁X₂ = [ [1,0,0,0], [0,1,0,0], [0,0,0,1], [0,0,1,0] ] + operation Interface_CX (control : Qubit, target : Qubit) : Unit { body intrinsic; - } - - /// - /// Performs the onResultZeroOp when measurementResult is Zero, else performs the onResultOneOp. - /// onReusltZeroOp and onResultOneOp must both be adjointable. - /// - operation Interface_ApplyIfElseA ( - measurementResult : Result, - onResultZeroOp : (Unit => Unit is Adj), - onResultOneOp : (Unit => Unit is Adj) - ) : Unit is Adj { - body intrinsic; - } - - /// - /// Performs the onResultZeroOp when measurementResult is Zero, else performs the onResultOneOp. - /// onReusltZeroOp and onResultOneOp must both be controllable. - /// - operation Interface_ApplyIfElseC ( - measurementResult : Result, - onResultZeroOp : (Unit => Unit is Ctl), - onResultOneOp : (Unit => Unit is Ctl) - ) : Unit is Ctl { - body intrinsic; - } - - /// - /// Performs the onResultZeroOp when measurementResult is Zero, else performs the onResultOneOp. - /// onReusltZeroOp and onResultOneOp must both be controllable and adjointable. - /// - operation Interface_ApplyIfElseCA ( - measurementResult : Result, - onResultZeroOp : (Unit => Unit is Ctl + Adj), - onResultOneOp : (Unit => Unit is Ctl + Adj) - ) : Unit is Adj + Ctl { - body intrinsic; - } - - /// - /// Performs the onEqualOp when each element of measurementResults is equal to the corresponding - /// element of resultsValues, else performs onNonEqualOp. - /// - operation Interface_ApplyConditionally ( - measurementResults : Result[], - resultsValues : Result[], - onEqualOp : (Unit => Unit), - onNonEqualOp : (Unit => Unit) - ) : Unit { + } + + /// # Summary + /// R gate natively supported by the machine. It is exp(-iφP/2) where P is the Pauli matrix + /// + /// # Input + /// ## axis + /// Pauli matrix, P + /// ## angle + /// Rotation angle, φ + /// ## target + /// the qubit operation is acting on + operation Interface_R (axis : Pauli, angle : Double, target : Qubit) : Unit { body intrinsic; - } - - /// - /// Performs the onEqualOp when each element of measurementResults is equal to the corresponding - /// element of resultsValues, else performs onNonEqualOp. - /// onEqualOp and onNonEqualOp must both be adjointable. - /// - operation Interface_ApplyConditionallyA ( - measurementResults : Result[], - resultsValues : Result[], - onEqualOp : (Unit => Unit is Adj), - onNonEqualOp : (Unit => Unit is Adj) - ) : Unit is Adj { - body intrinsic; - } - - /// - /// Performs the onEqualOp when each element of measurementResults is equal to the corresponding - /// element of resultsValues, else performs onNonEqualOp. - /// onEqualOp and onNonEqualOp must both be controllable. - /// - operation Interface_ApplyConditionallyC ( - measurementResults : Result[], - resultsValues : Result[], - onEqualOp : (Unit => Unit is Ctl), - onNonEqualOp : (Unit => Unit is Ctl) - ) : Unit is Ctl { - body intrinsic; - } - - /// - /// Performs the onEqualOp when each element of measurementResults is equal to the corresponding - /// element of resultsValues, else performs onNonEqualOp. - /// onEqualOp and onNonEqualOp must both be controllable and adjointable. - /// - operation Interface_ApplyConditionallyCA ( - measurementResults : Result[], - resultsValues : Result[], - onEqualOp : (Unit => Unit is Ctl + Adj), - onNonEqualOp : (Unit => Unit is Ctl + Adj) - ) : Unit is Adj + Ctl { - body intrinsic; - } - -} + } + + /// # Summary + /// RzFrac gate natively supported by the machine. It is exp(iπkP/2ⁿ) where P is the Pauli matrix + /// + /// # Input + /// ## axis + /// Pauli matrix, P + /// ## numerator + /// k + /// ## power + /// n + /// ## target + /// the qubit operation is acting on + /// + /// # Remarks + /// When power is 3 or less the operation is guaranteed to use S and T and Z gates to perform rotation + operation Interface_RFrac (axis : Pauli, numerator : Int, power : Int, target : Qubit) : Unit { + body intrinsic; + } + + /// # Summary + /// Applies Clifford multiplied by a pauli matrix + /// given by 'pauli' to the qubit given by 'target' + /// + /// # Input + /// ## cliffordId + /// Id of the single qubit unitary to apply. See remarks + /// + /// # Remarks + /// The list of id's corresponding to Cliffords is given by: + /// Identity - 0 + /// H - 1 + /// S - 2 + /// H followed by S ( as circuit ) - 3 + /// S followed by H ( as circuit ) - 4 + /// H S H - 5 + operation Interface_Clifford (cliffordId : Int, pauli : Pauli, target : Qubit) : Unit { + body intrinsic; + } + + + /// Forces the future measurement of a given observable to give specified result + operation ForceMeasure (observable : Pauli[], target : Qubit[], result : Result) : Unit { + body intrinsic; + } +} diff --git a/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.ClassicalControl.cs b/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.ClassicalControl.cs deleted file mode 100644 index c00427bac1d..00000000000 --- a/src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.ClassicalControl.cs +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.IO; -using Microsoft.Quantum.Simulation.Core; - -namespace Microsoft.Quantum.Simulation.Simulators.QCTraceSimulators.Implementation -{ - public partial class QCTraceSimulatorImpl - { - #region Static Methods - - /// - /// Runs the given functor of the given operation with the given control qubits. - /// - 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, QVoid.Instance)); break; - case OperationFunctor.ControlledAdjoint: ((IUnitary)op).Controlled.Adjoint.Apply((ctrls, QVoid.Instance)); break; - } - } - - /// - /// This is a wrapper for an if-statement that will run either onZero if the - /// given measurement result is Zero, or onOne otherwise. - /// - private static QVoid ExecuteConditionalStatement(Result measurementResult, ICallable onZero, ICallable onOne, OperationFunctor type, IQArray? ctrls) - { - if (measurementResult == Result.Zero) - { - RunClause(onZero, type, ctrls); - } - else - { - RunClause(onOne, type, ctrls); - } - return QVoid.Instance; - } - - /// - /// This is a wrapper for an if-statement that will run either onEqualOp if the - /// given measurement result are pairwise-equal to the given comparison results, - /// or onNonEqualOp otherwise. Pairwise-equality between the qubit arrays is - /// determined by the AreEqual static method. - /// - private static QVoid ExecuteConditionalStatement(IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp, OperationFunctor type, IQArray? ctrls) - { - if (AreEqual(measurementResults, comparisonResults)) - { - RunClause(onEqualOp, type, ctrls); - } - else - { - RunClause(onNonEqualOp, type, ctrls); - } - return QVoid.Instance; - } - - /// - /// Determines if the given measurement results are pairwise-equal with the given comparison results. - /// Pairwise-equality is where each element of the first array is equal to its corresponding element - /// in the second array. For example: - /// measurementResults[0] == comparisonResults[0] AND measurementResults[1] == comparisonResults[1] AND ... - /// All pairwise comparisons must result in equality for the two arrays to be pairwise-equal. - /// - /// If either array is null or their lengths are unequal, this defaults to returning 'true'. This - /// is done to be consistent with the logic found in QuantumProcessorBase.cs under the - /// StartConditionalStatement method. - /// - private static bool AreEqual(IQArray measurementResults, IQArray comparisonResults) - { - if (measurementResults == null || comparisonResults == null || measurementResults.Count != comparisonResults.Count) - { - // Defaulting to true is based on the QuantumProcessorBase.cs behavior, under StartConditionalStatement. - return true; - } - - for (int i = 0; i < measurementResults.Count; i++) - { - if (measurementResults[i] != comparisonResults[i]) - { - return false; - } - } - - return true; - } - - /// - /// If a controlled functor is being used with no controls, this will change it - /// to the appropriate non-controlled functor. Otherwise, the given functor is returned. - /// - private static OperationFunctor AdjustForNoControls(OperationFunctor type, IQArray? ctrls) - { - if (ctrls == null || ctrls.Count == 0) - { - type = type switch - { - OperationFunctor.Controlled => OperationFunctor.Body, - OperationFunctor.ControlledAdjoint => OperationFunctor.Adjoint, - _ => type, - }; - } - - return type; - } - - #endregion - - #region ApplyIfElse - - public class TracerApplyIfElse : Interface_ApplyIfElse - { - private QCTraceSimulatorImpl tracerCore { get; } - - public TracerApplyIfElse(QCTraceSimulatorImpl m) : base(m) - { - this.tracerCore = m; - } - - public override Func<(Result, ICallable, ICallable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Body, null); - }; - } - - public class TracerApplyIfElseA : Interface_ApplyIfElseA - { - private QCTraceSimulatorImpl tracerCore { get; } - - public TracerApplyIfElseA(QCTraceSimulatorImpl m) : base(m) - { - this.tracerCore = m; - } - - public override Func<(Result, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Body, null); - }; - - public override Func<(Result, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Adjoint, null); - }; - } - - public class TracerApplyIfElseC : Interface_ApplyIfElseC - { - private QCTraceSimulatorImpl tracerCore { get; } - - public TracerApplyIfElseC(QCTraceSimulatorImpl m) : base(m) - { - this.tracerCore = m; - } - - public override Func<(Result, IControllable, IControllable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Body, null); - }; - - public override Func<(IQArray, (Result, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.Controlled, ctrls); - return ExecuteConditionalStatement(measurementResult, onZero, onOne, type, ctrls); - }; - } - - public class TracerApplyIfElseCA : Interface_ApplyIfElseCA - { - private QCTraceSimulatorImpl tracerCore { get; } - - public TracerApplyIfElseCA(QCTraceSimulatorImpl m) : base(m) - { - this.tracerCore = m; - } - - public override Func<(Result, IUnitary, IUnitary), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Body, null); - }; - - public override Func<(Result, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Adjoint, null); - }; - - public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.Controlled, ctrls); - return ExecuteConditionalStatement(measurementResult, onZero, onOne, type, ctrls); - }; - - public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.ControlledAdjoint, ctrls); - return ExecuteConditionalStatement(measurementResult, onZero, onOne, type, ctrls); - }; - } - - #endregion - - #region ApplyConditionally - - public class TracerApplyConditionally : Interface_ApplyConditionally - { - private QCTraceSimulatorImpl tracerCore { get; } - - public TracerApplyConditionally(QCTraceSimulatorImpl m) : base(m) - { - this.tracerCore = m; - } - - public override Func<(IQArray, IQArray, ICallable, ICallable), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - } - - public class TracerApplyConditionallyA : Interface_ApplyConditionallyA - { - private QCTraceSimulatorImpl tracerCore { get; } - - public TracerApplyConditionallyA(QCTraceSimulatorImpl m) : base(m) - { - this.tracerCore = m; - } - - public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - }; - } - - public class TracerApplyConditionallyC : Interface_ApplyConditionallyC - { - private QCTraceSimulatorImpl tracerCore { get; } - - public TracerApplyConditionallyC(QCTraceSimulatorImpl m) : base(m) - { - this.tracerCore = m; - } - - public override Func<(IQArray, IQArray, IControllable, IControllable), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - public override Func<(IQArray, (IQArray, IQArray, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.Controlled, ctrls); - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, type, ctrls); - }; - } - - public class TracerApplyConditionallyCA : Interface_ApplyConditionallyCA - { - private QCTraceSimulatorImpl tracerCore { get; } - - public TracerApplyConditionallyCA(QCTraceSimulatorImpl m) : base(m) - { - this.tracerCore = m; - } - - public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - }; - - public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.Controlled, ctrls); - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, type, ctrls); - }; - - public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.ControlledAdjoint, ctrls); - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, type, ctrls); - }; - } - - #endregion - } -} From 0d547b88eba87d6c0bf0b856dfaee2862aad2e18 Mon Sep 17 00:00:00 2001 From: Bettina Heim Date: Mon, 7 Sep 2020 16:19:56 -0700 Subject: [PATCH 6/6] removing the classical control handling from the QuantumSimulator --- .../QuantumSimulator/ClassicalControl.cs | 316 ------------------ 1 file changed, 316 deletions(-) delete mode 100644 src/Simulation/Simulators/QuantumSimulator/ClassicalControl.cs diff --git a/src/Simulation/Simulators/QuantumSimulator/ClassicalControl.cs b/src/Simulation/Simulators/QuantumSimulator/ClassicalControl.cs deleted file mode 100644 index c86e5abe4f0..00000000000 --- a/src/Simulation/Simulators/QuantumSimulator/ClassicalControl.cs +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using Microsoft.Quantum.Simulation.Core; - -namespace Microsoft.Quantum.Simulation.Simulators -{ - public partial class QuantumSimulator - { - #region Static Methods - - /// - /// Runs the given functor of the given operation with the given control qubits. - /// - 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, QVoid.Instance)); break; - case OperationFunctor.ControlledAdjoint: ((IUnitary)op).Controlled.Adjoint.Apply((ctrls, QVoid.Instance)); break; - } - } - - /// - /// This is a wrapper for an if-statement that will run either onZero if the - /// given measurement result is Zero, or onOne otherwise. - /// - private static QVoid ExecuteConditionalStatement(Result measurementResult, ICallable onZero, ICallable onOne, OperationFunctor type, IQArray? ctrls) - { - if (measurementResult == Result.Zero) - { - RunClause(onZero, type, ctrls); - } - else - { - RunClause(onOne, type, ctrls); - } - return QVoid.Instance; - } - - /// - /// This is a wrapper for an if-statement that will run either onEqualOp if the - /// given measurement result are pairwise-equal to the given comparison results, - /// or onNonEqualOp otherwise. Pairwise-equality between the qubit arrays is - /// determined by the AreEqual static method. - /// - private static QVoid ExecuteConditionalStatement(IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp, OperationFunctor type, IQArray? ctrls) - { - if (AreEqual(measurementResults, comparisonResults)) - { - RunClause(onEqualOp, type, ctrls); - } - else - { - RunClause(onNonEqualOp, type, ctrls); - } - return QVoid.Instance; - } - - /// - /// Determines if the given measurement results are pairwise-equal with the given comparison results. - /// Pairwise-equality is where each element of the first array is equal to its corresponding element - /// in the second array. For example: - /// measurementResults[0] == comparisonResults[0] AND measurementResults[1] == comparisonResults[1] AND ... - /// All pairwise comparisons must result in equality for the two arrays to be pairwise-equal. - /// - /// If either array is null or their lengths are unequal, this defaults to returning 'true'. This - /// is done to be consistent with the logic found in QuantumProcessorBase.cs under the - /// StartConditionalStatement method. - /// - private static bool AreEqual(IQArray measurementResults, IQArray comparisonResults) - { - if (measurementResults == null || comparisonResults == null || measurementResults.Count != comparisonResults.Count) - { - // Defaulting to true is based on the QuantumProcessorBase.cs behavior, under StartConditionalStatement. - return true; - } - - for (int i = 0; i < measurementResults.Count; i++) - { - if (measurementResults[i] != comparisonResults[i]) - { - return false; - } - } - - return true; - } - - /// - /// If a controlled functor is being used with no controls, this will change it - /// to the appropriate non-controlled functor. Otherwise, the given functor is returned. - /// - private static OperationFunctor AdjustForNoControls(OperationFunctor type, IQArray? ctrls) - { - if (ctrls == null || ctrls.Count == 0) - { - type = type switch - { - OperationFunctor.Controlled => OperationFunctor.Body, - OperationFunctor.ControlledAdjoint => OperationFunctor.Adjoint, - _ => type, - }; - } - - return type; - } - - #endregion - - #region ApplyIfElse - - public class QSimApplyIfElse : QuantumProcessor.Extensions.ApplyIfElseIntrinsic - { - private QuantumSimulator Simulator { get; } - - public QSimApplyIfElse(QuantumSimulator m) : base(m) - { - this.Simulator = m; - } - - public override Func<(Result, ICallable, ICallable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Body, null); - }; - } - - public class QSimApplyIfElseA : QuantumProcessor.Extensions.ApplyIfElseIntrinsicA - { - private QuantumSimulator Simulator { get; } - - public QSimApplyIfElseA(QuantumSimulator m) : base(m) - { - this.Simulator = m; - } - - public override Func<(Result, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Body, null); - }; - - public override Func<(Result, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Adjoint, null); - }; - } - - public class QSimApplyIfElseC : QuantumProcessor.Extensions.ApplyIfElseIntrinsicC - { - private QuantumSimulator Simulator { get; } - - public QSimApplyIfElseC(QuantumSimulator m) : base(m) - { - this.Simulator = m; - } - - public override Func<(Result, IControllable, IControllable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Body, null); - }; - - public override Func<(IQArray, (Result, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.Controlled, ctrls); - return ExecuteConditionalStatement(measurementResult, onZero, onOne, type, ctrls); - }; - } - - public class QSimApplyIfElseCA : QuantumProcessor.Extensions.ApplyIfElseIntrinsicCA - { - private QuantumSimulator Simulator { get; } - - public QSimApplyIfElseCA(QuantumSimulator m) : base(m) - { - this.Simulator = m; - } - - public override Func<(Result, IUnitary, IUnitary), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Body, null); - }; - - public override Func<(Result, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(measurementResult, onZero, onOne, OperationFunctor.Adjoint, null); - }; - - public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.Controlled, ctrls); - return ExecuteConditionalStatement(measurementResult, onZero, onOne, type, ctrls); - }; - - public override Func<(IQArray, (Result, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => - { - (IQArray ctrls, (Result measurementResult, ICallable onZero, ICallable onOne)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.ControlledAdjoint, ctrls); - return ExecuteConditionalStatement(measurementResult, onZero, onOne, type, ctrls); - }; - } - - #endregion - - #region ApplyConditionally - - public class QSimApplyConditionally : QuantumProcessor.Extensions.ApplyConditionallyIntrinsic - { - private QuantumSimulator Simulator { get; } - - public QSimApplyConditionally(QuantumSimulator m) : base(m) - { - this.Simulator = m; - } - - public override Func<(IQArray, IQArray, ICallable, ICallable), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - } - - public class QSimApplyConditionallyA : QuantumProcessor.Extensions.ApplyConditionallyIntrinsicA - { - private QuantumSimulator Simulator { get; } - - public QSimApplyConditionallyA(QuantumSimulator m) : base(m) - { - this.Simulator = m; - } - - public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __AdjointBody__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - }; - } - - public class QSimApplyConditionallyC : QuantumProcessor.Extensions.ApplyConditionallyIntrinsicC - { - private QuantumSimulator Simulator { get; } - - public QSimApplyConditionallyC(QuantumSimulator m) : base(m) - { - this.Simulator = m; - } - - public override Func<(IQArray, IQArray, IControllable, IControllable), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - public override Func<(IQArray, (IQArray, IQArray, IControllable, IControllable)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.Controlled, ctrls); - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, type, ctrls); - }; - } - - public class QSimApplyConditionallyCA : QuantumProcessor.Extensions.ApplyConditionallyIntrinsicCA - { - private QuantumSimulator Simulator { get; } - - public QSimApplyConditionallyCA(QuantumSimulator m) : base(m) - { - this.Simulator = m; - } - - public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __AdjointBody__ => (q) => - { - (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - }; - - public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.Controlled, ctrls); - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, type, ctrls); - }; - - public override Func<(IQArray, (IQArray, IQArray, IUnitary, IUnitary)), QVoid> __ControlledAdjointBody__ => (q) => - { - (IQArray ctrls, (IQArray measurementResults, IQArray comparisonResults, ICallable onEqualOp, ICallable onNonEqualOp)) = q; - OperationFunctor type = AdjustForNoControls(OperationFunctor.ControlledAdjoint, ctrls); - return ExecuteConditionalStatement(measurementResults, comparisonResults, onEqualOp, onNonEqualOp, type, ctrls); - }; - } - - #endregion - } -}