2019-03-19 19:48:49 +03:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
// Licensed under the MIT License.
|
|
|
|
|
2019-05-04 01:44:41 +03:00
|
|
|
namespace Microsoft.Quantum.Arithmetic {
|
|
|
|
open Microsoft.Quantum.Intrinsic;
|
|
|
|
open Microsoft.Quantum.Canon;
|
|
|
|
open Microsoft.Quantum.Math;
|
|
|
|
open Microsoft.Quantum.Diagnostics;
|
|
|
|
open Microsoft.Quantum.Measurement;
|
2019-03-15 21:04:17 +03:00
|
|
|
|
2019-05-04 01:44:41 +03:00
|
|
|
operation IntegerAdderTestHelper( IntegerAdder : ( (LittleEndian, LittleEndian, Qubit) => Unit is Ctl), summand1 : Int, summand2 : Int, numberOfQubits : Int ) : Unit {
|
2019-03-15 21:04:17 +03:00
|
|
|
body (...) {
|
|
|
|
using (register = Qubit[2*numberOfQubits + 1]) {
|
|
|
|
mutable actual_carry = 0;
|
|
|
|
mutable actual1 = 0;
|
|
|
|
mutable actual2 = 0;
|
|
|
|
mutable measured_carry = Zero;
|
|
|
|
let summand1LE = LittleEndian(register[0 .. numberOfQubits - 1]);
|
|
|
|
let summand2LE = LittleEndian(register[numberOfQubits .. 2*numberOfQubits - 1]);
|
|
|
|
let carry = register[2*numberOfQubits];
|
2020-01-15 23:14:02 +03:00
|
|
|
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(summand1, summand1LE);
|
|
|
|
ApplyXorInPlace(summand2, summand2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
|
|
|
|
IntegerAdder(summand1LE, summand2LE, carry);
|
2020-01-15 23:14:02 +03:00
|
|
|
|
2019-03-15 21:04:17 +03:00
|
|
|
let sum = summand1 + summand2;
|
2019-05-04 01:44:41 +03:00
|
|
|
let expected = ModulusI(sum, 2^numberOfQubits);
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual1 = MeasureInteger(summand1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(summand1, actual1, $"Expected {summand1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(summand2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(expected, actual2, $"Expected {expected}, got {actual2}");
|
2019-03-15 21:04:17 +03:00
|
|
|
let expected_carry = (sum / 2^numberOfQubits);
|
|
|
|
set measured_carry = MResetZ(carry);
|
|
|
|
if (measured_carry == One) {set actual_carry = 1;} else {set actual_carry = 0;}
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(expected_carry, actual_carry, $"Expected {expected_carry}, got {actual_carry}");
|
2019-03-15 21:04:17 +03:00
|
|
|
|
2020-01-15 23:14:02 +03:00
|
|
|
for (numberOfControls in 1..2) {
|
2019-03-15 21:04:17 +03:00
|
|
|
using (controls = Qubit[numberOfControls]) {
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(summand1, summand1LE);
|
|
|
|
ApplyXorInPlace(summand2, summand2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
// controls are |0>, no addition is computed
|
|
|
|
(Controlled IntegerAdder) (controls, (summand1LE, summand2LE, carry));
|
|
|
|
set actual1 = MeasureInteger(summand1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(summand1, actual1, $"Expected {summand1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(summand2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(summand2, actual2, $"Expected {expected}, got {actual2}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set measured_carry = MResetZ(carry);
|
|
|
|
if (measured_carry == One) {set actual_carry = 1;} else {set actual_carry = 0;}
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(0, actual_carry, $"Expected {0}, got {actual_carry}");
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(summand1, summand1LE);
|
|
|
|
ApplyXorInPlace(summand2, summand2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
// now controls are set to |1>, addition is computed
|
|
|
|
ApplyToEach(X, controls);
|
|
|
|
(Controlled IntegerAdder) (controls, (summand1LE, summand2LE, carry));
|
|
|
|
set actual1 = MeasureInteger(summand1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(summand1, actual1, $"Expected {summand1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(summand2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(expected, actual2, $"Expected {expected}, got {actual2}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set measured_carry = MResetZ(carry);
|
|
|
|
if (measured_carry == One) {set actual_carry = 1;} else {set actual_carry = 0;}
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(expected_carry, actual_carry, $"Expected {expected_carry}, got {actual_carry}");
|
2019-03-15 21:04:17 +03:00
|
|
|
ResetAll(controls);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-15 23:14:02 +03:00
|
|
|
|
2019-05-04 01:44:41 +03:00
|
|
|
operation IntegerAdderExhaustiveTestHelper (IntegerAdder : ( (LittleEndian, LittleEndian, Qubit) => Unit is Ctl), numberOfQubits : Int) : Unit {
|
2019-03-15 21:04:17 +03:00
|
|
|
for( summand1 in 0 .. 2^numberOfQubits - 1 ) {
|
|
|
|
for( summand2 in 0 .. 2^numberOfQubits - 1 ) {
|
|
|
|
IntegerAdderTestHelper(IntegerAdder, summand1, summand2, numberOfQubits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderDTest () : Unit {
|
|
|
|
let numberOfQubits = 7;
|
|
|
|
let summand1 = 127;
|
|
|
|
let summand2 = 17;
|
|
|
|
IntegerAdderTestHelper(RippleCarryAdderD, summand1, summand2, numberOfQubits);
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderDExhaustiveTestReversible () : Unit {
|
|
|
|
for (numberOfQubits in 3..6) {
|
|
|
|
IntegerAdderExhaustiveTestHelper (RippleCarryAdderD, numberOfQubits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderDTestReversible () : Unit {
|
|
|
|
let numberOfQubits = 20;
|
2020-01-15 23:14:02 +03:00
|
|
|
let summand1 = 823709;
|
|
|
|
let summand2 = 88487;
|
2019-03-15 21:04:17 +03:00
|
|
|
IntegerAdderTestHelper(RippleCarryAdderD, summand1, summand2, numberOfQubits);
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderCDKMExhaustiveTest () : Unit {
|
|
|
|
let numberOfQubits = 4;
|
2020-01-15 23:14:02 +03:00
|
|
|
IntegerAdderExhaustiveTestHelper (RippleCarryAdderCDKM, numberOfQubits);
|
2019-03-15 21:04:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderCDKMTestReversible () : Unit {
|
|
|
|
let numberOfQubits = 20;
|
2020-01-15 23:14:02 +03:00
|
|
|
let summand1 = 823709;
|
|
|
|
let summand2 = 88487;
|
2019-03-15 21:04:17 +03:00
|
|
|
IntegerAdderTestHelper(RippleCarryAdderCDKM, summand1, summand2, numberOfQubits);
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderCDKMExhaustiveTestReversible () : Unit {
|
|
|
|
for (numberOfQubits in 3..6) {
|
2020-01-15 23:14:02 +03:00
|
|
|
IntegerAdderExhaustiveTestHelper (RippleCarryAdderCDKM, numberOfQubits);
|
2019-03-15 21:04:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderTTKExhaustiveTest () : Unit {
|
|
|
|
let numberOfQubits = 4;
|
|
|
|
IntegerAdderExhaustiveTestHelper (RippleCarryAdderTTK, numberOfQubits);
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderTTKExhaustiveTestReversible () : Unit {
|
|
|
|
for (numberOfQubits in 1..6){
|
|
|
|
IntegerAdderExhaustiveTestHelper (RippleCarryAdderTTK, numberOfQubits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-04 01:44:41 +03:00
|
|
|
operation IntegerAdderNoCarryTestHelper( IntegerAdder : ( (LittleEndian, LittleEndian) => Unit is Ctl), summand1 : Int, summand2 : Int, numberOfQubits : Int ) : Unit {
|
2019-03-15 21:04:17 +03:00
|
|
|
using (register = Qubit[2*numberOfQubits]) {
|
|
|
|
mutable actual1 = 0;
|
|
|
|
mutable actual2 = 0;
|
|
|
|
let summand1LE = LittleEndian(register[0 .. numberOfQubits - 1]);
|
|
|
|
let summand2LE = LittleEndian(register[numberOfQubits .. 2*numberOfQubits - 1]);
|
2020-01-15 23:14:02 +03:00
|
|
|
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(summand1, summand1LE);
|
|
|
|
ApplyXorInPlace(summand2, summand2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
|
|
|
|
IntegerAdder(summand1LE, summand2LE);
|
2020-01-15 23:14:02 +03:00
|
|
|
|
2019-03-15 21:04:17 +03:00
|
|
|
let sum = summand1 + summand2;
|
2019-05-04 01:44:41 +03:00
|
|
|
let expected = ModulusI(sum, 2^numberOfQubits);
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual1 = MeasureInteger(summand1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(summand1, actual1, $"Expected {summand1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(summand2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(expected, actual2, $"Expected {expected}, got {actual2}");
|
2019-03-15 21:04:17 +03:00
|
|
|
let expected_carry = (sum / 2^numberOfQubits);
|
|
|
|
|
2020-01-15 23:14:02 +03:00
|
|
|
for (numberOfControls in 1..2) {
|
2019-03-15 21:04:17 +03:00
|
|
|
using (controls = Qubit[numberOfControls]) {
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(summand1, summand1LE);
|
|
|
|
ApplyXorInPlace(summand2, summand2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
// controls are |0>, no addition is computed
|
|
|
|
(Controlled IntegerAdder) (controls, (summand1LE, summand2LE));
|
|
|
|
set actual1 = MeasureInteger(summand1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(summand1, actual1, $"Expected {summand1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(summand2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(summand2, actual2, $"Expected {expected}, got {actual2}");
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(summand1, summand1LE);
|
|
|
|
ApplyXorInPlace(summand2, summand2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
// now controls are set to |1>, addition is computed
|
|
|
|
ApplyToEach(X, controls);
|
|
|
|
(Controlled IntegerAdder) (controls, (summand1LE, summand2LE));
|
|
|
|
set actual1 = MeasureInteger(summand1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(summand1, actual1, $"Expected {summand1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(summand2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(expected, actual2, $"Expected {expected}, got {actual2}");
|
2019-03-15 21:04:17 +03:00
|
|
|
ResetAll(controls);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-04 01:44:41 +03:00
|
|
|
operation IntegerAdderNoCarryExhaustiveTestHelper (IntegerAdder : ( (LittleEndian, LittleEndian) => Unit is Ctl), numberOfQubits : Int) : Unit {
|
2019-03-15 21:04:17 +03:00
|
|
|
for( summand1 in 0 .. 2^numberOfQubits - 1 ) {
|
|
|
|
for( summand2 in 0 .. 2^numberOfQubits - 1 ) {
|
|
|
|
IntegerAdderNoCarryTestHelper(IntegerAdder, summand1, summand2, numberOfQubits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderNoCarryTTKTestReversible () : Unit {
|
|
|
|
let numberOfQubits = 10;
|
2020-01-15 23:14:02 +03:00
|
|
|
let summand1 = 1021;
|
|
|
|
let summand2 = 973;
|
2019-03-15 21:04:17 +03:00
|
|
|
IntegerAdderNoCarryTestHelper(RippleCarryAdderNoCarryTTK, summand1, summand2, numberOfQubits);
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderNoCarryTTKExhaustiveTest () : Unit {
|
|
|
|
let numberOfQubits = 4;
|
|
|
|
IntegerAdderNoCarryExhaustiveTestHelper (RippleCarryAdderNoCarryTTK, numberOfQubits);
|
|
|
|
}
|
|
|
|
|
|
|
|
operation RippleCarryAdderNoCarryTTKExhaustiveTestReversible () : Unit {
|
|
|
|
for (numberOfQubits in 1..6) {
|
|
|
|
IntegerAdderNoCarryExhaustiveTestHelper (RippleCarryAdderNoCarryTTK, numberOfQubits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
operation GreaterThanTestHelper( integer1 : Int, integer2 : Int, numberOfQubits : Int ) : Unit {
|
|
|
|
using (register = Qubit[2*numberOfQubits+1]) {
|
|
|
|
mutable actual1 = 0;
|
|
|
|
mutable actual2 = 0;
|
|
|
|
mutable actualr = Zero;
|
|
|
|
mutable gt = Zero;
|
|
|
|
let integer1LE = LittleEndian(register[0 .. numberOfQubits - 1]);
|
|
|
|
let integer2LE = LittleEndian(register[numberOfQubits .. 2*numberOfQubits - 1]);
|
|
|
|
let result = register[2*numberOfQubits];
|
2020-01-15 23:14:02 +03:00
|
|
|
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(integer1, integer1LE);
|
|
|
|
ApplyXorInPlace(integer2, integer2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
|
|
|
|
GreaterThan(integer1LE, integer2LE, result);
|
|
|
|
|
2020-01-15 23:14:02 +03:00
|
|
|
if (integer1 > integer2) {set gt = One;}
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual1 = MeasureInteger(integer1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(integer1, actual1, $"Expected {integer1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(integer2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(integer2, actual2, $"Expected {integer2}, got {actual2}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actualr = M(result);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactB((gt == actualr), true, $"Expected {gt}, got {actualr}");
|
2019-03-15 21:04:17 +03:00
|
|
|
|
|
|
|
Reset(result);
|
2020-01-15 23:14:02 +03:00
|
|
|
for (numberOfControls in 1..2) {
|
2019-03-15 21:04:17 +03:00
|
|
|
using (controls = Qubit[numberOfControls]) {
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(integer1, integer1LE);
|
|
|
|
ApplyXorInPlace(integer2, integer2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
(Controlled GreaterThan) (controls, (integer1LE, integer2LE, result));
|
|
|
|
|
|
|
|
set actual1 = MeasureInteger(integer1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(integer1, actual1, $"Expected {integer1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(integer2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(integer2, actual2, $"Expected {integer2}, got {actual2}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actualr = M(result);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactB((actualr == Zero), true, $"Expected Zero, got {actualr}");
|
2019-03-15 21:04:17 +03:00
|
|
|
|
|
|
|
ApplyToEach(X, controls);
|
2019-10-24 01:29:01 +03:00
|
|
|
ApplyXorInPlace(integer1, integer1LE);
|
|
|
|
ApplyXorInPlace(integer2, integer2LE);
|
2019-03-15 21:04:17 +03:00
|
|
|
(Controlled GreaterThan) (controls, (integer1LE, integer2LE, result));
|
|
|
|
|
|
|
|
set actual1 = MeasureInteger(integer1LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(integer1, actual1, $"Expected {integer1}, got {actual1}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actual2 = MeasureInteger(integer2LE);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactI(integer2, actual2, $"Expected {integer2}, got {actual2}");
|
2019-03-15 21:04:17 +03:00
|
|
|
set actualr = M(result);
|
2019-05-04 01:44:41 +03:00
|
|
|
EqualityFactB((gt == actualr), true, $"Expected {gt}, got {actualr}");
|
2019-03-15 21:04:17 +03:00
|
|
|
|
|
|
|
ResetAll(controls);
|
|
|
|
Reset(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
operation GreaterThanExhaustiveTestReversible () : Unit {
|
|
|
|
for (numberOfQubits in 1..5) {
|
|
|
|
for (integer1 in 0..2^numberOfQubits-1) {
|
|
|
|
for (integer2 in 0..2^numberOfQubits-1) {
|
|
|
|
GreaterThanTestHelper(integer1, integer2, numberOfQubits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|