Ripple Carry AdderΒΆ

Download Notebook - ripple_carry_addition_example.ipynb

Example of ripple carry adder circuit using Guppy.

from guppylang import guppy
from guppylang.std.builtins import array, comptime, output
from selene_sim import Quest, build
from hugr.qsystem.result import QsysResult
from guppylang.std.quantum import qubit, discard_array, measure_array, measure, collect_measurements
from guppyalgos.primitives.arithmetic import adder_ripple_cuccaro_carry_out, subtractor_ripple_cuccaro_carry_out
from guppyalgos.utils import int_to_bits, apply_bitstring, qarray

I.e. the length of bitstring is set as n=5, the first integer is 5(00101), the second integer is 31(11111), then, the binary of a+b is 36(001001)

n = 5 
n_qubits = 2 * (n + 1)
a = 5
b = 31

a_bits = int_to_bits(a, n)
a_bit_array = array(*a_bits)  
b_bits = int_to_bits(b, n)
b_bit_array = array(*b_bits)  
a_plus_b = int_to_bits(a + b, n + 1)

print("The first integer a is:", str(a)+ ", the binary of a is:", a_bits)
print("The second integer b is:", str(b)+ ", the binary of b is:", b_bits)
print("The correct a+b is:", str(a + b)+ ", the binary of a+b is:", a_plus_b)
The first integer a is: 5, the binary of a is: [True, False, True, False, False]
The second integer b is: 31, the binary of b is: [True, True, True, True, True]
The correct a+b is: 36, the binary of a+b is: [False, False, True, False, False, True]

Then, we convert the bool strings of a and b and apply the ripple carry adder

@guppy
def main() -> None:
    """Main function."""
    a_reg = qarray(n)
    b_reg = qarray(n)
    carry_out = qubit()
    apply_bitstring(a_reg, a_bit_array)
    apply_bitstring(b_reg, b_bit_array)
    
    adder_ripple_cuccaro_carry_out(a_reg, b_reg, carry_out)
    discard_array(a_reg)

    output("b_reg", collect_measurements(measure_array(b_reg)))
    output("carry_out", measure(carry_out).read())

To see if the generated the string is correct, we append the b_reg and the second qubit of anci_reg

HUGR = main.compile()
runner = build(HUGR)

run_shots = 1
shots = QsysResult(
    runner.run_shots(
        simulator=Quest(),
        n_qubits=n_qubits,
        n_shots=run_shots,
    )
)
b_reg = dict(shots.register_counts()["b_reg"])
carry_out = dict(shots.register_counts()["carry_out"])
output_string = list(b_reg.keys())[0] + list(carry_out.keys())[0]
output_string_bool = [bool(int(bit)) for bit in output_string]

print("The the a+b entry from the quantum circuit is:", str(output_string_bool) + ",", "if this is equal to the classical results,", output_string_bool ==a_plus_b)
The the a+b entry from the quantum circuit is: [False, False, True, False, False, True], if this is equal to the classical results, True

The subtraction is similar, but with using two complements representation for instance

b_minus_a = b - a
b_minus_a_bits = int_to_bits(b_minus_a % 2**n, n)
print("The correct a-b is:", str(b_minus_a) + ", the binary of a-b is:", b_minus_a_bits)
The correct a-b is: 26, the binary of a-b is: [False, True, False, True, True]

Thus, we can implement the subtractor_ripple_cuccaro guppy function

@guppy
def main() -> None:
    """Apply main."""
    a_reg = qarray(n)
    b_reg = qarray(n)
    carry_out = qubit()
    apply_bitstring(a_reg, a_bit_array)
    apply_bitstring(b_reg, b_bit_array)
    subtractor_ripple_cuccaro_carry_out(a_reg, b_reg, carry_out)
    discard_array(a_reg)
    output("b_reg", collect_measurements(measure_array(b_reg)))
    output("carry_out", measure(carry_out).read())

The b_reg stores the minus results, and the second qubit of anci_reg includes the sign

HUGR = main.compile()
runner = build(HUGR)

run_shots = 1
shots = QsysResult(
    runner.run_shots(
        simulator=Quest(),
        n_qubits=n_qubits,
        n_shots=run_shots,
    )
)
b_reg = dict(shots.register_counts()["b_reg"])
carry_out = dict(shots.register_counts()["carry_out"])
b_reg_bool = [bool(int(bit)) for bit in list(b_reg.keys())[0]]
carry_out_bool = int(list(carry_out.keys())[0])

print("The the b-a entry from the quantum circuit is:", str(b_reg_bool) + ",", "if this is equal to the classical results,", b_reg_bool == b_minus_a_bits)
print("The sign qubit is:", str(carry_out_bool) + ",", "0 means positive and neutral, 1 means negative.")
The the b-a entry from the quantum circuit is: [False, True, False, True, True], if this is equal to the classical results, True
The sign qubit is: 0, 0 means positive and neutral, 1 means negative.