From 8281a5f8fd1a070547118362f3b29c500e9c62ff Mon Sep 17 00:00:00 2001 From: "Stefan J. Wernli" Date: Sat, 5 Sep 2020 15:36:18 -0700 Subject: [PATCH 1/6] Adding support for QCI to quantum machine factory (#368) * Adding support for QCI to quantum machine factory * Update src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs Co-authored-by: Sarah Marshall <33814365+samarsha@users.noreply.github.com> Co-authored-by: Sarah Marshall <33814365+samarsha@users.noreply.github.com> --- src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs index fd709cee94e..cd61dd5ce49 100644 --- a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs +++ b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs @@ -23,6 +23,8 @@ public static class QuantumMachineFactory var machineName = targetName is null ? null + : targetName.StartsWith("qci.") + ? "Microsoft.Quantum.Providers.QCI.Targets.QCIQuantumMachine, Microsoft.Quantum.Providers.QCI" : targetName.StartsWith("ionq.") ? "Microsoft.Quantum.Providers.IonQ.Targets.IonQQuantumMachine, Microsoft.Quantum.Providers.IonQ" : targetName.StartsWith("honeywell.") From 75be986b48adc2a7a8eb4c42405da21ede9064d3 Mon Sep 17 00:00:00 2001 From: bettinaheim <34236215+bettinaheim@users.noreply.github.com> Date: Thu, 10 Sep 2020 16:15:27 -0700 Subject: [PATCH 2/6] Adding handling of branching based on measurement results to SimulatorBase (#369) --- src/Simulation/Common/AbstractFactory.cs | 7 +- ...onException.cs => TranslationException.cs} | 0 src/Simulation/Common/QuantumProcessorBase.cs | 51 +-- src/Simulation/Common/SimulatorBase.cs | 395 +++++++++++++++--- .../Circuits/ClassicalControl.qs | 43 -- .../QCTraceSimulator/Circuits/Interface.qs | 259 ++++-------- .../QCTraceSimulator.ClassicalControl.cs | 317 -------------- .../QuantumProcessor/ClassicalControl.cs | 283 +------------ .../QuantumSimulator/ClassicalControl.cs | 316 -------------- 9 files changed, 426 insertions(+), 1245 deletions(-) rename src/Simulation/Common/Exceptions/{QuantumProcessorTranslationException.cs => TranslationException.cs} (100%) delete mode 100644 src/Simulation/Simulators/QCTraceSimulator/Circuits/ClassicalControl.qs delete mode 100644 src/Simulation/Simulators/QCTraceSimulator/QCTraceSimulator.ClassicalControl.cs delete mode 100644 src/Simulation/Simulators/QuantumSimulator/ClassicalControl.cs 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..fd9043f8a12 100644 --- a/src/Simulation/Common/QuantumProcessorBase.cs +++ b/src/Simulation/Common/QuantumProcessorBase.cs @@ -2,9 +2,8 @@ // Licensed under the MIT License. using System; +using System.Linq; using Microsoft.Quantum.Simulation.Core; -using System.Diagnostics; -using System.Runtime.CompilerServices; namespace Microsoft.Quantum.Simulation.Common { @@ -179,37 +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 1; }; - if (resultsValues == null) { return 1; }; - Debug.Assert(measurementResults.Count == resultsValues.Count); - if (measurementResults.Count != resultsValues.Count) { return 1; }; - - int equal = 1; - - for (int i = 0; i < measurementResults.Count; i++) - { - if (measurementResults[i] != resultsValues[i]) - { - equal = 0; - } - } - - return equal; + 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) { - - if (measurementResult == resultValue) - { - return 1; - } - else - { - return 0; - } + return result1 == result2 ? 1 : 0; } public virtual bool RunThenClause(long statement) @@ -234,7 +212,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 +263,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..e2529cf75c7 100644 --- a/src/Simulation/Common/SimulatorBase.cs +++ b/src/Simulation/Common/SimulatorBase.cs @@ -4,14 +4,30 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; 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. + /// + 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 +47,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 +63,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 +94,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 +109,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 +283,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 +294,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 +313,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 +341,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 +371,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 +416,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 +452,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 +473,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 => { @@ -482,6 +489,256 @@ 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; + (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 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; + (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; + (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; + }; + } + + 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; + (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 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; + (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; + (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; + }; + } + + 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); @@ -492,7 +749,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/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 - } -} diff --git a/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs index 8b19da839c7..c9f8b4bb8e5 100644 --- a/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs +++ b/src/Simulation/Simulators/QuantumProcessor/ClassicalControl.cs @@ -8,293 +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 static QVoid ExecuteConditionalStatementInternal(QuantumProcessorDispatcher Simulator, - long statement, - ICallable onEqualOp, - ICallable onNonEqualOp, - OperationFunctor type, - IQArray? ctrls) + public override void ExecuteBranchingBasedOnMeasurement(long condition, Action onEqual, Action onNonEqual) { - bool run; - - run = Simulator.QuantumProcessor.RunThenClause(statement); + bool run = this.QuantumProcessor.RunThenClause(condition); while (run) { - RunClause(onEqualOp, type, ctrls); - run = Simulator.QuantumProcessor.RepeatThenClause(statement); + onEqual?.Invoke(); + run = this.QuantumProcessor.RepeatThenClause(condition); } - run = Simulator.QuantumProcessor.RunElseClause(statement); + run = this.QuantumProcessor.RunElseClause(condition); while (run) { - RunClause(onNonEqualOp, type, ctrls); - run = Simulator.QuantumProcessor.RepeatElseClause(statement); + onNonEqual?.Invoke(); + run = this.QuantumProcessor.RepeatElseClause(condition); } - - 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) + public override long StartBranchingBasedOnMeasurement(Result result1, Result result2) { - long statement = Simulator.QuantumProcessor.StartConditionalStatement(measurementResults, resultsValues); - return ExecuteConditionalStatementInternal(Simulator, - statement, - onEqualOp, - onNonEqualOp, - type, - ctrls); + return this.QuantumProcessor.StartConditionalStatement(result1, result2); } - private static QVoid ExecuteConditionalStatement(QuantumProcessorDispatcher Simulator, - Result measurementResult, - Result resultValue, - ICallable onEqualOp, - ICallable onNonEqualOp, - OperationFunctor type, - IQArray? ctrls) + public override long StartBranchingBasedOnMeasurement(IQArray results1, IQArray results2) { - long statement = Simulator.QuantumProcessor.StartConditionalStatement(measurementResult, resultValue); - return ExecuteConditionalStatementInternal(Simulator, - statement, - onEqualOp, - onNonEqualOp, - type, - ctrls); - } - - - public class QuantumProcessorApplyIfElse : Extensions.ApplyIfElseIntrinsic - { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyIfElse(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(Result, ICallable, ICallable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - }; - } - - public class QuantumProcessorApplyIfElseA : Extensions.ApplyIfElseIntrinsicA - { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyIfElseA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(Result, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - }; - - 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); - }; + return this.QuantumProcessor.StartConditionalStatement(results1, results2); } - public class QuantumProcessorApplyIfElseC : Extensions.ApplyIfElseIntrinsicC + public override void EndBranchingBasedOnMeasurement(long statement) { - 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; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - }; - - 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)) - { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - } - else - { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); - } - }; + this.QuantumProcessor.EndConditionalStatement(statement); } - - public class QuantumProcessorApplyIfElseCA : Extensions.ApplyIfElseIntrinsicCA - { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyIfElseCA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(Result, IUnitary, IUnitary), QVoid> __Body__ => (q) => - { - (Result measurementResult, ICallable onZero, ICallable onOne) = q; - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - }; - - 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); - }; - - 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)) - { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Body, null); - } - else - { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Controlled, ctrls); - } - }; - - 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)) - { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.Adjoint, null); - } - else - { - return ExecuteConditionalStatement(Simulator, measurementResult, Result.Zero, onZero, onOne, OperationFunctor.ControlledAdjoint, ctrls); - } - }; - } - - - - public class QuantumProcessorApplyConditionally : Extensions.ApplyConditionallyIntrinsic - { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyConditionally(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(IQArray, IQArray, ICallable, ICallable), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - } - - public class QuantumProcessorApplyConditionallyA : Extensions.ApplyConditionallyIntrinsicA - { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyConditionallyA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(IQArray, IQArray, IAdjointable, IAdjointable), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - 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); - }; - } - - 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; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - 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)) - { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - } - else - { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); - } - }; - } - - public class QuantumProcessorApplyConditionallyCA : Extensions.ApplyConditionallyIntrinsicCA - { - private QuantumProcessorDispatcher Simulator { get; } - - public QuantumProcessorApplyConditionallyCA(QuantumProcessorDispatcher m) : base(m) { this.Simulator = m; } - - public override Func<(IQArray, IQArray, IUnitary, IUnitary), QVoid> __Body__ => (q) => - { - (IQArray measurementResults, IQArray resultsValues, ICallable onEqualOp, ICallable onNonEqualOp) = q; - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - }; - - 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); - }; - - 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)) - { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Body, null); - } - else - { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Controlled, ctrls); - } - }; - - 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)) - { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.Adjoint, null); - } - else - { - return ExecuteConditionalStatement(Simulator, measurementResults, resultsValues, onEqualOp, onNonEqualOp, OperationFunctor.ControlledAdjoint, ctrls); - } - }; - } - } } 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 - } -} From 6c44f6df1806849b947612fd179c3c7f6db6ca61 Mon Sep 17 00:00:00 2001 From: bettinaheim <34236215+bettinaheim@users.noreply.github.com> Date: Sat, 12 Sep 2020 06:56:20 -0700 Subject: [PATCH 3/6] renaming master -> main (#373) --- .github/workflows/automerge.yml | 4 ++-- README.md | 2 +- build/ci.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml index d45a296b737..143313aa57e 100644 --- a/.github/workflows/automerge.yml +++ b/.github/workflows/automerge.yml @@ -5,7 +5,7 @@ on: pull_request: # Note that we only support automerge on branches that have required checks. branches: - - master + - main - feature/* types: - labeled @@ -19,7 +19,7 @@ on: pull_request_review: # Note that we only support automerge on branches that have required checks. branches: - - master + - main - feature/* types: - submitted diff --git a/README.md b/README.md index d20ed0093ae..1cc7621c6cd 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ You may also visit our [Quantum](https://github.com/microsoft/quantum) repositor ## Building from Source ## -[![Build Status](https://dev.azure.com/ms-quantum-public/Microsoft%20Quantum%20(public)/_apis/build/status/microsoft.qsharp-runtime?branchName=master)](https://dev.azure.com/ms-quantum-public/Microsoft%20Quantum%20(public)/_build/latest?definitionId=15&branchName=master) +[![Build Status](https://dev.azure.com/ms-quantum-public/Microsoft%20Quantum%20(public)/_apis/build/status/microsoft.qsharp-runtime?branchName=main)](https://dev.azure.com/ms-quantum-public/Microsoft%20Quantum%20(public)/_build/latest?definitionId=15&branchName=main) Note that when building from source, this repository is configured so that .NET Core will automatically look at the [Quantum Development Kit prerelease feed](https://dev.azure.com/ms-quantum-public/Microsoft%20Quantum%20(public)/_packaging?_a=feed&feed=alpha) in addition to any other feeds you may have configured. diff --git a/build/ci.yml b/build/ci.yml index b274f861d26..8e67760aea6 100644 --- a/build/ci.yml +++ b/build/ci.yml @@ -1,6 +1,6 @@ name: $(Build.Major).$(Build.Minor).$(date:yyMM).$(DayOfMonth)$(rev:rr) trigger: -- master +- main variables: Build.Major: 0 From 838aa7f6ad0f032e12979c77e5e55dec699f4be3 Mon Sep 17 00:00:00 2001 From: Andres Paz Date: Mon, 14 Sep 2020 08:50:38 -0700 Subject: [PATCH 4/6] End-to-end build (#374) --- .github/workflows/qdk-sync.yml | 28 ++++++++++++++++++++++++++++ build/ci.yml | 10 ++++++++-- build/e2e.yml | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/qdk-sync.yml create mode 100644 build/e2e.yml diff --git a/.github/workflows/qdk-sync.yml b/.github/workflows/qdk-sync.yml new file mode 100644 index 00000000000..26b4da3d7d6 --- /dev/null +++ b/.github/workflows/qdk-sync.yml @@ -0,0 +1,28 @@ +name: Sync QDK repos + +on: + push: + branches: + - main + +jobs: + sync-repos: + runs-on: ubuntu-latest + steps: + - name: Login to Azure + uses: Azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - id: AzureKeyVault + uses: Azure/get-keyvault-secrets@v1.0 + with: + keyvault: 'kv-qdk-build' + secrets: 'qdkBuildPAT' + + - name: 'Trigger QDK sync build' + uses: Azure/pipelines@releases/v1 + with: + azure-devops-project-url: 'https://dev.azure.com/ms-quantum-public/Microsoft Quantum (public)' + azure-pipeline-name: 'microsoft.qdk.sync' + azure-devops-token: ${{ steps.AzureKeyVault.outputs.qdkBuildPAT }} diff --git a/build/ci.yml b/build/ci.yml index 8e67760aea6..b194fa64afd 100644 --- a/build/ci.yml +++ b/build/ci.yml @@ -1,6 +1,12 @@ name: $(Build.Major).$(Build.Minor).$(date:yyMM).$(DayOfMonth)$(rev:rr) -trigger: + +trigger: none + +pr: - main +- feature/* +- features/* +- release/* variables: Build.Major: 0 @@ -28,4 +34,4 @@ jobs: - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Detection' inputs: - failOnAlert: true \ No newline at end of file + failOnAlert: true diff --git a/build/e2e.yml b/build/e2e.yml new file mode 100644 index 00000000000..1a56ac89ab3 --- /dev/null +++ b/build/e2e.yml @@ -0,0 +1,33 @@ +name: $(Build.Major).$(Build.Minor).$(date:yyMM).$(BuildId) + +parameters: +- name: validation_level + displayName: Validation Level + type: string + default: normal + values: + - minimal + - normal + - full + +trigger: none + +pr: +- main +- feature/* +- features/* +- release/* + +resources: + repositories: + - repository: qdk + type: github + endpoint: github + name: microsoft/qdk + ref: refs/heads/main + +extends: + template: build/qdk-module-e2e.yml@qdk + parameters: + module: qsharp-runtime + validation_level: ${{ parameters.validation_level }} From 9207633235301934609e9119182c01e3781432d2 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Thu, 17 Sep 2020 10:32:38 -0700 Subject: [PATCH 5/6] Include inner exception in message of WorkspaceClientException so it's available to Azure CLI output. (#378) Extending the message in WorkspaceClientException to include the inner exception as well if present. This exception message is provided to the user through the console during execution (e.g. when using the Azure CLI) and should include this information to be more actionable. --- .../Exceptions/WorkspaceClientException.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Azure/Azure.Quantum.Client/Exceptions/WorkspaceClientException.cs b/src/Azure/Azure.Quantum.Client/Exceptions/WorkspaceClientException.cs index 48381424b03..821e3a64bc2 100644 --- a/src/Azure/Azure.Quantum.Client/Exceptions/WorkspaceClientException.cs +++ b/src/Azure/Azure.Quantum.Client/Exceptions/WorkspaceClientException.cs @@ -66,7 +66,8 @@ public WorkspaceClientException( $"ResourceGroupName: {resourceGroupName}{Environment.NewLine}" + $"WorkspaceName: {workspaceName}{Environment.NewLine}" + $"BaseUri: {baseUri}{Environment.NewLine}" + - $"JobId: {jobId}", + $"JobId: {jobId}{Environment.NewLine}" + + (inner != null ? $"Inner Exception: {inner}" : string.Empty), inner) { } From 4ad13c11315aa8902e569aee84cbb7b3c21790ed Mon Sep 17 00:00:00 2001 From: "Stefan J. Wernli" Date: Tue, 22 Sep 2020 13:32:43 -0700 Subject: [PATCH 6/6] Moving UnsupportedOperationException into Common --- src/Simulation/Common/OperationException.cs | 25 +++++++++++++++++++ .../QuantumSimulator/SimulatorBase.cs | 15 ----------- 2 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 src/Simulation/Common/OperationException.cs diff --git a/src/Simulation/Common/OperationException.cs b/src/Simulation/Common/OperationException.cs new file mode 100644 index 00000000000..ab4d7e6d177 --- /dev/null +++ b/src/Simulation/Common/OperationException.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Runtime.CompilerServices; + +#nullable enable + +namespace Microsoft.Quantum.Simulation.Common +{ + /// + /// A class that implements exception to be thrown when Operation is not supported. + /// + public class UnsupportedOperationException : PlatformNotSupportedException + { + public UnsupportedOperationException(string text = "", + [CallerFilePath] string file = "", + [CallerMemberName] string member = "", + [CallerLineNumber] int line = 0) + : base($"{file}::{line}::[{member}]:{text}") + { + } + } + +} \ No newline at end of file diff --git a/src/Simulation/Simulators/QuantumSimulator/SimulatorBase.cs b/src/Simulation/Simulators/QuantumSimulator/SimulatorBase.cs index e2529cf75c7..bb7050d54e8 100644 --- a/src/Simulation/Simulators/QuantumSimulator/SimulatorBase.cs +++ b/src/Simulation/Simulators/QuantumSimulator/SimulatorBase.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.Quantum.Simulation.Core; @@ -14,20 +13,6 @@ namespace Microsoft.Quantum.Simulation.Common { - /// - /// A class that implements exception to be thrown when Operation is not supported. - /// - 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