Esempio n. 1
0
    def __init__(
        self,
        local: bool = False,
        s3_bucket: str = "",
        s3_folder: str = "",
        device_type: str = "quantum-simulator",
        provider: str = "amazon",
        device: str = "sv1",
    ):
        """
        Construct a new braket backend.

        If `local=True`, other parameters are ignored.

        :param local: use simulator running on local machine
        :param s3_bucket: name of S3 bucket to store results
        :param s3_folder: name of folder ("key") in S3 bucket to store results in
        :param device_type: device type from device ARN (e.g. "qpu")
        :param provider: provider name from device ARN (e.g. "ionq", "rigetti", ...)
        :paran device: device name from device ARN (e.g. "ionQdevice", "Aspen-8", ...)
        """
        super().__init__()
        if local:
            self._device = LocalSimulator()
            self._device_type = _DeviceType.LOCAL
        else:
            self._device = AwsDevice(
                "arn:aws:braket:::" +
                "/".join(["device", device_type, provider, device]))
            self._s3_dest = (s3_bucket, s3_folder)
            aws_device_type = self._device.type
            if aws_device_type == AwsDeviceType.SIMULATOR:
                self._device_type = _DeviceType.SIMULATOR
            elif aws_device_type == AwsDeviceType.QPU:
                self._device_type = _DeviceType.QPU
            else:
                raise ValueError(f"Unsupported device type {aws_device_type}")

        props = self._device.properties.dict()
        paradigm = props["paradigm"]
        n_qubits = paradigm["qubitCount"]
        connectivity_graph = None  # None means "fully connected"
        if self._device_type == _DeviceType.QPU:
            connectivity = paradigm["connectivity"]
            if connectivity["fullyConnected"]:
                self._all_qubits: List = list(range(n_qubits))
            else:
                connectivity_graph = connectivity["connectivityGraph"]
                # Convert strings to ints
                connectivity_graph = dict(
                    (int(k), [int(v) for v in l])
                    for k, l in connectivity_graph.items())
                self._all_qubits = sorted(connectivity_graph.keys())
                if n_qubits < len(self._all_qubits):
                    # This can happen, at least on rigetti devices, and causes errors.
                    # As a kludgy workaround, remove some qubits from the architecture.
                    self._all_qubits = self._all_qubits[:(
                        n_qubits - len(self._all_qubits))]
                    connectivity_graph = dict(
                        (k, [v for v in l if v in self._all_qubits])
                        for k, l in connectivity_graph.items()
                        if k in self._all_qubits)
            self._characteristics: Optional[Dict] = props["provider"]
        else:
            self._all_qubits = list(range(n_qubits))
            self._characteristics = None

        device_info = props["action"][DeviceActionType.JAQCD]
        supported_ops = set(op.lower()
                            for op in device_info["supportedOperations"])
        supported_result_types = device_info["supportedResultTypes"]
        self._result_types = set()
        for rt in supported_result_types:
            rtname = rt["name"]
            rtminshots = rt["minShots"]
            rtmaxshots = rt["maxShots"]
            self._result_types.add(rtname)
            if rtname == "StateVector":
                self._supports_state = True
                # Always use n_shots = 0 for StateVector
            elif rtname == "Amplitude":
                pass  # Always use n_shots = 0 for Amplitude
            elif rtname == "Probability":
                self._probability_min_shots = rtminshots
                self._probability_max_shots = rtmaxshots
            elif rtname == "Expectation":
                self._supports_expectation = True
                self._expectation_allows_nonhermitian = False
                self._expectation_min_shots = rtminshots
                self._expectation_max_shots = rtmaxshots
            elif rtname == "Sample":
                self._supports_shots = True
                self._supports_counts = True
                self._sample_min_shots = rtminshots
                self._sample_max_shots = rtmaxshots
            elif rtname == "Variance":
                self._variance_min_shots = rtminshots
                self._variance_max_shots = rtmaxshots

        self._multiqs = set()
        self._singleqs = set()
        if not {"cnot", "rx", "rz"} <= supported_ops:
            # This is so that we can define RebaseCustom without prior knowledge of the
            # gate set. We could do better than this, by having a few different options
            # for the CX- and tk1-replacement circuits. But it seems all existing
            # backends support these gates.
            raise NotImplementedError(
                "Device must support cnot, rx and rz gates.")
        for t in supported_ops:
            tkt = _gate_types[t]
            if tkt is not None:
                if t in _multiq_gate_types:
                    if self._device_type == _DeviceType.QPU and t in [
                            "ccnot", "cswap"
                    ]:
                        # FullMappingPass can't handle 3-qubit gates, so ignore them.
                        continue
                    self._multiqs.add(tkt)
                else:
                    self._singleqs.add(tkt)
        self._req_preds = [
            NoClassicalControlPredicate(),
            NoFastFeedforwardPredicate(),
            NoMidMeasurePredicate(),
            NoSymbolsPredicate(),
            GateSetPredicate(self._multiqs | self._singleqs),
            MaxNQubitsPredicate(n_qubits),
        ]

        if connectivity_graph is None:
            arch = FullyConnected(n_qubits)
        else:
            arch = Architecture([(k, v) for k, l in connectivity_graph.items()
                                 for v in l])
        if self._device_type == _DeviceType.QPU:
            assert self._characteristics is not None
            node_errs = {}
            edge_errs = {}
            schema = self._characteristics["braketSchemaHeader"]
            if schema == IONQ_SCHEMA:
                fid = self._characteristics["fidelity"]
                mean_1q_err = 1 - fid["1Q"]["mean"]
                mean_2q_err = 1 - fid["2Q"]["mean"]
                err_1q_cont = QubitErrorContainer(self._singleqs)
                for optype in self._singleqs:
                    err_1q_cont.add_error((optype, mean_1q_err))
                err_2q_cont = QubitErrorContainer(self._multiqs)
                for optype in self._multiqs:
                    err_2q_cont.add_error((optype, mean_2q_err))
                for node in arch.nodes:
                    node_errs[node] = err_1q_cont
                for coupling in arch.coupling:
                    edge_errs[coupling] = err_2q_cont
            elif schema == RIGETTI_SCHEMA:
                specs = self._characteristics["specs"]
                specs1q, specs2q = specs["1Q"], specs["2Q"]
                for node in arch.nodes:
                    nodespecs = specs1q[f"{node.index[0]}"]
                    err_1q_cont = QubitErrorContainer(self._singleqs)
                    for optype in self._singleqs:
                        err_1q_cont.add_error(
                            (optype, 1 - nodespecs.get("f1QRB", 1)))
                    err_1q_cont.add_readout(nodespecs.get("fRO", 1))
                    node_errs[node] = err_1q_cont
                for coupling in arch.coupling:
                    node0, node1 = coupling
                    n0, n1 = node0.index[0], node1.index[0]
                    couplingspecs = specs2q[f"{min(n0,n1)}-{max(n0,n1)}"]
                    err_2q_cont = QubitErrorContainer({OpType.CZ})
                    err_2q_cont.add_error(
                        (OpType.CZ, 1 - couplingspecs.get("fCZ", 1)))
                    edge_errs[coupling] = err_2q_cont
            self._tket_device = Device(node_errs, edge_errs, arch)
            if connectivity_graph is not None:
                self._req_preds.append(ConnectivityPredicate(
                    self._tket_device))
        else:
            self._tket_device = None

        self._rebase_pass = RebaseCustom(
            self._multiqs,
            Circuit(),
            self._singleqs,
            lambda a, b, c: Circuit(1).Rz(c, 0).Rx(b, 0).Rz(a, 0),
        )
        self._squash_pass = SquashCustom(
            self._singleqs,
            lambda a, b, c: Circuit(1).Rz(c, 0).Rx(b, 0).Rz(a, 0),
        )
Esempio n. 2
0
def test_estimates() -> None:
    """
    Check that the resource estimator gives reasonable results.
    """
    b = QsharpEstimatorBackend()
    c = Circuit(3)
    c.H(0)
    c.CX(0, 1)
    c.CCX(0, 1, 2)
    c.Rx(0.3, 1)
    c.Ry(0.4, 2)
    c.Rz(1.1, 0)
    c.S(1)
    c.SWAP(0, 2)
    c.T(1)
    c.X(0)
    c.Y(1)
    c.Z(2)
    pbox = PauliExpBox([Pauli.X, Pauli.I, Pauli.Z], 0.25)
    c.add_pauliexpbox(pbox, [2, 0, 1])
    b.compile_circuit(c, 0)
    resources = b.get_resources(c)
    assert resources["CNOT"] >= 1
    assert resources["QubitClifford"] >= 1
    assert resources["R"] >= 1
    assert resources["T"] >= 1
    assert resources["Depth"] >= 1
    assert resources["Width"] == 3
    assert resources["BorrowedWidth"] == 0
def tk_to_pyquil(
    tkcirc: Circuit,
    active_reset: bool = False,
    return_used_bits: bool = False
) -> Union[Program, Tuple[Program, List[Bit]]]:
    """
       Convert a tket :py:class:`Circuit` to a :py:class:`pyquil.Program` .

    :param tkcirc: A circuit to be converted

    :return: The converted circuit
    """
    p = Program()
    qregs = set()
    for qb in tkcirc.qubits:
        if len(qb.index) != 1:
            raise NotImplementedError(
                "PyQuil registers must use a single index")
        qregs.add(qb.reg_name)
    if len(qregs) > 1:
        raise NotImplementedError(
            "Cannot convert circuit with multiple quantum registers to pyQuil")
    creg_sizes: Dict = {}
    for b in tkcirc.bits:
        if len(b.index) != 1:
            raise NotImplementedError(
                "PyQuil registers must use a single index")
        if (b.reg_name
                not in creg_sizes) or (b.index[0] >= creg_sizes[b.reg_name]):
            creg_sizes.update({b.reg_name: b.index[0] + 1})
    cregmap = {}
    for reg_name, size in creg_sizes.items():
        name = reg_name
        if name == "c":
            name = "ro"
        quil_reg = p.declare(name, "BIT", size)
        cregmap.update({reg_name: quil_reg})
    for sym in tkcirc.free_symbols():
        p.declare(str(sym), "REAL")
    if active_reset:
        p.reset()
    measures = []
    measured_qubits: List[Qubit] = []
    used_bits: List[Bit] = []
    for command in tkcirc:
        op = command.op
        optype = op.type
        if optype == OpType.Measure:
            qb = Qubit_(command.args[0].index[0])
            if qb in measured_qubits:
                raise NotImplementedError("Cannot apply gate on qubit " +
                                          qb.__repr__() + " after measurement")
            bit = command.args[1]
            b = cregmap[bit.reg_name][bit.index[0]]
            measures.append(Measurement(qb, b))
            measured_qubits.append(qb)
            used_bits.append(bit)
            continue
        elif optype == OpType.Barrier:
            continue  # pyQuil cannot handle barriers
        qubits = [Qubit_(qb.index[0]) for qb in command.args]
        for qb in qubits:
            if qb in measured_qubits:
                raise NotImplementedError("Cannot apply gate on qubit " +
                                          qb.__repr__() + " after measurement")
        try:
            gatetype = _known_quil_gate_rev[optype]
        except KeyError as error:
            raise NotImplementedError(
                "Cannot convert tket Op to pyQuil gate: " +
                op.get_name()) from error
        params = [param_to_pyquil(p) for p in op.params]
        g = Gate(gatetype, params, qubits)
        p += g
    for m in measures:
        p += m
    if return_used_bits:
        return p, used_bits
    return p
Esempio n. 4
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. 5
0
import time
from pytket.circuit import Circuit, PauliExpBox
from pytket.pauli import Pauli
from pytket.extensions.qiskit import AerStateBackend
from pytket.passes import FullPeepholeOptimise
from statistics import mean, stdev
nb_steps = 100
step_size = 0.01
n_qubits = [5, 10, 20, 30, 40, 50]
n_runs = 10
for nb_qubits in n_qubits:
    data = []
    for run_id in range(n_runs):
        # Start timer
        start = time.time()
        circ = Circuit(nb_qubits)

        h = 1.0
        Jz = 1.0
        for i in range(nb_steps):
            # Using Heisenberg Hamiltonian:
            for q in range(nb_qubits):
                circ.add_pauliexpbox(PauliExpBox([Pauli.X], -h * step_size),
                                     [q])
            for q in range(nb_qubits - 1):
                circ.add_pauliexpbox(
                    PauliExpBox([Pauli.Z, Pauli.Z], -Jz * step_size),
                    [q, q + 1])

        # Compile to gates
        backend = AerStateBackend()
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])
Esempio n. 7
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
    OpType.H,
    OpType.S,
    OpType.Sdg,
    OpType.T,
    OpType.Tdg,
    OpType.V,
    OpType.Vdg,
    OpType.Measure,
    OpType.noop,
}

ionq_gates = ionq_multiqs.union(ionq_singleqs)

ionq_pass = RebaseCustom(
    ionq_multiqs,
    Circuit(),  # cx_replacement (irrelevant)
    ionq_singleqs,  # singleqs
    _from_tk1,
)  # tk1_replacement

ionq_gate_dict = {
    OpType.X: "x",
    OpType.Y: "y",
    OpType.Z: "z",
    OpType.Rx: "rx",
    OpType.Ry: "ry",
    OpType.Rz: "rz",
    OpType.H: "h",
    OpType.CX: "cnot",
    OpType.S: "s",
    OpType.Sdg: "si",
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)
Esempio n. 10
0
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)
Esempio n. 11
0
def test_honeywell() -> None:
    token = os.getenv("HQS_AUTH")
    backend = HoneywellBackend(device_name="HQS-LT-1.0-APIVAL",
                               machine_debug=skip_remote_tests)
    c = Circuit(4, 4, "test 1")
    c.H(0)
    c.CX(0, 1)
    c.Rz(0.3, 2)
    c.CSWAP(0, 1, 2)
    c.CRz(0.4, 2, 3)
    c.CY(1, 3)
    c.ZZPhase(0.1, 2, 0)
    c.Tdg(3)
    c.measure_all()
    backend.compile_circuit(c)
    n_shots = 4
    handle = backend.process_circuits([c], n_shots)[0]
    correct_shots = np.zeros((4, 4))
    correct_counts = {(0, 0, 0, 0): 4}
    res = backend.get_result(handle, timeout=49)
    shots = res.get_shots()
    counts = res.get_counts()
    assert backend.circuit_status(handle).status is StatusEnum.COMPLETED
    assert np.all(shots == correct_shots)
    assert counts == correct_counts
    newshots = backend.get_shots(c, 4, timeout=49)
    assert np.all(newshots == correct_shots)
    newcounts = backend.get_counts(c, 4)
    assert newcounts == correct_counts
    if token is None:
        assert backend.device is None
Esempio n. 12
0
def test_classical() -> None:
    # circuit to cover capabilities covered in HQS example notebook
    c = Circuit(1)
    a = c.add_c_register("a", 8)
    b = c.add_c_register("b", 10)
    c.add_c_register("c", 10)

    c.add_c_setbits([True], [a[0]])
    c.add_c_setbits([False, True] + [False] * 6, list(a))
    c.add_c_setbits([True, True] + [False] * 8, list(b))

    c.X(0, condition=reg_eq(a ^ b, 1))
    c.X(0, condition=(a[0] ^ b[0]))
    c.X(0, condition=reg_eq(a & b, 1))
    c.X(0, condition=reg_eq(a | b, 1))

    c.X(0, condition=a[0])
    c.X(0, condition=reg_neq(a, 1))
    c.X(0, condition=if_not_bit(a[0]))
    c.X(0, condition=reg_gt(a, 1))
    c.X(0, condition=reg_lt(a, 1))
    c.X(0, condition=reg_geq(a, 1))
    c.X(0, condition=reg_leq(a, 1))

    b = HoneywellBackend("HQS-LT-S1-APIVAL")

    b.compile_circuit(c)
    assert b.get_counts(c, 10)
Esempio n. 13
0
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
Esempio n. 14
0
def test_aqt() -> None:
    # Run a circuit on the noisy simulator.
    token = cast(str, os.getenv("AQT_AUTH"))
    b = AQTBackend(device_name="sim/noise-model-1",
                   access_token=token,
                   label="test 1")
    c = Circuit(4, 4)
    c.H(0)
    c.CX(0, 1)
    c.Rz(0.3, 2)
    c.CSWAP(0, 1, 2)
    c.CRz(0.4, 2, 3)
    c.CY(1, 3)
    c.add_barrier([0, 1])
    c.ZZPhase(0.1, 2, 0)
    c.Tdg(3)
    c.measure_all()
    b.compile_circuit(c)
    n_shots = 10
    shots = b.get_shots(c, n_shots, seed=1, timeout=30)
    counts = b.get_counts(c, n_shots)
    assert len(shots) == n_shots
    assert sum(counts.values()) == n_shots
Esempio n. 15
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 ...
Esempio n. 16
0
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. 17
0
def test_statevector() -> None:
    b = AerStateBackend()
    circ = Circuit(3, name="test")
    circ.H(2)
    circ.X(0)
    circ.H(0)
    circ.CX(0, 1)
    circ.CZ(1, 2)
    circ.Sdg(0)
    circ.Tdg(1)
    circ.Z(1)
    circ.T(2)
    circ.Rx(0.3333, 1)
    circ.Rz(0.3333, 1)
    zxcirc = tk_to_pyzx(circ)
    assert zxcirc.name == circ.name
    b.compile_circuit(circ)
    state = b.get_state(circ)
    circ2 = pyzx_to_tk(zxcirc)
    assert circ2.name == circ.name
    b.compile_circuit(circ2)
    state2 = b.get_state(circ2)
    assert np.allclose(state, state2, atol=1e-10)
Esempio n. 18
0
def _from_tk1(a: float, b: float, c: float) -> Circuit:
    circ = Circuit(1)
    circ.Rz(c, 0)
    circ.Rx(b, 0)
    circ.Rz(a, 0)
    return circ
Esempio n. 19
0
def test_invalid_gate() -> None:
    circ = Circuit(1, name="test")
    circ.measure_all()
    with pytest.raises(Exception) as excinfo:
        _ = tk_to_pyzx(circ)
        assert "as the gate type is unrecognised." in str(excinfo.value)
Esempio n. 20
0
# We will use Qiskit for circuit visualisation and for an example backend. For this it is necessary to have installed `pytket_qiskit` via `pip`.
#
# ## Passes

# The basic mechanism of compilation is the 'pass', which is a transform that can be applied to a circuit. There is an extensive library of passes in `pytket`, and several standard ways in which they can be combined to form new passes. For example:

from pytket.passes import DecomposeMultiQubitsIBM

pass1 = DecomposeMultiQubitsIBM()

# This pass converts all multi-qubit gates into CX and single-qubit gates. So let's create a circuit containing some non-CX multi-qubit gates:

from pytket.circuit import Circuit

circ = Circuit(3)
circ.CRz(0.5, 0, 1)
circ.T(2)
circ.CSWAP(2, 0, 1)

# In order to apply a pass to a circuit, we must first create a `CompilationUnit` from it. We can think of this as a 'bridge' between the circuit and the pass. The `CompilationUnit` is constructed from the circuit; the pass is applied to the `CompilationUnit`; and the transformed circuit is extracted from the `CompilationUnit`:

from pytket.predicates import CompilationUnit

cu = CompilationUnit(circ)
pass1.apply(cu)
circ1 = cu.circuit

# Let's have a look at the result of the transformation:

print(circ1.get_commands())
Esempio n. 21
0
    for filename in os.listdir(op_directory):
        path = op_directory + "/" + filename
        with open(path, "rb") as pickle_in:
            qubit_pauli_operator = pickle.load(pickle_in)
        name = filename.replace(".pickle", "")
        print(name)
        active_spin_orbitals = orbitals_lookup_table[name]

        # Qiskit removed 2 qubits per circuit for us using Z2
        # Symmetries for the Parity encoding
        if encoding_name == "P":
            n_qubits = active_spin_orbitals - 2
        else:
            n_qubits = active_spin_orbitals

        initial_circ = Circuit(n_qubits)

        print("sequencing")
        t1_a = datetime.datetime.now()
        set_synth_circuit = gen_term_sequence_circuit(qubit_pauli_operator,
                                                      initial_circ)
        t1_b = datetime.datetime.now()
        print("Partitions: {}".format(
            set_synth_circuit.n_gates_of_type(OpType.CircBox)))

        naive_circuit = set_synth_circuit.copy()
        pairwise_circuit = set_synth_circuit.copy()

        Transform.DecomposeBoxes().apply(naive_circuit)
        # Naive construction: decompose each Pauli exponential invidually
        naive_cx_count = naive_circuit.n_gates_of_type(OpType.CX)