From d748a6b3ebc8212f99afdff014e8f40fd2a9ed34 Mon Sep 17 00:00:00 2001 From: Vineet Thumuluri Date: Sun, 25 Oct 2020 18:04:33 +0530 Subject: [PATCH 1/4] Changed RippleCarryAdderD to use temporary logical-AND adder blocks --- Standard/src/Arithmetic/Integer.qs | 71 ++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/Standard/src/Arithmetic/Integer.qs b/Standard/src/Arithmetic/Integer.qs index 03e4fd1ff17..7a1d72abe7f 100644 --- a/Standard/src/Arithmetic/Integer.qs +++ b/Standard/src/Arithmetic/Integer.qs @@ -30,6 +30,43 @@ namespace Microsoft.Quantum.Arithmetic { CCNOT (carryIn, summand2, carryOut); } + /// # Summary + /// Implements an adder block that uses a temporary logical-AND construction. + /// The carryOut is computed and then erased using the adjoint operation. + /// + /// # Input + /// ## carryIn + /// Carry-in qubit. + /// ## summand1 + /// First summand qubit. + /// ## summand2 + /// Second summand qubit, is replaced with the lower bit of the sum of + /// `summand1` and `summand2`. + /// ## carryOut + /// Carry-out qubit, will be xored with the higher bit of the sum. + operation AdderBlockUsingTemporaryLogicalAnd(carryIn: Qubit, summand1: Qubit, summand2: Qubit, carryOut: Qubit) + : Unit is Adj + Ctl { + body (...) { + CNOT(carryIn, summand2); + CNOT(carryIn, summand1); + ApplyAnd(summand1, summand2, carryOut); + CNOT(carryIn, carryOut); + } + controlled (controls, ...) { + CNOT(carryIn, summand2); + CNOT(carryIn, summand1); + ApplyAnd(summand1, summand2, carryOut); + CNOT(carryIn, carryOut); + } + controlled adjoint (controls, ...) { + CNOT (carryIn, carryOut); + (Adjoint ApplyAnd) (summand1, summand2, carryOut); + (Controlled CNOT) (controls, (summand1, summand2)); + CNOT(carryIn, summand1); + CNOT(carryIn, summand2); + } + } + /// # Summary /// Implements a reversible sum gate. Given a carry-in bit encoded in /// qubit `carryIn` and two summand bits encoded in `summand1` and `summand2`, @@ -73,10 +110,12 @@ namespace Microsoft.Quantum.Arithmetic { /// - Thomas G. Draper: "Addition on a Quantum Computer", 2000. /// https://arxiv.org/abs/quant-ph/0008033 /// + /// - Craig Gidney: "Halving the cost of quantum addition", 2018. + /// https://arxiv.org/abs/1709.06648 + /// /// # Remarks - /// The specified controlled operation makes use of symmetry and mutual - /// cancellation of operations to improve on the default implementation - /// that adds a control to every operation. + /// The high-bit uses carry and sum blocks to compute the output carry bit + /// since adder block implementation erases the carry bit. operation RippleCarryAdderD(xs : LittleEndian, ys : LittleEndian, carry : Qubit) : Unit is Adj + Ctl { body (...) { @@ -90,17 +129,23 @@ namespace Microsoft.Quantum.Arithmetic { "Input registers must have the same number of qubits." ); - using (auxRegister = Qubit[nQubits]) { - for (idx in 0..(nQubits-2)) { - Carry(auxRegister[idx], xs![idx], ys![idx], auxRegister[idx+1]); // (1) - } - (Controlled Carry) (controls, (auxRegister[nQubits-1], xs![nQubits-1], ys![nQubits-1], carry)); - (Controlled CNOT) (controls, (xs![nQubits-1], ys![nQubits-1])); - (Controlled Sum) (controls, (auxRegister[nQubits-1], xs![nQubits-1], ys![nQubits-1])); - for (idx in (nQubits-2)..(-1)..0 ) { - (Adjoint Carry) (auxRegister[idx], xs![idx], ys![idx], auxRegister[idx+1]); // cancels with (1) - (Controlled Sum) (controls, (auxRegister[idx], xs![idx], ys![idx])); + using (auxRegister = Qubit[nQubits-1]) { + within { + ApplyAnd (xs![0], ys![0], auxRegister[0]); + } + apply { + within { + for (idx in 1..(nQubits-2)) { + (Controlled AdderBlockUsingTemporaryLogicalAnd) (controls, (auxRegister[idx-1], xs![idx], ys![idx], auxRegister[idx])); + } + } + apply { + (Controlled Carry) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1], carry)); + (Controlled CNOT) (controls, (xs![nQubits-1], ys![nQubits-1])); + (Controlled Sum) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1])); + } } + (Controlled CNOT) (controls,(xs![0], ys![0])); } } } From a5e8081102579fd331fd5be82bd36b41809584b1 Mon Sep 17 00:00:00 2001 From: Vineet Thumuluri Date: Sun, 25 Oct 2020 18:16:27 +0530 Subject: [PATCH 2/4] indentation fix --- Standard/src/Arithmetic/Integer.qs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Standard/src/Arithmetic/Integer.qs b/Standard/src/Arithmetic/Integer.qs index 7a1d72abe7f..d9cbd1f6b00 100644 --- a/Standard/src/Arithmetic/Integer.qs +++ b/Standard/src/Arithmetic/Integer.qs @@ -51,20 +51,20 @@ namespace Microsoft.Quantum.Arithmetic { CNOT(carryIn, summand1); ApplyAnd(summand1, summand2, carryOut); CNOT(carryIn, carryOut); - } + } controlled (controls, ...) { CNOT(carryIn, summand2); CNOT(carryIn, summand1); ApplyAnd(summand1, summand2, carryOut); CNOT(carryIn, carryOut); - } + } controlled adjoint (controls, ...) { CNOT (carryIn, carryOut); (Adjoint ApplyAnd) (summand1, summand2, carryOut); (Controlled CNOT) (controls, (summand1, summand2)); CNOT(carryIn, summand1); CNOT(carryIn, summand2); - } + } } /// # Summary @@ -131,19 +131,19 @@ namespace Microsoft.Quantum.Arithmetic { using (auxRegister = Qubit[nQubits-1]) { within { - ApplyAnd (xs![0], ys![0], auxRegister[0]); - } + ApplyAnd (xs![0], ys![0], auxRegister[0]); + } apply { within { for (idx in 1..(nQubits-2)) { (Controlled AdderBlockUsingTemporaryLogicalAnd) (controls, (auxRegister[idx-1], xs![idx], ys![idx], auxRegister[idx])); } - } + } apply { (Controlled Carry) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1], carry)); (Controlled CNOT) (controls, (xs![nQubits-1], ys![nQubits-1])); (Controlled Sum) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1])); - } + } } (Controlled CNOT) (controls,(xs![0], ys![0])); } From 860312555eed2917a25fddbdb62e6fb5f50d4dbe Mon Sep 17 00:00:00 2001 From: Vineet Thumuluri Date: Mon, 26 Oct 2020 00:29:46 +0530 Subject: [PATCH 3/4] split AdderBlockUsingTemporaryLogicalAnd into two and added some comments --- Standard/src/Arithmetic/Integer.qs | 76 ++++++++++++++++++------------ 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/Standard/src/Arithmetic/Integer.qs b/Standard/src/Arithmetic/Integer.qs index d9cbd1f6b00..942dbdaaf4c 100644 --- a/Standard/src/Arithmetic/Integer.qs +++ b/Standard/src/Arithmetic/Integer.qs @@ -31,8 +31,7 @@ namespace Microsoft.Quantum.Arithmetic { } /// # Summary - /// Implements an adder block that uses a temporary logical-AND construction. - /// The carryOut is computed and then erased using the adjoint operation. + /// Implements a compute carry gate using a temporary logical-AND construction. /// /// # Input /// ## carryIn @@ -40,25 +39,41 @@ namespace Microsoft.Quantum.Arithmetic { /// ## summand1 /// First summand qubit. /// ## summand2 - /// Second summand qubit, is replaced with the lower bit of the sum of + /// Second summand qubit. /// `summand1` and `summand2`. /// ## carryOut /// Carry-out qubit, will be xored with the higher bit of the sum. - operation AdderBlockUsingTemporaryLogicalAnd(carryIn: Qubit, summand1: Qubit, summand2: Qubit, carryOut: Qubit) - : Unit is Adj + Ctl { - body (...) { - CNOT(carryIn, summand2); + internal operation ComputeTemporaryCarry(carryIn: Qubit, summand1: Qubit, summand2: Qubit, carryOut: Qubit) + : Unit is Adj{ + CNOT(carryIn, summand2); + CNOT(carryIn, summand1); + ApplyAnd(summand1, summand2, carryOut); + CNOT(carryIn, carryOut); + } + + /// # Summary + /// Implements a erase carry gate by uncomputing the logical-AND. + /// + /// # Input + /// ## carryIn + /// Carry-in qubit. + /// ## summand1 + /// First summand qubit. + /// ## summand2 + /// Second summand qubit, is replaced with the lower bit of the sum of + /// `summand1` and `summand2`. + /// ## carryOut + /// Carry-out qubit, will be erased + internal operation EraseTemporaryCarry(carryIn: Qubit, summand1: Qubit, summand2: Qubit, carryOut: Qubit) + : Unit is Adj + Ctl{ + body (...){ + CNOT (carryIn, carryOut); + (Adjoint ApplyAnd) (summand1, summand2, carryOut); + CNOT (summand1, summand2); CNOT(carryIn, summand1); - ApplyAnd(summand1, summand2, carryOut); - CNOT(carryIn, carryOut); - } - controlled (controls, ...) { CNOT(carryIn, summand2); - CNOT(carryIn, summand1); - ApplyAnd(summand1, summand2, carryOut); - CNOT(carryIn, carryOut); - } - controlled adjoint (controls, ...) { + } + controlled (controls, ...) { CNOT (carryIn, carryOut); (Adjoint ApplyAnd) (summand1, summand2, carryOut); (Controlled CNOT) (controls, (summand1, summand2)); @@ -130,22 +145,23 @@ namespace Microsoft.Quantum.Arithmetic { ); using (auxRegister = Qubit[nQubits-1]) { - within { - ApplyAnd (xs![0], ys![0], auxRegister[0]); - } + within { + ApplyAnd (xs![0], ys![0], auxRegister[0]); + } apply { - within { - for (idx in 1..(nQubits-2)) { - (Controlled AdderBlockUsingTemporaryLogicalAnd) (controls, (auxRegister[idx-1], xs![idx], ys![idx], auxRegister[idx])); - } - } - apply { - (Controlled Carry) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1], carry)); - (Controlled CNOT) (controls, (xs![nQubits-1], ys![nQubits-1])); - (Controlled Sum) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1])); + for (idx in 1..(nQubits-2)) { + ComputeTemporaryCarry(auxRegister[idx-1], xs![idx], ys![idx], auxRegister[idx]); } - } - (Controlled CNOT) (controls,(xs![0], ys![0])); + // carry out is computed using Carry and Sum since using temporary Logical-AND construction erases the carry bit + (Controlled Carry) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1], carry)); + (Controlled CNOT) (controls, (xs![nQubits-1], ys![nQubits-1])); + (Controlled Sum) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1])); + for (idx in (nQubits-2)..-1..1) { + (Controlled EraseTemporaryCarry) (controls, (auxRegister[idx-1], xs![idx], ys![idx], auxRegister[idx])); + } + } + // low bit output computation is simplified since CarryIn is always |0> + (Controlled CNOT) (controls, (xs![0], ys![0])); } } } From 6d7300c60b21f9280ee98b1eaf63974cb6bafc00 Mon Sep 17 00:00:00 2001 From: Vineet Thumuluri Date: Mon, 26 Oct 2020 00:32:05 +0530 Subject: [PATCH 4/4] indentation fix --- Standard/src/Arithmetic/Integer.qs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Standard/src/Arithmetic/Integer.qs b/Standard/src/Arithmetic/Integer.qs index 942dbdaaf4c..ad25bd2def1 100644 --- a/Standard/src/Arithmetic/Integer.qs +++ b/Standard/src/Arithmetic/Integer.qs @@ -72,7 +72,7 @@ namespace Microsoft.Quantum.Arithmetic { CNOT (summand1, summand2); CNOT(carryIn, summand1); CNOT(carryIn, summand2); - } + } controlled (controls, ...) { CNOT (carryIn, carryOut); (Adjoint ApplyAnd) (summand1, summand2, carryOut); @@ -147,7 +147,7 @@ namespace Microsoft.Quantum.Arithmetic { using (auxRegister = Qubit[nQubits-1]) { within { ApplyAnd (xs![0], ys![0], auxRegister[0]); - } + } apply { for (idx in 1..(nQubits-2)) { ComputeTemporaryCarry(auxRegister[idx-1], xs![idx], ys![idx], auxRegister[idx]); @@ -158,8 +158,8 @@ namespace Microsoft.Quantum.Arithmetic { (Controlled Sum) (controls, (auxRegister[nQubits-2], xs![nQubits-1], ys![nQubits-1])); for (idx in (nQubits-2)..-1..1) { (Controlled EraseTemporaryCarry) (controls, (auxRegister[idx-1], xs![idx], ys![idx], auxRegister[idx])); - } - } + } + } // low bit output computation is simplified since CarryIn is always |0> (Controlled CNOT) (controls, (xs![0], ys![0])); }