public void TestQubitManagerDisabledBorrowing()
        {
            QubitManagerTrackingScope qm = new QubitManagerTrackingScope(20, mayExtendCapacity: true, disableBorrowing: true);

            Qubit q1 = qm.Allocate();

            Assert.True(q1.Id == 0);

            var qa1 = qm.Allocate(4);

            Assert.True(qa1.Length == 4);
            Assert.True(qa1[0].Id == 1);
            Assert.True(qa1[1].Id == 2);
            Assert.True(qa1[2].Id == 3);
            Assert.True(qa1[3].Id == 4);

            Qubit q2 = qm.Allocate();

            Assert.True(q2.Id == 5);

            qm.OnOperationStart(null, qa1);

            long qubitsAvailable;

            qubitsAvailable = qm.GetFreeQubitsCount();
            var qb1 = qm.Borrow(3);

            Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 3);
            Assert.True(qb1[0].Id == 6);
            Assert.True(qb1[1].Id == 7);
            Assert.True(qb1[2].Id == 8);

            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 11);
            qm.Return(qb1[0]);
            qm.Return(qb1[2]);
            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 13);

            qubitsAvailable = qm.GetFreeQubitsCount();
            var qb2 = qm.Borrow(3);

            Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 3);
            Assert.True(qb2[0].Id == 8);
            Assert.True(qb2[1].Id == 6);
            Assert.True(qb2[2].Id == 9);
            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 10);

            {
                qm.OnOperationStart(null, qb2);

                qubitsAvailable = qm.GetFreeQubitsCount();
                var qb3 = qm.Borrow(3);
                Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 3);
                Assert.True(qb3[0].Id == 10);
                Assert.True(qb3[1].Id == 11);
                Assert.True(qb3[2].Id == 12);

                qubitsAvailable = qm.GetFreeQubitsCount();
                Assert.True(qubitsAvailable == 7);

                qm.OnOperationEnd(null, QVoid.Instance);
            }

            qm.Release(qb2[1]);
            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 8);

            qubitsAvailable = qm.GetFreeQubitsCount();
            var qb4 = qm.Borrow(1);

            Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 1);
            Assert.True(qb4[0].Id == 6);
            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 7);

            qm.OnOperationEnd(null, QVoid.Instance);
        }
        public void TestQubitManagerGrowth()
        {
            QubitManagerTrackingScope qm = new QubitManagerTrackingScope(7, mayExtendCapacity: true, disableBorrowing: false);

            Qubit q1 = qm.Allocate();

            Assert.True(q1.Id == 0);

            var qa1 = qm.Allocate(4);

            Assert.True(qa1.Length == 4);
            Assert.True(qa1[0].Id == 1);
            Assert.True(qa1[1].Id == 2);
            Assert.True(qa1[2].Id == 3);
            Assert.True(qa1[3].Id == 4);

            Qubit q2 = qm.Allocate();

            Assert.True(q2.Id == 5);

            qm.OnOperationStart(null, qa1);

            long qubitsAvailable;

            qubitsAvailable = qm.GetFreeQubitsCount();
            var qb1 = qm.Borrow(3);

            Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 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();
            Assert.True(qubitsAvailable == 1);
            var qb2 = qm.Borrow(3); // This should grow qubit capacity

            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 6);
            Assert.True(qb2[0].Id == 0);
            Assert.True(qb2[1].Id == 6);
            Assert.True(qb2[2].Id == 7);

            qm.OnOperationEnd(null, null);

            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 6);
            var qa2 = qm.Allocate(4);

            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 2);
            Assert.True(qa2.Length == 4);
            Assert.True(qa2[0].Id == 8);
            Assert.True(qa2[1].Id == 9);
            Assert.True(qa2[2].Id == 10);
            Assert.True(qa2[3].Id == 11);

            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 2);
            qm.Release(qa2[0]);
            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 3);

            var qa3 = qm.Allocate(4); // This should grow qubit capacity

            qubitsAvailable = qm.GetFreeQubitsCount();
            Assert.True(qubitsAvailable == 13);
            Assert.True(qa3.Length == 4);
            Assert.True(qa3[0].Id == 8);
            Assert.True(qa3[1].Id == 12);
            Assert.True(qa3[2].Id == 13);
            Assert.True(qa3[3].Id == 14);
        }
        public void TestQubitManagerTrackingScope()
        {
            QubitManagerTrackingScope qm = new QubitManagerTrackingScope(20);

            Qubit q1 = qm.Allocate();

            Assert.True(q1.Id == 0);

            IQArray <Qubit> qa1 = qm.Allocate(4);

            Assert.True(qa1.Length == 4);
            Assert.True(qa1[0].Id == 1);
            Assert.True(qa1[1].Id == 2);
            Assert.True(qa1[2].Id == 3);
            Assert.True(qa1[3].Id == 4);

            Qubit q2 = qm.Allocate();

            Assert.True(q2.Id == 5);

            qm.OnOperationStart(null, qa1);

            long qubitsAvailable;

            qubitsAvailable = qm.GetFreeQubitsCount();
            IQArray <Qubit> qb1 = qm.Borrow(3);

            Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 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();
            IQArray <Qubit> qb2 = qm.Borrow(3);

            Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 2);
            Assert.True(qb2[0].Id == 0);
            Assert.True(qb2[1].Id == 6);
            Assert.True(qb2[2].Id == 7);

            {
                qm.OnOperationStart(null, qb2);

                qubitsAvailable = qm.GetFreeQubitsCount();
                IQArray <Qubit> qb3 = qm.Borrow(3);
                Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 0);
                Assert.True(qb3[0].Id == 1);
                Assert.True(qb3[1].Id == 2);
                Assert.True(qb3[2].Id == 3);

                qm.OnOperationEnd(null, QVoid.Instance);
            }

            qubitsAvailable = qm.GetFreeQubitsCount();
            IQArray <Qubit> qb4 = qm.Borrow(1);

            Assert.True(qubitsAvailable - qm.GetFreeQubitsCount() == 1);
            Assert.True(qb4[0].Id == 8);

            qm.OnOperationEnd(null, QVoid.Instance);
        }