Exemple #1
0
def _add_single_qubit_op_to_circuit(cmd: ProjectQCommand,
                                    circ: Circuit) -> bool:
    assert len(cmd.qubits) == 1
    assert len(cmd.qubits[0]) == 1
    qubit_no = cmd.qubits[0][0].id
    new_qubit = False
    if get_control_count(cmd) > 0:
        raise Exception("singleq gate " + str(cmd.gate) + " has " +
                        str(get_control_count(cmd)) + " control qubits")
    else:
        if qubit_no >= circ.n_qubits:
            circ.add_blank_wires(1 + qubit_no - circ.n_qubits)
            new_qubit = True
        if type(cmd.gate) == pqo.MeasureGate:
            bit = Bit("c", qubit_no)
            if bit not in circ.bits:
                circ.add_bit(bit)
            circ.Measure(qubit_no, qubit_no)
            return new_qubit
        elif type(cmd.gate) in (pqo.Rx, pqo.Ry, pqo.Rz):
            op = Op.create(_pq_to_tk_singleqs[type(cmd.gate)],
                           cmd.gate.angle / np.pi)
        else:
            op = Op.create(_pq_to_tk_singleqs[type(cmd.gate)])
        circ.add_gate(Op=op, args=[qubit_no])
    return new_qubit
def pyzx_to_tk(pyzx_circ: pyzxCircuit) -> Circuit:
    """
    Convert a :py:class:`pyzx.Circuit` to a tket :py:class:`Circuit` .
    All PyZX basic gate operations are currently supported by pytket. Run
    `pyzx_circuit_name.to_basic_gates()` before conversion.

    :param pyzx_circ: A circuit to be converted

    :return: The converted circuit
    """
    c = Circuit(pyzx_circ.qubits, name=pyzx_circ.name)
    for g in pyzx_circ.gates:
        if not type(g) in _pyzx_to_tk_gates:
            raise Exception("Cannot parse PyZX gate of type " + g.name +
                            "into tket Circuit")
        op_type = _pyzx_to_tk_gates[type(g)]
        if hasattr(g, "control"):
            qbs = [getattr(g, "control"), getattr(g, "target")]
        else:
            qbs = [getattr(g, "target")]

        if op_type == OpType.Sdg and not getattr(g, "adjoint"):
            op_type = OpType.S
        elif op_type == OpType.Tdg and not getattr(g, "adjoint"):
            op_type = OpType.T

        if hasattr(g, "printphase") and op_type in _parameterised_gates:
            op = Op.create(op_type, g.phase)
        else:
            op = Op.create(op_type)

        c.add_gate(Op=op, args=qbs)
    return c
Exemple #3
0
def test_incrementer() -> None:
    """
    Simulate an 8-bit incrementer
    """
    b = QsharpToffoliSimulatorBackend()
    c = Circuit(8)
    c.add_gate(OpType.CnX, [0, 1, 2, 3, 4, 5, 6, 7])
    c.add_gate(OpType.CnX, [0, 1, 2, 3, 4, 5, 6])
    c.add_gate(OpType.CnX, [0, 1, 2, 3, 4, 5])
    c.add_gate(OpType.CnX, [0, 1, 2, 3, 4])
    c.add_gate(OpType.CnX, [0, 1, 2, 3])
    c.CCX(0, 1, 2)
    c.CX(0, 1)
    c.X(0)

    for x in [0, 23, 79, 198, 255]:  # some arbitrary 8-bit numbers
        circ = Circuit(8)
        # prepare the state corresponding to x
        for i in range(8):
            if (x >> i) % 2 == 1:
                circ.X(i)
        # append the incrementer
        circ.add_circuit(c, list(range(8)))
        circ.measure_all()
        # run the simulator
        b.compile_circuit(circ)
        bits = b.get_shots(circ, 1)[0]
        # check the result
        for i in range(8):
            assert bits[i] == ((x + 1) >> i) % 2
def circuits(
    draw: Callable[[SearchStrategy[Any]], Any],
    n_qubits: SearchStrategy[int] = st.integers(min_value=2, max_value=6),
    depth: SearchStrategy[int] = st.integers(min_value=1, max_value=100),
) -> Circuit:
    total_qubits = draw(n_qubits)
    circuit = Circuit(total_qubits, total_qubits)
    for _ in range(draw(depth)):
        gate = draw(st.sampled_from(list(_GATE_SET)))
        control = draw(st.integers(min_value=0, max_value=total_qubits - 1))
        if gate == OpType.ZZMax:
            target = draw(
                st.integers(min_value=0, max_value=total_qubits - 1).filter(
                    lambda x: x != control
                )
            )
            circuit.add_gate(gate, [control, target])
        elif gate == OpType.Measure:
            circuit.add_gate(gate, [control, control])
            circuit.add_gate(OpType.Reset, [control])
        elif gate == OpType.Rz:
            param = draw(st.floats(min_value=0, max_value=2))
            circuit.add_gate(gate, [param], [control])
        elif gate == OpType.PhasedX:
            param1 = draw(st.floats(min_value=0, max_value=2))
            param2 = draw(st.floats(min_value=0, max_value=2))
            circuit.add_gate(gate, [param1, param2], [control])
    circuit.measure_all()

    return circuit
Exemple #5
0
def test_handles() -> None:
    b = QsharpSimulatorBackend()
    c = Circuit(4)
    c.X(0).X(1).X(2)
    c.add_gate(OpType.CnX, [0, 1, 2, 3])
    c.measure_all()
    b.compile_circuit(c)
    n_shots = 3
    shots = b.get_shots(c, n_shots=n_shots)
    assert all(shots[i, 3] == 1 for i in range(n_shots))
Exemple #6
0
def test_handles() -> None:
    b = QsharpToffoliSimulatorBackend()
    c = Circuit(4)
    c.CX(0, 1)
    c.CCX(0, 1, 2)
    c.add_gate(OpType.CnX, [0, 1, 2, 3])
    c.add_gate(OpType.noop, [2])
    c.X(3)
    c.SWAP(1, 2)
    c.measure_all()
    b.compile_circuit(c)
    shots = b.get_shots(c, n_shots=2)
    assert all(shots[0] == shots[1])
Exemple #7
0
def _aqt_rebase() -> BasePass:
    # CX replacement
    c_cx = Circuit(2)
    c_cx.Ry(0.5, 0)
    c_cx.add_gate(OpType.XXPhase, 0.5, [0, 1])
    c_cx.Ry(1.0, 0).Rx(-0.5, 0).Ry(0.5, 0)
    c_cx.Rx(-0.5, 1)

    # TK1 replacement
    c_tk1 = lambda a, b, c: Circuit(1).Rx(-0.5, 0).Ry(a, 0).Rx(b, 0).Ry(
        c, 0).Rx(0.5, 0)

    return RebaseCustom({OpType.XXPhase}, c_cx, {OpType.Rx, OpType.Ry}, c_tk1)
def test_rebase_singleq() -> None:
    circ = Circuit(1)
    # some arbitrary unitary
    circ.add_gate(OpType.U3, [0.01231, 0.848, 38.200], [0])
    orig_circ = circ.copy()

    _aqt_rebase().apply(circ)

    # TODO use tketsim for this test once available
    u1 = AerUnitaryBackend().get_unitary(orig_circ)
    u2 = AerUnitaryBackend().get_unitary(circ)

    assert np.allclose(u1, u2)
Exemple #9
0
def test_default_pass() -> None:
    b = QsharpToffoliSimulatorBackend()
    for ol in range(3):
        comp_pass = b.default_compilation_pass(ol)
        c = Circuit(4, 4)
        c.CX(0, 1)
        c.CCX(0, 1, 2)
        c.add_gate(OpType.CnX, [0, 1, 2, 3])
        c.add_gate(OpType.noop, [2])
        c.X(3)
        c.SWAP(1, 2)
        c.measure_all()
        comp_pass.apply(c)
        for pred in b.required_predicates:
            assert pred.verify(c)
def test_convert() -> None:
    circ = Circuit(4, 4)
    circ.H(0).CX(0, 1)
    circ.add_gate(OpType.noop, [1])
    circ.CRz(0.5, 1, 2)
    circ.add_barrier([2])
    circ.ZZPhase(0.3, 2, 3).CX(3, 0).Tdg(1)
    circ.Measure(0, 0)
    circ.Measure(1, 2)
    circ.Measure(2, 3)
    circ.Measure(3, 1)

    circ_aqt = tk_to_aqt(circ)
    assert json.loads(circ_aqt[1]) == [0, 3, 1, 2]
    assert all(gate[0] in ["X", "Y", "MS"] for gate in circ_aqt[0])
def pyquil_to_tk(prog: Program) -> Circuit:
    """
    Convert a :py:class:`pyquil.Program` to a tket :py:class:`Circuit` .
    Note that not all pyQuil operations are currently supported by pytket.

    :param prog: A circuit to be converted

    :return: The converted circuit
    """
    tkc = Circuit()
    qmap = {}
    for q in prog.get_qubits():
        uid = Qubit("q", q)
        tkc.add_qubit(uid)
        qmap.update({q: uid})
    cregmap: Dict = {}
    for i in prog.instructions:
        if isinstance(i, Gate):
            try:
                optype = _known_quil_gate[i.name]
            except KeyError as error:
                raise NotImplementedError("Operation not supported by tket: " +
                                          str(i)) from error
            qubits = [qmap[q.index] for q in i.qubits]
            params = [param_from_pyquil(p) for p in i.params]  # type: ignore
            tkc.add_gate(optype, params, qubits)
        elif isinstance(i, Measurement):
            qubit = qmap[i.qubit.index]
            reg = cregmap[i.classical_reg.name]  # type: ignore
            bit = reg[i.classical_reg.offset]  # type: ignore
            tkc.Measure(qubit, bit)
        elif isinstance(i, Declare):
            if i.memory_type == "BIT":
                new_reg = tkc.add_c_register(i.name, i.memory_size)
                cregmap.update({i.name: new_reg})
            elif i.memory_type == "REAL":
                continue
            else:
                raise NotImplementedError("Cannot handle memory of type " +
                                          i.memory_type)
        elif isinstance(i, Pragma):
            continue
        elif isinstance(i, Halt):
            return tkc
        else:
            raise NotImplementedError("PyQuil instruction is not a gate: " +
                                      str(i))
    return tkc
Exemple #12
0
def test_compile() -> None:
    """
    Compile a circuit containing SWAPs and noops down to CnX's
    """
    b = QsharpToffoliSimulatorBackend()
    c = Circuit(4)
    c.CX(0, 1)
    c.CCX(0, 1, 2)
    c.add_gate(OpType.CnX, [0, 1, 2, 3])
    c.add_gate(OpType.noop, [2])
    c.X(3)
    c.SWAP(1, 2)
    c.measure_all()
    b.compile_circuit(c)
    shots = b.get_shots(c, 2)
    assert all(shots[0] == shots[1])
Exemple #13
0
def test_convert() -> None:
    circ = Circuit(4)
    circ.H(0).CX(0, 1)
    circ.add_gate(OpType.noop, [1])
    circ.CRz(0.5, 1, 2)
    circ.add_barrier([2])
    circ.ZZPhase(0.3, 2, 3).CX(3, 0).Tdg(1)
    circ.measure_all()

    RebaseHQS().apply(circ)
    circ_hqs = circuit_to_qasm_str(circ, header="hqslib1")
    qasm_str = circ_hqs.split("\n")[6:-1]
    test = True
    for com in qasm_str:
        test &= any(
            com.startswith(gate)
            for gate in ("rz", "U1q", "ZZ", "measure", "barrier"))
    assert test
Exemple #14
0
def _add_daggered_op_to_circuit(cmd: ProjectQCommand, circ: Circuit) -> bool:
    undaggered_gate = cmd.gate.get_inverse()
    if type(undaggered_gate) == pqo.TGate:
        op = Op.create(OpType.Tdg)
    elif type(undaggered_gate) == pqo.SGate:
        op = Op.create(OpType.Sdg)
    else:
        raise Exception("cannot recognise daggered op of type " +
                        str(cmd.gate))
    qubit_no = cmd.qubits[0][0].id
    assert len(cmd.qubits) == 1
    assert len(cmd.qubits[0]) == 1
    new_qubit = False
    if qubit_no >= circ.n_qubits:
        circ.add_blank_wires(1 + qubit_no - circ.n_qubits)
        new_qubit = True
    circ.add_gate(Op=op, args=[qubit_no])
    return new_qubit
Exemple #15
0
def test_convert() -> None:
    circ = Circuit(3, 3)
    circ.H(0).CX(0, 1)
    circ.add_gate(OpType.XXPhase, 0.12, [1, 2])
    circ.add_gate(OpType.noop, [1])
    circ.add_barrier([2])
    circ.Measure(0, 1)
    circ.Measure(1, 0)
    circ.Measure(2, 2)

    (circ_ionq, measures) = tk_to_ionq(circ)
    assert measures[0] == 1
    assert measures[1] == 0
    assert measures[2] == 2

    assert circ_ionq["qubits"] == 3
    assert circ_ionq["circuit"][0]["gate"] == "h"
    assert circ_ionq["circuit"][1]["gate"] == "cnot"
    assert circ_ionq["circuit"][2]["gate"] == "xx"
def test_aer_default_pass() -> None:
    with open(os.path.join(sys.path[0], "ibmqx2_properties.pickle"),
              "rb") as f:
        properties = pickle.load(f)

    noise_model = NoiseModel.from_backend(properties)
    for nm in [None, noise_model]:
        b = AerBackend(nm)
        for ol in range(3):
            comp_pass = b.default_compilation_pass(ol)
            c = Circuit(3, 3)
            c.H(0)
            c.CX(0, 1)
            c.CSWAP(1, 0, 2)
            c.ZZPhase(0.84, 2, 0)
            c.add_gate(OpType.TK1, [0.2, 0.3, 0.4], [0])
            comp_pass.apply(c)
            c.measure_all()
            for pred in b.required_predicates:
                assert pred.verify(c)
Exemple #17
0
def _add_multi_qubit_op_to_circuit(cmd: ProjectQCommand,
                                   circ: Circuit) -> list:
    assert len(cmd.qubits) > 0
    qubs = [qb for qr in cmd.all_qubits for qb in qr]
    if get_control_count(cmd) < 1:
        raise Exception("multiq gate " + str(cmd.gate) + " has no controls")
    else:
        new_qubits = []
        for q in qubs:
            qubit_no = q.id
            if qubit_no >= circ.n_qubits:
                circ.add_blank_wires(1 + qubit_no - circ.n_qubits)
                new_qubits.append(q)
        if type(cmd.gate) == pqo.CRz:
            op = Op.create(_pq_to_tk_multiqs[type(cmd.gate)],
                           cmd.gate.angle / np.pi)
        else:
            op = Op.create(_pq_to_tk_multiqs[type(cmd.gate)])
        qubit_nos = [qb.id for qr in cmd.all_qubits for qb in qr]
        circ.add_gate(Op=op, args=qubit_nos)
        return new_qubits
def test_aer_expanded_gates() -> None:
    c = Circuit(3).CX(0, 1)
    c.add_gate(OpType.ZZPhase, 0.1, [0, 1])
    c.add_gate(OpType.CY, [0, 1])
    c.add_gate(OpType.CCX, [0, 1, 2])

    backend = AerBackend()
    assert backend.valid_circuit(c)
def test_remote_simulator() -> None:
    remote_qasm = IBMQBackend("ibmq_qasm_simulator",
                              hub="ibm-q",
                              group="open",
                              project="main")
    c = Circuit(3).CX(0, 1)
    c.add_gate(OpType.ZZPhase, 0.1, [0, 1])
    c.add_gate(OpType.CY, [0, 1])
    c.add_gate(OpType.CCX, [0, 1, 2])
    c.measure_all()

    assert remote_qasm.valid_circuit(c)

    assert sum(remote_qasm.get_counts(c, 10).values()) == 10
Exemple #20
0
def test_ibm_gateset() -> None:
    state = QuantumState(3)
    state.set_zero_state()
    circ = Circuit(3)
    circ.add_gate(OpType.U1, 0.19, [0])
    circ.add_gate(OpType.U2, [0.19, 0.24], [1])
    circ.add_gate(OpType.U3, [0.19, 0.24, 0.32], [2])
    qulacs_circ = tk_to_qulacs(circ)
    qulacs_circ.update_quantum_state(state)

    state1 = QuantumState(3)
    state1.set_zero_state()
    qulacs_circ1 = QuantumCircuit(3)
    qulacs_circ1.add_U1_gate(0, 0.19 * np.pi)
    qulacs_circ1.add_U2_gate(1, 0.19 * np.pi, 0.24 * np.pi)
    qulacs_circ1.add_U3_gate(2, 0.19 * np.pi, 0.24 * np.pi, 0.32 * np.pi)
    qulacs_circ1.update_quantum_state(state1)
    overlap = inner_product(state1, state)
    assert np.isclose(1, overlap)
Exemple #21
0
class CircuitBuilder:
    def __init__(
        self,
        qregs: List[QuantumRegister],
        cregs: Optional[List[ClassicalRegister]] = None,
        name: Optional[str] = None,
        phase: Optional[float] = 0.0,
    ):
        self.qregs = qregs
        self.cregs = [] if cregs is None else cregs
        self.tkc = Circuit(name=name)
        self.tkc.add_phase(phase)
        self.qregmap = {}
        for reg in qregs:
            tk_reg = self.tkc.add_q_register(reg.name, len(reg))
            self.qregmap.update({reg: tk_reg})
        self.cregmap = {}
        for reg in self.cregs:
            tk_reg = self.tkc.add_c_register(reg.name, len(reg))
            self.cregmap.update({reg: tk_reg})

    def circuit(self) -> Circuit:
        return self.tkc

    def add_qiskit_data(self, data: "QuantumCircuitData") -> None:
        for i, qargs, cargs in data:
            condition_kwargs = {}
            if i.condition is not None:
                cond_reg = self.cregmap[i.condition[0]]
                condition_kwargs = {
                    "condition_bits":
                    [cond_reg[k] for k in range(len(cond_reg))],
                    "condition_value": i.condition[1],
                }
            if type(i) == ControlledGate:
                if type(i.base_gate) == qiskit_gates.RYGate:
                    optype = OpType.CnRy
                else:
                    # Maybe handle multicontrolled gates in a more general way,
                    # but for now just do CnRy
                    raise NotImplementedError(
                        "qiskit ControlledGate with " +
                        "base gate {} not implemented".format(i.base_gate))
            else:
                optype = _known_qiskit_gate[type(i)]

            qubits = [
                self.qregmap[qbit.register][qbit.index] for qbit in qargs
            ]
            bits = [self.cregmap[bit.register][bit.index] for bit in cargs]

            if optype == OpType.Unitary2qBox:
                u = i.to_matrix()
                ubox = Unitary2qBox(u)
                self.tkc.add_unitary2qbox(ubox, qubits[0], qubits[1],
                                          **condition_kwargs)
            elif optype == OpType.Barrier:
                self.tkc.add_barrier(qubits)
            elif optype in (OpType.CircBox, OpType.Custom):
                qregs = [QuantumRegister(i.num_qubits, "q")
                         ] if i.num_qubits > 0 else []
                cregs = ([ClassicalRegister(i.num_clbits, "c")]
                         if i.num_clbits > 0 else [])
                builder = CircuitBuilder(qregs, cregs)
                builder.add_qiskit_data(i.definition)
                subc = builder.circuit()
                if optype == OpType.CircBox:
                    cbox = CircBox(subc)
                    self.tkc.add_circbox(cbox, qubits + bits,
                                         **condition_kwargs)
                else:
                    # warning, this will catch all `Gate` instances
                    # that were not picked up as a subclass in _known_qiskit_gate
                    params = [param_to_tk(p) for p in i.params]
                    gate_def = CustomGateDef.define(i.name, subc,
                                                    list(subc.free_symbols()))
                    self.tkc.add_custom_gate(gate_def, params, qubits + bits)
            else:
                params = [param_to_tk(p) for p in i.params]
                self.tkc.add_gate(optype, params, qubits + bits,
                                  **condition_kwargs)
def tk_to_cirq(tkcirc: Circuit,
               copy_all_qubits: bool = False) -> cirq.circuits.Circuit:
    """Converts a tket :py:class:`Circuit` object to a Cirq :py:class:`Circuit`.

    :param tkcirc: The input tket :py:class:`Circuit`

    :return: The Cirq :py:class:`Circuit` corresponding to the input circuit
    """
    if copy_all_qubits:
        tkcirc = tkcirc.copy()
        for q in tkcirc.qubits:
            tkcirc.add_gate(OpType.noop, [q])

    qmap = {}
    line_name = None
    grid_name = None
    # Since Cirq can only support registers of up to 2 dimensions, we explicitly
    # check for 3-dimensional registers whose third dimension is trivial.
    # SquareGrid architectures are of this form.
    indices = [qb.index for qb in tkcirc.qubits]
    is_flat_3d = all(idx[2] == 0 for idx in indices if len(idx) == 3)
    for qb in tkcirc.qubits:
        if len(qb.index) == 0:
            qmap.update({qb: cirq.ops.NamedQubit(qb.reg_name)})
        elif len(qb.index) == 1:
            if line_name != None and line_name != qb.reg_name:
                raise NotImplementedError(
                    "Cirq can only support a single linear register")
            line_name = qb.reg_name
            qmap.update({qb: LineQubit(qb.index[0])})
        elif len(qb.index) == 2 or (len(qb.index) == 3 and is_flat_3d):
            if grid_name != None and grid_name != qb.reg_name:
                raise NotImplementedError(
                    "Cirq can only support a single grid register")
            grid_name = qb.reg_name
            qmap.update({qb: GridQubit(qb.index[0], qb.index[1])})
        else:
            raise NotImplementedError(
                "Cirq can only support registers of dimension <=2")
    oplst = []
    for command in tkcirc:
        op = command.op
        optype = op.type
        try:
            gatetype = _ops2cirq_mapping[optype]
        except KeyError as error:
            raise NotImplementedError("Cannot convert tket Op to Cirq gate: " +
                                      op.get_name()) from error
        if optype == OpType.Measure:
            qid = qmap[command.args[0]]
            bit = command.args[1]
            cirqop = cirq.ops.measure(qid, key=bit.__repr__())
        else:
            qids = [qmap[qbit] for qbit in command.args]
            params = op.params
            if len(params) == 0:
                cirqop = gatetype(*qids)
            elif optype == OpType.PhasedX:
                cirqop = gatetype(phase_exponent=params[1],
                                  exponent=params[0])(*qids)
            elif optype == OpType.FSim:
                cirqop = gatetype(theta=float(params[0] * pi),
                                  phi=float(params[1] * pi))(*qids)
            elif optype == OpType.PhasedISWAP:
                cirqop = gatetype(phase_exponent=params[0],
                                  exponent=params[1])(*qids)
            else:
                cirqop = gatetype(exponent=params[0])(*qids)
        oplst.append(cirqop)
    try:
        coeff = cmath.exp(float(tkcirc.phase) * cmath.pi * 1j)
        if coeff != 1.0:
            oplst.append(cirq.ops.GlobalPhaseOperation(coeff))
    except ValueError:
        warning(
            "Global phase is dependent on a symbolic parameter, so cannot adjust for "
            "phase")
    return cirq.circuits.Circuit(*oplst)
Exemple #23
0
# # Circuit analysis: tket example

# This notebook will introduce the basic methods of analysis and visualization of circuits available in `pytket`.
#
# It makes use of the modules `pytket_qiskit` and `pytket_cirq` for visualization; these need to be installed (with `pip`) in addition to `pytket`.
#
# We'll start by generating a small circuit to use as an example, and give it a name.

from pytket.circuit import Circuit, OpType

c = Circuit(4, name="example")
c.add_gate(OpType.CU1, 0.5, [0, 1])
c.H(0).X(1).Y(2).Z(3)
c.X(0).CX(1, 2).Y(1).Z(2).H(3)
c.Y(0).Z(1)
c.add_gate(OpType.CU1, 0.5, [2, 3])
c.H(2).X(3)
c.Z(0).H(1).X(2).Y(3).CX(3, 0)

# ## Basic statistics

# From the circuit we can easily read off the number of qubits ...

c.n_qubits

# ... the name ...

c.name

# ... the overall depth of the circuit ...
Exemple #24
0
def _tk1_to_u(a: float, b: float, c: float) -> Circuit:
    circ = Circuit(1)
    circ.add_gate(OpType.U3, [b, a - 0.5, c + 0.5], [0])
    circ.add_phase(-0.5 * (a + c))
    return circ
def test_convert() -> None:
    c = Circuit(3)
    c.add_gate(OpType.CCX, [0, 1, 2])
    c.add_gate(OpType.CX, [0, 1])
    c.add_gate(OpType.CU1, 0.1, [0, 1])
    c.add_gate(OpType.CSWAP, [0, 1, 2])
    c.add_gate(OpType.CY, [0, 1])
    c.add_gate(OpType.CZ, [0, 1])
    c.add_gate(OpType.H, [0])
    c.add_gate(OpType.ISWAPMax, [0, 1])
    c.add_gate(OpType.U1, 0.2, [0])
    c.add_gate(OpType.Rx, 0.3, [0])
    c.add_gate(OpType.Ry, 0.4, [0])
    c.add_gate(OpType.Rz, 0.5, [0])
    c.add_gate(OpType.S, [0])
    c.add_gate(OpType.Sdg, [0])
    c.add_gate(OpType.SWAP, [0, 1])
    c.add_gate(OpType.T, [0])
    c.add_gate(OpType.Tdg, [0])
    c.add_gate(OpType.V, [0])
    c.add_gate(OpType.Vdg, [0])
    c.add_gate(OpType.X, [0])
    c.add_gate(OpType.XXPhase, 0.6, [0, 1])
    c.add_gate(OpType.ISWAP, 0.7, [0, 1])
    c.add_gate(OpType.Y, [0])
    c.add_gate(OpType.YYPhase, 0.8, [0, 1])
    c.add_gate(OpType.Z, [0])
    c.add_gate(OpType.ZZPhase, 0.9, [0, 1])
    bkc = tk_to_braket(c)
    c1 = braket_to_tk(bkc)
    assert c.get_commands() == c1.get_commands()
Exemple #26
0
def braket_to_tk(bkcirc: BK_Circuit) -> Circuit:
    """
    Convert a braket circuit to a tket :py:class:`Circuit`

    :param bkcirc: circuit to be converted

    :returns: circuit converted to tket
    """
    n_qbs = len(bkcirc.qubits)
    tkcirc = Circuit(n_qbs)
    for instr in bkcirc.instructions:
        op = instr.operator
        qbs = [bkcirc.qubits.index(qb) for qb in instr.target]
        opname = op.name
        if opname == "CCNot":
            tkcirc.add_gate(OpType.CCX, qbs)
        elif opname == "CNot":
            tkcirc.add_gate(OpType.CX, qbs)
        elif opname == "CPhaseShift":
            tkcirc.add_gate(OpType.CU1, op.angle / pi, qbs)
        elif opname == "CSwap":
            tkcirc.add_gate(OpType.CSWAP, qbs)
        elif opname == "CY":
            tkcirc.add_gate(OpType.CY, qbs)
        elif opname == "CZ":
            tkcirc.add_gate(OpType.CZ, qbs)
        elif opname == "H":
            tkcirc.add_gate(OpType.H, qbs)
        elif opname == "I":
            pass
        elif opname == "ISwap":
            tkcirc.add_gate(OpType.ISWAPMax, qbs)
        elif opname == "PhaseShift":
            tkcirc.add_gate(OpType.U1, op.angle / pi, qbs)
        elif opname == "Rx":
            tkcirc.add_gate(OpType.Rx, op.angle / pi, qbs)
        elif opname == "Ry":
            tkcirc.add_gate(OpType.Ry, op.angle / pi, qbs)
        elif opname == "Rz":
            tkcirc.add_gate(OpType.Rz, op.angle / pi, qbs)
        elif opname == "S":
            tkcirc.add_gate(OpType.S, qbs)
        elif opname == "Si":
            tkcirc.add_gate(OpType.Sdg, qbs)
        elif opname == "Swap":
            tkcirc.add_gate(OpType.SWAP, qbs)
        elif opname == "T":
            tkcirc.add_gate(OpType.T, qbs)
        elif opname == "Ti":
            tkcirc.add_gate(OpType.Tdg, qbs)
        elif opname == "V":
            tkcirc.add_gate(OpType.V, qbs)
            tkcirc.add_phase(0.25)
        elif opname == "Vi":
            tkcirc.add_gate(OpType.Vdg, qbs)
            tkcirc.add_phase(-0.25)
        elif opname == "X":
            tkcirc.add_gate(OpType.X, qbs)
        elif opname == "XX":
            tkcirc.add_gate(OpType.XXPhase, op.angle / pi, qbs)
        elif opname == "XY":
            tkcirc.add_gate(OpType.ISWAP, op.angle / pi, qbs)
        elif opname == "Y":
            tkcirc.add_gate(OpType.Y, qbs)
        elif opname == "YY":
            tkcirc.add_gate(OpType.YYPhase, op.angle / pi, qbs)
        elif opname == "Z":
            tkcirc.add_gate(OpType.Z, qbs)
        elif opname == "ZZ":
            tkcirc.add_gate(OpType.ZZPhase, op.angle / pi, qbs)
        else:
            # The following don't have direct equivalents:
            # - CPhaseShift00, CPhaseShift01, CPhaseShift10: diagonal unitaries with 1s
            # on the diagonal except for a phase e^{ia} in the (0,0), (1,1) or (2,2)
            # position respectively.
            # - PSwap: unitary with 1s at (0,0) and (3,3), a phase e^{ia} at (1,2) and
            # (2,1), and zeros elsewhere.
            # They could be decomposed into pytket gates, but it would be better to add
            # the gate types to tket.
            # The "Unitary" type could be represented as a box in the 1q and 2q cases,
            # but not in general.
            raise NotImplementedError(f"Cannot convert {opname} to tket")
    return tkcirc
Exemple #27
0
# ## Classical controls

# Most of the examples above involve only pure quantum gates. However, `pytket` can also represent gates whose operation is conditional on one or more classical inputs.
#
# For example, suppose we want to run the complex circuit `c` we've just constructed, then measure qubits 0 and 1, and finally apply an $\mathrm{Rz}(\frac{1}{2})$ rotation to qubit 2 if and only if the measurements were 0 and 1 respectively.
#
# First, we'll add two classical wires to the circuit to store the measurement results:

from pytket.circuit import Bit

c.add_c_register("m", 2)
m = [Bit("m", i) for i in range(2)]

# Classically conditioned operations depend on all their inputs being 1. Since we want to condition on `m[0]` being 0, we must first apply an X gate to its qubit, and then measure:

q = [Qubit("q", i) for i in range(3)]
c.X(q[0])
c.Measure(q[0], m[0])
c.Measure(q[1], m[1])

# Finally we add the classically conditioned Rz operation, using the `add_gate()` method:

from pytket.circuit import OpType

c.add_gate(OpType.Rz, [0.5], [q[2]],
           condition_bits=[m[0], m[1]],
           condition_value=3)

# Note that many of the transforms and compilation passes will not accept circuits that contain classical controls.
def cirq_to_tk(circuit: cirq.circuits.Circuit) -> Circuit:
    """Converts a Cirq :py:class:`Circuit` to a tket :py:class:`Circuit` object.

    :param circuit: The input Cirq :py:class:`Circuit`

    :raises NotImplementedError: If the input contains a Cirq :py:class:`Circuit`
        operation which is not yet supported by pytket

    :return: The tket :py:class:`Circuit` corresponding to the input circuit
    """
    tkcirc = Circuit()
    qmap = {}
    for qb in circuit.all_qubits():
        if isinstance(qb, LineQubit):
            uid = Qubit("q", qb.x)
        elif isinstance(qb, GridQubit):
            uid = Qubit("g", qb.row, qb.col)
        elif isinstance(qb, cirq.ops.NamedQubit):
            uid = Qubit(qb.name)
        else:
            raise NotImplementedError("Cannot convert qubits of type " +
                                      str(type(qb)))
        tkcirc.add_qubit(uid)
        qmap.update({qb: uid})
    for moment in circuit:
        for op in moment.operations:
            if isinstance(op, cirq.ops.GlobalPhaseOperation):
                tkcirc.add_phase(cmath.phase(op.coefficient) / pi)
                continue
            gate = op.gate
            gatetype = type(gate)
            qb_lst = [qmap[q] for q in op.qubits]

            if isinstance(gate, cirq_common.HPowGate) and gate.exponent == 1:
                gate = cirq_common.H
            elif (gatetype == cirq_common.CNotPowGate
                  and cast(cirq_common.CNotPowGate, gate).exponent == 1):
                gate = cirq_common.CNOT
            elif (gatetype == cirq_pauli._PauliX
                  and cast(cirq_pauli._PauliX, gate).exponent == 1):
                gate = cirq_pauli.X
            elif (gatetype == cirq_pauli._PauliY
                  and cast(cirq_pauli._PauliY, gate).exponent == 1):
                gate = cirq_pauli.Y
            elif (gatetype == cirq_pauli._PauliZ
                  and cast(cirq_pauli._PauliZ, gate).exponent == 1):
                gate = cirq_pauli.Z

            if gate in _constant_gates:
                try:
                    optype = _cirq2ops_mapping[gate]
                except KeyError as error:
                    raise NotImplementedError(
                        "Operation not supported by tket: " +
                        str(op.gate)) from error
                params = []
            elif isinstance(gate, cirq_common.MeasurementGate):
                uid = Bit(gate.key)
                tkcirc.add_bit(uid)
                tkcirc.Measure(*qb_lst, uid)
                continue
            elif isinstance(gate, cirq.ops.PhasedXPowGate):
                optype = OpType.PhasedX
                pe = gate.phase_exponent
                params = [gate.exponent, pe]
            elif isinstance(gate, cirq.ops.FSimGate):
                optype = OpType.FSim
                params = [gate.theta / pi, gate.phi / pi]
            elif isinstance(gate, cirq.ops.PhasedISwapPowGate):
                optype = OpType.PhasedISWAP
                params = [gate.phase_exponent, gate.exponent]
            else:
                try:
                    optype = _cirq2ops_mapping[gatetype]
                    params = [cast(Any, gate).exponent]
                except (KeyError, AttributeError) as error:
                    raise NotImplementedError(
                        "Operation not supported by tket: " +
                        str(op.gate)) from error
            tkcirc.add_gate(optype, params, qb_lst)
    return tkcirc
Exemple #29
0
def _tk1_to_phasedxrz(a: float, b: float, c: float) -> Circuit:
    circ = Circuit(1)
    circ.Rz(a + c, 0)
    circ.add_gate(OpType.PhasedX, [b, a], [0])
    RemoveRedundancies().apply(circ)
    return circ