예제 #1
0
 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()
예제 #2
0
 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)
예제 #3
0
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
예제 #4
0
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
예제 #5
0
 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)
예제 #6
0
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
예제 #7
0
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