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