예제 #1
0
    def test_missing_qubits(self):
        """Test that an error is raised if qubits are missing."""
        with self.subTest(msg="no control qubits"):
            with self.assertRaises(AttributeError):
                _ = MCMT(XGate(), num_ctrl_qubits=0, num_target_qubits=1)

        with self.subTest(msg="no target qubits"):
            with self.assertRaises(AttributeError):
                _ = MCMT(ZGate(), num_ctrl_qubits=4, num_target_qubits=0)
예제 #2
0
 def test_different_gate_types(self):
     """Test the different supported input types for the target gate."""
     x_circ = QuantumCircuit(1)
     x_circ.x(0)
     for input_gate in [x_circ, QuantumCircuit.cx, QuantumCircuit.x, "cx", "x", CXGate()]:
         with self.subTest(input_gate=input_gate):
             mcmt = MCMT(input_gate, 2, 2)
             if isinstance(input_gate, QuantumCircuit):
                 self.assertEqual(mcmt.gate.definition[0][0], XGate())
                 self.assertEqual(len(mcmt.gate.definition), 1)
             else:
                 self.assertEqual(mcmt.gate, XGate())
def controlled_controlled_minus_iY():

    target = QuantumRegister(1,'t_qbit')
    register = QuantumRegister(2,'r_qbit')
    ancillae = QuantumRegister(1,'a_qbit')
    or_qubit = QuantumRegister(1,'o_qbit')
    qc = QuantumCircuit(or_qubit,register,ancillae,target)

    qc.ccx(or_qubit,register[0],ancillae[0])
    qc.append(MCMT(minus_iY(),2,1),[ancillae[-1],register[-1],target])
    qc.ccx(or_qubit,register[0],ancillae[0])

    return qc.to_instruction()
def controlled_U(theta):
    """
    Controlled post-select unitary U
    """
    new_qubit = QuantumRegister(1, 'n_qbit')
    old_qubit = QuantumRegister(1, 'o_qbit')
    target = QuantumRegister(1, 't_qbit')

    qc = QuantumCircuit(old_qubit, new_qubit, target)

    qc.ry(2 * theta, new_qubit)
    qc.append(MCMT(minus_iY(), 2, 1), [old_qubit, new_qubit, target])
    qc.ry(-2 * theta, new_qubit)

    return qc.to_instruction()
def U(theta):

    """
    Post-select unitary U
    """
    register = QuantumRegister(2,'a_qbit')
    target = QuantumRegister(1,'t_qbit')

    qc = QuantumCircuit(register,target)

    qc.ry(2*theta,[*register])
    qc.append(MCMT(minus_iY(),2,1),[*register,*target])
    qc.ry(-2*theta,[*register])

    return qc.to_instruction()
def U(theta):
    """
    Post-select unitary U
    """

    ancillae = QuantumRegister(1, 'a_qbit')
    target = QuantumRegister(1, 't_qbit')

    qc = QuantumCircuit(ancillae, target)

    qc.ry(2 * theta, [*ancillae])
    qc.append(MCMT(minus_iY(), 1, 1),
              [*ancillae, *target])  #qc.u3(np.pi,0,0) = -iY
    qc.ry(-2 * theta, [*ancillae])

    return qc.to_instruction()
def add_cnry(
    param: float,
    qbits: List[int],
    qr: QuantumRegister,
    circuits: List[Union[Circuit, QuantumCircuit]],
) -> None:
    """Add a CnRy gate to each circuit in a list,
    each one being either a tket or qiskit circuit."""
    assert len(qbits) >= 2
    for circ in circuits:
        if isinstance(circ, Circuit):
            circ.add_gate(OpType.CnRy, param, qbits)
        else:
            # param was "raw", so needs an extra PI.
            new_ry_gate = RYGate(param * pi)
            new_gate = MCMT(gate=new_ry_gate,
                            num_ctrl_qubits=len(qbits) - 1,
                            num_target_qubits=1)
            circ.append(new_gate, [qr[nn] for nn in qbits])
    def S_m():

        """
        Reflection operator S_m(pi/3)
        """

        def phase_shift():
            S = Operator(np.array([[1,0],[0,np.exp(1j*np.pi/3)]]))
            target = QuantumRegister(1,'t_qbit')
            qc = QuantumCircuit(target)
            qc.unitary(S,[*target])
            return qc


        target_register = QuantumRegister(1,'ta_qbit')
        register = QuantumRegister(1,'r_qbit')
        qc = QuantumCircuit(target_register,register)

        qc.x([*register,*target_register])
        qc.append(MCMT(phase_shift(),1,1),[*register,*target_register])
        qc.x([*register,*target_register])
        return qc.to_instruction()
예제 #9
0
        def ram(nqubits, lists_final):
            list_qram = [i for i in range(nqubits)]
            qram = QuantumRegister(nqubits, "qram")
            qalgo = QuantumRegister(nqubits, "algo")
            qc = QuantumCircuit(qram, qalgo)

            control_h = MCMT("h", nqubits, 1).to_gate()

            map_ram_2 = [["x", "x"], ["o", "x"], ["x", "o"], ["o", "o"]]
            map_ram_3 = [
                ["x", "x", "x"],
                ["o", "x", "x"],
                ["x", "o", "x"],
                ["o", "o", "x"],
                ["x", "x", "o"],
                ["o", "x", "o"],
                ["x", "o", "o"],
                ["o", "o", "o"],
            ]
            if len(bin(len(lists_final))[2:]) == 3:
                map_ram = map_ram_3
            if len(bin(len(lists_final))[2:]) == 2:
                map_ram = map_ram_2

            for i, m_ram in zip(range(len(lists_final)), map_ram):
                # qc.barrier()
                for index, gate in enumerate(m_ram):
                    if gate == "x":
                        qc.x(qram[index])

                if lists_final[i][0] == "x" or lists_final[i][0] == "sup":
                    qc.mcx(qram, qalgo[0])
                else:
                    qc.append(control_h, [*list_qram, qalgo[0]])

                if len(lists_final[i]) == 3:
                    if lists_final[i][1] == "x":
                        qc.mcx(qram, qalgo[1])
                    elif lists_final[i][1] == "intric":
                        qc.mcx([qram[0], qram[1], qram[2], qalgo[0]], qalgo[1])
                    else:
                        qc.append(control_h, [*list_qram, qalgo[1]])

                if lists_final[i][-1] == "x":
                    qc.mcx(qram, qalgo[-1])
                elif lists_final[i][-1] == "intric":
                    if len(lists_final[i]) == 3:
                        qc.mcx([qram[0], qram[1], qram[2], qalgo[1]],
                               qalgo[-1])
                    else:
                        qc.mcx([qram[0], qram[1], qalgo[0]], qalgo[-1])
                else:
                    qc.append(control_h, [*list_qram, qalgo[-1]])

                for index, gate in enumerate(m_ram):
                    if gate == "x":
                        qc.x(qram[index])

            # print(qc.draw())
            U_s = qc.to_gate()
            U_s.name = "$Qram$"
            return U_s
def experiment(p, t, measure_type=None, noise_model=None):

    n_register_qubits = t + p * t
    n_state_qubits = 1
    n_or_qubits = (p + 1) * (t - 1
                             )  #additional OR gates for scrambling at the end

    register_qubits = QuantumRegister(n_register_qubits, 'r_qbit')
    state_qubits = QuantumRegister(n_state_qubits, 's_qbit')
    or_qubits = QuantumRegister(n_or_qubits, 'o_qbit')
    c = ClassicalRegister(1)

    circ = QuantumCircuit(register_qubits, or_qubits, state_qubits, c)

    circ.h(state_qubits)  #initial input state

    circ.h(register_qubits)

    #Initial Round

    #Controlled Unitary
    for i, q in enumerate(register_qubits[:t][::-1]):
        circ.append(MCMT(Unitary(i), 1, 1), [q, state_qubits])

    #QFT-dagger
    for qubit in range(int(t / 2)):
        circ.swap(qubit, t - qubit - 1)
    for j in range(t, 0, -1):
        k = t - j
        for m in range(k):
            circ.cu1(-np.pi / float(2**(k - m)), t - m - 1, t - k - 1)
        circ.h(t - k - 1)

    #OR-Gate
    circ.x([*register_qubits[:t], *or_qubits[:t - 1]])
    circ.ccx(register_qubits[0], register_qubits[1], or_qubits[0])
    for i in range(t - 2):
        circ.x(or_qubits[i])
        circ.ccx(or_qubits[i], register_qubits[i + 2], or_qubits[i + 1])

    #Reset / Scrambling gate
    circ.ch(or_qubits[t - 2], state_qubits)

    #Subsequent Rounds
    for j in range(1, p + 1):

        #CCU
        for i, q in enumerate(register_qubits[t * j:t * (j + 1)][::-1]):
            #circ.append(MCMT(Unitary(i),2,1),[or_qubits[j-1],q,state_qubits])
            circ.x(q)
            circ.cx(or_qubits[j - 1], q)
            circ.append(MCMT(Unitary(i), 1, 1), [q, state_qubits])

        #QFT-dagger
        for qubit in range(int(t / 2)):
            circ.swap(qubit + t * j, t - qubit - 1 + t * j)
        for f in range(t, 0, -1):
            k = t - f
            for m in range(k):
                circ.cu1(-np.pi / float(2**(k - m)), t - m - 1 + t * j,
                         t - k - 1 + t * j)
            circ.h(t - k - 1 + t * j)

        #Or Gate
        circ.x([
            *register_qubits[t * j:t * (j + 1)],
            *or_qubits[(t - 1) * j:(t - 1) * (j + 1)]
        ])
        circ.ccx(register_qubits[t * j], register_qubits[t * j + 1],
                 or_qubits[(t - 1) * j])

        for i in range(t - 2):
            circ.x(or_qubits[(t - 1) * j + i])
            circ.ccx(or_qubits[(t - 1) * j + i],
                     register_qubits[t * j + 2 + i],
                     or_qubits[(t - 1) * j + i + 1])

        #Scrambling gate
        circ.ch(or_qubits[(t - 1) * j + t - 2], state_qubits)

    #Pauli Measurements
    if measure_type == 'x':
        circ.h(state_qubits)
    elif measure_type == 'y':
        circ.sdg(state_qubits)
        circ.h(state_qubits)

    circ.measure(state_qubits, c)
    #IBMQ.load_account()
    #provider = IBMQ.get_provider('ibm-q')
    #qcomp = provider.get_backend('ibmq_qasm_simulator')
    qcomp = Aer.get_backend('qasm_simulator')

    shots = 8192

    if noise_model is None:
        job = execute(circ, backend=qcomp, shots=shots)
    else:
        job = execute(circ,
                      backend=qcomp,
                      shots=shots,
                      noise_model=noise_model,
                      basis_gates=noise_model.basis_gates)

    #print(job_monitor(job))
    result = job.result()
    result_dictionary = result.get_counts(circ)

    probs = {}
    for output in ['0', '1']:
        if output in result_dictionary:
            probs[output] = result_dictionary[output]
        else:
            probs[output] = 0

    return (probs['0'] - probs['1']) / shots
예제 #11
0
def append_tk_command_to_qiskit(
    op: "Op",
    args: List["UnitID"],
    qcirc: QuantumCircuit,
    qregmap: Dict[str, QuantumRegister],
    cregmap: Dict[str, ClassicalRegister],
    symb_map: Dict[Parameter, sympy.Symbol],
    range_preds: Dict[Bit, Tuple[List["UnitID"], int]],
) -> Instruction:
    optype = op.type
    if optype == OpType.Measure:
        qubit = args[0]
        bit = args[1]
        qb = qregmap[qubit.reg_name][qubit.index[0]]
        b = cregmap[bit.reg_name][bit.index[0]]
        return qcirc.measure(qb, b)

    if optype == OpType.Reset:
        qb = qregmap[args[0].reg_name][args[0].index[0]]
        return qcirc.reset(qb)

    if optype in [
            OpType.CircBox, OpType.ExpBox, OpType.PauliExpBox, OpType.Custom
    ]:
        subcircuit = op.get_circuit()
        subqc = tk_to_qiskit(subcircuit)
        qargs = []
        cargs = []
        for a in args:
            if a.type == UnitType.qubit:
                qargs.append(qregmap[a.reg_name][a.index[0]])
            else:
                cargs.append(cregmap[a.reg_name][a.index[0]])
        if optype == OpType.Custom:
            instruc = subqc.to_gate()
            instruc.name = op.get_name()
        else:
            instruc = subqc.to_instruction()
        return qcirc.append(instruc, qargs, cargs)
    if optype == OpType.Unitary2qBox:
        qargs = [qregmap[q.reg_name][q.index[0]] for q in args]
        u = op.get_matrix()
        g = UnitaryGate(u, label="u2q")
        return qcirc.append(g, qargs=qargs)
    if optype == OpType.Barrier:
        qargs = [qregmap[q.reg_name][q.index[0]] for q in args]
        g = Barrier(len(args))
        return qcirc.append(g, qargs=qargs)
    if optype == OpType.RangePredicate:
        if op.lower != op.upper:
            raise NotImplementedError
        range_preds[args[-1]] = (args[:-1], op.lower)
        # attach predicate to bit,
        # subsequent conditional will handle it
        return Instruction("", 0, 0, [])
    if optype == OpType.ConditionalGate:
        if args[0] in range_preds:
            assert op.value == 1
            condition_bits, value = range_preds[args[0]]
            del range_preds[args[0]]
            args = condition_bits + args[1:]
            width = len(condition_bits)
        else:
            width = op.width
            value = op.value
        regname = args[0].reg_name
        if len(cregmap[regname]) != width:
            raise NotImplementedError(
                "OpenQASM conditions must be an entire register")
        for i, a in enumerate(args[:width]):
            if a.reg_name != regname:
                raise NotImplementedError(
                    "OpenQASM conditions can only use a single register")
            if a.index != [i]:
                raise NotImplementedError(
                    "OpenQASM conditions must be an entire register in order")
        instruction = append_tk_command_to_qiskit(op.op, args[width:], qcirc,
                                                  qregmap, cregmap, symb_map,
                                                  range_preds)

        instruction.c_if(cregmap[regname], value)
        return instruction
    # normal gates
    qargs = [qregmap[q.reg_name][q.index[0]] for q in args]
    if optype == OpType.CnX:
        return qcirc.mcx(qargs[:-1], qargs[-1])

    # special case
    if optype == OpType.CnRy:
        # might as well do a bit more checking
        assert len(op.params) == 1
        alpha = param_to_qiskit(op.params[0], symb_map)
        assert len(qargs) >= 2
        if len(qargs) == 2:
            # presumably more efficient; single control only
            new_gate = CRYGate(alpha)
        else:
            new_ry_gate = RYGate(alpha)
            new_gate = MCMT(gate=new_ry_gate,
                            num_ctrl_qubits=len(qargs) - 1,
                            num_target_qubits=1)
        qcirc.append(new_gate, qargs)
        return qcirc

    # others are direct translations
    try:
        gatetype = _known_qiskit_gate_rev[optype]
    except KeyError as error:
        raise NotImplementedError("Cannot convert tket Op to Qiskit gate: " +
                                  op.get_name()) from error
    params = [param_to_qiskit(p, symb_map) for p in op.params]
    g = gatetype(*params)
    return qcirc.append(g, qargs=qargs)