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 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 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 _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 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 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 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