Пример #1
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)
Пример #2
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()
Пример #3
0
 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()
Пример #4
0
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
Пример #5
0
 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
Пример #6
0
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'])
Пример #7
0
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()
Пример #8
0
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
Пример #9
0
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)
Пример #10
0
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']))
Пример #11
0
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
Пример #12
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
Пример #13
0
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'])
Пример #14
0
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
Пример #15
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)
Пример #16
0
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
Пример #17
0
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
Пример #18
0
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)
Пример #19
0
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)
Пример #20
0
    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
Пример #21
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
Пример #22
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
Пример #23
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