Esempio n. 1
0
def test_state() -> None:
    c = Circuit(2).H(0).CX(0, 1)
    b = CirqStateSimBackend()
    state = b.get_state(c)
    assert np.allclose(state, [math.sqrt(0.5), 0, 0, math.sqrt(0.5)], atol=1e-10)
    c.add_phase(0.5)
    state1 = b.get_state(c)
    assert np.allclose(state1, state * 1j, atol=1e-10)
Esempio n. 2
0
def test_state() -> None:
    c0 = Circuit(2).H(0).CX(0, 1)
    b = CirqStateSimBackend()
    state0 = b.get_state(c0)
    assert np.allclose(state0, [math.sqrt(0.5), 0, 0, math.sqrt(0.5)], atol=1e-10)
    c0.add_phase(0.5)
    state1 = b.get_state(c0)
    assert np.allclose(state1, state0 * 1j, atol=1e-10)
    assert np.allclose(b.get_state(Circuit(2).X(1)), [0, 1.0, 0, 0], atol=1e-10)
def test_statevector_phase() -> None:
    for b in backends:
        circ = Circuit(2)
        circ.H(0).CX(0, 1)
        b.compile_circuit(circ)
        state = b.get_state(circ)
        assert np.allclose(
            state, [math.sqrt(0.5), 0, 0, math.sqrt(0.5)], atol=1e-10)
        circ.add_phase(0.5)
        state1 = b.get_state(circ)
        assert np.allclose(state1, state * 1j, atol=1e-10)
Esempio n. 4
0
def _aqt_rebase() -> BasePass:
    # CX replacement
    c_cx = Circuit(2)
    c_cx.Ry(0.5, 0).Rx(0.5, 0)
    c_cx.Rx(-0.5, 1)
    c_cx.add_gate(OpType.XXPhase, 0.5, [0, 1])
    c_cx.Ry(0.5, 0).Rx(-1, 0)
    c_cx.add_phase(-0.25)

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

    return RebaseCustom({OpType.XXPhase}, c_cx, {OpType.Rx, OpType.Ry}, c_tk1)
Esempio n. 5
0
def _tk1_to_x_sx_rz(a: float, b: float, c: float) -> Circuit:
    circ = Circuit(1)
    if _approx_0_mod_2(b):
        circ.Rz(a + c, 0)
    elif _approx_0_mod_2(b + 1):
        if _approx_0_mod_2(a - 0.5) and _approx_0_mod_2(c - 0.5):
            circ.X(0)
        else:
            circ.Rz(c, 0).X(0).Rz(a, 0)
    else:
        # use SX; SX = e^{i\pi/4}V; V = RX(1/2)
        if _approx_0_mod_2(a - 0.5) and _approx_0_mod_2(c - 0.5):
            circ.SX(0).Rz(1 - b, 0).SX(0)
            circ.add_phase(-0.5)
        else:
            circ.Rz(c + 0.5, 0).SX(0).Rz(b - 1, 0).SX(0).Rz(a + 0.5, 0)
            circ.add_phase(-0.5)
    return circ
Esempio n. 6
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
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
Esempio n. 8
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
Esempio n. 9
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)