def test_adder_inverse(self, name, a_int, b_int): """ Test the adder + adder_inverse. The output should be equal to the original state of the circuit. """ bits = binary.get_required_bits(a_int, b_int) self._prepare_adder_circuit(bits) qregs.initialize_qureg_given_int(a_int, self.a, self.qc) qregs.initialize_qureg_given_int(b_int, self.b, self.qc) adder.adder_circuit(self.qc, self.cin, self.a, self.b, self.cout) adder.adder_circuit_i(self.qc, self.cin, self.a, self.b, self.cout) # Measure results ans = ClassicalRegister(self.b.size + self.cout.size, "ans") self.qc.add_register(ans) for j in range(self.b.size): self.qc.measure(self.b[j], ans[j]) self.qc.measure(self.cout[0], ans[self.b.size]) ############################################################### # execute the program on qasm ############################################################### counts = CircuitTestCase.execute_qasm(self.qc).get_counts() expected = binary.get_bitstring_from_int(b_int, ans.size) self._del_qubits() self.assertEqual(len(counts), 1) self.assertIn(expected, counts)
def test_adder(self, name, a_int, b_int): """ Add a_int and b_int and check their result. The number of bits used to represent the ints is computed at runtime. """ bits = binary.get_required_bits(a_int, b_int) self._prepare_adder_circuit(bits) qregs.initialize_qureg_given_int(a_int, self.a, self.qc) qregs.initialize_qureg_given_int(b_int, self.b, self.qc) # Apply the adder adder.adder_circuit(self.qc, self.cin, self.a, self.b, self.cout) # Measure the output register in the computational basis ans = ClassicalRegister(self.b.size + self.cout.size, "ans") self.qc.add_register(ans) for j in range(self.b.size): self.qc.measure(self.b[j], ans[j]) self.qc.measure(self.cout[0], ans[self.b.size]) ############################################################### # execute the program on qasm ############################################################### counts = CircuitTestCase.execute_qasm(self.qc).get_counts() expected = binary.get_bitstring_from_int(a_int + b_int, ans.size) self._del_qubits() self.assertEqual(len(counts), 1) self.assertIn(expected, counts)
def get_circuit_for_qubits_weight(circuit, a_qs, cin_q, cout_qs, patterns_dict): assert len(a_qs) == patterns_dict['n_lines'] assert len(cin_q) == 1 assert len(cout_qs) == patterns_dict['n_couts'] for i in patterns_dict['adders_pattern']: cout_idx = int(i[-1][1:]) half_bits = int((len(i) - 1) / 2) input_qubits = [] for j in i: if j[0] == 'a': input_qubits.append(a_qs[int(j[1:])]) elif j[0] == 'c': input_qubits.append(cout_qs[int(j[1:])]) else: raise Exception("Invalid") logger.debug("{0}".format([input_qubits[i] for i in range(half_bits)])) logger.debug("{0}".format( [input_qubits[i] for i in range(half_bits, 2 * half_bits)])) logger.debug("{0}".format([cout_qs[cout_idx]])) adder.adder_circuit( circuit, cin_q, [input_qubits[i] for i in range(half_bits)], [input_qubits[i] for i in range(half_bits, 2 * half_bits)], [cout_qs[cout_idx]]) to_measure_qubits = [] for j in patterns_dict['results']: if j[0] == 'a': to_measure_qubits.append(a_qs[int(j[1:])]) elif j[0] == 'c': to_measure_qubits.append(cout_qs[int(j[1:])]) else: raise Exception("Invalid") return to_measure_qubits
def test_halves_sum(self, name, a_int, bits): """ Add two halves of a register on a given number of bits """ if bits % 2 == 1: bits = bits + 1 self.logger.debug("n bits = {0}".format(bits)) binary.check_enough_bits(a_int, bits) half_bits = int(bits / 2) # WARNING: also self.b is set, be careful to not use it self._prepare_adder_circuit(bits) # Initialize a to its value qregs.initialize_qureg_given_int(a_int, self.a, self.qc) adder.adder_circuit(self.qc, self.cin, [self.a[i] for i in range(half_bits)], [self.a[i] for i in range(half_bits, bits)], self.cout) # Measure the output register in the computational basis ans = ClassicalRegister(half_bits + self.cout.size, "ans") self.qc.add_register(ans) for j in range(half_bits, bits): self.qc.measure(self.a[j], ans[j - half_bits]) self.qc.measure(self.cout[0], ans[half_bits]) counts = self.execute_qasm(self.qc).get_counts() self.logger.debug("counts {0}".format(counts)) a_str = binary.get_bitstring_from_int(a_int, bits) a_half1_int = binary.get_int_from_bitstring(a_str[0:half_bits]) a_half2_int = binary.get_int_from_bitstring(a_str[half_bits:bits]) # a_half1_int = int(a_str[0:half_bits], 2) # a_half2_int = int(a_str[half_bits:bits], 2) self.logger.debug("a first half = {0}".format(a_half1_int)) self.logger.debug("a second half = {0}".format(a_half2_int)) expected = binary.get_bitstring_from_int(a_half1_int + a_half2_int, half_bits + 1) self.logger.debug(" '{0}': expected".format(expected)) self._del_qubits() self.assertEqual(len(counts), 1) self.assertIn(expected, counts)
def test_weight_equals_w_hadamards(self, name, eq_int, bits): """ Test how the adder works when using hadamards. The idea is to check the weight of a single register, which could be in any state. After adding the two halves of the register to get its weight, we check this weight against the given eq_int. If the two weights are equal, we set a specific register to 1. """ # Prepare qubits if bits % 2 == 1: bits = bits + 1 half_bits = int(bits / 2) binary.check_enough_bits(eq_int, half_bits + 1) equal_str = binary.get_bitstring_from_int(eq_int, half_bits + 1) self.logger.debug("equal_str = {0}".format(equal_str)) # In reality, instead of two separete register, we should have one # single register and compute its weight. However, it changes pretty # much nothing to just use two separate registers. self._prepare_adder_circuit(half_bits) eq = QuantumRegister(1, 'eq') anc = QuantumRegister(1, 'anc') # Have to measure a, b and eq ans = ClassicalRegister(self.a.size + self.b.size + eq.size, "ans") self.qc.add_register(eq, anc, ans) # Hadamards a and b self.qc.h(self.a) self.qc.h(self.b) # Apply the adder adder.adder_circuit(self.qc, self.cin, self.a, self.b, self.cout) # Add the negated equal_str to {cout, b}. Note that the result of # a + b is stored in [cout_0, b_n, b_{n_1}, ..., b_0], w/ the most # significant bit on cout. qregs.initialize_qureg_to_complement_of_bitstring( equal_str, [qb for qb in self.b] + [self.cout[0]], self.qc) # If output is 11..1, i.e. a + b == eq_int, set eq to 1 self.qc.mct([qb for qb in self.b] + [qcout for qcout in self.cout], eq[0], anc, mode='advanced') # Restore b qregs.initialize_qureg_to_complement_of_bitstring( equal_str, [qb for qb in self.b] + [self.cout[0]], self.qc) adder.adder_circuit_i(self.qc, self.cin, self.a, self.b, self.cout) # Measure a, b, eq for i, qr in enumerate(chain(self.a, self.b, eq)): self.qc.measure(qr, ans[i]) ############################################################### # execute the program on qasm ############################################################### counts = CircuitTestCase.execute_qasm(self.qc).get_counts() self._del_qubits() # self.logger.debug(counts) # The idea is that the eq qubit is the first bit of the result state. # If it is one, it should mean that a + b == eq_int. So, we get the # full state and check the correctness of the equality. for i in counts.keys(): if i[0] == '1': self.logger.debug("Eq active, full state is {0}".format(i)) a_int = binary.get_int_from_bitstring(i[1:half_bits + 1]) b_int = binary.get_int_from_bitstring(i[half_bits + 1:bits + 1]) self.assertEqual(a_int + b_int, eq_int)