// register x - initially loaded with x
        // register N - initially loaded with N
        // control - control bit
        // other registers - initially 0
        // after computation register B changes and contains: [(a*x) mod N]
        // Insecure version: registers widths etc. are not checked
        public static void CMultModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            Register x,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            ulong power2 = 1;
            for (int i = 0; i < x.Width; i++, power2 *= 2)
            {
                // loading A register with (2^i * a) mod N
                ulong toLoad = (valueA * power2) % valueN;
                comp.LoadNumber(a, toLoad, control, x[i]);

                // adding [(2^i * a) + B] modulo N
                comp.AddModulo(a, b, c, N, valueN);

                // unloading [(2^i * a) mod N] from A register
                comp.LoadNumber(a, toLoad, control, x[i]);
            }

            // if control == 0
            // then B register contains still 0
            // so we copy X register into B register
            comp.SigmaX(control);
            for (int i = 0; i < x.Width; i++)
            {
                comp.Toffoli(b[i], control, x[i]);
            }
            comp.SigmaX(control);
        }
        public static void AddModuloQFTPhi(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register b, params RegisterRef[] controls)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, N, ctrl, b, controls };
                comp.AddParametricGate("AddModuloQFTPhi", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            comp.AddQFTPhi(a, b, controls);
            comp.InverseAddQFTPhi(N, b);

            comp.InverseQFT(b);
            comp.CNot(ctrl, b[b.Width - 1]);
            comp.QFT(b);

            comp.AddQFTPhi(N, b, ctrl);
            comp.InverseAddQFTPhi(a, b, controls);

            comp.InverseQFT(b);
            comp.SigmaX(b[b.Width - 1]);
            comp.CNot(ctrl, b[b.Width - 1]);
            comp.SigmaX(b[b.Width - 1]);
            comp.QFT(b);

            comp.AddQFTPhi(a, b, controls);
        }
Example #3
0
        // register A - initially loaded with a
        // register B - initially loaded with b
        // register C - initially 0, exactly one bit wider than A, stores overflow bit
        // register N - initially loaded with N
        // after computation in register B: (a+b) mod N
        // other registers dont change their states
        // register B must be exactly one bit wider than A to store carry bit
        // register B must be exactly one bit wider than N to store carry bit
        // registers A, N must be the same length
        // Insecure version: registers widths etc. are not checked
        public static void AddModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            ulong valueN)
        {
            RegisterRef carry    = b[b.Width - 1];
            RegisterRef overflow = c[c.Width - 1];

            comp.Add(a, b, c);
            comp.InverseAdd(N, b, c);
            comp.SigmaX(carry);
            comp.CNot(overflow, carry);
            comp.SigmaX(carry);

            //resetting N
            comp.LoadNumber(N, valueN, overflow);

            comp.Add(N, b, c);

            // now we have [(a+b) mod N] in B register
            // next steps lead to recover the initial state of registers N and overflow bit

            //setting N back
            comp.LoadNumber(N, valueN, overflow);

            comp.InverseAdd(a, b, c);
            comp.CNot(overflow, carry);
            comp.Add(a, b, c);
        }
Example #4
0
        // register x - initially loaded with x
        // register b - initially loaded with 0
        // after computation register b changes and contains: [(a*x) mod N]
        // Secure version: throws Exceptions if arguments are invalid
        public static void CMultModulo(
            this QuantumComputer comp,
            Register x,
            Register b,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, x, b, control, valueA, valueN };
                comp.AddParametricGate("CMultModulo", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Validate(x, b, valueN);

            Register a = comp.NewRegister(0, x.Width - 1);
            Register c = comp.NewRegister(0, x.Width);
            Register N = comp.NewRegister(valueN, x.Width - 1);

            comp.CMultModulo(a, b, c, N, x, control, valueA, valueN);

            comp.DeleteRegister(ref N);
            comp.DeleteRegister(ref c);
            comp.DeleteRegister(ref a);
        }
 public static void InverseAddModuloQFT(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register b, params RegisterRef[] controls)
 {
     Validate(a, b, N);
     comp.QFT(b);
     comp.InverseAddModuloQFTPhi(a, N, ctrl, b, controls);
     comp.InverseQFT(b);
 }
Example #6
0
        // Insecure version: registers widths etc. are not checked
        public static void InverseAddModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            ulong valueN)
        {
            RegisterRef carry    = b[b.Width - 1];
            RegisterRef overflow = c[c.Width - 1];

            comp.InverseAdd(a, b, c);
            comp.CNot(overflow, carry);
            comp.Add(a, b, c);

            //resetting N:
            comp.LoadNumber(N, valueN, overflow);

            comp.InverseAdd(N, b, c);

            //setting N back:
            comp.LoadNumber(N, valueN, overflow);

            comp.SigmaX(carry);
            comp.CNot(overflow, carry);
            comp.SigmaX(carry);
            comp.Add(N, b, c);
            comp.InverseAdd(a, b, c);
        }
        public static void ControlledUaGate(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register x, Register reg0, RegisterRef control)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, N, ctrl, x, reg0, control };
                comp.AddParametricGate("ControlledUaGate", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Validate(x, N);

            int? invA = Quantum.Utils.InversionModulo((int)a, (int)N);

            if (invA == null)
            {
                throw new ArgumentException("No inversion for specified a = " + a);
            }

            comp.MultModuloQFT(a, N, ctrl, x, reg0, control);
            comp.Swap(x, reg0, control);
            comp.InverseMultModuloQFT((ulong)invA, N, ctrl, x, reg0, control);
        }
Example #8
0
        public static void Swap(this QuantumComputer comp, Register r1, Register r2, RegisterRef control)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, r1, r2, control };
                comp.AddParametricGate("Swap", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Validate(r1, r2);

            Register root    = comp.GetRootRegister(r1, r2, control);
            int      target1 = r1.OffsetToRoot;
            int      target2 = r2.OffsetToRoot;
            int      ctrl    = control.OffsetToRoot;

            for (int i = 0; i < r1.Width; i++)
            {
                //comp.Toffoli(root[target1 + i], root[target2 + i], root[ctrl]);
                //comp.Toffoli(root[target2 + i], root[target1 + i], root[ctrl]);
                //comp.Toffoli(root[target1 + i], root[target2 + i], root[ctrl]);
                root.Toffoli(target1 + i, target2 + i, ctrl);
                root.Toffoli(target2 + i, target1 + i, ctrl);
                root.Toffoli(target1 + i, target2 + i, ctrl);
            }
        }
Example #9
0
 public static void AddModuloQFT(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register b, params RegisterRef[] controls)
 {
     Validate(a, b, N);
     comp.QFT(b);
     comp.AddModuloQFTPhi(a, N, ctrl, b, controls);
     comp.InverseQFT(b);
 }
        public static void CNot(this QuantumComputer comp, RegisterRef target, RegisterRef control)
        {
            Register root = comp.GetRootRegister(control, target);
            int c = control.OffsetToRoot;
            int t = target.OffsetToRoot;

            root.CNot(t, c);
        }
Example #11
0
        public static void CNot(this QuantumComputer comp, RegisterRef target, RegisterRef control)
        {
            Register root = comp.GetRootRegister(control, target);
            int      c    = control.OffsetToRoot;
            int      t    = target.OffsetToRoot;

            root.CNot(t, c);
        }
        /// <summary>
        /// Swaps the values of two given qubits.
        /// </summary>
        /// <param name="comp">The <see cref="Quantum.QuantumComputer"/> instance.</param>
        /// <param name="r1">The reference to the first swapped qubit.</param>
        /// <param name="r2">The reference to the second swapped qubit.</param>
        public static void Swap(this QuantumComputer comp, RegisterRef r1, RegisterRef r2)
        {
            Register root = comp.GetRootRegister(r1, r2);
            int target1 = r1.OffsetToRoot;
            int target2 = r2.OffsetToRoot;

            root.CNot(target1, target2);
            root.CNot(target2, target1);
            root.CNot(target1, target2);
        }
Example #13
0
        /// <summary>
        /// Swaps the values of two given qubits.
        /// </summary>
        /// <param name="comp">The <see cref="Quantum.QuantumComputer"/> instance.</param>
        /// <param name="r1">The reference to the first swapped qubit.</param>
        /// <param name="r2">The reference to the second swapped qubit.</param>
        public static void Swap(this QuantumComputer comp, RegisterRef r1, RegisterRef r2)
        {
            Register root    = comp.GetRootRegister(r1, r2);
            int      target1 = r1.OffsetToRoot;
            int      target2 = r2.OffsetToRoot;

            root.CNot(target1, target2);
            root.CNot(target2, target1);
            root.CNot(target1, target2);
        }
Example #14
0
        /// <summary>
        /// Computes the least significant bit of sum of two given bits.
        /// Used with <see cref="Carry(QuantumComputer, RegisterRef, RegisterRef, RegisterRef, RegisterRef)"/> to perform addition.
        /// </summary>
        /// <param name="comp">The QuantumComputer instance.</param>
        /// <param name="refA">The reference to first qubit being sumed.</param>
        /// <param name="refB">The reference to second qubit being sumed.</param>
        /// <param name="refTarget">The reference to qubit for storing the result.</param>
        public static void Sum(this QuantumComputer comp,
                               RegisterRef refA, RegisterRef refB, RegisterRef refTarget)
        {
            Register root   = comp.GetRootRegister(refA, refB, refTarget);
            int      a      = refA.OffsetToRoot;
            int      b      = refB.OffsetToRoot;
            int      target = refTarget.OffsetToRoot;

            root.CNot(target, a);
            root.CNot(target, b);
        }
Example #15
0
        /// <summary>
        /// Inversion of <see cref="Carry(QuantumComputer, RegisterRef, RegisterRef, RegisterRef, RegisterRef)"/> method.
        /// </summary>
        /// <param name="comp">The QuantumComputer instance.</param>
        /// <param name="rc0">The reference to previous carry qubit.</param>
        /// <param name="ra0">The reference to qubit, for which the carry bit was computed, in the first register.</param>
        /// <param name="rb0">The reference to qubit, for which the carry bit was computed, in the second register.</param>
        /// <param name="rc1">The reference to qubit storing the resulted carry value.</param>
        public static void InverseCarry(this QuantumComputer comp,
                                        RegisterRef rc0, RegisterRef ra0, RegisterRef rb0, RegisterRef rc1)
        {
            Register root = comp.GetRootRegister(rc0, ra0, rb0, rc1);
            int      c0   = rc0.OffsetToRoot;
            int      a0   = ra0.OffsetToRoot;
            int      b0   = rb0.OffsetToRoot;
            int      c1   = rc1.OffsetToRoot;

            root.Toffoli(c1, c0, b0);
            root.CNot(b0, a0);
            root.Toffoli(c1, a0, b0);
        }
        public static void MultModuloQFT(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register x, Register b, RegisterRef control)
        {
            Validate(a, b, N);
            comp.QFT(b);

            for (int i = 0; i < x.Width; i++)
            {
                //Console.WriteLine("MultModulo i = {2}, a = {0}, N = {1}", a, N, i);
                comp.AddModuloQFTPhi(((((ulong)1 << i) * a) % N), N, ctrl, b, x[i], control);
            }

            comp.InverseQFT(b);
        }
Example #17
0
        // Insecure version: registers widths etc. are not checked
        public static void InverseCMultModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            Register x,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, b, c, N, x, control, valueA, valueN };
                comp.AddParametricGate("InverseCMultModulo", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            // if control == 0
            // then the X register is copied into B register
            // so we uncopy it remaining 0
            comp.SigmaX(control);
            for (int i = 0; i < x.Width; i++)
            {
                comp.Toffoli(b[i], control, x[i]);
            }
            comp.SigmaX(control);

            ulong power2 = (ulong)(Math.Pow(2, x.Width - 1));

            for (int i = x.Width - 1;
                 i >= 0;
                 i--, power2 /= 2)
            {
                // loading A register with (2^i * a) mod N
                ulong toLoad = (valueA * power2) % valueN;
                comp.LoadNumber(a, toLoad, control, x[i]);

                // inverse adding [(2^i * a) + B] modulo N
                comp.InverseAddModulo(a, b, c, N, valueN);

                // unloading [(2^i * a) mod N] from A register
                comp.LoadNumber(a, toLoad, control, x[i]);
            }
        }
Example #18
0
 public static void PhaseKick(this QuantumComputer comp, double gamma, RegisterRef target, params RegisterRef[] controls)
 {
     if (controls.Length == 0)
     {
         Register root = comp.GetRootRegister(target);
         int      t    = target.OffsetToRoot;
         root.PhaseKick(gamma, t);
     }
     else
     {
         Register root = comp.GetRootRegister(target, comp.GetRootRegister(controls));
         int      t    = target.OffsetToRoot;
         root.PhaseKick(gamma, t, controls.Select <RegisterRef, int>(x => x.OffsetToRoot).ToArray <int>());
     }
 }
Example #19
0
 public static void InverseCPhaseShift(this QuantumComputer comp, int dist, RegisterRef target, params RegisterRef[] controls)
 {
     if (controls.Length == 0)
     {
         Register root = comp.GetRootRegister(target);
         int      t    = target.OffsetToRoot;
         root.InverseCPhaseShift(dist, t);
     }
     else
     {
         Register root = comp.GetRootRegister(target, comp.GetRootRegister(controls));
         int      t    = target.OffsetToRoot;
         root.InverseCPhaseShift(dist, t, controls.Select <RegisterRef, int>(x => x.OffsetToRoot).ToArray <int>());
     }
 }
Example #20
0
        public static void InverseSwap(this QuantumComputer comp, RegisterRef r1, RegisterRef r2)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, r1, r2 };
                comp.AddParametricGate("InverseSwap", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            comp.Swap(r1, r2);
        }
 public static void CPhaseShift(this QuantumComputer comp, int dist, RegisterRef target, params RegisterRef[] controls)
 {
     if (controls.Length == 0)
     {
         Register root = comp.GetRootRegister(target);
         int t = target.OffsetToRoot;
         root.CPhaseShift(dist, t);
     }
     else
     {
         Register root = comp.GetRootRegister(target, comp.GetRootRegister(controls));
         int t = target.OffsetToRoot;
         root.CPhaseShift(dist, t, controls.Select<RegisterRef, int>(x => x.OffsetToRoot).ToArray<int>());
     }
 }
        public static void InverseSwap(this QuantumComputer comp, Register r1, Register r2, RegisterRef control)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, r1, r2, control };
                comp.AddParametricGate("InverseSwap", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            comp.Swap(r1, r2, control);
        }
Example #23
0
        public static void InverseSum(this QuantumComputer comp,
                                      RegisterRef refA, RegisterRef refB, RegisterRef refTarget)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, refA, refB, refTarget };
                comp.AddParametricGate("Sum", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            comp.Sum(refA, refB, refTarget);
        }
Example #24
0
 public static void RotateZ(this QuantumComputer comp, double gamma, RegisterRef target, RegisterRef?control = null)
 {
     if (control.HasValue)
     {
         Register root = comp.GetRootRegister(control.Value, target);
         int      c    = control.Value.OffsetToRoot;
         int      t    = target.OffsetToRoot;
         root.RotateZ(gamma, t, c);
     }
     else
     {
         Register root = comp.GetRootRegister(target);
         int      t    = target.OffsetToRoot;
         root.RotateZ(gamma, t);
     }
 }
        public static void MultModuloQFT(this QuantumComputer comp, ulong a, ulong N, Register x, Register b, RegisterRef control)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, N, x, b, control };
                comp.AddParametricGate("MultModuloQFT", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Register ctrl = comp.NewRegister(0, 1);
            comp.MultModuloQFT(a, N, ctrl, x, b, control);
        }
 public static void Hadamard(this QuantumComputer comp, RegisterRef target, RegisterRef? control = null)
 {
     if (control.HasValue)
     {
         Register root = comp.GetRootRegister(control.Value, target);
         int c = control.Value.OffsetToRoot;
         int t = target.OffsetToRoot;
         root.Hadamard(t, c);
     }
     else
     {
         Register root = comp.GetRootRegister(target);
         int t = target.OffsetToRoot;
         root.Hadamard(t);
     }
 }
Example #27
0
 public static void Gate1(this QuantumComputer comp, Complex[,] matrix, RegisterRef target, RegisterRef?control = null)
 {
     if (control.HasValue)
     {
         Register root = comp.GetRootRegister(control.Value, target);
         int      c    = control.Value.OffsetToRoot;
         int      t    = target.OffsetToRoot;
         root.Gate1(matrix, t, c);
     }
     else
     {
         Register root = comp.GetRootRegister(target);
         int      t    = target.OffsetToRoot;
         root.Gate1(matrix, t);
     }
 }
Example #28
0
 public static void Hadamard(this QuantumComputer comp, RegisterRef target, RegisterRef?control = null)
 {
     if (control.HasValue)
     {
         Register root = comp.GetRootRegister(control.Value, target);
         int      c    = control.Value.OffsetToRoot;
         int      t    = target.OffsetToRoot;
         root.Hadamard(t, c);
     }
     else
     {
         Register root = comp.GetRootRegister(target);
         int      t    = target.OffsetToRoot;
         root.Hadamard(t);
     }
 }
 public static void Gate1(this QuantumComputer comp, Complex[,] matrix, RegisterRef target, RegisterRef? control = null)
 {
     if (control.HasValue)
     {
         Register root = comp.GetRootRegister(control.Value, target);
         int c = control.Value.OffsetToRoot;
         int t = target.OffsetToRoot;
         root.Gate1(matrix, t, c);
     }
     else
     {
         Register root = comp.GetRootRegister(target);
         int t = target.OffsetToRoot;
         root.Gate1(matrix, t);
     }
 }
Example #30
0
        // register x - initially loaded with x
        // register N - initially loaded with N
        // control - control bit
        // other registers - initially 0
        // after computation register B changes and contains: [(a*x) mod N]
        // Insecure version: registers widths etc. are not checked
        public static void CMultModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            Register x,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, b, c, N, x, control, valueA, valueN };
                comp.AddParametricGate("CMultModulo", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            ulong power2 = 1;

            for (int i = 0; i < x.Width; i++, power2 *= 2)
            {
                // loading A register with (2^i * a) mod N
                ulong toLoad = (valueA * power2) % valueN;
                comp.LoadNumber(a, toLoad, control, x[i]);

                // adding [(2^i * a) + B] modulo N
                comp.AddModulo(a, b, c, N, valueN);

                // unloading [(2^i * a) mod N] from A register
                comp.LoadNumber(a, toLoad, control, x[i]);
            }

            // if control == 0
            // then B register contains still 0
            // so we copy X register into B register
            comp.SigmaX(control);
            for (int i = 0; i < x.Width; i++)
            {
                comp.Toffoli(b[i], control, x[i]);
            }
            comp.SigmaX(control);
        }
        public static void InverseControlledUaGate(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register x, Register reg0, RegisterRef control)
        {
            Validate(x, N);

            int? invA = Utils.InversionModulo((int)a, (int)N);

            if (invA == null)
            {
                throw new ArgumentException("No inversion for specified a");
            }

            //Console.WriteLine("InverseControlledUa a = {0}, N = {1}", a, N);

            comp.MultModuloQFT((ulong)invA, N, ctrl, x, reg0, control);
            comp.Swap(reg0[0, reg0.Width - 1], x, control);
            comp.InverseMultModuloQFT(a, N, ctrl, x, reg0, control);
        }
        // register x - initially loaded with x
        // register N - initially loaded with N
        // control - control bit
        // other registers - initially 0
        // after computation register B changes and contains: [(a*x) mod N]
        // Insecure version: registers widths etc. are not checked
        public static void CMultModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            Register x,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, b, c, N, x, control, valueA, valueN };
                comp.AddParametricGate("CMultModulo", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            ulong power2 = 1;
            for (int i = 0; i < x.Width; i++, power2 *= 2)
            {
                // loading A register with (2^i * a) mod N
                ulong toLoad = (valueA * power2) % valueN;
                comp.LoadNumber(a, toLoad, control, x[i]);

                // adding [(2^i * a) + B] modulo N
                comp.AddModulo(a, b, c, N, valueN);

                // unloading [(2^i * a) mod N] from A register
                comp.LoadNumber(a, toLoad, control, x[i]);
            }

            // if control == 0
            // then B register contains still 0
            // so we copy X register into B register
            comp.SigmaX(control);
            for (int i = 0; i < x.Width; i++)
            {
                comp.Toffoli(b[i], control, x[i]);
            }
            comp.SigmaX(control);
        }
        public static void InverseControlledUaGate(this QuantumComputer comp, ulong a, ulong N, Register x, RegisterRef control)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, N, x, control };
                comp.AddParametricGate("InverseControlledUaGate", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Register ctrl = comp.NewRegister(0, 1);
            Register reg0 = comp.NewRegister(0, x.Width);
            comp.InverseControlledUaGate(a, N, ctrl, x, reg0, control);
        }
Example #34
0
        public static void AddModuloQFT(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register b, params RegisterRef[] controls)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, N, ctrl, b, controls };
                comp.AddParametricGate("AddModuloQFT", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Validate(a, b, N);
            comp.QFT(b);
            comp.AddModuloQFTPhi(a, N, ctrl, b, controls);
            comp.InverseQFT(b);
        }
        public static void AddModuloQFT(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register b, params RegisterRef[] controls)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, N, ctrl, b, controls };
                comp.AddParametricGate("AddModuloQFT", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Validate(a, b, N);
            comp.QFT(b);
            comp.AddModuloQFTPhi(a, N, ctrl, b, controls);
            comp.InverseQFT(b);
        }
        /// <summary>
        /// The controlled Swap. Swaps the values of two given qubits, if the control qubit is set.
        /// </summary>
        /// <param name="comp">The <see cref="Quantum.QuantumComputer"/> instance.</param>
        /// <param name="r1">The reference to the first swapped qubit.</param>
        /// <param name="r2">The reference to the second swapped qubit.</param>
        /// <param name="control">The reference to the control qubit.</param>
        public static void Swap(this QuantumComputer comp, Register r1, Register r2, RegisterRef control)
        {
            Validate(r1, r2);

            Register root = comp.GetRootRegister(r1, r2, control);
            int target1 = r1.OffsetToRoot;
            int target2 = r2.OffsetToRoot;
            int ctrl = control.OffsetToRoot;

            for (int i = 0; i < r1.Width; i++)
            {
                //comp.Toffoli(root[target1 + i], root[target2 + i], root[ctrl]);
                //comp.Toffoli(root[target2 + i], root[target1 + i], root[ctrl]);
                //comp.Toffoli(root[target1 + i], root[target2 + i], root[ctrl]);
                root.Toffoli(target1 + i, target2 + i, ctrl);
                root.Toffoli(target2 + i, target1 + i, ctrl);
                root.Toffoli(target1 + i, target2 + i, ctrl);
            }
        }
Example #37
0
        /// <summary>
        /// The controlled Swap. Swaps the values of two given qubits, if the control qubit is set.
        /// </summary>
        /// <param name="comp">The <see cref="Quantum.QuantumComputer"/> instance.</param>
        /// <param name="r1">The reference to the first swapped qubit.</param>
        /// <param name="r2">The reference to the second swapped qubit.</param>
        /// <param name="control">The reference to the control qubit.</param>
        public static void Swap(this QuantumComputer comp, Register r1, Register r2, RegisterRef control)
        {
            Validate(r1, r2);

            Register root    = comp.GetRootRegister(r1, r2, control);
            int      target1 = r1.OffsetToRoot;
            int      target2 = r2.OffsetToRoot;
            int      ctrl    = control.OffsetToRoot;

            for (int i = 0; i < r1.Width; i++)
            {
                //comp.Toffoli(root[target1 + i], root[target2 + i], root[ctrl]);
                //comp.Toffoli(root[target2 + i], root[target1 + i], root[ctrl]);
                //comp.Toffoli(root[target1 + i], root[target2 + i], root[ctrl]);
                root.Toffoli(target1 + i, target2 + i, ctrl);
                root.Toffoli(target2 + i, target1 + i, ctrl);
                root.Toffoli(target1 + i, target2 + i, ctrl);
            }
        }
Example #38
0
        // register A - initially loaded with a
        // register B - initially loaded with b
        // register C - initially 0, exactly one bit wider than A, stores overflow bit
        // register N - initially loaded with N
        // after computation in register B: (a+b) mod N
        // other registers dont change their states
        // register B must be exactly one bit wider than A to store carry bit
        // register B must be exactly one bit wider than N to store carry bit
        // registers A, N must be the same length
        // Insecure version: registers widths etc. are not checked
        public static void AddModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            ulong valueN)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, b, c, N, valueN };
                comp.AddParametricGate("AddModulo", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            RegisterRef carry    = b[b.Width - 1];
            RegisterRef overflow = c[c.Width - 1];

            comp.Add(a, b, c);
            comp.InverseAdd(N, b, c);
            comp.SigmaX(carry);
            comp.CNot(overflow, carry);
            comp.SigmaX(carry);

            //resetting N
            comp.LoadNumber(N, valueN, overflow);

            comp.Add(N, b, c);

            // now we have [(a+b) mod N] in B register
            // next steps lead to recover the initial state of registers N and overflow bit

            //setting N back
            comp.LoadNumber(N, valueN, overflow);

            comp.InverseAdd(a, b, c);
            comp.CNot(overflow, carry);
            comp.Add(a, b, c);
        }
Example #39
0
        // register x - initially loaded with x
        // register b - initially loaded with 0
        // after computation register b changes and contains: [(a*x) mod N]
        // Secure version: throws Exceptions if arguments are invalid
        public static void CMultModulo(
            this QuantumComputer comp,
            Register x,
            Register b,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            Validate(x, b, valueN);

            Register a = comp.NewRegister(0, x.Width - 1);
            Register c = comp.NewRegister(0, x.Width);
            Register N = comp.NewRegister(valueN, x.Width - 1);

            comp.CMultModulo(a, b, c, N, x, control, valueA, valueN);

            comp.DeleteRegister(ref N);
            comp.DeleteRegister(ref c);
            comp.DeleteRegister(ref a);
        }
        // register x - initially loaded with x
        // register b - initially loaded with 0
        // after computation register b changes and contains: [(a*x) mod N]
        // Secure version: throws Exceptions if arguments are invalid
        public static void CMultModulo(
            this QuantumComputer comp,
            Register x,
            Register b,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            Validate(x, b, valueN);

            Register a = comp.NewRegister(0, x.Width - 1);
            Register c = comp.NewRegister(0, x.Width);
            Register N = comp.NewRegister(valueN, x.Width - 1);

            comp.CMultModulo(a, b, c, N, x, control, valueA, valueN);

            comp.DeleteRegister(ref N);
            comp.DeleteRegister(ref c);
            comp.DeleteRegister(ref a);
        }
        public static void InverseAddModuloQFTPhi(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register b, params RegisterRef[] controls)
        {
            comp.InverseAddQFTPhi(a, b, controls);

            comp.InverseQFT(b);
            comp.SigmaX(b[b.Width - 1]);
            comp.CNot(ctrl, b[b.Width - 1]);
            comp.SigmaX(b[b.Width - 1]);
            comp.QFT(b);

            comp.AddQFTPhi(a, b, controls);
            comp.InverseAddQFTPhi(N, b, ctrl);

            comp.InverseQFT(b);
            comp.CNot(ctrl, b[b.Width - 1]);
            comp.QFT(b);

            comp.AddQFTPhi(N, b);
            comp.InverseAddQFTPhi(a, b, controls);
        }
Example #42
0
        // Swap two bits
        public static void Swap(this QuantumComputer comp, RegisterRef r1, RegisterRef r2)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, r1, r2 };
                comp.AddParametricGate("Swap", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Register root    = comp.GetRootRegister(r1, r2);
            int      target1 = r1.OffsetToRoot;
            int      target2 = r2.OffsetToRoot;

            root.CNot(target1, target2);
            root.CNot(target2, target1);
            root.CNot(target1, target2);
        }
Example #43
0
        // Insecure version: registers widths etc. are not checked
        public static void InverseAddModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            ulong valueN)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, b, c, N, valueN };
                comp.AddParametricGate("InverseAddModulo", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            RegisterRef carry    = b[b.Width - 1];
            RegisterRef overflow = c[c.Width - 1];

            comp.InverseAdd(a, b, c);
            comp.CNot(overflow, carry);
            comp.Add(a, b, c);

            //resetting N:
            comp.LoadNumber(N, valueN, overflow);

            comp.InverseAdd(N, b, c);

            //setting N back:
            comp.LoadNumber(N, valueN, overflow);

            comp.SigmaX(carry);
            comp.CNot(overflow, carry);
            comp.SigmaX(carry);
            comp.Add(N, b, c);
            comp.InverseAdd(a, b, c);
        }
Example #44
0
        public static void Sum(this QuantumComputer comp,
                               RegisterRef refA, RegisterRef refB, RegisterRef refTarget)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, refA, refB, refTarget };
                comp.AddParametricGate("Sum", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Register root   = comp.GetRootRegister(refA, refB, refTarget);
            int      a      = refA.OffsetToRoot;
            int      b      = refB.OffsetToRoot;
            int      target = refTarget.OffsetToRoot;

            root.CNot(target, a);
            root.CNot(target, b);
        }
        public static void InverseMultModuloQFT(this QuantumComputer comp, ulong a, ulong N, RegisterRef ctrl, Register x, Register b, RegisterRef control)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, a, N, ctrl, x, b, control };
                comp.AddParametricGate("InverseMultModuloQFT", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Validate(a, b, N);
            comp.QFT(b);

            for (int i = x.Width - 1; i >= 0; i--)
            {
                comp.InverseAddModuloQFTPhi(((((ulong)1 << i) * a) % N), N, ctrl, b, x[i], control);
            }

            comp.InverseQFT(b);
        }
Example #46
0
        // Oracle is working on input register x (of width n)
        // and output register y (of width 1)
        public static void Oracle(this QuantumComputer comp, int target, Register x, Register y)
        {
            var controlBits = new RegisterRef[x.Width];

            for (int i = 0; i < x.Width; i++)
            {
                if ((target & (1 << i)) == 0)
                {
                    x.SigmaX(i);
                }
                controlBits[i] = x[i];
            }

            comp.Toffoli(y[0], controlBits);                    // Toffoli(<target_bit>, ... <control_bits> ...)

            for (int i = 0; i < x.Width; i++)
            {
                if ((target & (1 << i)) == 0)
                {
                    x.SigmaX(i);
                }
            }
        }
Example #47
0
        public static void InverseCarry(this QuantumComputer comp,
                                        RegisterRef rc0, RegisterRef ra0, RegisterRef rb0, RegisterRef rc1)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, rc0, ra0, rb0, rc1 };
                comp.AddParametricGate("InverseCarry", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Register root = comp.GetRootRegister(rc0, ra0, rb0, rc1);
            int      c0   = rc0.OffsetToRoot;
            int      a0   = ra0.OffsetToRoot;
            int      b0   = rb0.OffsetToRoot;
            int      c1   = rc1.OffsetToRoot;

            root.Toffoli(c1, c0, b0);
            root.CNot(b0, a0);
            root.Toffoli(c1, a0, b0);
        }
Example #48
0
        // register x - initially loaded with x
        // register N - initially loaded with N
        // control - control bit
        // other registers - initially 0
        // after computation register B changes and contains: [(a*x) mod N]
        // Insecure version: registers widths etc. are not checked
        public static void CMultModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            Register x,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            ulong power2 = 1;

            for (int i = 0; i < x.Width; i++, power2 *= 2)
            {
                // loading A register with (2^i * a) mod N
                ulong toLoad = (valueA * power2) % valueN;
                comp.LoadNumber(a, toLoad, control, x[i]);

                // adding [(2^i * a) + B] modulo N
                comp.AddModulo(a, b, c, N, valueN);

                // unloading [(2^i * a) mod N] from A register
                comp.LoadNumber(a, toLoad, control, x[i]);
            }

            // if control == 0
            // then B register contains still 0
            // so we copy X register into B register
            comp.SigmaX(control);
            for (int i = 0; i < x.Width; i++)
            {
                comp.Toffoli(b[i], control, x[i]);
            }
            comp.SigmaX(control);
        }
        public static void Carry(this QuantumComputer comp,
            RegisterRef rc0, RegisterRef ra0, RegisterRef rb0, RegisterRef rc1)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, rc0, ra0, rb0, rc1 };
                comp.AddParametricGate("Carry", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Register root = comp.GetRootRegister(rc0, ra0, rb0, rc1);
            int c0 = rc0.OffsetToRoot;
            int a0 = ra0.OffsetToRoot;
            int b0 = rb0.OffsetToRoot;
            int c1 = rc1.OffsetToRoot;

            root.Toffoli(c1, a0, b0);
            root.CNot(b0, a0);
            root.Toffoli(c1, c0, b0);
        }
        public static void Swap(this QuantumComputer comp, Register r1, Register r2, RegisterRef control)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, r1, r2, control };
                comp.AddParametricGate("Swap", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Validate(r1, r2);

            Register root = comp.GetRootRegister(r1, r2, control);
            int target1 = r1.OffsetToRoot;
            int target2 = r2.OffsetToRoot;
            int ctrl = control.OffsetToRoot;

            for (int i = 0; i < r1.Width; i++)
            {
                //comp.Toffoli(root[target1 + i], root[target2 + i], root[ctrl]);
                //comp.Toffoli(root[target2 + i], root[target1 + i], root[ctrl]);
                //comp.Toffoli(root[target1 + i], root[target2 + i], root[ctrl]);
                root.Toffoli(target1 + i, target2 + i, ctrl);
                root.Toffoli(target2 + i, target1 + i, ctrl);
                root.Toffoli(target1 + i, target2 + i, ctrl);
            }
        }
        // Swap two bits
        public static void Swap(this QuantumComputer comp, RegisterRef r1, RegisterRef r2)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, r1, r2 };
                comp.AddParametricGate("Swap", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Register root = comp.GetRootRegister(r1, r2);
            int target1 = r1.OffsetToRoot;
            int target2 = r2.OffsetToRoot;

            root.CNot(target1, target2);
            root.CNot(target2, target1);
            root.CNot(target1, target2);
        }
 /// <summary>
 /// Inversion of <see cref="Carry(QuantumComputer, RegisterRef, RegisterRef, RegisterRef, RegisterRef)"/> method.
 /// </summary>
 /// <param name="comp">The QuantumComputer instance.</param>
 /// <param name="rc0">The reference to previous carry qubit.</param>
 /// <param name="ra0">The reference to qubit, for which the carry bit was computed, in the first register.</param>
 /// <param name="rb0">The reference to qubit, for which the carry bit was computed, in the second register.</param>
 /// <param name="rc1">The reference to qubit storing the resulted carry value.</param>
 public static void InverseCarry(this QuantumComputer comp,
     RegisterRef rc0, RegisterRef ra0, RegisterRef rb0, RegisterRef rc1)
 {
     Register root = comp.GetRootRegister(rc0, ra0, rb0, rc1);
     int c0 = rc0.OffsetToRoot;
     int a0 = ra0.OffsetToRoot;
     int b0 = rb0.OffsetToRoot;
     int c1 = rc1.OffsetToRoot;
     root.Toffoli(c1, c0, b0);
     root.CNot(b0, a0);
     root.Toffoli(c1, a0, b0);
 }
 /// <summary>
 /// Computes the least significant bit of sum of two given bits. 
 /// Used with <see cref="Carry(QuantumComputer, RegisterRef, RegisterRef, RegisterRef, RegisterRef)"/> to perform addition.
 /// </summary>
 /// <param name="comp">The QuantumComputer instance.</param>
 /// <param name="refA">The reference to first qubit being sumed.</param>
 /// <param name="refB">The reference to second qubit being sumed.</param>
 /// <param name="refTarget">The reference to qubit for storing the result.</param>
 public static void Sum(this QuantumComputer comp,
     RegisterRef refA, RegisterRef refB, RegisterRef refTarget)
 {
     Register root = comp.GetRootRegister(refA, refB, refTarget);
     int a = refA.OffsetToRoot;
     int b = refB.OffsetToRoot;
     int target = refTarget.OffsetToRoot;
     root.CNot(target, a);
     root.CNot(target, b);
 }
 public static void RotateZ(this QuantumComputer comp, double gamma, RegisterRef target, RegisterRef? control = null)
 {
     if (control.HasValue)
     {
         Register root = comp.GetRootRegister(control.Value, target);
         int c = control.Value.OffsetToRoot;
         int t = target.OffsetToRoot;
         root.RotateZ(gamma, t, c);
     }
     else
     {
         Register root = comp.GetRootRegister(target);
         int t = target.OffsetToRoot;
         root.RotateZ(gamma, t);
     }
 }
 public static void Toffoli(this QuantumComputer comp, RegisterRef target, params RegisterRef[] controls)
 {
     Register root = comp.GetRootRegister(comp.GetRootRegister(controls), target);
     root.Toffoli(target.OffsetToRoot, controls.Select<RegisterRef, int>(x => x.OffsetToRoot).ToArray<int>());
 }
        public static void Sum(this QuantumComputer comp,
            RegisterRef refA, RegisterRef refB, RegisterRef refTarget)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, refA, refB, refTarget };
                comp.AddParametricGate("Sum", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            Register root = comp.GetRootRegister(refA, refB, refTarget);
            int a = refA.OffsetToRoot;
            int b = refB.OffsetToRoot;
            int target = refTarget.OffsetToRoot;
            root.CNot(target, a);
            root.CNot(target, b);
        }
        public static void InverseSum(this QuantumComputer comp,
            RegisterRef refA, RegisterRef refB, RegisterRef refTarget)
        {
            if (comp.Group)
            {
                object[] parameters = new object[] { comp, refA, refB, refTarget };
                comp.AddParametricGate("Sum", parameters);
                return;
            }
            else
            {
                comp.Group = true;
            }

            comp.Sum(refA, refB, refTarget);
        }
        // Insecure version: registers widths etc. are not checked
        public static void InverseCMultModulo(
            this QuantumComputer comp,
            Register a,
            Register b,
            Register c,
            Register N,
            Register x,
            RegisterRef control,
            ulong valueA,
            ulong valueN)
        {
            // if control == 0
            // then the X register is copied into B register
            // so we uncopy it remaining 0
            comp.SigmaX(control);
            for (int i = 0; i < x.Width; i++)
            {
                comp.Toffoli(b[i], control, x[i]);
            }
            comp.SigmaX(control);

            ulong power2 = (ulong)(Math.Pow(2, x.Width - 1));
            for (int i = x.Width - 1;
                i >= 0;
                i--, power2 /= 2)
            {
                // loading A register with (2^i * a) mod N
                ulong toLoad = (valueA * power2) % valueN;
                comp.LoadNumber(a, toLoad, control, x[i]);

                // inverse adding [(2^i * a) + B] modulo N
                comp.InverseAddModulo(a, b, c, N, valueN);

                // unloading [(2^i * a) mod N] from A register
                comp.LoadNumber(a, toLoad, control, x[i]);
            }
        }
Example #59
0
 public static void InverseSwap(this QuantumComputer comp, Register r1, Register r2, RegisterRef control)
 {
     comp.Swap(r1, r2, control);
 }
Example #60
0
 public static void InverseSwap(this QuantumComputer comp, RegisterRef r1, RegisterRef r2)
 {
     comp.Swap(r1, r2);
 }