/// <summary> /// Allocates numToAllocate new qubits. /// </summary> public virtual IQArray <Qubit> Allocate(long numToAllocate) { IgnorableAssert.Assert(numToAllocate >= 0, "Attempt to allocate negative number of qubits."); if (numToAllocate < 0) { throw new ArgumentException("Attempt to allocate negative number of qubits."); } else if (numToAllocate == 0) { return(QArray <Qubit> .Create(0)); } QArray <Qubit> result = QArray <Qubit> .Create(numToAllocate); for (int i = 0; i < numToAllocate; i++) { result.Modify(i, AllocateOneQubit(usedOnlyForBorrowing: false)); if (result[i] == null) { for (int k = 0; k < i; k++) { Release(result[k]); } throw new NotEnoughQubits(numToAllocate, GetFreeQubitsCount()); } } return(result); }
/// <summary> /// 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. /// </summary> public virtual IQArray <Qubit> Borrow(long numToBorrow, IEnumerable <Qubit> excludedQubitsSortedById) // Note, excluded could be an array of Ids for efficiency, if it is convenient for compiler. { IgnorableAssert.Assert(numToBorrow > 0, "Attempt to borrow zero qubits."); if (numToBorrow <= 0) { throw new ArgumentException("Attempt to borrow zero qubits."); } if (DisableBorrowing) { return(Allocate(numToBorrow)); } var result = QArray <Qubit> .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); }
protected virtual void DisableOneQubit(Qubit qubit) { // Note: Borrowed qubits cannot be disabled. IgnorableAssert.Assert(qubits[qubit.Id] == Allocated, "Attempt to disable qubit that has not been allocated."); qubits[qubit.Id] = Disabled; numDisabledQubits++; numAllocatedQubits--; Debug.Assert(numAllocatedQubits >= 0); }
/// <summary> /// Makes sure the angle for a rotation or exp operation is not NaN or Infinity. /// </summary> static void CheckAngle(double angle) { IgnorableAssert.Assert(!(double.IsNaN(angle) || double.IsInfinity(angle)), "Invalid angle for rotation/exponentiation."); if (double.IsNaN(angle)) { throw new ArgumentOutOfRangeException("angle", "Angle can't be NaN."); } if (double.IsInfinity(angle)) { throw new ArgumentOutOfRangeException("angle", "Angle can't be Infity."); } }
protected virtual void ReleaseOneQubit(Qubit qubit, bool usedOnlyForBorrowing) { long Occupied = (usedOnlyForBorrowing? AllocatedForBorrowing : Allocated); IgnorableAssert.Assert(qubits[qubit.Id] == Occupied, "Attempt to free qubit that has not been allocated."); if (qubits[qubit.Id] != Occupied) { throw new ArgumentException("Attempt to free qubit that has not been allocated."); } qubits[qubit.Id] = free; free = qubit.Id; numAllocatedQubits--; Debug.Assert(numAllocatedQubits >= 0); }
protected virtual void ReleaseOneQubit(Qubit qubit, bool usedOnlyForBorrowing) { if (qubits[qubit.Id] == Disabled) { // Nothing to do. It will stay disabled. // Alternatively, we could mark is as None here. } else { long Occupied = (usedOnlyForBorrowing ? AllocatedForBorrowing : Allocated); IgnorableAssert.Assert(qubits[qubit.Id] == Occupied, "Attempt to free qubit that has not been allocated."); if (qubits[qubit.Id] != Occupied) { throw new ArgumentException("Attempt to free qubit that has not been allocated."); } qubits[qubit.Id] = free; free = qubit.Id; numAllocatedQubits--; Debug.Assert(numAllocatedQubits >= 0); } }