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); }
// Add(a, b, 0) -> (a, a+b, 0) // Registers a, b and c must not overlap // Registers a and b have the same width // Register c is used for storing carries and must be minimum one bit wider than register a (or b) // Initial value of c must be 0 public static void Add(this QuantumComputer comp, Register a, Register b, Register c) { if (comp.Group) { object[] parameters = new object[] { comp, a, b, c }; comp.AddParametricGate("Add", parameters); return; } else { comp.Group = true; } int width = a.Width; int i = 0; for (; i < width - 1; i++) { comp.Carry(c[i], a[i], b[i], c[i + 1]); } comp.Carry(c[i], a[i], b[i], b[i + 1]); comp.CNot(b[i], a[i]); comp.Sum(c[i], a[i], b[i]); i--; for (; i >= 0; i--) { comp.InverseCarry(c[i], a[i], b[i], c[i + 1]); comp.Sum(c[i], a[i], b[i]); } }
public static void AddQFTPhi(this QuantumComputer comp, Register a, Register b, params RegisterRef[] controls) { if (comp.Group) { object[] parameters = new object[] { comp, a, b, controls }; comp.AddParametricGate("AddQFTPhi", parameters); return; } else { comp.Group = true; } Validate(a, b); for (int j = b.Width - 1; j >= 0; j--) { for (int i = j; i >= 0; i--) { List<RegisterRef> list = controls.ToList<RegisterRef>(); list.Add(a[i]); RegisterRef[] controls2 = list.ToArray(); comp.CPhaseShift(Math.Abs(j-i), b[j], controls2); } } }
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); }
public static void InverseLoadNumber(this QuantumComputer comp, Register target, ulong number, params RegisterRef[] controlBits) { if (comp.Group) { object[] parameters = new object[] { comp, target, number, controlBits }; comp.AddParametricGate("InverseLoadNumber", parameters); return; } else { comp.Group = true; } comp.LoadNumber(target, number, controlBits); }
public static void InverseReverse(this QuantumComputer comp, Register a) { if (comp.Group) { object[] parameters = new object[] { comp, a }; comp.AddParametricGate("InverseReverse", parameters); return; } else { comp.Group = true; } comp.Reverse(a); }
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); }
public static void InverseWalsh(this QuantumComputer comp, Register register) { if (comp.Group) { object[] parameters = new object[] { comp, register }; comp.AddParametricGate("InverseWalsh", parameters); return; } else { comp.Group = true; } comp.Walsh(register); }
// register X - initially loaded with x // register X_1 - initially loaded with 1 // W = width(a) = width(N) // width(b) = width(c) = width(x1) = W + 1 // width(X) is 2 * W // register N - initially loaded with N // other registers - initially 0 // after computation register X_1 changes and contains: [(a^x) mod N] // Insecure version: registers widths etc. are not checked public static void ExpModulo( this QuantumComputer comp, Register a, Register b, Register c, Register N, Register x1, Register x, int valueA, int valueN) { if (comp.Group) { object[] parameters = new object[] { comp, a, b, c, N, x1, x, valueA, valueN }; comp.AddParametricGate("ExpModulo", parameters); return; } else { comp.Group = true; } bool firstRegisterB = false; int pow_a_2 = valueA; for (int i = 0; i < x.Width; i++) { // finding the inversion modulo of pow_a_2 int inv_mod = InversionModulo(pow_a_2, valueN); if (firstRegisterB) { comp.CMultModulo(a, x1, c, N, b, x[i], (ulong)pow_a_2, (ulong)valueN); comp.InverseCMultModulo(a, b, c, N, x1, x[i], (ulong)inv_mod, (ulong)valueN); } else { comp.CMultModulo(a, b, c, N, x1, x[i], (ulong)pow_a_2, (ulong)valueN); comp.InverseCMultModulo(a, x1, c, N, b, x[i], (ulong)inv_mod, (ulong)valueN); } pow_a_2 = (pow_a_2 * pow_a_2) % valueN; firstRegisterB = !firstRegisterB; } }
public static void AddModuloQFT(this QuantumComputer comp, ulong a, ulong N, Register b, params RegisterRef[] controls) { if (comp.Group) { object[] parameters = new object[] { comp, a, N, b, controls }; comp.AddParametricGate("AddModuloQFT", parameters); return; } else { comp.Group = true; } Register ctrl = comp.NewRegister(0, 1); comp.AddModuloQFT(a, N, ctrl, b, controls); }
public static void InverseMultModuloQFT(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("InverseMultModuloQFT", parameters); return; } else { comp.Group = true; } Register ctrl = comp.NewRegister(0, 1); comp.InverseMultModuloQFT(a, N, ctrl, x, b, control); }
public static void ControlledUaGate(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("ControlledUaGate", parameters); return; } else { comp.Group = true; } Register ctrl = comp.NewRegister(0, 1); Register reg0 = comp.NewRegister(0, x.Width); comp.ControlledUaGate(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); }
//Apply a walsh-hadamard transform on whole register public static void Walsh(this QuantumComputer comp, Register register) { if (comp.Group) { object[] parameters = new object[] { comp, register }; comp.AddParametricGate("Walsh", parameters); return; } else { comp.Group = true; } for (int i = 0; i < register.Width; i++) { register.Hadamard(i); } }
public static void AddQFT(this QuantumComputer comp, ulong a, Register b, params RegisterRef[] controls) { if (comp.Group) { object[] parameters = new object[] { comp, a, b, controls }; comp.AddParametricGate("AddQFT", parameters); return; } else { comp.Group = true; } Validate(a, b); comp.QFT(b); comp.AddQFTPhi(a, b, controls); comp.InverseQFT(b); }
// 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); }
// Add(a, b) -> (a, a+b) // Registers a and b must not overlap // Registers a and b have the same width // Initially, there is scratch register used public static void Add(this QuantumComputer comp, Register a, Register b) { if (comp.Group) { object[] parameters = new object[] { comp, a, b }; comp.AddParametricGate("Add", parameters); return; } else { comp.Group = true; } Validate(a, b); Register c = comp.NewRegister(0, a.Width); comp.Add(a, b, c); comp.DeleteRegister(ref c); }
// controlled loading a number into register // using Toffoli gates // if controlBits are empty, the number is loaded unconditionally public static void LoadNumber(this QuantumComputer comp, Register target, ulong number, params RegisterRef[] controlBits) { if (comp.Group) { object[] parameters = new object[] { comp, target, number, controlBits }; comp.AddParametricGate("LoadNumber", parameters); return; } else { comp.Group = true; } Validate(target, number); int controlLength = controlBits.Length; int i = 0; ulong tmpN = number; while (tmpN > 0) { int rest = (int)(tmpN % 2); tmpN = tmpN / 2; if (rest == 1) { if (controlLength > 1) { comp.Toffoli(target[i], controlBits); } else if (controlLength > 0) { comp.CNot(target[i], controlBits[0]); } else { target.SigmaX(i); } } i++; } }
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); }
public static void InverseQFT(this QuantumComputer comp, Register register) { if (comp.Group) { object[] parameters = new object[] { comp, register }; comp.AddParametricGate("InverseQFT", parameters); return; } else { comp.Group = true; } int width = register.Width; for (int i = 0; i < width; i++) { register.Hadamard(i); for (int j = i + 1; j < width; j++) { register.InverseCPhaseShift(i - j, i, j); } } }
public static void Reverse(this QuantumComputer comp, Register a) { if (comp.Group) { object[] parameters = new object[] { comp, a }; comp.AddParametricGate("Reverse", parameters); return; } else { comp.Group = true; } for (int i = 0; i < a.Width / 2; i++) { comp.Swap(a[i], a[a.Width - 1 - i]); } }
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); }
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); }
//public static void QFT(this QuantumComputer comp, Register register) //{ // int width = register.Width; // for (int i = width - 1; i >= 0; i--) // { // register.Hadamard(i); // for (int j = i - 1; j >= 0; j--) // { // register.CPhaseShift(i - j, i, j); // } // } //} //public static void InverseQFT(this QuantumComputer comp, Register register) //{ // int width = register.Width; // for (int i = 0; i < width; i++) // { // for (int j = 0; j < i; j++) // { // register.InverseCPhaseShift(i - j, i, j); // } // register.Hadamard(i); // } //} public static void QFT(this QuantumComputer comp, Register register) { if (comp.Group) { object[] parameters = new object[] { comp, register }; comp.AddParametricGate("QFT", parameters); return; } else { comp.Group = true; } int width = register.Width; for (int i = width - 1; i >= 0; i--) { for (int j = width - 1; j > i; j--) { register.CPhaseShift(i - j, i, j); } register.Hadamard(i); } }
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 InverseAddQFTPhi(this QuantumComputer comp, ulong a, Register b, params RegisterRef[] controls) { if (comp.Group) { object[] parameters = new object[] { comp, a, b, controls }; comp.AddParametricGate("InverseAddQFTPhi", parameters); return; } else { comp.Group = true; } bool[] aBin = Quantum.Utils.getBinaryRepresentation(a, b.Width); for (int j = 0; j < b.Width; j++) { for (int i = 0; i <= j; i++) { if (aBin[i]) { comp.InverseCPhaseShift(Math.Abs(j - i), b[j], controls); } } } }
public static void AddQFTPhi(this QuantumComputer comp, ulong a, Register b, params RegisterRef[] controls) { if (comp.Group) { object[] parameters = new object[] { comp, a, b, controls }; comp.AddParametricGate("AddQFTPhi", parameters); return; } else { comp.Group = true; } bool[] aBin = Quantum.Utils.getBinaryRepresentation(a, b.Width); for (int j = b.Width - 1; j >= 0; j--) { //comp.ClassicalCPhaseShift(b[j], aBin[j], b.Width - j, controls); for (int i = j; i >= 0; i--) { if (aBin[i]) { comp.CPhaseShift(Math.Abs(j - i), b[j], controls); } } } }
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); }
// register X - initially loaded with x // register X_1 - initially loaded with 1 // width(x1) = W + 1 // width(X) is 2 * W // after computation register X_1 changes and contains: [(a^x) mod N] // Secure version: throws Exceptions if arguments are invalid public static void ExpModulo( this QuantumComputer comp, Register x, Register x1, int valueA, int valueN) { if (comp.Group) { object[] parameters = new object[] { comp, x, x1, valueA, valueN }; comp.AddParametricGate("ExpModulo", parameters); return; } else { comp.Group = true; } Validate(x, x1, valueN); Register a = comp.NewRegister(0, x1.Width - 1); Register b = comp.NewRegister(0, x1.Width); Register c = comp.NewRegister(0, x1.Width); Register N = comp.NewRegister((ulong)valueN, x1.Width - 1); comp.ExpModulo(a, b, c, N, x1, x, valueA, valueN); comp.DeleteRegister(ref N); comp.DeleteRegister(ref c); comp.DeleteRegister(ref b); comp.DeleteRegister(ref a); }