def neg_mct_gate(lneg): neg_mct = AncillaCircuit(3) for i in lneg: neg_mct.x(i) neg_mct.ccx(0, 1, 2) for i in lneg: neg_mct.x(i) return neg_mct.to_ancilla_gate(True)
def carry_gate(): carry_circ = AncillaCircuit(4) (c0, a, b, c1) = (carry_circ.qubits[0], carry_circ.qubits[1], carry_circ.qubits[2], carry_circ.qubits[3]) carry_circ.ccx(a, b, c1) carry_circ.append(neg_mct_gate(), [c0, a, b, c1]) return carry_circ.to_ancilla_gate()
def sum_gate(): sum_circ = AncillaCircuit(3) (c0, a, b) = (sum_circ.qubits[0], sum_circ.qubits[1], sum_circ.qubits[2]) sum_circ.cx(a, b) sum_circ.cx(c0, b) return sum_circ.to_ancilla_gate()
def makeRecursiveCircuitUnqomp(n, m): # creates (recursively) a circuit to compute u_n where u_0 is the input on m bits, and u_(n+1) = f(u_n), returns an AncillaCircuit, without uncomputation f_gate = makesFGate(m, True) qr_input = QuantumRegister(m, "input") qr_output = QuantumRegister(m, "output") if n == 1: circuit = AncillaCircuit(qr_input, qr_output) circuit.append(f_gate, [*qr_input, *qr_output]) return circuit qr_ancillas = AncillaRegister(m, "ancilla-" + str(n)) circuit = AncillaCircuit(qr_input, qr_output, qr_ancillas) rec_circ = makeRecursiveCircuitUnqomp(n - 1, m) rec_gate = rec_circ.to_ancilla_gate() circuit.append(rec_gate, [*qr_input, *qr_ancillas]) circuit.append(f_gate, [*qr_ancillas, *qr_output]) return circuit
def qc_amplitude_amplification_iteration(): reg = QuantumRegister(n + 1, name='reg') _qc_aa_iteration = AncillaCircuit(QuantumRegister(n + 1)) _qc_aa_iteration.append(oracle, reg) _qc_aa_iteration.append( _construct_diffusion_circuit().to_ancilla_gate(), reg[:-1]) return _qc_aa_iteration
def mcx(relative_numbers): from unqomp.ancillaallocation import AncillaCircuit from qiskit import QuantumRegister, QuantumCircuit n = 12 print('MCX ; ', end = '') #for qiskit ctrls2 = QuantumRegister(n, 'ctrls') target2 = QuantumRegister(1, 'target') anc = QuantumRegister(n - 2, 'anc') circuit2 = QuantumCircuit(ctrls2, target2, anc) circuit2.mcx(ctrls2, target2, anc, mode = 'v-chain') nb_qb_qi = circuit2.num_qubits nb_gates_qi = circuit2.decompose().decompose().decompose().decompose().decompose().count_ops() if not relative_numbers: print(str(nb_qb_qi) + ' ; ' + str(nb_gates_qi['cx'] + nb_gates_qi['u3']) + ' ; ' + str(nb_gates_qi['cx']) + ' ; ', end = '') ctrls = QuantumRegister(n, 'ctrls') target = QuantumRegister(1, 'target') circuit1 = AncillaCircuit(ctrls, target) circuit1.mcx(ctrls, target) circuit1 = circuit1.circuitWithUncomputation() nb_qb_mi = circuit1.num_qubits nb_gates_mi = circuit1.decompose().decompose().decompose().decompose().decompose().count_ops() if not relative_numbers: print(str(nb_qb_mi) + ' ; ' + str(nb_gates_mi['cx'] + nb_gates_mi['u3']) + ' ; ' + str(nb_gates_mi['cx'])) if relative_numbers: print_relative_vals(nb_qb_qi, nb_gates_qi['cx'], nb_gates_qi['u3'], nb_qb_mi, nb_gates_mi['cx'], nb_gates_mi['u3'])
def makesOracle(i, n): # Creates the oracle finding exactly i on n qubits (+ 1 for target)(or its lowest n bits if i >= 2^n) # Could use some uncomputation... ctrls = QuantumRegister(n) target = QuantumRegister(1) fcirc = AncillaCircuit(ctrls, target, name="oracle_" + str(i) + "_" + str(n)) format_str = '{0:0' + str(n) + 'b}' binary_i = format_str.format(i)[::-1] for j in range(n): if binary_i[j] == '0': fcirc.x(ctrls[j]) fcirc.mcx(ctrls[:], target[0]) for j in range(n): if binary_i[j] == '0': fcirc.x(ctrls[j]) return fcirc.to_ancilla_gate()
def makesPLR(num_state_qubits, breakpoints, slopes, offsets): qr_state = QuantumRegister(num_state_qubits, name='state') qr_target = QuantumRegister(1, name='target') circuit = AncillaCircuit(qr_state, qr_target) mapped_slopes = np.zeros_like(slopes) for i, slope in enumerate(slopes): mapped_slopes[i] = slope - sum(mapped_slopes[:i]) mapped_offsets = np.zeros_like(offsets) for i, (offset, slope, point) in enumerate(zip(offsets, slopes, breakpoints)): mapped_offsets[i] = offset - slope * point - sum(mapped_offsets[:i]) basis = 'Y' # apply comparators and controlled linear rotations for i, point in enumerate(breakpoints): if i == 0 and _contains_zero_breakpoint(breakpoints): # apply rotation lin_r = LinearPauliRotations(num_state_qubits=num_state_qubits, slope=mapped_slopes[i], offset=mapped_offsets[i], basis='Y') circuit.append(lin_r.to_gate(), qr_state[:] + [qr_target]) else: comp_ancilla = circuit.new_ancilla_register(1, name='ac' + str(i)) circuit.append( makeIntegerComparator(num_state_qubits, point).to_ancilla_gate(), [*qr_state[:], comp_ancilla[0]]) # apply controlled rotation lin_r = LinearPauliRotations(num_state_qubits=num_state_qubits, slope=mapped_slopes[i], offset=mapped_offsets[i], basis=basis) circuit.append(lin_r.to_gate().control(), [comp_ancilla[0]] + qr_state[:] + [qr_target]) return circuit
def GroverQpp( n, oracle ): # oracle should be an ancilla gate on n + 1 qb, result in last qb _num_iterations = int(np.floor(np.pi / 4.0 * np.sqrt(pow(2, n)))) def _construct_diffusion_circuit(): num_variable_qubits = n var_reg2 = QuantumRegister(num_variable_qubits) qc = AncillaCircuit(var_reg2) qc.h(var_reg2) qc.u(np.pi, 0, np.pi, var_reg2) qc.u(np.pi / 2, 0, np.pi, var_reg2[-1]) qc.mcx(var_reg2[:-1], var_reg2[-1]) qc.u(np.pi / 2, 0, np.pi, var_reg2[-1]) qc.u(np.pi, 0, np.pi, var_reg2) qc.h(var_reg2) return qc def qc_amplitude_amplification_iteration(): reg = QuantumRegister(n + 1, name='reg') _qc_aa_iteration = AncillaCircuit(QuantumRegister(n + 1)) _qc_aa_iteration.append(oracle, reg) _qc_aa_iteration.append( _construct_diffusion_circuit().to_ancilla_gate(), reg[:-1]) return _qc_aa_iteration var_reg = QuantumRegister(n, name='var_reg') out_reg = QuantumRegister(1, name='out_reg') qc = AncillaCircuit(var_reg, out_reg) qc.u(np.pi, 0, np.pi, out_reg) # x qc.u(np.pi / 2, 0, np.pi, out_reg) # h qc.h(var_reg) for _ in range(_num_iterations): qc.append(qc_amplitude_amplification_iteration().to_ancilla_gate(), [*var_reg, out_reg]) return (qc, var_reg)
def mcx(): x = QuantumRegister(10) r = QuantumRegister(1) circuit = AncillaCircuit(x, r) circuit.mcx(x[:], r) circuit = circuit.circuitWithUncomputation() nb_qb_mi = circuit.num_qubits nb_gates_mi = circuit.decompose().decompose().decompose().decompose( ).decompose().count_ops() print("MCX " + str(nb_qb_mi) + ';' + str(nb_gates_mi['cx'] + nb_gates_mi['u3']) + ';' + str(nb_gates_mi['cx']))
def makesAdder(num_qubits): #[a, b]: b = a + b, a and b made of num_qubits each # returns an AncillaCircuit, without uncomputation def neg_mct_gate(): neg_mct = AncillaCircuit(4) neg_mct.cx(1, 2) neg_mct.ccx(0, 2, 3) neg_mct.cx(1, 2) return neg_mct.to_ancilla_gate(True) def carry_gate(): carry_circ = AncillaCircuit(4) (c0, a, b, c1) = (carry_circ.qubits[0], carry_circ.qubits[1], carry_circ.qubits[2], carry_circ.qubits[3]) carry_circ.ccx(a, b, c1) carry_circ.append(neg_mct_gate(), [c0, a, b, c1]) return carry_circ.to_ancilla_gate() def sum_gate(): sum_circ = AncillaCircuit(3) (c0, a, b) = (sum_circ.qubits[0], sum_circ.qubits[1], sum_circ.qubits[2]) sum_circ.cx(a, b) sum_circ.cx(c0, b) return sum_circ.to_ancilla_gate() a = QuantumRegister(num_qubits, name="a") b = QuantumRegister(num_qubits, name="b") c = AncillaRegister(num_qubits, name="c") circuit = AncillaCircuit(a, b, c) for i in range(num_qubits - 1): circuit.append(carry_gate(), [c[i], a[i], b[i], c[i + 1]]) circuit.append(sum_gate(), [c[i], a[i], b[i]]) circuit.append(sum_gate(), [c[num_qubits - 1], a[num_qubits - 1], b[num_qubits - 1]]) return circuit
def makesMult(num_qubits): #[x, y, b] b = x * y; x, y, and b all made of num_qubits each #returns an AncillaCircuit, without uncomputation b = QuantumRegister(num_qubits) y = QuantumRegister(num_qubits) x = QuantumRegister(num_qubits) circuit = AncillaCircuit(b, y, x) for i, x_i in enumerate(x): # a = (y*(2**i))*x_i a = circuit.new_ancilla_register(num_qubits) for a_qubit, y_qubit in zip(a[i:], y[:num_qubits - i]): circuit.ccx(x_i, y_qubit, a_qubit) # b += a circuit.append( makesAdder(num_qubits).to_ancilla_gate(), [*a[:], *b[:]]) return circuit
def mcry(relative_numbers): from unqomp.ancillaallocation import AncillaCircuit from qiskit import QuantumRegister, QuantumCircuit from unqomp.examples.mcx import makeQiskitMCRY n = 12 ctrls = QuantumRegister(n, 'ctrls') target = QuantumRegister(1, 'target') circuit1 = AncillaCircuit(ctrls, target) circuit1.mcry(2.0, ctrls, target) circuit1 = circuit1.circuitWithUncomputation() qiskitMCRY = makeQiskitMCRY(2.0, n) print('MCRY with regression bug ; ', end = '') #qiskit buggy ctrls2 = QuantumRegister(n, 'ctrls') target2 = QuantumRegister(1, 'target') anc = QuantumRegister(n - 2, 'anc') circuit2 = QuantumCircuit(ctrls2, target2, anc) circuit2.mcry(2.0, ctrls2,target2[0], anc, mode = 'basic') nb_qb_qi = circuit2.num_qubits nb_gates_qi = circuit2.decompose().decompose().decompose().decompose().decompose().count_ops() if not relative_numbers: print(str(nb_qb_qi) + ' ; ' + str(nb_gates_qi['cx'] + nb_gates_qi['u3']) + ' ; ' + str(nb_gates_qi['cx']) + str(' ; '), end = '') nb_qb_mi = circuit1.num_qubits nb_gates_mi = circuit1.decompose().decompose().decompose().decompose().decompose().count_ops() if not relative_numbers: print(str(nb_qb_mi) + ' ; ' + str(nb_gates_mi['cx'] + nb_gates_mi['u3']) + ' ; ' + str(nb_gates_mi['cx'])) if relative_numbers: print_relative_vals(nb_qb_qi, nb_gates_qi['cx'], nb_gates_qi['u3'], nb_qb_mi, nb_gates_mi['cx'], nb_gates_mi['u3']) #qiskit with bug fixed nb_qb_qi = qiskitMCRY.num_qubits nb_gates_qi = qiskitMCRY.decompose().decompose().decompose().decompose().decompose().count_ops() print('MCRY *, regression bug fixed ; ', end = '') if not relative_numbers: print(str(nb_qb_qi) + ' ; ' + str(nb_gates_qi['cx'] + nb_gates_qi['u3']) + ' ; '+ str(nb_gates_qi['cx']) + str(' ; '), end = '') print(str(nb_qb_mi) + ' ; ' + str(nb_gates_mi['cx'] + nb_gates_mi['u3']) + ' ; ' + str(nb_gates_mi['cx'])) else: print_relative_vals(nb_qb_qi, nb_gates_qi['cx'], nb_gates_qi['u3'], nb_qb_mi, nb_gates_mi['cx'], nb_gates_mi['u3'])
def mcry(nb_vars_max=40): from unqomp.ancillaallocation import AncillaCircuit from qiskit import QuantumRegister, QuantumCircuit from unqomp.examples.mcx import makeQiskitMCRY nb_vars_t = [] nb_qb_qi = [] nb_qb_mi = [] nb_qb_bq = [] nb_gates_qi = [] nb_gates_mi = [] nb_gates_bq = [] for nb_vars in range(3, nb_vars_max, 1): n = nb_vars ctrls = QuantumRegister(n, 'ctrls') target = QuantumRegister(1, 'target') circuit1 = AncillaCircuit(ctrls, target) circuit1.mcry(0.2, ctrls, target) circuit1 = circuit1.circuitWithUncomputation() qiskitMCX = makeQiskitMCRY(0.2, n) nb_vars_t.append(nb_vars) #qiskit nb_qb_qi.append(qiskitMCX.num_qubits) nb_gates_qi.append(qiskitMCX.decompose().decompose().decompose(). decompose().decompose().count_ops()) #mine nb_qb_mi.append(circuit1.num_qubits) nb_gates_mi.append(circuit1.decompose().decompose().decompose(). decompose().decompose().count_ops()) #qiskit buggy if n < 15: ctrls2 = QuantumRegister(n, 'ctrls') target2 = QuantumRegister(1, 'target') anc = QuantumRegister(n - 2, 'anc') circuit2 = QuantumCircuit(ctrls2, target2, anc) circuit2.mcry(0.2, ctrls2, target2[0], anc, mode='basic') nb_qb_bq.append(circuit2.num_qubits) nb_gates_bq.append(circuit2.decompose().decompose().decompose(). decompose().decompose().count_ops()) else: nb_qb_bq.append(0) nb_gates_bq.append({'u3': 0, 'cx': 0}) with open('evaluation/plot_values/mcry.csv', 'w') as f: sys.stdout = f print( "input size; n_qb Qiskit without regression bug; n_gates Qiskit without regression bug; n_cx_gates Qiskitwithout regression bug; n_qb Unqomp; n_gates Unqomp ; n_cx_gates Uncomp; n_qb Qiskit with regression bug; n_gates Qiskit with regression bug ; n_cx_gates Qiskit with regression bug" ) for i in range(len(nb_vars_t)): print(nb_vars_t[i], ";", nb_qb_qi[i], ";", nb_gates_qi[i]['u3'] + nb_gates_qi[i]['cx'], ";", nb_gates_qi[i]['cx'], ";", nb_qb_mi[i], ";", nb_gates_mi[i]['u3'] + nb_gates_mi[i]['cx'], ";", nb_gates_mi[i]['cx'], ";", nb_qb_bq[i], ";", nb_gates_bq[i]['u3'] + nb_gates_bq[i]['cx'], ";", nb_gates_bq[i]['cx']) sys.stdout = original_stdout
def neg_mct_gate(): neg_mct = AncillaCircuit(4) neg_mct.cx(1, 2) neg_mct.ccx(0, 2, 3) neg_mct.cx(1, 2) return neg_mct.to_ancilla_gate(True)
def makesPolyPauliRot(num_state_qubits=None, coeffs=None): # basis is y degree = len(coeffs) - 1 qr_state = QuantumRegister(num_state_qubits, name='state') qr_target = QuantumRegister(1, name='target') def _get_rotation_coefficients(): """Compute the coefficient of each monomial. Returns: A dictionary with pairs ``{control_state: rotation angle}`` where ``control_state`` is a tuple of ``0`` or ``1`` bits. """ # determine the control states all_combinations = list(product([0, 1], repeat=num_state_qubits)) valid_combinations = [] for combination in all_combinations: if 0 < sum(combination) <= degree: valid_combinations += [combination] rotation_coeffs = { control_state: 0 for control_state in valid_combinations } # compute the coefficients for the control states for i, coeff in enumerate(coeffs[1:]): i += 1 # since we skip the first element we need to increase i by one # iterate over the multinomial coefficients for comb, num_combs in _multinomial_coefficients( num_state_qubits, i).items(): control_state = () power = 1 for j, qubit in enumerate(comb): if qubit > 0: # means we control on qubit i control_state += (1, ) power *= 2**(j * qubit) else: control_state += (0, ) # Add angle rotation_coeffs[control_state] += coeff * num_combs * power return rotation_coeffs circuit = AncillaCircuit(qr_state, qr_target) rotation_coeffs = _get_rotation_coefficients() circuit.ry(coeffs[0], qr_target) for c in rotation_coeffs: qr_control = [] for i, _ in enumerate(c): if c[i] > 0: qr_control.append(qr_state[i]) # apply controlled rotations if len(qr_control) > 1: circuit.mcry(rotation_coeffs[c], qr_control, qr_target) elif len(qr_control) == 1: circuit.cry(rotation_coeffs[c], qr_control[0], qr_target) return circuit
def makesAdder(num_qubits): #[a, b, s]: s = a + b, a and b made of num_qubits each # returns an AncillaCircuit, without uncomputation def neg_mct_gate(lneg): neg_mct = AncillaCircuit(3) for i in lneg: neg_mct.x(i) neg_mct.ccx(0, 1, 2) for i in lneg: neg_mct.x(i) return neg_mct.to_ancilla_gate(True) a = QuantumRegister(num_qubits, name="a") b = QuantumRegister(num_qubits, name="b") s = QuantumRegister(num_qubits, name="s") c = AncillaRegister(num_qubits, name="c") circuit = AncillaCircuit(a, b, s, c) for i in range(num_qubits - 1): #sum t = circuit.new_ancilla_register(1, name='t' + str(i)) circuit.cx(a[i], t) circuit.cx(b[i], t) #to be quipper like circuit.cx(t, s[i]) circuit.cx(c[i], s[i]) #carry v = circuit.new_ancilla_register(1, name='v' + str(i)) circuit.append(neg_mct_gate([0, 1]), [a[i], b[i], v]) circuit.append(neg_mct_gate([1]), [v, c[i], c[i + 1]]) circuit.x(c[i + 1]) circuit.cx(a[num_qubits - 1], s[num_qubits - 1]) circuit.cx(b[num_qubits - 1], s[num_qubits - 1]) circuit.cx(c[num_qubits - 1], s[num_qubits - 1]) return circuit
def makesDJ(num_qubits, oracle_gate=None): #Builds the Deutsch Jozsa circuit for n + 1 qubits, finding the value 111...111 var_reg = QuantumRegister(num_qubits, name='vals') out_reg = QuantumRegister(1, name='out') circ = AncillaCircuit(var_reg, out_reg) circ.h(var_reg) circ.x(out_reg) circ.h(out_reg) if oracle_gate: circ.append(oracle_gate, [*var_reg, out_reg[0]]) else: circ.mcx(var_reg, out_reg) circ.h(var_reg) return (circ, var_reg)
def makesGroverCircuit(n, oracle=None, nb_sols=1): # grover circuit on n qubits, without measurements as uncomp cannot deal with that yet nbIter = int(np.floor(np.pi / 4.0 * np.sqrt(pow(2, n)))) working_qubits = QuantumRegister(n, name='r') phase_qubit = QuantumRegister(1, name='p') circ = AncillaCircuit(working_qubits, phase_qubit) circ.x(phase_qubit[0]) circ.h(phase_qubit[0]) circ.h(working_qubits) for l in range(nbIter): if oracle: circ.append(oracle, [*working_qubits[:], phase_qubit[0]]) else: circ.mcx(working_qubits, phase_qubit) #Grover diffusion operator circ.h(working_qubits) circ.x(working_qubits) circ.h(working_qubits[-1]) circ.mcx(working_qubits[:-1], working_qubits[-1]) circ.h(working_qubits[-1]) circ.x(working_qubits) circ.h(working_qubits) # bring the phase qubit back to 0, we can't uncompute it, as it went through cz, non qfree -> no need to uncomp it, Qiskit doesn't #circ.h(phase_qubit[0]) #circ.x(phase_qubit) return (circ, working_qubits)
def _construct_diffusion_circuit(): num_variable_qubits = n var_reg2 = QuantumRegister(num_variable_qubits) qc = AncillaCircuit(var_reg2) qc.h(var_reg2) qc.u(np.pi, 0, np.pi, var_reg2) qc.u(np.pi / 2, 0, np.pi, var_reg2[-1]) qc.mcx(var_reg2[:-1], var_reg2[-1]) qc.u(np.pi / 2, 0, np.pi, var_reg2[-1]) qc.u(np.pi, 0, np.pi, var_reg2) qc.h(var_reg2) return qc
def makeWeightedAdderWOExtraCtrlsQb(num_state_qubits, weights): # Implementation using Unqomp but enforcing local uncomputation, uses less qubits, but is not fully modular, ancillas have to be taken care of manually def neg_mct_gate(negated_ctrls): #circuit.mcx([q_state, qr_sum[j], qr_carry[j - 1]], qr_carry[j], negated_ctrls = [1, 2]) ctrls = QuantumRegister(3) anc = QuantumRegister(1) targ = QuantumRegister(1) neg_mct = QuantumCircuit(ctrls, anc, targ) #[ctrl0...ctrl3, anc, targ] for i in negated_ctrls: neg_mct.x(ctrls[i]) neg_mct.mcx(ctrls, targ, anc, mode='basic') for i in negated_ctrls: neg_mct.x(ctrls[i]) return neg_mct.to_gate() num_sum_qubits = int(np.floor(np.log2(sum(weights))) + 1) if sum(weights) > 0 else 1 # The number of sum qubits in the circuit num_carry_qubits = num_sum_qubits - 1 # The number of carry qubits required to compute the sum. for i, weight in enumerate(weights): if not np.isclose(weight, np.round(weight)): raise ValueError('Non-integer weights are not supported!') weights[i] = np.round(weight) num_result_qubits = num_state_qubits + num_sum_qubits qr_state = QuantumRegister(num_state_qubits, name='state') qr_sum = QuantumRegister(num_sum_qubits, name='sum') qr_ctrl = QuantumRegister(1, name='ctrl') circuit = AncillaCircuit(qr_state, qr_sum, qr_ctrl) neg_mct_g = neg_mct_gate([1, 2]) mct_g = neg_mct_gate([]) circuit.addQfreeGate(neg_mct_g) circuit.addQfreeGate(mct_g) # loop over state qubits and corresponding weights for i, weight in enumerate(weights): # only act if non-trivial weight if np.isclose(weight, 0): continue # get state control qubit q_state = qr_state[i] # get bit representation of current weight weight_binary = '{0:b}'.format(int(weight)).rjust(num_sum_qubits, '0')[::-1] #print("carry qb" + str(num_carry_qubits)) qr_carry = circuit.new_ancilla_register(num_carry_qubits, name="anccarryite" + str(i)) # loop over bits of current weight and add them to sum and carry registers for j, bit in enumerate(weight_binary): if bit == '1': if num_sum_qubits == 1: circuit.cx(q_state, qr_sum[j]) elif j == 0: # compute (q_sum[0] + 1) into (q_sum[0], q_carry[0]) # - controlled by q_state[i] circuit.ccx(q_state, qr_sum[j], qr_carry[j]) circuit.cx(q_state, qr_sum[j]) elif j == num_sum_qubits - 1: # compute (q_sum[j] + q_carry[j-1] + 1) into (q_sum[j]) # - controlled by q_state[i] / last qubit, # no carry needed by construction circuit.cx(q_state, qr_sum[j]) circuit.ccx(q_state, qr_carry[j - 1], qr_sum[j]) else: # compute (q_sum[j] + q_carry[j-1] + 1) into (q_sum[j], q_carry[j]) # - controlled by q_state[i] circuit.append(neg_mct_g, [ q_state, qr_sum[j], qr_carry[j - 1], qr_ctrl, qr_carry[j] ]) circuit.cx(q_state, qr_carry[j]) circuit.cx(q_state, qr_sum[j]) circuit.ccx(q_state, qr_carry[j - 1], qr_sum[j]) else: if num_sum_qubits == 1: pass # nothing to do, since nothing to add elif j == 0: pass # nothing to do, since nothing to add elif j == num_sum_qubits - 1: # compute (q_sum[j] + q_carry[j-1]) into (q_sum[j]) # - controlled by q_state[i] / last qubit, # no carry needed by construction circuit.ccx(q_state, qr_carry[j - 1], qr_sum[j]) else: # compute (q_sum[j] + q_carry[j-1]) into (q_sum[j], q_carry[j]) # - controlled by q_state[i] circuit.append(mct_g, [ q_state, qr_sum[j], qr_carry[j - 1], qr_ctrl, qr_carry[j] ]) circuit.ccx(q_state, qr_carry[j - 1], qr_sum[j]) return circuit
def makeIntegerComparator(num_state_qubits, value, geq=True, with_uncomp=True): """Build the comparator circuit.""" or_gate = OR(2).to_gate() qr_state = QuantumRegister(num_state_qubits, name='state') q_compare = QuantumRegister(1, name='compare') circuit = AncillaCircuit(qr_state, q_compare) circuit.addQfreeGate(or_gate) qr_ancilla = circuit.new_ancilla_register( num_state_qubits - 1, name='ancilla') if num_state_qubits > 1 else None if value <= 0: # condition always satisfied for non-positive values if geq: # otherwise the condition is never satisfied circuit.x(q_compare) # condition never satisfied for values larger than or equal to 2^n elif value < pow(2, num_state_qubits): if num_state_qubits > 1: twos = _get_twos_complement(num_state_qubits, value) for i in range(num_state_qubits): if i == 0: if twos[i] == 1: circuit.cx(qr_state[i], qr_ancilla[i]) elif i < num_state_qubits - 1: if twos[i] == 1: circuit.append( or_gate, [qr_state[i], qr_ancilla[i - 1], qr_ancilla[i]]) else: circuit.ccx(qr_state[i], qr_ancilla[i - 1], qr_ancilla[i]) else: if twos[i] == 1: circuit.append( or_gate, [qr_state[i], qr_ancilla[i - 1], q_compare]) else: circuit.ccx(qr_state[i], qr_ancilla[i - 1], q_compare) # flip result bit if geq flag is false if not geq: circuit.x(q_compare) else: # num_state_qubits == 1 and value == 1: circuit.cx(qr_state[0], q_compare) # flip result bit if geq flag is false if not geq: circuit.x(q_compare) else: if not geq: # otherwise the condition is never satisfied circuit.x(q_compare) return circuit
def makeWeightedAdder(num_state_qubits, weights): # Straightforward implementation using Unqomp, uses less gate but more qubits num_sum_qubits = int(np.floor(np.log2(sum(weights))) + 1) if sum(weights) > 0 else 1 # The number of sum qubits in the circuit num_carry_qubits = num_sum_qubits - 1 # The number of carry qubits required to compute the sum. for i, weight in enumerate(weights): if not np.isclose(weight, np.round(weight)): raise ValueError('Non-integer weights are not supported!') weights[i] = np.round(weight) num_result_qubits = num_state_qubits + num_sum_qubits qr_state = QuantumRegister(num_state_qubits, name='state') qr_sum = QuantumRegister(num_sum_qubits, name='sum') circuit = AncillaCircuit(qr_state, qr_sum) #print(num_state_qubits) #print(num_sum_qubits) # loop over state qubits and corresponding weights for i, weight in enumerate(weights): # only act if non-trivial weight if np.isclose(weight, 0): continue # get state control qubit q_state = qr_state[i] # get bit representation of current weight weight_binary = '{0:b}'.format(int(weight)).rjust(num_sum_qubits, '0')[::-1] #print("carry qb" + str(num_carry_qubits)) qr_carry = circuit.new_ancilla_register(num_carry_qubits, name="anccarryite" + str(i)) # loop over bits of current weight and add them to sum and carry registers for j, bit in enumerate(weight_binary): if bit == '1': if num_sum_qubits == 1: circuit.cx(q_state, qr_sum[j]) elif j == 0: # compute (q_sum[0] + 1) into (q_sum[0], q_carry[0]) # - controlled by q_state[i] circuit.ccx(q_state, qr_sum[j], qr_carry[j]) circuit.cx(q_state, qr_sum[j]) elif j == num_sum_qubits - 1: # compute (q_sum[j] + q_carry[j-1] + 1) into (q_sum[j]) # - controlled by q_state[i] / last qubit, # no carry needed by construction circuit.cx(q_state, qr_sum[j]) circuit.ccx(q_state, qr_carry[j - 1], qr_sum[j]) else: # compute (q_sum[j] + q_carry[j-1] + 1) into (q_sum[j], q_carry[j]) # - controlled by q_state[i] circuit.mcx([q_state, qr_sum[j], qr_carry[j - 1]], qr_carry[j], negated_ctrls=[1, 2]) circuit.cx(q_state, qr_carry[j]) circuit.cx(q_state, qr_sum[j]) circuit.ccx(q_state, qr_carry[j - 1], qr_sum[j]) else: if num_sum_qubits == 1: pass # nothing to do, since nothing to add elif j == 0: pass # nothing to do, since nothing to add elif j == num_sum_qubits - 1: # compute (q_sum[j] + q_carry[j-1]) into (q_sum[j]) # - controlled by q_state[i] / last qubit, # no carry needed by construction circuit.ccx(q_state, qr_carry[j - 1], qr_sum[j]) else: # compute (q_sum[j] + q_carry[j-1]) into (q_sum[j], q_carry[j]) # - controlled by q_state[i] circuit.mcx([q_state, qr_sum[j], qr_carry[j - 1]], qr_carry[j]) circuit.ccx(q_state, qr_carry[j - 1], qr_sum[j]) return circuit