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 test_fast_population_count(self, name): nwr_dict = hwc.get_circuit_for_qubits_weight_get_pattern(len(name)) result_bit_length = len(nwr_dict['results']) a = QuantumRegister(nwr_dict['n_lines'], 'a') cin = QuantumRegister(1, 'cin') cout = QuantumRegister(nwr_dict['n_couts'], 'cout') cr = ClassicalRegister(len(nwr_dict['results'])) qc = QuantumCircuit(cin, a, cout, cr, name='test_fpt_{0}'.format(name)) _ = qregs.initialize_qureg_given_bitstring(name, a, qc) to_measure_qubits = hwc.get_circuit_for_qubits_weight( qc, a, cin, cout, nwr_dict) for i, qb in enumerate(to_measure_qubits): qc.measure(qb, cr[i]) result = CircuitTestCase.execute_qasm(qc, 2048) counts = result.get_counts() self.logger.info(counts) exp_w = name.count("1") exp_w_bitstring = binary.get_bitstring_from_int( exp_w, result_bit_length) self.assertEqual(len(counts), 1) self.assertIn(exp_w_bitstring, counts)
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 initialize_qureg_given_int(a_int, qreg, circuit): """ Given a decimal integer, initialize the qreg to the proper value corresponding to it. Basically, if a_int is 11, i.e. 1011 in binary, the function negate bits 3, 2 and 0 of the qreg. Note that the qreg has the most significant bit in the leftmost part (big endian) :param a_int: the integer in decimal base :param qreg: the QuantumRegister on which the integer should be set :param circuit: the QuantumCircuit containing the q_reg """ a_str = binary.get_bitstring_from_int(a_int, len(qreg)) return initialize_qureg_given_bitstring(a_str, qreg, circuit)
def test_initialize_complemented_qureg_give_int(self, name, a_int): bits = binary.get_required_bits(a_int) qreg = QuantumRegister(bits) qc = QuantumCircuit(qreg) has_op = qregs.initialize_qureg_to_complement_of_int(a_int, qreg, qc) if (not has_op): self.skipTest("No operation to perform given bitstring") vec = CircuitTestCase.execute_statevector(qc).get_statevector(qc) exp_vec = [0] * (2**bits) neg_bs = binary.get_negated_bistring( binary.get_bitstring_from_int(a_int, bits)) neg_i = binary.get_int_from_bitstring(neg_bs) exp_vec[neg_i] = 1 f = state_fidelity(vec, exp_vec) self.assertAlmostEqual(f, 1)
def get_circuit_for_qubits_weight_check(circuit, a_qs, cin_q, cout_qs, eq_q, anc_q, weight_int, patterns_dict, mode='advanced'): equal_str = binary.get_bitstring_from_int(weight_int, len(patterns_dict['results'])) circuit.barrier() result_qubits = get_circuit_for_qubits_weight(circuit, a_qs, cin_q, cout_qs, patterns_dict) circuit.barrier() _ = qregs.initialize_qureg_to_complement_of_bitstring( equal_str, result_qubits, circuit) circuit.barrier() circuit.mct([qb for qb in result_qubits], eq_q[0], anc_q, mode=mode) circuit.barrier() return result_qubits
def initialize_qureg_to_complement_of_int(a_int, qreg, circuit): a_str = binary.get_bitstring_from_int(a_int, len(qreg)) return initialize_qureg_to_complement_of_bitstring(a_str, qreg, circuit)
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)