diff --git a/src/Simulation/Common/AssemblyInfo.cs b/src/Simulation/Common/AssemblyInfo.cs new file mode 100644 index 00000000000..98a8d5a45f2 --- /dev/null +++ b/src/Simulation/Common/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Runtime.CompilerServices; + +// Allow the test assembly to use our internal methods +[assembly: InternalsVisibleTo("Tests.Microsoft.Quantum.Simulators" + SigningConstants.PUBLIC_KEY)] diff --git a/src/Simulation/Common/Extensions.cs b/src/Simulation/Common/Extensions.cs index b36867a7388..22b14c4f7c3 100644 --- a/src/Simulation/Common/Extensions.cs +++ b/src/Simulation/Common/Extensions.cs @@ -30,7 +30,7 @@ public static uint[] GetIds(this IQArray qubits) /// a subclass of T and registers as the override of the BaseType /// it implements. /// - public static void InitBuiltinOperations(this AbstractFactory factory, Type t) + public static void InitBuiltinOperations(this Factory factory, Type t) { if (t == null) { diff --git a/src/Simulation/Common/AbstractFactory.cs b/src/Simulation/Common/Factory.cs similarity index 98% rename from src/Simulation/Common/AbstractFactory.cs rename to src/Simulation/Common/Factory.cs index fc5430288d4..c8e3e8d12bd 100644 --- a/src/Simulation/Common/AbstractFactory.cs +++ b/src/Simulation/Common/Factory.cs @@ -13,7 +13,7 @@ namespace Microsoft.Quantum.Simulation.Common /// It also provides a mechanism to register overrides when a given /// type should be replaced by a subclass. /// - public abstract class AbstractFactory + public class Factory { protected Dictionary opsOverrides = new Dictionary(); protected Dictionary opsCache = new Dictionary(); diff --git a/src/Simulation/Common/IQuantumProcessor.cs b/src/Simulation/Common/IQuantumProcessor.cs index dd61aed3bdd..ed6d7fcc3eb 100644 --- a/src/Simulation/Common/IQuantumProcessor.cs +++ b/src/Simulation/Common/IQuantumProcessor.cs @@ -11,7 +11,6 @@ namespace Microsoft.Quantum.Simulation.Common /// /// /// To implement a target machine that executes quantum commands, implement this interface. - /// Consider using as a stub for easy impementation of this interface. /// Implementors of interface do not manage qubits on their own. /// All qubit management (allocation, dealocation, etc.) is done by the caller of this interface. /// Implementors are notified when qubits are allocated, released, borrowed and returned allowing them to react to these events if necessary. diff --git a/src/Simulation/Common/IQubitManager.cs b/src/Simulation/Common/IQubitManager.cs index 774158b80ab..f00ce28d8c0 100644 --- a/src/Simulation/Common/IQubitManager.cs +++ b/src/Simulation/Common/IQubitManager.cs @@ -3,41 +3,37 @@ namespace Microsoft.Quantum.Simulation.Common { - using Microsoft.Quantum.Simulation.Core; using System.Collections.Generic; + using Microsoft.Quantum.Simulation.Core; public interface IQubitManager { + bool DisableBorrowing { get; } + + bool IsValid(Qubit qubit); + bool IsFree(Qubit qubit); + bool IsDisabled(Qubit qubit); + + long FreeQubitsCount { get; } + long AllocatedQubitsCount { get; } + IEnumerable AllocatedIds(); + long QubitsAvailableToBorrowCount(int stackFrame = 0); + + void Disable(Qubit qubit); + void Disable(IQArray qubits); + Qubit Allocate(); IQArray Allocate(long count); void Release(Qubit qubit); void Release(IQArray qubits); - void Disable(Qubit qubit); - void Disable(IQArray qubits); - Qubit Borrow(); IQArray Borrow(long count); void Return(Qubit q); void Return(IQArray qubits); - bool ToBeReleasedAfterReturn(Qubit qubit); - long ToBeReleasedAfterReturnCount(IQArray qubitsToReturn); - - bool IsValid(Qubit qubit); - bool IsFree(Qubit qubit); - bool IsDisabled(Qubit qubit); - - long GetFreeQubitsCount(); - long GetQubitsAvailableToBorrowCount(); - long GetParentQubitsAvailableToBorrowCount(); // Required for GetAvailableQubitsToBorrow - long GetAllocatedQubitsCount(); - IEnumerable GetAllocatedIds(); - - bool DisableBorrowing { get; } - /// /// Callback to notify QubitManager that an operation execution has started. /// This helps manage qubits scope. diff --git a/src/Simulation/Common/QubitManager.cs b/src/Simulation/Common/QubitManager.cs index 9bc54dfce3d..deec96a147e 100644 --- a/src/Simulation/Common/QubitManager.cs +++ b/src/Simulation/Common/QubitManager.cs @@ -5,10 +5,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Microsoft.Quantum.Intrinsic; using Microsoft.Quantum.Simulation.Core; using Microsoft.Quantum.Simulation.Simulators.Exceptions; +#nullable enable + namespace Microsoft.Quantum.Simulation.Common { /// @@ -17,22 +18,35 @@ namespace Microsoft.Quantum.Simulation.Common /// Allocation and release are O(1) operations. /// QubitManager uses memory - sizeof(long)*qubitCapacity. qubitCapacity is passed in to the constructor. /// - public class QubitManager + public class QubitManager : IQubitManager { - long NumQubits; // Total number of qubits this QubitManager is capable of handling. - long None; // Indicates the end of the list of free qubits. If we reach it - we are out of qubits. - long Allocated; // All qubits allocated by user will be marked with this number. - long Disabled; // All qubits disabled via DisableQubit interface will be marked with this number. - long AllocatedForBorrowing; // All qubits allocated only for borrowing, will be marked with this number or higher. - long[] qubits; // Tracks the allocation state of all qubits. - long free; // Points to the first free (unallocated) qubit. - long freeTail; // Points to the last free (unallocated) qubit. Only valid iff (!EncourageReuse). - long numAllocatedQubits; // Tracking this for optimization. - long numDisabledQubits; // Number of disabled qubits. + /// + /// Total number of qubits this QubitManager is capable of handling. + /// + protected long NumQubits; + /// + /// The number of currently allocated qubits. + /// + protected long NumAllocatedQubits; + /// + /// The number of disabled qubits. + /// + protected long NumDisabledQubits; + /// + /// Tracks the allocation state of all qubits. + /// + protected long[] qubits; + + private long None; // Indicates the end of the list of free qubits. If we reach it - we are out of qubits. + private long Allocated; // All qubits allocated by user will be marked with this number. + private long Disabled; // All qubits disabled via DisableQubit interface will be marked with this number. + private long AllocatedForBorrowing; // All qubits allocated only for borrowing, will be marked with this number or higher. + private long free; // Points to the first free (unallocated) qubit. + private long freeTail; // Points to the last free (unallocated) qubit. Only valid iff (!EncourageReuse). // Options - bool MayExtendCapacity; - bool EncourageReuse; + protected readonly bool MayExtendCapacity; + protected readonly bool EncourageReuse; public bool DisableBorrowing { get; } const long MaxQubitCapacity = long.MaxValue - 3; @@ -49,6 +63,84 @@ public class QubitManager // For qubits that are free, the array stores the index of the next free qubit (a value less than "Allocated" constant). // The last free qubit in the list of free qubits stores the value "None". + private void UpdateQubitCapacity(long newQubitCapacity) + { + Debug.Assert(newQubitCapacity < MaxQubitCapacity); + NumQubits = newQubitCapacity; + None = NumQubits; + Allocated = NumQubits + 1; + Disabled = NumQubits + 2; + AllocatedForBorrowing = NumQubits + 3; + this.qubits = new long[NumQubits]; + } + + // stack frame management needed to support borrowing qubits + #region StackFrameManagement + + protected class StackFrame + { + internal IApplyData? Data; + internal IEnumerable? QubitsInArgument => Data?.Qubits; + private List? _locals; // Qubits allocated/borrowed in the current operation + + public StackFrame(IApplyData data = null) + { + Data = data; + } + + public List Locals + { + get + { + if (_locals == null) + { + _locals = new List(); + } + + return _locals; + } + } + } + + protected readonly Stack operationStack; // Stack of operation calls, including the current frame for the current scope + + public virtual void OnOperationStart(ICallable _, IApplyData values) + { + if (!DisableBorrowing) + { + operationStack.Push(new StackFrame(values)); + } + } + + public virtual void OnOperationEnd(ICallable _, IApplyData values) + { + if (!DisableBorrowing) + { + operationStack.Pop(); + } + } + + protected IEnumerable QubitsInUse(StackFrame frame) + { + if (DisableBorrowing || frame == null) + { + return Qubit.NO_QUBITS; + } + + return frame.Locals.Concat(frame.QubitsInArgument ?? Array.Empty()) + .Where(q => q != null && !this.IsDisabled(q)); + } + + protected int QubitsInUseCount(StackFrame frame) + { + // The following is not really efficient, but let's wait to see if distinct can be part of the contract + // for the qubitsInArgument parameter of StartOperation call. + // Well, we are talking about really small arrays here anyway. + return QubitsInUse(frame).Distinct().Count(); + } + + #endregion + /// /// Creates and initializes QubitManager that can handle up to numQubits qubits /// @@ -74,66 +166,40 @@ public QubitManager( free = 0; freeTail = NumQubits - 1; - numAllocatedQubits = 0; - numDisabledQubits = 0; - } + NumAllocatedQubits = 0; + NumDisabledQubits = 0; - private void UpdateQubitCapacity(long newQubitCapacity) - { - Debug.Assert(newQubitCapacity < MaxQubitCapacity); - NumQubits = newQubitCapacity; - None = NumQubits; - Allocated = NumQubits + 1; - Disabled = NumQubits + 2; - AllocatedForBorrowing = NumQubits + 3; - this.qubits = new long[NumQubits]; + if (!DisableBorrowing) + { + operationStack = new Stack(); + operationStack.Push(new StackFrame()); + } } - private void ExtendQubitArray() + private class QubitNonAbstract : Qubit { - long oldNumQubits = NumQubits; - long oldNone = None; - long oldAllocated = Allocated; - long oldDisabled = Disabled; - long oldAllocatedForBorrowing = AllocatedForBorrowing; - long[] oldQubitsArray = this.qubits; - - UpdateQubitCapacity(oldNumQubits*2); // This changes Allocated, Disabled, AllocatedForBorrowing markers. - - for (long i = 0; i < oldNumQubits; i++) - { - if (oldQubitsArray[i] == oldNone) { - // Point to the first new (free) element - this.qubits[i] = oldNumQubits; - } else if (oldQubitsArray[i] == oldAllocated) { - // Allocated qubits are marked differently now. - this.qubits[i] = Allocated; - } - else if (oldQubitsArray[i] == oldDisabled) - { - // Disabled qubits are marked differently now. - this.qubits[i] = Disabled; - } - else if (oldQubitsArray[i] >= oldAllocatedForBorrowing) { - // This updates refCounts - this.qubits[i] = (oldQubitsArray[i] - oldAllocatedForBorrowing) + AllocatedForBorrowing ; - } - } - - for (long i = oldNumQubits; i < NumQubits; i++) - { - this.qubits[i] = i + 1; - } - Debug.Assert(this.qubits[NumQubits - 1] == None); + // This class is only needed because Qubit is abstract. + // It is equivalent to Qubit and adds nothing to it except the ability to create it. + // It should be used only in CreateQubitObject below, and nowhere else. + // When Qubit stops being abstract, this class should be removed. + public QubitNonAbstract(int id) : base(id) { } + } - if (free == oldNone) + /// + /// May be overriden to create a custom Qubit object of a derived type. + /// + /// unique qubit id + /// a newly instantiated qubit + public virtual Qubit CreateQubitObject(long id) + { + if (id >= Int32.MaxValue) { - free = oldNumQubits; - freeTail = NumQubits - 1; + throw new NotSupportedException($"Qubit id out of range."); } + return new QubitNonAbstract((int)id); } - public bool IsValid(Qubit qubit) + public virtual bool IsValid(Qubit qubit) { if (qubit == null) { return false; } if (qubit.Id >= NumQubits) { return false; } @@ -141,21 +207,14 @@ public bool IsValid(Qubit qubit) return true; } - public bool IsFree(Qubit qubit) - { - if (!IsValid(qubit)) { return false; } - return IsFree(qubit.Id); - } - private bool IsFree(long id) { return qubits[id] < Allocated; } - public bool IsDisabled(Qubit qubit) + public virtual bool IsFree(Qubit qubit) { - if (!IsValid(qubit)) { return false; } - return IsDisabled(qubit.Id); + return IsValid(qubit) && IsFree(qubit.Id); } private bool IsDisabled(long id) @@ -163,107 +222,175 @@ private bool IsDisabled(long id) return (qubits[id] == Disabled); } + public virtual bool IsDisabled(Qubit qubit) + { + return IsValid(qubit) && IsDisabled(qubit.Id); + } + private bool IsAllocatedForBorrowing(long id) { return qubits[id] >= AllocatedForBorrowing; } - // Returns true if qubit needs to be released: It has been allocated for borrowing and is not borrowed any more. - private bool BorrowingRefCountIsOne(long id) + public virtual long QubitsAvailableToBorrowCount(int stackFrame) { - if (IsAllocatedForBorrowing(id)) + if (DisableBorrowing) { - if (qubits[id] == AllocatedForBorrowing) - { - return true; - } + return 0; } - return false; + + var popped = new Stack(); + while (stackFrame-- > 0) + { + popped.Push(operationStack.Pop()); + } + StackFrame frame = operationStack.Peek(); + while (popped.TryPop(out var f)) + { + operationStack.Push(f); + } + return NumAllocatedQubits - QubitsInUseCount(frame); } - // Returns true if qubit needs to be released: It has been allocated for borrowing and is not borrowed any more. - private bool DecreaseBorrowingRefCount(long id) + public long FreeQubitsCount => NumQubits - NumDisabledQubits - NumAllocatedQubits; + + public long AllocatedQubitsCount => NumAllocatedQubits; + + public virtual IEnumerable AllocatedIds() { - if (IsAllocatedForBorrowing(id)) { - if (qubits[id] == AllocatedForBorrowing) - { - return true; - } - else - { - qubits[id]--; - return false; - } - } else + for (long i = 0; i < qubits.LongLength; i++) { - return false; + if (!IsFree(i)) yield return i; } } - private void IncreaseBorrowingRefCount(long id) + #region Disable + + /// + /// Disables a given qubit. + /// Once a qubit is disabled it can never be reallocated. + /// + public virtual void Disable(Qubit qubit) { - if (IsAllocatedForBorrowing(id)) + qubits[qubit.Id] = Disabled; + NumDisabledQubits++; + + NumAllocatedQubits--; + Debug.Assert(NumAllocatedQubits >= 0); + } + + /// + /// Disables a set of given qubits. + /// Once a qubit is disabled it can never be reallocated. + /// + public void Disable(IQArray qubitsToDisable) + { + if (qubitsToDisable == null || qubitsToDisable.Length == 0) { - qubits[id]++; + return; + } + + foreach (Qubit qubit in qubitsToDisable) + { + this.Disable(qubit); } } + #endregion + + #region Allocate + /// /// Allocates a qubit. + /// Returns null if the qubit cannot be allocated. /// - protected virtual Qubit AllocateOneQubit(bool usedOnlyForBorrowing) + protected virtual Qubit? Allocate(bool usedOnlyForBorrowing) { if (free == None) { - if (MayExtendCapacity) + if (!MayExtendCapacity) { - ExtendQubitArray(); + return null; } - else + + long oldNumQubits = NumQubits; + long oldNone = None; + long oldAllocated = Allocated; + long oldDisabled = Disabled; + long oldAllocatedForBorrowing = AllocatedForBorrowing; + long[] oldQubitsArray = this.qubits; + + UpdateQubitCapacity(oldNumQubits * 2); // This changes Allocated, Disabled, AllocatedForBorrowing markers. + + for (long i = 0; i < oldNumQubits; i++) { - return null; + if (oldQubitsArray[i] == oldNone) + { + // Point to the first new (free) element + this.qubits[i] = oldNumQubits; + } + else if (oldQubitsArray[i] == oldAllocated) + { + // Allocated qubits are marked differently now. + this.qubits[i] = Allocated; + } + else if (oldQubitsArray[i] == oldDisabled) + { + // Disabled qubits are marked differently now. + this.qubits[i] = Disabled; + } + else if (oldQubitsArray[i] >= oldAllocatedForBorrowing) + { + // This updates refCounts + this.qubits[i] = (oldQubitsArray[i] - oldAllocatedForBorrowing) + AllocatedForBorrowing; + } + } + + for (long i = oldNumQubits; i < NumQubits; i++) + { + this.qubits[i] = i + 1; + } + Debug.Assert(this.qubits[NumQubits - 1] == None); + + if (free == oldNone) + { + free = oldNumQubits; + freeTail = NumQubits - 1; } } - Qubit result = CreateQubitObject(free); + + Qubit ret = CreateQubitObject(free); long temp = free; free = qubits[free]; qubits[temp] = (usedOnlyForBorrowing ? AllocatedForBorrowing : Allocated); - numAllocatedQubits++; - return result; - } - - private class QubitNonAbstract : Qubit - { - // This class is only needed because Qubit is abstract. - // It is equivalent to Qubit and adds nothing to it except the ability to create it. - // It should be used only in CreateQubitObject below, and nowhere else. - // When Qubit stops being abstract, this class should be removed. - public QubitNonAbstract(int id) : base(id) { } - } - - public virtual Qubit CreateQubitObject(long id) - { // User may override it to create his own Qubit object of a derived type. - return new QubitNonAbstract((int)id); + NumAllocatedQubits++; + if (!DisableBorrowing) + { + operationStack.Peek().Locals.Add(ret); + } + return ret; } /// /// Allocates a qubit. + /// Throws a NotEnoughQubits exception if the qubit cannot be allocated. /// - public virtual Qubit Allocate() + public Qubit Allocate() { - Qubit qb = AllocateOneQubit(usedOnlyForBorrowing: false); + Qubit? qb = Allocate(usedOnlyForBorrowing: false); if (qb == null) { - throw new NotEnoughQubits(1, GetFreeQubitsCount()); + throw new NotEnoughQubits(1, this.FreeQubitsCount); } return qb; } /// /// Allocates numToAllocate new qubits. + /// Throws a NotEnoughQubits exception without allocating any qubits if the qubits cannot be allocated. /// - public virtual IQArray Allocate(long numToAllocate) + public IQArray Allocate(long numToAllocate) { if (numToAllocate < 0) { @@ -275,78 +402,86 @@ public virtual IQArray Allocate(long numToAllocate) } QArray result = QArray.Create(numToAllocate); - for (int i = 0; i < numToAllocate; i++) { - result.Modify(i, AllocateOneQubit(usedOnlyForBorrowing: false)); - if (result[i] == null) + Qubit? allocated = Allocate(usedOnlyForBorrowing: false); + if (allocated == null) { for (int k = 0; k < i; k++) { - Release(result[k]); + Release(result[k], wasUsedOnlyForBorrowing: false); } - throw new NotEnoughQubits(numToAllocate, GetFreeQubitsCount()); + throw new NotEnoughQubits(numToAllocate, this.FreeQubitsCount); } + result.Modify(i, allocated); } return result; } - protected virtual void ReleaseOneQubit(Qubit qubit, bool usedOnlyForBorrowing) + #endregion + + #region Release + + protected virtual void Release(Qubit qubit, bool wasUsedOnlyForBorrowing) { if (qubits[qubit.Id] == Disabled) { // Nothing to do. It will stay disabled. - // Alternatively, we could mark is as None here. + return; + } + + if (qubits[qubit.Id] != (wasUsedOnlyForBorrowing ? AllocatedForBorrowing : Allocated)) + { + throw new ArgumentException("Attempt to free qubit that has not been allocated."); } + + if (EncourageReuse) { + qubits[qubit.Id] = free; + free = qubit.Id; + } else { - long Occupied = (usedOnlyForBorrowing ? AllocatedForBorrowing : Allocated); - if (qubits[qubit.Id] != Occupied) - { - throw new ArgumentException("Attempt to free qubit that has not been allocated."); - } - if (EncourageReuse) { - qubits[qubit.Id] = free; - free = qubit.Id; - } - else + // If we are allowed to extend capacity we will never reuse this qubit, + // otherwise we need to add it to the free qubits list. + if (!MayExtendCapacity) { - // If we are allowed to extend capacity we will never reuse this qubit, - // otherwise we need to add it to the free qubits list. - if (!MayExtendCapacity) + if (qubits[freeTail] != None) { - if (qubits[freeTail] != None) - { - // There were no free qubits at all - free = qubit.Id; - } - else - { - qubits[freeTail] = qubit.Id; - } + // There were no free qubits at all + free = qubit.Id; + } + else + { + qubits[freeTail] = qubit.Id; } - qubits[qubit.Id] = None; - freeTail = qubit.Id; } + qubits[qubit.Id] = None; + freeTail = qubit.Id; + } - numAllocatedQubits--; - Debug.Assert(numAllocatedQubits >= 0); + NumAllocatedQubits--; + Debug.Assert(NumAllocatedQubits >= 0); + + if (!DisableBorrowing) + { + bool success = operationStack.Peek().Locals.Remove(qubit); + Debug.Assert(success, "Releasing qubit that is not a local variable in scope."); } } /// /// Releases a given qubit. /// - public virtual void Release(Qubit qubit) + public void Release(Qubit qubit) { - ReleaseOneQubit(qubit, usedOnlyForBorrowing: false); + Release(qubit, wasUsedOnlyForBorrowing: false); } /// /// Releases a set of given qubits. /// - public virtual void Release(IQArray qubitsToRelease) + public void Release(IQArray qubitsToRelease) { if (qubitsToRelease == null || qubitsToRelease.Length == 0) { @@ -355,91 +490,98 @@ public virtual void Release(IQArray qubitsToRelease) for (long i = qubitsToRelease.Length-1; i>=0; i--) { // Going from the end is more efficient in case we are tracking scope. - this.ReleaseOneQubit(qubitsToRelease[i], usedOnlyForBorrowing: false); + this.Release(qubitsToRelease[i], wasUsedOnlyForBorrowing: false); } } - protected virtual void DisableOneQubit(Qubit qubit) - { - // Note: Borrowed qubits cannot be disabled. - Debug.Assert(qubits[qubit.Id] == Allocated); - qubits[qubit.Id] = Disabled; - numDisabledQubits++; + #endregion - numAllocatedQubits--; - Debug.Assert(numAllocatedQubits >= 0); - } - - /// - /// Disables a given qubit. - /// Once a qubit is disabled it can never be reallocated. - /// - public virtual void Disable(Qubit qubit) - { - DisableOneQubit(qubit); - } + #region Borrow /// - /// Disables a set of given qubits. - /// Once a qubit is disabled it can never be reallocated. + /// Returns a qubit that is allocated, not disabled, and not listed as in use, whose id is in [minId, maxId). /// - public virtual void Disable(IQArray qubitsToDisable) + /// Contains the qubits that cannot be borrowed, where the qubits with the lowest ids are queued first. + /// Only qubits whose id is larger or equal to minId will be considered for borrowing. Set to 0 if unspecified. + /// Only qubits whose id is smaller than maxId will be considered for borrowing. Set to NumQubits if unspecified. + /// + protected virtual Qubit? Borrow(Stack qubitsInUseSortedById, long minId = 0, long maxId = -1) { - if (qubitsToDisable == null || qubitsToDisable.Length == 0) + maxId = maxId < 0 ? NumQubits : maxId; + for (long curQubit = System.Math.Max(0, minId); curQubit < maxId; curQubit++) { - return; - } - - foreach (Qubit qubit in qubitsToDisable) - { - this.DisableOneQubit(qubit); - } - } - - - public long GetQubitsAvailableToBorrowCount(IEnumerable excludedQubitsSortedById) - { - // Note: this function is not allowed to call its no-parameters cousin: GetQubitsAvailableToBorrowCount() - return numAllocatedQubits - excludedQubitsSortedById.Count(); - } - - public virtual long GetQubitsAvailableToBorrowCount() - { - return numAllocatedQubits; - } + if (IsFree(curQubit) || IsDisabled(curQubit)) + { + continue; + } - public virtual long GetParentQubitsAvailableToBorrowCount() - { - return GetQubitsAvailableToBorrowCount(); - } + bool gotNextInUse = qubitsInUseSortedById.TryPeek(out Qubit nextInUse); + if (gotNextInUse && nextInUse.Id == curQubit) + { + qubitsInUseSortedById.Pop(); + continue; + } + if (IsAllocatedForBorrowing(curQubit)) + { + qubits[curQubit]++; + } - public long GetFreeQubitsCount() - { - return NumQubits - numDisabledQubits - numAllocatedQubits; + Qubit ret = CreateQubitObject(curQubit); + if (!DisableBorrowing) + { + operationStack.Peek().Locals.Add(ret); + } + return ret; + } + return null; } - public long GetAllocatedQubitsCount() + // internal for testing purposes + internal IQArray Borrow(long numToBorrow, IEnumerable qubitsInUse) { - return numAllocatedQubits; - } + var inUse = new Stack(qubitsInUse.Distinct().OrderByDescending(q => q.Id)); + var borrowed = QArray.Create(numToBorrow); + long numBorrowed = System.Math.Min(NumAllocatedQubits - inUse.Count, numToBorrow); - public IEnumerable GetAllocatedIds() - { - for (long i = 0; i < qubits.LongLength; i++) + long lastBorrowedId = -1; + for (long curBorrowed = 0; curBorrowed < numBorrowed; ++curBorrowed) { - if (!IsFree(i)) yield return i; + Qubit? bq = Borrow(inUse, minId: lastBorrowedId + 1); + if (bq == null) // should not happen + { + numBorrowed = curBorrowed; + break; + } + borrowed.Modify(curBorrowed, bq); + lastBorrowedId = borrowed[curBorrowed].Id; + } + + if (numBorrowed < numToBorrow) + { // Not enough qubits to borrow. Allocate what was not borrowed. + for (long i = numBorrowed; i < numToBorrow; i++) + { + Qubit? allocated = Allocate(usedOnlyForBorrowing: true); + if (allocated == null) + { + for (long k = numBorrowed; k < i; k++) + { + Release(borrowed[(int)k], wasUsedOnlyForBorrowing: true); + } + throw new NotEnoughQubits(numToBorrow, numBorrowed + this.FreeQubitsCount); + } + borrowed.Modify(i, allocated); + } } + + return borrowed; } /// /// Borrows a number of qubits. Chooses them from among already allocated ones. - /// Makes sure borrowed qubits are not on the exclusion list. - /// Exclusion list is supposed to contain qubits that can not be borrowed, - /// for example those, that are being used (or could be used) in the current context. /// If there are not enough qubits to borrow, allocates new ones. /// - public virtual IQArray Borrow(long numToBorrow, IEnumerable excludedQubitsSortedById) // Note, excluded could be an array of Ids for efficiency, if it is convenient for compiler. + public IQArray Borrow(long numToBorrow) { if (numToBorrow < 0) { @@ -455,105 +597,23 @@ public IEnumerable GetAllocatedIds() return Allocate(numToBorrow); } - if (excludedQubitsSortedById == null) { - excludedQubitsSortedById = new Qubit[0]; - } - - QArray result = QArray.Create(numToBorrow); - long numBorrowed = TryBorrow(numToBorrow, result, excludedQubitsSortedById); - - if (numBorrowed < numToBorrow) - { // Not enough qubits to borrow. Allocate what was not borrowed. - for (long i = numBorrowed; i < numToBorrow; i++) - { - result.Modify(i, AllocateOneQubit(usedOnlyForBorrowing: true)); - if (result[(int)i] == null) - { - for (long k = numBorrowed; k < i; k++) - { - ReleaseOneQubit(result[(int)k], usedOnlyForBorrowing: true); - } - throw new NotEnoughQubits(numToBorrow, numBorrowed + GetFreeQubitsCount()); - } - } - } - - return result; + return Borrow(numToBorrow, QubitsInUse(operationStack.Peek())); } - protected virtual Qubit BorrowOneQubit(long id) + public Qubit Borrow() { - IncreaseBorrowingRefCount(id); - return CreateQubitObject(id); - } - - private long TryBorrow(long numToBorrow, QArray result, IEnumerable excludedQubitsSortedById) - { - long curQubit = 0; - long numBorrowed = 0; - long curBorrowed = 0; - IEnumerator enumer = excludedQubitsSortedById.GetEnumerator(); - bool exclusionsPresent = enumer.MoveNext(); - - numBorrowed = System.Math.Min(GetQubitsAvailableToBorrowCount(excludedQubitsSortedById), numToBorrow); - - while (curBorrowed < numBorrowed) + if (DisableBorrowing) { - while (IsFree(curQubit) || IsDisabled(curQubit)) - { - curQubit++; - Debug.Assert(curQubit < NumQubits); - } - Debug.Assert((!exclusionsPresent) || (enumer.Current.Id >= curQubit)); - if ((!exclusionsPresent) || (enumer.Current.Id != curQubit)) - { - result.Modify(curBorrowed, BorrowOneQubit(curQubit)); - curBorrowed++; - } - else - { - exclusionsPresent = enumer.MoveNext(); - } - curQubit++; - Debug.Assert(curQubit < NumQubits); + return Allocate(); } - return numBorrowed; - } - protected virtual void ReturnOneQubit(Qubit qubit) - { + var inUse = new Stack(QubitsInUse(operationStack.Peek()).Distinct().OrderByDescending(q => q.Id)); + return NumAllocatedQubits == inUse.Count ? Allocate() : (Borrow(inUse) ?? Allocate()); } - /// - /// Returns true if a qubit has been allocated just for borrowing, has been borrowed exactly once, - /// and thus will be released after it is returned. - /// - public virtual bool ToBeReleasedAfterReturn(Qubit qubit) - { - return BorrowingRefCountIsOne(qubit.Id); - } + #endregion - /// - /// 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. - /// - public virtual long ToBeReleasedAfterReturnCount(IQArray qubitsToReturn) - { - if (qubitsToReturn == null || qubitsToReturn.Length == 0) - { - return 0; - } - - long count = 0; - foreach (Qubit qubit in qubitsToReturn) - { - if (this.ToBeReleasedAfterReturn(qubit)) - { - count++; - } - } - return count; - } + #region Return /// /// Returns a given borrowed qubit. @@ -563,17 +623,31 @@ public virtual void Return(Qubit qubit) { if (DisableBorrowing) { - this.ReleaseOneQubit(qubit, usedOnlyForBorrowing: false); + this.Release(qubit, wasUsedOnlyForBorrowing: false); } else { - if (DecreaseBorrowingRefCount(qubit.Id)) + var needsToBeReleased = false; + if (IsAllocatedForBorrowing(qubit.Id)) + { + if (qubits[qubit.Id] == AllocatedForBorrowing) + { + needsToBeReleased = true; + } + else + { + qubits[qubit.Id]--; + } + } + + if (needsToBeReleased) { - this.ReleaseOneQubit(qubit, usedOnlyForBorrowing: true); + this.Release(qubit, wasUsedOnlyForBorrowing: true); } else { - this.ReturnOneQubit(qubit); + bool success = operationStack.Peek().Locals.Remove(qubit); // Could be more efficient here going from the end manually. + Debug.Assert(success, "Returning qubit that is not a local variable in scope."); } } } @@ -582,7 +656,7 @@ public virtual void Return(Qubit qubit) /// Returns a set of borrowed qubits given. /// Releases those that have been allocated just for borrowing. /// - public virtual void Return(IQArray qubitsToReturn) + public void Return(IQArray qubitsToReturn) { if (qubitsToReturn == null || qubitsToReturn.Length == 0) { @@ -594,21 +668,7 @@ public virtual void Return(IQArray qubitsToReturn) this.Return(qubitsToReturn[i]); } } - - /// - /// Same as Borrow, but allows array of exluded qubits to be unsorted. It is recommended to use Borrow instead. - /// - /// - /// - /// - public virtual IQArray BorrowUnsorted(long numToBorrow, IEnumerable excludedQubits) // Note, excluded could be an array of Ids for efficiency, if it is convenient for compiler. - { - if (DisableBorrowing) - { - return Allocate(numToBorrow); - } - return Borrow(numToBorrow, excludedQubits.OrderBy(Qubit => Qubit.Id)); - } } + #endregion } diff --git a/src/Simulation/Common/QubitManagerTrackingScope.cs b/src/Simulation/Common/QubitManagerTrackingScope.cs deleted file mode 100644 index a166f98bfa0..00000000000 --- a/src/Simulation/Common/QubitManagerTrackingScope.cs +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using Microsoft.Quantum.Simulation.Core; - -namespace Microsoft.Quantum.Simulation.Common -{ - public class QubitManagerTrackingScope : QubitManager, IQubitManager - { - - private class StackFrame - { - internal IApplyData Data; - internal IEnumerable QubitsInArgument => Data?.Qubits; - internal List _locals; // Qubits allocated/borrowed in the current operation - - public StackFrame() - { - Data = null; - } - - public StackFrame(IApplyData data) - { - Data = data; - } - - public List Locals - { - get - { - if (_locals == null) - { - _locals = new List(); - } - - return _locals; - } - } - } - - private Stack operationStack; // Stack of operation calls. - private StackFrame curFrame; // Current stack frame - all qubits in current scope are listed here. - - public QubitManagerTrackingScope( - long qubitCapacity, - bool mayExtendCapacity = false, - bool disableBorrowing = false, - bool encourageReuse = true) - : base(qubitCapacity, mayExtendCapacity, disableBorrowing, encourageReuse) - { - if (!DisableBorrowing) - { - operationStack = new Stack(); - curFrame = new StackFrame(); - } - } - - public void OnOperationStart(ICallable operation, IApplyData values) - { - if (!DisableBorrowing) - { - operationStack.Push(curFrame); - curFrame = new StackFrame(values); - } - } - - public void OnOperationEnd(ICallable operation, IApplyData values) - { - if (!DisableBorrowing) - { - curFrame = operationStack.Pop(); - } - } - - protected override Qubit AllocateOneQubit(bool usedOnlyForBorrowing) - { - Qubit ret = base.AllocateOneQubit(usedOnlyForBorrowing); - if (!DisableBorrowing) - { - curFrame.Locals.Add(ret); - } - return ret; - } - - protected override void ReleaseOneQubit(Qubit qubit, bool usedOnlyForBorrowing) - { - base.ReleaseOneQubit(qubit, usedOnlyForBorrowing); - if (!DisableBorrowing) - { - bool success = curFrame.Locals.Remove(qubit); - Debug.Assert(success, "Releasing qubit that is not a local variable in scope."); - } - } - - protected override Qubit BorrowOneQubit(long id) - { - Qubit ret = base.BorrowOneQubit(id); - if (!DisableBorrowing) - { - curFrame.Locals.Add(ret); - } - return ret; - } - - protected override void ReturnOneQubit(Qubit qubit) - { - base.ReturnOneQubit(qubit); - if (!DisableBorrowing) - { - bool success = curFrame.Locals.Remove(qubit); // Could be more efficient here going from the end manually. - Debug.Assert(success, "Returning qubit that is not a local variable in scope."); - } - } - - private IEnumerable ExcludedQubitsForFrame(StackFrame curFrame) - { - var qubitsInArgument = curFrame.QubitsInArgument?.ToArray(); - long numExcluded = curFrame.Locals.Count + (qubitsInArgument?.Length ?? 0); - var excludedQubits = new Qubit[numExcluded]; - - int k = 0; - if (qubitsInArgument != null) - { - foreach (Qubit q in qubitsInArgument) - { - excludedQubits[k] = q; - k++; - } - } - foreach (Qubit q in curFrame.Locals) - { - excludedQubits[k] = q; - k++; - } - Debug.Assert(k == numExcluded); - - // The following is not really efficient, but let's wait to see if distinct can be part of the contract - // for the qubitsInArgument parameter of StartOperation call. - // Well, we are talking about really small arrays here anyway. - return excludedQubits.Where(q => q != null).Distinct().OrderBy(Qubit => Qubit.Id); - } - - private IEnumerable ConstructExcludedQubitsArray() - { - if (DisableBorrowing) - { - return Qubit.NO_QUBITS; - } - - return ExcludedQubitsForFrame(curFrame); - } - - private IEnumerable ConstructParentExcludedQubitsArray() - { - if (DisableBorrowing) - { - return Qubit.NO_QUBITS; - } - - if (operationStack.Count < 1) - { - return Qubit.NO_QUBITS; - } - - // curFrame is the current frame. operationStack only contains "out" frames, - // but not the current frame. Thus, the top of the stack is the parent frame, - // not the current frame. - return ExcludedQubitsForFrame(operationStack.Peek()); - } - - public virtual Qubit Borrow() - { - return base.Borrow(1, ConstructExcludedQubitsArray())[0]; - } - - public virtual IQArray Borrow(long numToBorrow) - { - return base.Borrow(numToBorrow, ConstructExcludedQubitsArray()); - } - - public override long GetQubitsAvailableToBorrowCount() - { - if (!DisableBorrowing) - { - return GetQubitsAvailableToBorrowCount(ConstructExcludedQubitsArray()); - } - else - { - return 0; - } - } - - public override long GetParentQubitsAvailableToBorrowCount() - { - if (!DisableBorrowing) - { - return GetQubitsAvailableToBorrowCount(ConstructParentExcludedQubitsArray()); - } - else - { - return 0; - } - } - } -} diff --git a/src/Simulation/Common/SimulatorBase.cs b/src/Simulation/Common/SimulatorBase.cs index e2529cf75c7..4b7d4e25945 100644 --- a/src/Simulation/Common/SimulatorBase.cs +++ b/src/Simulation/Common/SimulatorBase.cs @@ -35,17 +35,24 @@ public UnsupportedOperationException(string text = "", /// can be tied to this simulator) and /// to manage the allocation of Qubits (via the QubitManager). /// - public abstract class SimulatorBase : AbstractFactory, IOperationFactory + public abstract class SimulatorBase : Factory, IOperationFactory { public event Action? OnOperationStart = null; public event Action? OnOperationEnd = null; + + public event Action? BeforeAllocateQubits = null; + public event Action>? AfterAllocateQubits = null; + public event Action>? BeforeReleaseQubits = null; + public event Action? AfterReleaseQubits = null; + + public event Action? BeforeBorrowQubits = null; + public event Action>? AfterBorrowQubits = null; + public event Action>? BeforeReturnQubits = null; + public event Action? AfterReturnQubits = null; + public event Action? OnFail = null; - public event Action? OnAllocateQubits = null; - public event Action>? OnReleaseQubits = null; - public event Action? OnBorrowQubits = null; - public event Action>? OnReturnQubits = null; - public event Action? OnLog = null; public event Action>? OnException = null; + public event Action? OnLog = null; protected readonly int randomSeed; protected readonly Lazy randomGenerator; @@ -294,15 +301,17 @@ public Allocate(SimulatorBase m) : base(m) public override Qubit Apply() { + sim.BeforeAllocateQubits?.Invoke(1); Qubit qubit = manager.Allocate(); - sim.OnAllocateQubits?.Invoke(1); + sim.AfterAllocateQubits?.Invoke(new QArray(qubit)); return qubit; } public override IQArray Apply(long count) { + sim.BeforeAllocateQubits?.Invoke(count); IQArray qubits = manager.Allocate(count); - sim.OnAllocateQubits?.Invoke(count); + sim.AfterAllocateQubits?.Invoke(qubits); return qubits; } } @@ -324,14 +333,16 @@ public Release(SimulatorBase m) : base(m) public override void Apply(Qubit q) { - sim.OnReleaseQubits?.Invoke(new QArray(new[] { q })); + sim.BeforeReleaseQubits?.Invoke(new QArray(q)); manager.Release(q); + sim.AfterReleaseQubits?.Invoke(1); } public override void Apply(IQArray qubits) { - sim.OnReleaseQubits?.Invoke(qubits); + sim.BeforeReleaseQubits?.Invoke(qubits); manager.Release(qubits); + sim.AfterReleaseQubits?.Invoke(qubits.Length); } } @@ -352,15 +363,17 @@ public Borrow(SimulatorBase m) : base(m) public override Qubit Apply() { + sim.BeforeBorrowQubits?.Invoke(1); Qubit qubit = manager.Borrow(); - sim.OnBorrowQubits?.Invoke(1); + sim.AfterBorrowQubits?.Invoke(new QArray(qubit)); return qubit; } public override IQArray Apply(long count) { + sim.BeforeBorrowQubits?.Invoke(count); IQArray qubits = manager.Borrow(count); - sim.OnBorrowQubits?.Invoke(count); + sim.AfterBorrowQubits?.Invoke(qubits); return qubits; } } @@ -382,14 +395,16 @@ public Return(SimulatorBase m) : base(m) public override void Apply(Qubit q) { - sim.OnReturnQubits?.Invoke(new QArray(new[] { q })); + sim.BeforeReturnQubits?.Invoke(new QArray(q)); manager.Return(q); + sim.AfterReturnQubits?.Invoke(1); } public override void Apply(IQArray qubits) { - sim.OnReturnQubits?.Invoke(qubits); + sim.BeforeReturnQubits?.Invoke(qubits); manager.Return(qubits); + sim.AfterReturnQubits?.Invoke(qubits.Length); } } @@ -408,7 +423,7 @@ public GetQubitsAvailableToUse(SimulatorBase m) : base(m) } public override Func __Body__ => (arg) => - manager.GetFreeQubitsCount(); + manager.FreeQubitsCount; } /// @@ -426,7 +441,7 @@ public GetQubitsAvailableToBorrow(SimulatorBase m) : base(m) } public override Func __Body__ => (arg) => - manager.GetParentQubitsAvailableToBorrowCount() + manager.GetFreeQubitsCount(); + manager.QubitsAvailableToBorrowCount(1); } diff --git a/src/Simulation/Core/Properties/AssemblyInfo.cs b/src/Simulation/Core/Properties/AssemblyInfo.cs index c2a5d12dced..f9807358194 100644 --- a/src/Simulation/Core/Properties/AssemblyInfo.cs +++ b/src/Simulation/Core/Properties/AssemblyInfo.cs @@ -1,9 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System.Reflection; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; // Allow the test assembly to use our internal methods [assembly: InternalsVisibleTo("Tests.Microsoft.Quantum.Simulators" + SigningConstants.PUBLIC_KEY)] diff --git a/src/Simulation/Core/Qubit.cs b/src/Simulation/Core/Qubit.cs index ec1e0d40125..3ed1d618dec 100644 --- a/src/Simulation/Core/Qubit.cs +++ b/src/Simulation/Core/Qubit.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Text; namespace Microsoft.Quantum.Simulation.Core { @@ -15,7 +14,7 @@ namespace Microsoft.Quantum.Simulation.Core public abstract class Qubit : IApplyData, IEquatable, IEqualityComparer { [DebuggerBrowsable(DebuggerBrowsableState.Never)] - public static readonly Qubit[] NO_QUBITS = new Qubit[0]; + public static readonly Qubit[] NO_QUBITS = Array.Empty(); /// /// Used by UDTs that extend Qubit. diff --git a/src/Simulation/QCTraceSimulator/QCTraceSimulatorCore.cs b/src/Simulation/QCTraceSimulator/QCTraceSimulatorCore.cs index 25eaef0f258..8aa3cc341fe 100644 --- a/src/Simulation/QCTraceSimulator/QCTraceSimulatorCore.cs +++ b/src/Simulation/QCTraceSimulator/QCTraceSimulatorCore.cs @@ -147,9 +147,9 @@ public IQArray Allocate(long count) public IQArray Borrow(long count) { - long qubitBeforeBorrow = qubitManager.GetAllocatedQubitsCount(); + long qubitBeforeBorrow = qubitManager.AllocatedQubitsCount; IQArray res = qubitManager.Borrow(count); - long newQubitsAllocated = qubitManager.GetAllocatedQubitsCount() - qubitBeforeBorrow; + long newQubitsAllocated = qubitManager.AllocatedQubitsCount - qubitBeforeBorrow; object[][] tracingData = GetTracingData(res); for (int i = 0; i < listeners.Length; ++i) @@ -164,9 +164,9 @@ public void Return(Qubit qubit) { Debug.Assert(qubit != null); - long qubitBeforeBorrow = qubitManager.GetAllocatedQubitsCount(); + long qubitBeforeBorrow = qubitManager.AllocatedQubitsCount; qubitManager.Return(qubit); - long qubitsReleased = qubitBeforeBorrow - qubitManager.GetAllocatedQubitsCount(); + long qubitsReleased = qubitBeforeBorrow - qubitManager.AllocatedQubitsCount; object[][] tracingData = GetTracingData(new QArray(qubit)); for (int i = 0; i < listeners.Length; ++i) @@ -179,9 +179,9 @@ public void Return(IQArray qubits) { Debug.Assert(qubits != null); - long qubitBeforeBorrow = qubitManager.GetAllocatedQubitsCount(); + long qubitBeforeBorrow = qubitManager.AllocatedQubitsCount; qubitManager.Return(qubits); - long qubitsReleased = qubitBeforeBorrow - qubitManager.GetAllocatedQubitsCount(); + long qubitsReleased = qubitBeforeBorrow - qubitManager.AllocatedQubitsCount; object[][] tracingData = GetTracingData(qubits); for (int i = 0; i < listeners.Length; ++i) diff --git a/src/Simulation/QCTraceSimulator/TraceableQubitManager.cs b/src/Simulation/QCTraceSimulator/TraceableQubitManager.cs index f386485f527..667d7a43fd5 100644 --- a/src/Simulation/QCTraceSimulator/TraceableQubitManager.cs +++ b/src/Simulation/QCTraceSimulator/TraceableQubitManager.cs @@ -12,7 +12,7 @@ namespace Microsoft.Quantum.Simulation.QCTraceSimulatorRuntime /// Qubit manager for TraceableQubit type. Ensures that all the traceable /// qubits are configured as requested during qubit manage construction. /// - class TraceableQubitManager : QubitManagerTrackingScope + class TraceableQubitManager : QubitManager { const long NumQubits = 1024; diff --git a/src/Simulation/QsharpCore/Environment.qs b/src/Simulation/QsharpCore/Environment.qs index 7cc91153d50..145a9f0d645 100644 --- a/src/Simulation/QsharpCore/Environment.qs +++ b/src/Simulation/QsharpCore/Environment.qs @@ -20,11 +20,10 @@ namespace Microsoft.Quantum.Environment { /// # Summary /// Returns the number of qubits currently available to borrow. - /// This includes unused qubits; that is, this includes the qubits - /// returned by `GetQubitsAvailableToUse`. /// /// # Output - /// The number of qubits that could be allocated in a `borrowing` statement. + /// The number of qubits that could be borrowed and + /// won't be allocated as part of a `borrowing` statement. /// If the target machine being used does not provide this information, then /// `-1` is returned. /// diff --git a/src/Simulation/Simulators.Tests/Circuits/GetAvailableTest.qs b/src/Simulation/Simulators.Tests/Circuits/GetAvailableTest.qs index 0016786c024..916792d3a07 100644 --- a/src/Simulation/Simulators.Tests/Circuits/GetAvailableTest.qs +++ b/src/Simulation/Simulators.Tests/Circuits/GetAvailableTest.qs @@ -9,22 +9,22 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests.Circuits { mutable innerBorrow = 0; borrowing (qb = Qubit()) { - set innerBorrow = GetQubitsAvailableToBorrow(); + set innerBorrow = GetQubitsAvailableToBorrow() + GetQubitsAvailableToUse(); } - return (GetQubitsAvailableToBorrow(), innerBorrow); + return (GetQubitsAvailableToBorrow() + GetQubitsAvailableToUse(), innerBorrow); } operation GetAvailableTest (allocSize : Int) : (Int, Int, Int, Int, Int, Int) { let initialUse = GetQubitsAvailableToUse(); - let initialBorrow = GetQubitsAvailableToBorrow(); + let initialBorrow = GetQubitsAvailableToBorrow() + initialUse; mutable result = (0, 0, 0, 0, 0, 0); using (qs = Qubit[allocSize]) { let afterUse = GetQubitsAvailableToUse(); - let afterBorrow = GetQubitsAvailableToBorrow(); + let afterBorrow = GetQubitsAvailableToBorrow() + afterUse; let (subBorrow, innerBorrow) = BorrowSubTest(); set result = (initialUse, initialBorrow, afterUse, afterBorrow, subBorrow, innerBorrow); } diff --git a/src/Simulation/Simulators.Tests/OperationsTestHelper.cs b/src/Simulation/Simulators.Tests/OperationsTestHelper.cs index a14adfa3021..bde77e602d8 100644 --- a/src/Simulation/Simulators.Tests/OperationsTestHelper.cs +++ b/src/Simulation/Simulators.Tests/OperationsTestHelper.cs @@ -293,7 +293,7 @@ internal static void ctrlOnReleasedCtrlQubitTest(SimulatorBase sim, Action<(IQAr internal static void CheckNoQubitLeak(this SimulatorBase sim) { - Assert.True(sim.QubitManager.GetAllocatedQubitsCount() == 0); + Assert.True(sim.QubitManager.AllocatedQubitsCount == 0); } /// diff --git a/src/Simulation/Simulators.Tests/QCTraceSimulatorPrimitivesTests.cs b/src/Simulation/Simulators.Tests/QCTraceSimulatorPrimitivesTests.cs index 6b1767dc3e8..d9a15e1a27c 100644 --- a/src/Simulation/Simulators.Tests/QCTraceSimulatorPrimitivesTests.cs +++ b/src/Simulation/Simulators.Tests/QCTraceSimulatorPrimitivesTests.cs @@ -20,7 +20,7 @@ public PrimitivesTestsQuite(ITestOutputHelper output) this.output = output; } - private static void OverrideOperation(AbstractFactory sim) + private static void OverrideOperation(Factory sim) where TypeToOverrideBy : AbstractCallable, OperationType where TypeToOverride : AbstractCallable, OperationType { diff --git a/src/Simulation/Simulators.Tests/QubitManagerTests.cs b/src/Simulation/Simulators.Tests/QubitManagerTests.cs index 8ee972883a8..e47cabe899e 100644 --- a/src/Simulation/Simulators.Tests/QubitManagerTests.cs +++ b/src/Simulation/Simulators.Tests/QubitManagerTests.cs @@ -17,7 +17,7 @@ public class QubitManagerTests [Fact] public void TestQubitManager() { - QubitManager qm = new QubitManager(20); + QubitManager qm = new QubitManager(30); // Test allocation of single qubit Qubit q1 = qm.Allocate(); @@ -63,22 +63,22 @@ public void TestQubitManager() long qubitsAvailable; - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qab = qm.Borrow(5, exclusion); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 1); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 1); Assert.True(qab[0].Id == 0); Assert.True(qab[1].Id == 2); Assert.True(qab[2].Id == 4); - Assert.True(qab[3].Id == 5); + Assert.True(qab[3].Id == 7); Assert.True(qab[4].Id == 8); Qubit q6 = qm.Allocate(); Assert.True(q6.Id == 9); // Test borrowing of the same qubit again - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb1 = qm.Borrow(1, exclusion); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 0); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 0); Assert.True(qb1[0].Id == 0); qm.Return(qb1[0]); @@ -92,7 +92,7 @@ public void TestQubitManager() qm.Release(q4); qm.Release(qa1[2]); qm.Release(q1); - + IQArray qa3 = qm.Allocate(4); Assert.True(qa3.Length == 4); Assert.True(qa3[0].Id == 0); @@ -104,17 +104,17 @@ public void TestQubitManager() Qubit q8 = qm.Allocate(); Assert.True(q8.Id == 11); qm.Disable(q8); - IQArray qab2 = qm.Borrow(12, null); - Assert.True(qab2[11].Id == 12); // make sure 11 is not borrowed. + IQArray qab2 = qm.Borrow(12); + Assert.True(qab2[11].Id == 23); // make sure 11 is not borrowed. qm.Release(q8); qm.Return(qab2); - + IQArray qa4 = qm.Allocate(2); Assert.True(qa4[0].Id == 12); // make sure 11 is not reused. Assert.True(qa4[1].Id == 13); // make sure 11 is not reused. qm.Release(qa4); - + { // Test allocating zero qubits IQArray n_q; n_q = qm.Allocate(0); @@ -136,7 +136,7 @@ public void TestQubitManager() { QubitManager qm_small = new QubitManager(2); IQArray n_q; - Assert.Throws(() => n_q = qm_small.Borrow(5, null)); + Assert.Throws(() => n_q = qm_small.Borrow(5)); } // Test for negative input to allocate and borrow. @@ -148,7 +148,7 @@ public void TestQubitManager() { QubitManager qm_small = new QubitManager(20); IQArray n_q; - Assert.Throws(() => n_q = qm_small.Borrow(-2, null)); + Assert.Throws(() => n_q = qm_small.Borrow(-2)); } } @@ -243,7 +243,7 @@ public void TestQubitManagerDiscouragingReuse() [Fact] public void TestQubitManagerTrackingScope() { - QubitManagerTrackingScope qm = new QubitManagerTrackingScope(20); + QubitManager qm = new QubitManager(20); Qubit q1 = qm.Allocate(); Assert.True(q1.Id == 0); @@ -262,18 +262,18 @@ public void TestQubitManagerTrackingScope() long qubitsAvailable; - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb1 = qm.Borrow(3); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 1); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 1); Assert.True(qb1[0].Id == 0); Assert.True(qb1[1].Id == 5); Assert.True(qb1[2].Id == 6); qm.Return(qb1[0]); qm.Return(qb1[2]); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb2 = qm.Borrow(3); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 2); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 2); Assert.True(qb2[0].Id == 0); Assert.True(qb2[1].Id == 6); Assert.True(qb2[2].Id == 7); @@ -281,9 +281,9 @@ public void TestQubitManagerTrackingScope() { qm.OnOperationStart(null, qb2); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb3 = qm.Borrow(3); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 0); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 0); Assert.True(qb3[0].Id == 1); Assert.True(qb3[1].Id == 2); Assert.True(qb3[2].Id == 3); @@ -291,9 +291,9 @@ public void TestQubitManagerTrackingScope() qm.OnOperationEnd(null, QVoid.Instance); } - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb4 = qm.Borrow(1); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 1); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 1); Assert.True(qb4[0].Id == 8); qm.OnOperationEnd(null, QVoid.Instance); @@ -302,7 +302,7 @@ public void TestQubitManagerTrackingScope() [Fact] public void TestQubitManagerDisabledBorrowing() { - QubitManagerTrackingScope qm = new QubitManagerTrackingScope(20, mayExtendCapacity: true, disableBorrowing: true); + QubitManager qm = new QubitManager(20, mayExtendCapacity: true, disableBorrowing: true); Qubit q1 = qm.Allocate(); Assert.True(q1.Id == 0); @@ -321,54 +321,54 @@ public void TestQubitManagerDisabledBorrowing() long qubitsAvailable; - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb1 = qm.Borrow(3); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 3); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 3); Assert.True(qb1[0].Id == 6); Assert.True(qb1[1].Id == 7); Assert.True(qb1[2].Id == 8); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 11); qm.Return(qb1[0]); qm.Return(qb1[2]); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 13); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb2 = qm.Borrow(3); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 3); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 3); Assert.True(qb2[0].Id == 8); Assert.True(qb2[1].Id == 6); Assert.True(qb2[2].Id == 9); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 10); { qm.OnOperationStart(null, qb2); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb3 = qm.Borrow(3); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 3); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 3); Assert.True(qb3[0].Id == 10); Assert.True(qb3[1].Id == 11); Assert.True(qb3[2].Id == 12); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 7); qm.OnOperationEnd(null, QVoid.Instance); } qm.Release(qb2[1]); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 8); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb4 = qm.Borrow(1); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 1); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 1); Assert.True(qb4[0].Id == 6); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 7); qm.OnOperationEnd(null, QVoid.Instance); @@ -377,7 +377,7 @@ public void TestQubitManagerDisabledBorrowing() [Fact] public void TestQubitManagerGrowth() { - QubitManagerTrackingScope qm = new QubitManagerTrackingScope(7, mayExtendCapacity : true, disableBorrowing: false); + QubitManager qm = new QubitManager(7, mayExtendCapacity : true, disableBorrowing: false); Qubit q1 = qm.Allocate(); Assert.True(q1.Id == 0); @@ -396,19 +396,19 @@ public void TestQubitManagerGrowth() long qubitsAvailable; - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; IQArray qb1 = qm.Borrow(3); - Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 1); + Assert.True(qubitsAvailable - qm.FreeQubitsCount == 1); Assert.True(qb1[0].Id == 0); Assert.True(qb1[1].Id == 5); Assert.True(qb1[2].Id == 6); qm.Return(qb1[0]); qm.Return(qb1[2]); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 1); IQArray qb2 = qm.Borrow(3); // This should grow qubit capacity - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 6); Assert.True(qb2[0].Id == 0); Assert.True(qb2[1].Id == 6); @@ -416,10 +416,10 @@ public void TestQubitManagerGrowth() qm.OnOperationEnd(null, null); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 6); IQArray qa2 = qm.Allocate(4); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 2); Assert.True(qa2.Length == 4); Assert.True(qa2[0].Id == 8); @@ -427,14 +427,14 @@ public void TestQubitManagerGrowth() Assert.True(qa2[2].Id == 10); Assert.True(qa2[3].Id == 11); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 2); qm.Release(qa2[0]); - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 3); IQArray qa3 = qm.Allocate(4); // This should grow qubit capacity - qubitsAvailable = qm.GetFreeQubitsCount(); + qubitsAvailable = qm.FreeQubitsCount; Assert.True(qubitsAvailable == 13); Assert.True(qa3.Length == 4); Assert.True(qa3[0].Id == 8); diff --git a/src/Simulation/Simulators.Tests/SimulatorBaseTests.cs b/src/Simulation/Simulators.Tests/SimulatorBaseTests.cs index 84c78044fdb..da983d1e352 100644 --- a/src/Simulation/Simulators.Tests/SimulatorBaseTests.cs +++ b/src/Simulation/Simulators.Tests/SimulatorBaseTests.cs @@ -47,12 +47,12 @@ public void SimulatorBuiltInOperations() // are actually called. var calledOnAllocate = false; var calledOnRelease = false; - subject.OnAllocateQubits += count => + subject.BeforeAllocateQubits += count => { output.WriteLine($"Allocate count = {count}"); calledOnAllocate = true; }; - subject.OnReleaseQubits += register => + subject.BeforeReleaseQubits += register => { output.WriteLine($"Release qubits = {register}"); calledOnRelease = true; diff --git a/src/Simulation/Simulators.Tests/TrivialSimulator.cs b/src/Simulation/Simulators.Tests/TrivialSimulator.cs index f11afdea853..7b10bf834db 100644 --- a/src/Simulation/Simulators.Tests/TrivialSimulator.cs +++ b/src/Simulation/Simulators.Tests/TrivialSimulator.cs @@ -11,7 +11,7 @@ namespace Microsoft.Quantum.Simulation.Simulators.Tests /// public class TrivialSimulator : SimulatorBase { - public TrivialSimulator() : base(new QubitManagerTrackingScope(32)) + public TrivialSimulator() : base(new QubitManager(32)) { } diff --git a/src/Simulation/Simulators/QuantumProcessor/Borrow.cs b/src/Simulation/Simulators/QuantumProcessor/Borrow.cs index d497549ccb9..00010ab101c 100644 --- a/src/Simulation/Simulators/QuantumProcessor/Borrow.cs +++ b/src/Simulation/Simulators/QuantumProcessor/Borrow.cs @@ -16,18 +16,18 @@ public QuantumProcessorDispatcherBorrow(QuantumProcessorDispatcher m) : base(m){ public override Qubit Apply() { - long allocatedBefore = sim.QubitManager.GetAllocatedQubitsCount(); - IQArray qubits = sim.QubitManager.Borrow(1); - long allocatedAfter = sim.QubitManager.GetAllocatedQubitsCount(); - sim.QuantumProcessor.OnBorrowQubits(qubits, allocatedAfter - allocatedBefore); - return qubits[0]; + long allocatedBefore = sim.QubitManager.AllocatedQubitsCount; + Qubit qubit = sim.QubitManager.Borrow(); + long allocatedAfter = sim.QubitManager.AllocatedQubitsCount; + sim.QuantumProcessor.OnBorrowQubits(new QArray(qubit), allocatedAfter - allocatedBefore); + return qubit; } public override IQArray Apply(long count) { - long allocatedBefore = sim.QubitManager.GetAllocatedQubitsCount(); + long allocatedBefore = sim.QubitManager.AllocatedQubitsCount; IQArray qubits = sim.QubitManager.Borrow(count); - long allocatedAfter = sim.QubitManager.GetAllocatedQubitsCount(); + long allocatedAfter = sim.QubitManager.AllocatedQubitsCount; sim.QuantumProcessor.OnBorrowQubits(qubits, allocatedAfter - allocatedBefore); return qubits; } diff --git a/src/Simulation/Simulators/QuantumProcessor/QuantumProcessorDispatcher.cs b/src/Simulation/Simulators/QuantumProcessor/QuantumProcessorDispatcher.cs index c941ec7e133..0865e201a4e 100644 --- a/src/Simulation/Simulators/QuantumProcessor/QuantumProcessorDispatcher.cs +++ b/src/Simulation/Simulators/QuantumProcessor/QuantumProcessorDispatcher.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; using Microsoft.Quantum.Simulation.Common; namespace Microsoft.Quantum.Simulation.QuantumProcessor @@ -27,19 +26,19 @@ public IQuantumProcessor QuantumProcessor /// /// /// - /// An instance of a class implementing interface to be wrapped. If the parameter is null is used. - /// An instance of a class implementing interface. If the parameter is null is used. + /// An instance of a class implementing interface to be wrapped. + /// An instance of a class implementing interface. If the parameter is null is used. /// A seed to be used by Q# Microsoft.Quantum.Intrinsic.Random operation. - public QuantumProcessorDispatcher(IQuantumProcessor? quantumProcessor = null, IQubitManager? qubitManager = null, int? randomSeed = null) + public QuantumProcessorDispatcher(IQuantumProcessor quantumProcessor, IQubitManager? qubitManager = null, int? randomSeed = null) : base( - qubitManager ?? new QubitManagerTrackingScope( + qubitManager ?? new QubitManager( PreallocatedQubitCount, mayExtendCapacity: true, disableBorrowing: false ), randomSeed ) { - QuantumProcessor = quantumProcessor ?? new QuantumProcessorBase(); + QuantumProcessor = quantumProcessor; OnOperationStart += QuantumProcessor.OnOperationStart; OnOperationEnd += QuantumProcessor.OnOperationEnd; OnFail += QuantumProcessor.OnFail; diff --git a/src/Simulation/Simulators/QuantumProcessor/Return.cs b/src/Simulation/Simulators/QuantumProcessor/Return.cs index 2a5277340fd..14a5f7dc62a 100644 --- a/src/Simulation/Simulators/QuantumProcessor/Return.cs +++ b/src/Simulation/Simulators/QuantumProcessor/Return.cs @@ -16,16 +16,18 @@ public QuantumProcessorDispatcherReturn(QuantumProcessorDispatcher m) : base(m){ public override void Apply(Qubit q) { - long count = (sim.QubitManager.ToBeReleasedAfterReturn(q) ? 1 : 0); - sim.QuantumProcessor.OnReturnQubits(new QArray(q), count); + long allocatedBefore = sim.QubitManager.AllocatedQubitsCount; sim.QubitManager.Return(q); + long allocatedAfter = sim.QubitManager.AllocatedQubitsCount; + sim.QuantumProcessor.OnReturnQubits(new QArray(q), allocatedBefore - allocatedAfter); } public override void Apply(IQArray qubits) { - long count = sim.QubitManager.ToBeReleasedAfterReturnCount(qubits); - sim.QuantumProcessor.OnReturnQubits(qubits, count); + long allocatedBefore = sim.QubitManager.AllocatedQubitsCount; sim.QubitManager.Return(qubits); + long allocatedAfter = sim.QubitManager.AllocatedQubitsCount; + sim.QuantumProcessor.OnReturnQubits(qubits, allocatedBefore - allocatedAfter); } } } diff --git a/src/Simulation/Simulators/QuantumSimulator/QuantumSimulator.cs b/src/Simulation/Simulators/QuantumSimulator/QuantumSimulator.cs index a4f7bf96ece..acf8fdf29b5 100644 --- a/src/Simulation/Simulators/QuantumSimulator/QuantumSimulator.cs +++ b/src/Simulation/Simulators/QuantumSimulator/QuantumSimulator.cs @@ -200,7 +200,7 @@ public uint[] QubitIds { var ids = new List(); sim_QubitsIds(this.Id, ids.Add); - Debug.Assert(ids.Count == this.QubitManager.GetAllocatedQubitsCount()); + Debug.Assert(ids.Count == this.QubitManager.AllocatedQubitsCount); return ids.ToArray(); } } diff --git a/src/Simulation/Simulators/QuantumSimulator/Qubit.cs b/src/Simulation/Simulators/QuantumSimulator/Qubit.cs index 9fd546bf6b5..4a9f98c8760 100644 --- a/src/Simulation/Simulators/QuantumSimulator/Qubit.cs +++ b/src/Simulation/Simulators/QuantumSimulator/Qubit.cs @@ -4,10 +4,8 @@ using Microsoft.Quantum.Simulation.Common; using Microsoft.Quantum.Simulation.Core; using System; -using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Text; namespace Microsoft.Quantum.Simulation.Simulators { diff --git a/src/Simulation/Simulators/QuantumSimulator/QubitManager.cs b/src/Simulation/Simulators/QuantumSimulator/QubitManager.cs index 7b45f3f9ba4..06fc6f64697 100644 --- a/src/Simulation/Simulators/QuantumSimulator/QubitManager.cs +++ b/src/Simulation/Simulators/QuantumSimulator/QubitManager.cs @@ -11,9 +11,9 @@ namespace Microsoft.Quantum.Simulation.Simulators { public partial class QuantumSimulator { - class QSimQubitManager : QubitManagerTrackingScope + class QSimQubitManager : QubitManager { - bool throwOnReleasingQubitsNotInZeroState; + readonly bool throwOnReleasingQubitsNotInZeroState; [DllImport(QSIM_DLL_NAME, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, EntryPoint = "allocateQubit")] private static extern void AllocateOne(uint id, uint qubit_id); @@ -51,16 +51,16 @@ public override Qubit CreateQubitObject(long id) return new QSimQubit((int)id, SimulatorId); } - protected override Qubit AllocateOneQubit(bool usedOnlyForBorrowing) + protected override Qubit Allocate(bool usedOnlyForBorrowing) { - Qubit qubit = base.AllocateOneQubit(usedOnlyForBorrowing); + Qubit qubit = base.Allocate(usedOnlyForBorrowing); if (qubit != null) { AllocateOne(this.SimulatorId, (uint)qubit.Id); } return qubit; } - protected override void ReleaseOneQubit(Qubit qubit, bool usedOnlyForBorrowing) + protected override void Release(Qubit qubit, bool wasUsedOnlyForBorrowing) { - base.ReleaseOneQubit(qubit, usedOnlyForBorrowing); + base.Release(qubit, wasUsedOnlyForBorrowing); if (qubit != null) { bool isReleasedQubitZero = ReleaseOne(this.SimulatorId, (uint)qubit.Id); diff --git a/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs b/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs index ab08a75eee0..f074b6ed8ea 100644 --- a/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs +++ b/src/Simulation/Simulators/QuantumSimulator/StateDumper.cs @@ -177,7 +177,7 @@ public override bool Callback(uint idx, double real, double img) public override bool Dump(IQArray? qubits = null) { var count = qubits == null - ? this.Simulator.QubitManager.GetAllocatedQubitsCount() + ? this.Simulator.QubitManager.AllocatedQubitsCount : qubits.Length; this._maxCharsStateId = ((1 << (int)count) - 1).ToString().Length; diff --git a/src/Simulation/Simulators/ToffoliSimulator/Dump.cs b/src/Simulation/Simulators/ToffoliSimulator/Dump.cs index aec28a147aa..2e97ef268a7 100644 --- a/src/Simulation/Simulators/ToffoliSimulator/Dump.cs +++ b/src/Simulation/Simulators/ToffoliSimulator/Dump.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. using System; -using System.IO; using System.Linq; using Microsoft.Quantum.Simulation.Core; @@ -13,7 +12,7 @@ public partial class ToffoliSimulator /// /// Implementation of the DumpMachine operation for the Toffoli simulator. /// - public class DumpMachine : Quantum.Diagnostics.DumpMachine + public class DumpMachine : Diagnostics.DumpMachine { private ToffoliSimulator simulator { get; } @@ -33,7 +32,7 @@ public DumpMachine(ToffoliSimulator m) : base(m) { if (location == null) { throw new ArgumentNullException(nameof(location)); } - var ids = this.simulator.QubitManager.GetAllocatedIds().ToArray(); + var ids = this.simulator.QubitManager.AllocatedIds().ToArray(); var filename = (location is QVoid) ? "" : location.ToString(); this.simulator.DumpState(ids, filename); @@ -44,7 +43,7 @@ public DumpMachine(ToffoliSimulator m) : base(m) /// /// Implementation of the DumpRegister operation for the Toffoli simulator. /// - public class DumpRegister : Quantum.Diagnostics.DumpRegister + public class DumpRegister : Diagnostics.DumpRegister { private ToffoliSimulator simulator { get; } diff --git a/src/Simulation/Simulators/ToffoliSimulator/ToffoliSimulator.cs b/src/Simulation/Simulators/ToffoliSimulator/ToffoliSimulator.cs index 81dae1c4aa5..3b2fb99be5d 100644 --- a/src/Simulation/Simulators/ToffoliSimulator/ToffoliSimulator.cs +++ b/src/Simulation/Simulators/ToffoliSimulator/ToffoliSimulator.cs @@ -46,7 +46,7 @@ public ToffoliSimulator() : this(DEFAULT_QUBIT_COUNT) { } /// There is an overhead of one byte of memory usage per allocated qubit. /// There is no time overhead from allocating more qubits. public ToffoliSimulator(uint qubitCount) - : base(new QubitManagerTrackingScope(qubitCapacity: qubitCount, mayExtendCapacity: false, disableBorrowing: false)) + : base(new QubitManager(qubitCapacity: qubitCount, mayExtendCapacity: false, disableBorrowing: false)) { this.State = new bool[qubitCount]; this.borrowedQubitStates = new Dictionary>();