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