/// <summary> /// Modifies the elements at the given indices and returns the QArray. /// Note that the modification is an in-place modification! /// If the Length of the given values does not match the number of indices, /// or if an index is outside the array bounds, it throws /// and ArgumentOutOfRangeException. /// </summary> /// <param name="index">The long index of the element to access</param> /// <returns>The element</returns> public QArray <T> Modify(QRange indices, IQArray <T> values) { if (values.Length != indices.Count()) { throw new ArgumentOutOfRangeException(); } var index = 0; foreach (var i in indices) { this.Modify(i, values[index++]); } return(this); }
public override void Apply(IQArray <Qubit> qubits) { // Note that we need to handle null array pointers (as opposed to empty arrays) if (qubits != null) { foreach (var q in qubits) { if (simulator.State[q.Id]) { throw new ReleasedQubitsAreNotInZeroState(); } } } manager.Release(qubits); }
public virtual long StartConditionalStatement(IQArray <Result> measurementResults, IQArray <Result> resultsValues) { Debug.Assert(measurementResults.Count == resultsValues.Count); int equal = 1; for (int i = 0; i < measurementResults.Count; i++) { if (measurementResults[i] != resultsValues[i]) { equal = 0; } } return(equal); }
/// <summary> /// Converts matrix from Q# array to C# array. /// </summary> public static Complex[,] MatrixFromQs(IQArray <IQArray <Quantum.Math.Complex> > a) { long n1 = a.Length; long n2 = a[0].Length; var b = new Complex[n1, n2]; for (long i = 0; i < n1; i++) { Debug.Assert(a[i].Length == n2); for (long j = 0; j < n2; j++) { b[i, j] = new Complex(a[i][j].Real, a[i][j].Imag); } } return(b); }
/// <summary> /// Makes sure all qubits are valid as parameter of an intrinsic quantum operation. In particular it checks that /// - none of the qubits are null /// - there are no duplicated qubits /// Also sets the isMeasured flag to false for each qubit /// </summary> bool[] CheckQubits(IQArray <Qubit> ctrls, IQArray <Qubit> targets) { bool[] used = CheckQubits(targets); if (ctrls != null) { foreach (var q in ctrls) { CheckQubitInUse(q, used); //setting qubit as not measured to not allow release in case of gate operation on qubit q.IsMeasured = false; } } return(used); }
/// <summary> /// The implementation of the controlled specialization of the operation. /// For the Toffoli simulator, the implementation flips the target qubit /// if the rotation is effectively an X gate and all of the control qubits /// are in the One state. /// </summary> public void R__ControlledBody(IQArray <Qubit> controls, Pauli pauli, double angle, Qubit target) { if (target == null) { return; } this.CheckControlQubits(controls, target); var(isX, safe) = CheckRotation(pauli, angle / 2.0); if (!safe) { throw new InvalidOperationException($"The Toffoli simulator can only perform controlled rotations of multiples of 2*pi."); } // We never need to do anything since only the identity is safe to control }
/// <summary> /// Makes sure all qubits are valid as parameter of an intrinsic quantum operation. In particular it checks that /// - none of the qubits are null /// - there are no duplicated qubits /// </summary> bool[] CheckQubits(IQArray <Qubit> ctrls, Qubit q1) { bool[] used = new bool[((QSimQubitManager)QubitManager).MaxId]; CheckQubitInUse(q1, used); if (ctrls != null && ctrls.Length > 0) { foreach (var q in ctrls) { CheckQubitInUse(q, used); } } return(used); }
public virtual void IsingXX__ControlledBody(IQArray <Qubit> controls, double angle, Qubit target1, Qubit target2) { if (controls == null || controls.Length == 0) { IsingXX__Body(angle, target1, target2); } else { var targets = new QArray <Qubit>(new Qubit[] { target1, target2 }); var paulis = new Pauli[] { Pauli.PauliX, Pauli.PauliX }; CheckAngle(angle); this.CheckQubits(QArray <Qubit> .Add(controls, targets)); MCExp(this.Id, (uint)targets.Length, paulis, angle * 2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds()); } }
static void Main(string[] args) { using var qsim = new QuantumSimulator(); int n = 1000; System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew(); string[] results = new string[n]; for (int i = 0; i < n; i++) { IQArray <Result> res = QMPE.Run(qsim).Result; results[i] = res.ToString(); } stopwatch.Stop(); Console.WriteLine($"Elapsed time: {stopwatch.ElapsedMilliseconds / 1000.0} sec"); PrintResults(results); }
void IIntrinsicIsingZZ.ControlledBody(IQArray <Qubit> controls, double angle, Qubit target1, Qubit target2) { if (controls == null || controls.Length == 0) { ((IIntrinsicIsingZZ)this).Body(angle, target1, target2); } else { var targets = new QArray <Qubit>(new Qubit[] { target1, target2 }); var paulis = new Pauli[] { Pauli.PauliZ, Pauli.PauliZ }; CheckAngle(angle); this.CheckQubits(QArray <Qubit> .Add(controls, targets)); MCExp(this.Id, (uint)targets.Length, paulis, angle * 2.0, (uint)controls.Length, controls.GetIds(), targets.GetIds()); } }
public override bool Dump(IQArray <Qubit>?qubits = null) { var count = qubits?.Length ?? Simulator.QubitManager !.GetAllocatedQubitsCount(); var nQubitsPerRegister = ((int)count / 2); Data = np.empty(new Shape(1 << ((int)count), 2)); var result = base.Dump(qubits); // At this point, _data should be filled with the full state // vector, so let's display it, counting on the right display // encoder to be there to pack it into a table. var scaleFactor = System.Math.Sqrt(1 << nQubitsPerRegister); Data = scaleFactor * Data.reshape(1 << nQubitsPerRegister, 1 << nQubitsPerRegister, 2); return(result); }
/// <summary> /// Apply a permutation defined by a permutation table. This overload /// allows for perfomance optimizations like reuse of permutation /// tables. /// </summary> public static void ApplyOracle(QuantumSimulator simulator, Int64[] permutation, IQArray <Qubit> xbits, IQArray <Qubit> ybits, bool adjoint = false) { simulator.CheckQubits(xbits, "x"); simulator.CheckQubits(ybits, "y"); Debug.Assert(CheckPermutation(permutation)); var qbits = QArray <Qubit> .Add(xbits, ybits).GetIds(); if (adjoint) { AdjPermuteBasisTable(simulator.Id, (uint)qbits.Length, qbits, permutation.LongLength, permutation); } else { PermuteBasisTable(simulator.Id, (uint)qbits.Length, qbits, permutation.LongLength, permutation); } }
public IQArray <Qubit> Allocate(long count) { if (count == 0) { return(new QArray <Qubit>()); } IQArray <Qubit> res = qubitManager.Allocate(count); object[][] tracingData = GetTracingData(res); for (int i = 0; i < listeners.Length; ++i) { listeners[i].OnAllocate(tracingData[i]); } return(res); }
private static QVoid ExecuteConditionalStatement(QuantumProcessorDispatcher Simulator, Result measurementResult, Result resultValue, ICallable onEqualOp, ICallable onNonEqualOp, OperationFunctor type, IQArray <Qubit>?ctrls) { long statement = Simulator.QuantumProcessor.StartConditionalStatement(measurementResult, resultValue); return(ExecuteConditionalStatementInternal(Simulator, statement, onEqualOp, onNonEqualOp, type, ctrls)); }
public override bool Dump(IQArray <Qubit>?qubits = null) { _count = qubits == null ? this.Simulator?.QubitManager?.AllocatedQubitsCount ?? 0 : qubits.Length; _data = new Complex[1 << ((int)_count)]; var result = base.Dump(qubits); // At this point, _data should be filled with the full state // vector, so let's display it, counting on the right display // encoder to be there to pack it into a table. var id = System.Guid.NewGuid(); var state = new DisplayableState { // We cast here as we don't support a large enough number // of qubits to saturate an int. QubitIds = qubits?.Select(q => q.Id) ?? Simulator?.QubitIds.Select(q => (int)q) ?? Enumerable.Empty <int>(), NQubits = (int)_count, Amplitudes = _data, DivId = $"dump-machine-div-{id}" }; Channel.Display(state); if (ShowMeasurementDisplayHistogram) { Channel.SendIoPubMessage(new Message { Header = new MessageHeader() { MessageType = "iqsharp_state_dump" }, Content = new MeasurementHistogramContent() { State = state }, }); } // Clean up the state vector buffer. _data = null; return(result); }
/// <summary> /// 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. /// </summary> private static bool AreEqual(IQArray <Result> measurementResults, IQArray <Result> 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); }
/// <summary> /// Returns a count of input qubits that have been allocated just for borrowing, borrowed exactly once, /// and thus will be released after they are returned. /// </summary> public virtual long ToBeReleasedAfterReturnCount(IQArray <Qubit> qubitsToReturn) { if (qubitsToReturn == null || qubitsToReturn.Length == 0) { return(0); } long count = 0; foreach (Qubit qubit in qubitsToReturn) { if (this.ToBeReleasedAfterReturn(qubit)) { count++; } } return(count); }
static long XBitsFunc(IQArray <Pauli> pauli) { if (pauli.Length > 63) { throw new ExecutionFailException("Cannot pack X bits of Pauli array longer than 63"); } ulong res = 0; for (long i = pauli.Length - 1; i >= 0; --i) { res <<= 1; if (pauli[i] == Pauli.PauliX || pauli[i] == Pauli.PauliY) { res |= 1; } } return(System.Convert.ToInt64(res)); }
/// <summary> /// Dumps the wave function for the given qubits into the given target. /// If the target is QVoid or an empty string, it dumps it to the console /// using the `Message` function, otherwise it dumps the content into a file /// with the given name. /// If the given qubits is null, it dumps the entire wave function, otherwise /// it attemps to create the wave function or the resulting subsystem; if it fails /// because the qubits are entangled with some external qubit, it just generates a message. /// </summary> protected virtual QVoid Dump <T>(T target, IQArray <Qubit>?qubits = null) { var filename = (target is QVoid) ? "" : target.ToString(); QVoid process(Action <string> channel) { var ids = qubits?.Select(q => (uint)q.Id).ToArray() ?? QubitIds; var dumper = new SimpleDumper(this, channel); channel($"# wave function for qubits with ids (least to most significant): {string.Join(";", ids)}"); if (!dumper.Dump(qubits)) { channel("## Qubits were entangled with an external qubit. Cannot dump corresponding wave function. ##"); } return(QVoid.Instance); } var logMessage = this.Get <ICallable <string, QVoid>, Microsoft.Quantum.Intrinsic.Message>(); // If no file provided, use `Message` to generate the message into the console; if (string.IsNullOrWhiteSpace(filename)) { var op = this.Get <ICallable <string, QVoid>, Microsoft.Quantum.Intrinsic.Message>(); return(process((msg) => op.Apply(msg))); } else { try { using (var file = new StreamWriter(filename)) { return(process(file.WriteLine)); } } catch (Exception e) { logMessage.Apply($"[warning] Unable to write state to '{filename}' ({e.Message})"); return(QVoid.Instance); } } }
public virtual void SWAP__ControlledBody(IQArray <Qubit> controls, Qubit target1, Qubit target2) { if ((controls == null) || (controls.Count == 0)) { SWAP__Body(target1, target2); } else { var ctrls_1 = QArray <Qubit> .Add(controls, new QArray <Qubit>(target1)); var ctrls_2 = QArray <Qubit> .Add(controls, new QArray <Qubit>(target2)); this.CheckQubits(ctrls_1, target2); MCX(this.Id, (uint)ctrls_1.Length, ctrls_1.GetIds(), (uint)target2.Id); MCX(this.Id, (uint)ctrls_2.Length, ctrls_2.GetIds(), (uint)target1.Id); MCX(this.Id, (uint)ctrls_1.Length, ctrls_1.GetIds(), (uint)target2.Id); } }
/// <summary> /// Makes sure all qubits are valid as parameter of an intrinsic quantum operation. In particular it checks that /// - none of the qubits are null /// - there are no duplicated qubits /// Also sets the isMeasured flag to false for each qubit /// </summary> bool[] CheckQubits(IQArray <Qubit> ctrls, Qubit q1) { bool[] used = new bool[((QSimQubitManager)QubitManager).MaxId]; CheckQubitInUse(q1, used); q1.IsMeasured = false; if (ctrls != null && ctrls.Length > 0) { foreach (var q in ctrls) { CheckQubitInUse(q, used); //setting qubit as not measured to not allow release in case of gate operation on qubit q.IsMeasured = false; } } return(used); }
/// <summary> /// The main entry point for emulation of a permutation oracle: /// Apply the permutation defined by the oracle function /// f: (x, y) -> (x, f(x, y)). /// </summary> public static void ApplyOracle(QuantumSimulator simulator, Func <Int64, Int64, Int64, Int64> oracle, Int64 nLayers, IQArray <Qubit> xbits, Qubit ybit, bool adjoint = false) { var permutation = BuildPermutationTable(oracle, nLayers, (int)xbits.Length, 1); simulator.CheckQubits(xbits, "x"); simulator.CheckQubit(ybit, "y"); Debug.Assert(CheckPermutation(permutation)); IQArray <Qubit> ybits = new QArray <Qubit>(ybit); var qbits = QArray <Qubit> .Add(xbits, ybits).GetIds(); if (adjoint) { AdjPermuteBasisTable(simulator.Id, (uint)qbits.Length, qbits, permutation.LongLength, permutation); } else { PermuteBasisTable(simulator.Id, (uint)qbits.Length, qbits, permutation.LongLength, permutation); } }
internal void CheckControlQubits(IQArray <Qubit> ctrls, Qubit target) { CheckQubits(ctrls, "ctrls"); CheckQubit(target, "target"); var inUse = new HashSet <int>(); foreach (var c in ctrls) { if (!inUse.Add(c.Id)) { throw new NotDistinctQubits(c); } } if (inUse.Contains(target.Id)) { throw new NotDistinctQubits(target); } }
/// <summary> /// Intended to be used with simulator functions like Dump, Assert, AssertProb /// Makes sure all qubits are valid as parameter of an intrinsic quantum operation. In particular it checks that /// - none of the qubits are null /// - there are no duplicated qubits /// </summary> bool[] CheckAndPreserveQubits(IQArray <Qubit> targets) { if (targets == null) { throw new ArgumentNullException(nameof(targets), "Trying to perform an intrinsic operation on a null Qubit array."); } if (targets.Length == 0) { throw new ArgumentNullException(nameof(targets), "Trying to perform an intrinsic operation on an empty Qubit array."); } bool[] used = new bool[((QSimQubitManager)QubitManager).MaxId]; foreach (var q in targets) { CheckQubitInUse(q, used); } return(used); }
/// <summary> /// Makes sure all qubits are valid as parameter of an intrinsic quantum operation. In particular it checks that /// - none of the qubits are null /// - there are no duplicated qubits /// Also sets the isMeasured flag to false for each qubit /// </summary> bool[] CheckQubits(IQArray <Qubit> targets) { if (targets == null) { throw new ArgumentNullException(nameof(targets), "Trying to perform an intrinsic operation on a null Qubit array."); } if (targets.Length == 0) { throw new ArgumentNullException(nameof(targets), "Trying to perform an intrinsic operation on an empty Qubit array."); } bool[] used = new bool[((QSimQubitManager)QubitManager).MaxId]; foreach (var q in targets) { CheckQubitInUse(q, used); //setting qubit as not measured to not allow release in case of gate operation on qubit q.IsMeasured = false; } return(used); }
/// <summary> /// The implementation of the operation. /// For the Toffoli simulator, the implementation returns the joint parity of the /// states of the measured qubits. /// That is, Result.One is returned if an odd number of the measured qubits are /// in the One state. /// </summary> public Result Measure__Body(IQArray <Pauli> paulis, IQArray <Qubit> targets) { Qubit?f(Pauli p, Qubit q) => p switch { Pauli.PauliI => null, Pauli.PauliZ => q, _ => throw new InvalidOperationException($"The Toffoli simulator can only Measure in the Z basis.") }; if (paulis.Length != targets.Length) { throw new InvalidOperationException($"Both input arrays for Measure (paulis, targets), must be of same size"); } var qubitsToMeasure = paulis.Zip(targets, f).WhereNotNull(); var result = this.GetParity(qubitsToMeasure); return(result.ToResult()); } }
internal void CheckControlQubits(IQArray <Qubit> ctrls, IQArray <Qubit> targets) { CheckQubits(ctrls, "ctrls"); CheckQubits(targets, "targets"); var inUse = new HashSet <int>(); foreach (var c in ctrls) { if (!inUse.Add(c.Id)) { throw new NotDistinctQubits(c); } } foreach (var t in targets) { if (!inUse.Add(t.Id)) { throw new NotDistinctQubits(t); } } }
/// <summary> /// The implementation of the operation. /// For the Toffoli simulator, the implementation flips a target qubit /// if the respective rotation is effectively an X gate. /// </summary> void IIntrinsicExp.Body(IQArray <Pauli> paulis, double angle, IQArray <Qubit> targets) { if (targets == null) { return; } this.CheckQubits(targets, "targets"); if (targets.Length != paulis.Length) { throw new InvalidOperationException($"Both input arrays for Exp (paulis,targets), must be of same size"); } for (var i = 0; i < targets.Length; i++) { var(isX, safe) = CheckRotation(paulis[i], angle); if (isX) { this.State[targets[i].Id] = !this.State[targets[i].Id]; } } }
public override Result Measure(IQArray <Pauli> bases, IQArray <Qubit> qubits) { if (!bases.TryGetSingleZ(out var idx)) { // throw new UnsupportedOperationException("Not yet implemented."); var aux = this.Simulator !.QubitManager?.Allocate(); if (aux == null) { throw new NullReferenceException("Qubit manager was null."); } try { this.WriteToScratch(bases, qubits, aux); return(this.MeasureByIndex(aux.Id)); } finally { this.Simulator !.QubitManager?.Release(aux); } } return(this.MeasureByIndex(qubits[idx].Id)); }
/// <summary> /// The implementation of the controlled specialization of the operation. /// For the Toffoli simulator, the implementation flips the target qubit /// if the rotation is effectively an X gate and all of the control qubits /// are in the One state. /// </summary> void IIntrinsicExp.ControlledBody(IQArray <Qubit> controls, IQArray <Pauli> paulis, double angle, IQArray <Qubit> targets) { if (targets == null) { return; } this.CheckControlQubits(controls, targets); if (targets.Length != paulis.Length) { throw new InvalidOperationException($"Both input arrays for Exp (paulis,qubits), must be of same size"); } for (var i = 0; i < targets.Length; i++) { var(id, safe) = CheckRotation(paulis[i], angle); if (!safe) { throw new InvalidOperationException($"The Toffoli simulator can only perform controlled rotations of multiples of 2*pi."); } // We never need to do anything since only the identity is safe to control } }