Exemple #1
0
    def __init__(
        self,
        noise_model: Optional[NoiseModel] = None,
        simulation_method: str = "automatic",
    ):
        """Backend for running simulations on the Qiskit Aer QASM simulator.

        :param noise_model: Noise model to apply during simulation. Defaults to None.
        :type noise_model: Optional[NoiseModel], optional
        :param simulation_method: Simulation method, see
         https://qiskit.org/documentation/stubs/qiskit.providers.aer.QasmSimulator.html
         for available values. Defaults to "automatic".
        :type simulation_method: str
        """
        super().__init__("qasm_simulator")

        if not noise_model or all(value == []
                                  for value in noise_model.to_dict().values()):
            self._noise_model = None
        else:
            self._noise_model = noise_model
            self._characterisation = _process_model(noise_model,
                                                    self._gate_set)

            self._device = Device(
                self._characterisation.get("NodeErrors", {}),
                self._characterisation.get("EdgeErrors", {}),
                self._characterisation.get("Architecture", Architecture([])),
            )
        self._memory = True

        self._backend.set_options(method=simulation_method)
    def __init__(self,
                 qc_name: str,
                 simulator: bool = True,
                 connection: ForestConnection = None):
        """Backend for running circuits on a Rigetti QCS device or simulating with the QVM.

        :param qc_name: The name of the particular QuantumComputer to use. See the pyQuil docs for more details.
        :type qc_name: str
        :param simulator: Simulate the device with the QVM (True), or run on the QCS (False). Defaults to True.
        :type simulator: bool, optional
        :param connection: Customized connection to the rigetti backend
        :type
        """

        # skip the constructor of BaseForestBackend
        super(Backend, self).__init__()

        self._cache = {}

        self._qc: QuantumComputer = get_qc(qc_name,
                                           as_qvm=simulator,
                                           connection=connection)
        self._characterisation: dict = process_characterisation(self._qc)
        averaged_errors = get_avg_characterisation(self._characterisation)
        self._backend_info: BackendInfo = BackendInfo(
            name=type(self).__name__,
            device_name=qc_name,
            version="0.14.0",
            architecture=self._characterisation.get("Architecture",
                                                    Architecture([])),
            gate_set=self._GATE_SET,
            all_node_gate_errors=self._characterisation.get("NodeErrors", {}),
            all_edge_gate_errors=self._characterisation.get("EdgeErrors", {}),
            averaged_node_gate_errors=averaged_errors["node_errors"],
            averaged_edge_gate_errors=averaged_errors["link_errors"])
Exemple #3
0
def test_device() -> None:
    fox = Foxtail
    char = process_characterisation(fox)
    dev = Device(
        char.get("NodeErrors", {}),
        char.get("EdgeErrors", {}),
        char.get("Architecture", Architecture([])),
    )
    arc = dev.architecture
    assert str(arc) == "<tket::Architecture, nodes=22>"
Exemple #4
0
def test_characterisation(qvm: None, quilc: None) -> None:
    b = ForestBackend("9q-square")
    char = b.characterisation
    assert char
    dev = Device(
        char.get("NodeErrors", {}),
        char.get("EdgeErrors", {}),
        char.get("Architecture", Architecture([])),
    )
    assert dev
def test_routing_no_cx() -> None:
    circ = Circuit(2, 2)
    circ.H(1)
    # c.CX(1, 2)
    circ.Rx(0.2, 0)
    circ.measure_all()
    coupling = [[1, 0], [2, 0], [2, 1], [3, 2], [3, 4], [4, 2]]
    arc = Architecture(coupling)
    physical_c = route(circ, arc)

    assert len(physical_c.get_commands()) == 4
def test_routing_measurements() -> None:
    qc = get_test_circuit(True)
    circ = qiskit_to_tk(qc)
    sim = AerBackend()
    original_results = sim.get_shots(circ, 10, seed=4)
    coupling = [[1, 0], [2, 0], [2, 1], [3, 2], [3, 4], [4, 2]]
    arc = Architecture(coupling)
    physical_c = route(circ, arc)
    Transform.DecomposeSWAPtoCX().apply(physical_c)
    Transform.DecomposeCXDirected(arc).apply(physical_c)
    Transform.OptimisePostRouting().apply(physical_c)
    assert (sim.get_shots(physical_c, 10) == original_results).all()
Exemple #7
0
def tket_run(file_name, device_name):
    connection_list = qcdevice(device_name).connection_list
    circ = circuit_from_qasm(file_name)
    circ.measure_all()
    arc = Architecture(connection_list)
    dev = Device(arc)
    routed_circ = route(circ, arc)
    # cu = CompilationUnit(routed_circ)
    Transform.DecomposeBRIDGE().apply(routed_circ)
    # pass1 = DecomposeSwapsToCXs(dev)
    # pass1.apply(cu)
    # circ2 = cu.circuit
    return routed_circ
Exemple #8
0
def generate_architecture(environment):
    coupling_map = []

    a = environment.adjacency_matrix

    for i in range(len(a)):
        for j in range(len(a[0])):
            if a[i][j] == 1:
                coupling_map.append((i, j))

    architecture = Architecture(coupling_map)

    return architecture
def process_characterisation(qc: QuantumComputer) -> dict:
    """Convert a :py:class:`pyquil.api.QuantumComputer` to a dictionary containing
    Rigetti device Characteristics

    :param qc: A quantum computer to be converted
    :type qc: QuantumComputer
    :return: A dictionary containing Rigetti device characteristics
    """
    specs = qc.device.get_specs()

    coupling_map = [[n, ni]
                    for n, neigh_dict in qc.qubit_topology().adjacency()
                    for ni, _ in neigh_dict.items()]

    node_ers_dict = {}
    link_ers_dict = {}
    t1_times_dict = {}
    t2_times_dict = {}

    device_node_fidelities = specs.f1QRBs()  # type: ignore
    device_link_fidelities = specs.fCZs()  # type: ignore
    device_fROs = specs.fROs()  # type: ignore
    device_t1s = specs.T1s()  # type: ignore
    device_t2s = specs.T2s()  # type: ignore

    for index in qc.qubits():
        error_cont = QubitErrorContainer({OpType.Rx, OpType.Rz})
        error_cont.add_readout(1 - device_fROs[index])  # type: ignore
        t1_times_dict[index] = device_t1s[index]
        t2_times_dict[index] = device_t2s[index]
        error_cont.add_error(
            (OpType.Rx, 1 - device_node_fidelities[index]))  # type: ignore
        # Rigetti use frame changes for Rz, so they effectively have no error.
        node_ers_dict[Node(index)] = error_cont

    for (a, b), fid in device_link_fidelities.items():
        error_cont = QubitErrorContainer({OpType.CZ})
        error_cont.add_error((OpType.CZ, 1 - fid))  # type: ignore
        link_ers_dict[(Node(a), Node(b))] = error_cont
        link_ers_dict[(Node(b), Node(a))] = error_cont

    arc = Architecture(coupling_map)

    characterisation = dict()
    characterisation["NodeErrors"] = node_ers_dict
    characterisation["EdgeErrors"] = link_ers_dict
    characterisation["Architecture"] = arc
    characterisation["t1times"] = t1_times_dict
    characterisation["t2times"] = t2_times_dict

    return characterisation
def test_process_characterisation_complete_noise_model() -> None:
    my_noise_model = NoiseModel()

    readout_error_0 = 0.2
    readout_error_1 = 0.3
    my_noise_model.add_readout_error(
        [
            [1 - readout_error_0, readout_error_0],
            [readout_error_0, 1 - readout_error_0],
        ],
        [0],
    )
    my_noise_model.add_readout_error(
        [
            [1 - readout_error_1, readout_error_1],
            [readout_error_1, 1 - readout_error_1],
        ],
        [1],
    )

    my_noise_model.add_quantum_error(depolarizing_error(0.6, 2), ["cx"],
                                     [0, 1])
    my_noise_model.add_quantum_error(depolarizing_error(0.5, 1), ["u3"], [0])
    my_noise_model.add_quantum_error(pauli_error([("X", 0.35), ("Z", 0.65)]),
                                     ["u2"], [0])
    my_noise_model.add_quantum_error(pauli_error([("X", 0.35), ("Y", 0.65)]),
                                     ["u1"], [0])

    back = AerBackend(my_noise_model)
    char = cast(Dict[str, Any], back.characterisation)

    dev = Device(
        char.get("NodeErrors", {}),
        char.get("EdgeErrors", {}),
        char.get("Architecture", Architecture([])),
    )

    assert char["GenericTwoQubitQErrors"][(0, 1)][0][1][0] == 0.0375
    assert char["GenericTwoQubitQErrors"][(0, 1)][0][1][15] == 0.4375
    assert char["GenericOneQubitQErrors"][0][0][1][0] == 0.125
    assert char["GenericOneQubitQErrors"][0][0][1][3] == 0.625
    assert char["GenericOneQubitQErrors"][0][1][1][0] == 0.35
    assert char["GenericOneQubitQErrors"][0][1][1][1] == 0.65
    assert char["GenericOneQubitQErrors"][0][2][1][0] == 0.35
    assert char["GenericOneQubitQErrors"][0][2][1][1] == 0.65
    assert dev.get_error(OpType.U3, dev.nodes[0]) == 0.375
    assert dev.get_error(OpType.CX, (dev.nodes[0], dev.nodes[1])) == 0.5625
    assert dev.get_error(OpType.CX, (dev.nodes[1], dev.nodes[0])) == 0.80859375
    assert char["ReadoutErrors"][0] == [[0.8, 0.2], [0.2, 0.8]]
    assert char["ReadoutErrors"][1] == [[0.7, 0.3], [0.3, 0.7]]
def test_process_characterisation() -> None:
    if not IBMQ.active_account():
        IBMQ.load_account()

    provider = IBMQ.providers(hub="ibm-q", group="open")[0]
    back = provider.get_backend("ibmq_santiago")

    char = process_characterisation(back)
    dev = Device(
        char.get("NodeErrors", {}),
        char.get("EdgeErrors", {}),
        char.get("Architecture", Architecture([])),
    )

    assert len(dev.nodes) == 5
    assert len(dev.errors_by_node) == 5
    assert len(dev.coupling) == 8
Exemple #12
0
    def __init__(self, qc_name: str, simulator: bool = True):
        """Backend for running circuits on a Rigetti QCS device or simulating with the
        QVM.

        :param qc_name: The name of the particular QuantumComputer to use. See the
            pyQuil docs for more details.
        :type qc_name: str
        :param simulator: Simulate the device with the QVM (True), or run on the QCS
            (False). Defaults to True.
        :type simulator: bool, optional
        """
        super().__init__()
        self._qc: QuantumComputer = get_qc(qc_name, as_qvm=simulator)
        self._characterisation: dict = process_characterisation(self._qc)
        self._device: Device = Device(
            self._characterisation.get("NodeErrors", {}),
            self._characterisation.get("EdgeErrors", {}),
            self._characterisation.get("Architecture", Architecture([])),
        )
def route_circuit(tk_circuit, architecture_map):
    """Route the circuit to a given architecture map

    Parameters
    ----------
    tk_circuit : pytket Circuit
        A pytket circuit
    architecture_map : list
        A list of qubit pairings, which are in the form of tuples

    Returns
    -------
    pytket Circuit
        A pytket circuit routed for the given architecture

    Notes
    -----
    IBMQ architectures are provided in the IBMLayouts module, accessible with ALALI.ibm"""
    architecture = Architecture(architecture_map)
    routed_circuit = route(tk_circuit, architecture)
    return routed_circuit
def test_process_characterisation_incomplete_noise_model() -> None:

    my_noise_model = NoiseModel()

    my_noise_model.add_quantum_error(depolarizing_error(0.6, 2), ["cx"],
                                     [0, 1])
    my_noise_model.add_quantum_error(depolarizing_error(0.5, 1), ["u3"], [1])
    my_noise_model.add_quantum_error(depolarizing_error(0.1, 1), ["u3"], [3])
    my_noise_model.add_quantum_error(pauli_error([("X", 0.35), ("Z", 0.65)]),
                                     ["u2"], [0])
    my_noise_model.add_quantum_error(pauli_error([("X", 0.35), ("Y", 0.65)]),
                                     ["u1"], [2])

    back = AerBackend(my_noise_model)
    char = cast(Dict[str, Any], back.characterisation)

    c = Circuit(4).CX(0, 1).H(2).CX(2, 1).H(3).CX(0, 3).H(1).X(0).measure_all()
    back.compile_circuit(c)
    assert back.valid_circuit(c)

    dev = Device(
        char.get("NodeErrors", {}),
        char.get("EdgeErrors", {}),
        char.get("Architecture", Architecture([])),
    )
    nodes = dev.nodes
    assert set(dev.architecture.coupling) == set([
        (nodes[0], nodes[1]),
        (nodes[0], nodes[2]),
        (nodes[0], nodes[3]),
        (nodes[1], nodes[2]),
        (nodes[1], nodes[3]),
        (nodes[2], nodes[0]),
        (nodes[2], nodes[1]),
        (nodes[2], nodes[3]),
        (nodes[3], nodes[0]),
        (nodes[3], nodes[1]),
        (nodes[3], nodes[2]),
    ])
def process_characterisation(xmon: XmonDevice) -> dict:
    """Generates a tket dictionary containing device characteristics for a Cirq
    :py:class:`XmonDevice`.

    :param xmon: The device to convert

    :return: A dictionary containing device characteristics
    """
    qb_map = {q: Node("q", q.row, q.col) for q in xmon.qubits}

    indexed_qubits = _sort_row_col(xmon.qubits)
    coupling_map = []
    for qb in indexed_qubits:
        neighbours = xmon.neighbors_of(qb)
        for x in neighbours:
            coupling_map.append((qb_map[qb], qb_map[x]))
    arc = Architecture(coupling_map)

    node_ers_dict = {}
    link_ers_dict = {}

    for qb in xmon.qubits:
        error_cont = QubitErrorContainer({OpType.PhasedX, OpType.Rz})
        error_cont.add_error((OpType.PhasedX, 0.0))
        error_cont.add_error((OpType.Rz, 0.0))
        node_ers_dict[qb_map[qb]] = error_cont

    for a, b in coupling_map:
        error_cont = QubitErrorContainer({OpType.CZ})
        error_cont.add_error((OpType.CZ, 0.0))
        link_ers_dict[(a, b)] = error_cont
        link_ers_dict[(b, a)] = error_cont

    characterisation = dict()
    characterisation["NodeErrors"] = node_ers_dict
    characterisation["EdgeErrors"] = link_ers_dict
    characterisation["Architecture"] = arc

    return characterisation
Exemple #16
0
qasm_file = 'path to your qasm file'

q_circ = QuantumCircuit.from_qasm_file(qasm_file)

tk_circ = qiskit_to_tk(q_circ)

backend = FakeMelbourne()
coupling_list = backend.configuration().coupling_map
coupling_map = CouplingMap(coupling_list)

characterisation = process_characterisation(backend)
directed_arc = Device(
    characterisation.get("NodeErrors", {}),
    characterisation.get("EdgeErrors", {}),
    characterisation.get("Architecture", Architecture([])),
)

comp_tk = tk_circ.copy()

DecomposeBoxes().apply(comp_tk)
FullPeepholeOptimise().apply(comp_tk)
CXMappingPass(directed_arc,
              NoiseAwarePlacement(directed_arc),
              directed_cx=True,
              delay_measures=True).apply(comp_tk)
DecomposeSwapsToCXs(directed_arc).apply(comp_tk)
cost = lambda c: c.n_gates_of_type(OpType.CX)
comp = RepeatWithMetricPass(
    SequencePass(
        [CommuteThroughMultis(),
Exemple #17
0
M = int(sys.argv[1])
graph = nx.random_regular_graph(3, M)
edges = list(graph.edges())
print(edges)

connection_list = [(0, 2), (1, 2), (2, 3), (1, 5), (2, 6), (3, 7), (4, 5),
                   (5, 6), (6, 7), (7, 8), (4, 10), (5, 11), (6, 12), (7, 13),
                   (9, 10), (10, 11), (11, 12), (12, 13), (9, 15), (10, 16),
                   (11, 17), (12, 18), (14, 15), (15, 16), (16, 17), (17, 18),
                   (15, 19), (16, 20), (17, 21), (19, 20), (20, 21), (20, 22)]

circ = pytket.Circuit(23, 0)
for edge in edges:
    circ.ZZPhase(angle=0.75, qubit0=edge[0], qubit1=edge[1])

routed_circ = route(circ, Architecture(connection_list), decompose_swaps=False)
Transform.DecomposeBRIDGE().apply(routed_circ)

cirq_circuit = tk_to_cirq(routed_circ)
num_swap = 0
for layer in cirq_circuit:
    for gate in layer:
        if gate.__str__().startswith('SWAP'):
            num_swap += 1
tket_depth = len(cirq_circuit)
print("num_swap", num_swap, " depth", tket_depth)
for layer in cirq_circuit:
    print(layer)

[our_depth, our_swap] = qaoa_exp_smt(M, edges)
Exemple #18
0
def _process_model(noise_model: NoiseModel, gate_set: Set[OpType]) -> dict:
    # obtain approximations for gate errors from noise model by using probability of
    #  "identity" error
    assert OpType.CX in gate_set
    # TODO explicitly check for and separate 1 and 2 qubit gates
    supported_single_optypes = gate_set.difference({OpType.CX})
    supported_single_optypes.add(OpType.Reset)
    errors = [
        e for e in noise_model.to_dict()["errors"]
        if e["type"] == "qerror" or e["type"] == "roerror"
    ]
    link_ers_dict: dict = {}
    node_ers_dict: dict = defaultdict(
        lambda: QubitErrorContainer(supported_single_optypes))
    readout_errors_dict: dict = {}
    generic_single_qerrors_dict: dict = defaultdict(lambda: list())
    generic_2q_qerrors_dict: dict = defaultdict(lambda: list())

    node_ers_qubits: set = set()
    link_ers_qubits: set = set()

    coupling_map = []
    for error in errors:
        name = error["operations"]
        if len(name) > 1:
            raise RuntimeWarning("Error applies to multiple gates.")
        if "gate_qubits" not in error:
            raise RuntimeWarning(("Please define NoiseModel without using the"
                                  " add_all_qubit_quantum_error()"
                                  " or add_all_qubit_readout_error() method."))
        name = name[0]

        qubits = error["gate_qubits"][0]
        node_ers_qubits.add(qubits[0])
        gate_fid = error["probabilities"][-1]
        if len(qubits) == 1:
            if error["type"] == "qerror":
                node_ers_dict[qubits[0]].add_error(
                    (_gate_str_2_optype[name], 1 - gate_fid))
                generic_single_qerrors_dict[qubits[0]].append(
                    (error["instructions"], error["probabilities"]))
            elif error["type"] == "roerror":
                node_ers_dict[qubits[0]].add_readout(
                    error["probabilities"][0][1])
                readout_errors_dict[qubits[0]] = error["probabilities"]
            else:
                raise RuntimeWarning("Error type not 'qerror' or 'roerror'.")
        elif len(qubits) == 2:
            # note that if multiple multi-qubit errors are added to the CX gate,
            #  the resulting noise channel is composed and reflected in probabilities
            error_cont = QubitErrorContainer(
                {_gate_str_2_optype[name]: 1 - gate_fid})
            link_ers_qubits.add(qubits[0])
            link_ers_qubits.add(qubits[1])
            link_ers_dict[tuple(qubits)] = error_cont
            # to simulate a worse reverse direction square the fidelity
            rev_error_cont = QubitErrorContainer(
                {_gate_str_2_optype[name]: 1 - gate_fid**2})
            link_ers_dict[tuple(qubits[::-1])] = rev_error_cont
            generic_2q_qerrors_dict[tuple(qubits)].append(
                (error["instructions"], error["probabilities"]))
            coupling_map.append(qubits)

    free_qubits = node_ers_qubits - link_ers_qubits

    for q in free_qubits:
        for lq in link_ers_qubits:
            coupling_map.append([q, lq])
            coupling_map.append([lq, q])

    for pair in itertools.permutations(free_qubits, 2):
        coupling_map.append(pair)

    # convert qubits to architecture Nodes
    characterisation = {}
    node_ers_dict = {
        Node(q_index): ers
        for q_index, ers in node_ers_dict.items()
    }
    link_ers_dict = {(Node(q_indices[0]), Node(q_indices[1])): ers
                     for q_indices, ers in link_ers_dict.items()}

    characterisation["NodeErrors"] = node_ers_dict
    characterisation["EdgeErrors"] = link_ers_dict
    characterisation["ReadoutErrors"] = readout_errors_dict
    characterisation["GenericOneQubitQErrors"] = generic_single_qerrors_dict
    characterisation["GenericTwoQubitQErrors"] = generic_2q_qerrors_dict
    characterisation["Architecture"] = Architecture(coupling_map)

    return characterisation
Exemple #19
0
cu = CompilationUnit(circ)
pass2.apply(cu)
print(cu.circuit.get_commands())

# ## Targeting devices and architectures

# If we are given a target architecture, we can generate passes tailored to it.
#
# In `pytket` an architecture is defined by a connectivity graph, i.e. a list of pairs of qubits capable of executing two-qubit operations. For example, we can represent a 5-qubit linear architecture, with qubits labelled `n[i]`, as follows:

from pytket.routing import Architecture
from pytket.circuit import Node

n = [Node("n", i) for i in range(5)]

arc = Architecture([[n[0], n[1]], [n[1], n[2]], [n[2], n[3]], [n[3], n[4]]])

# A `Device` is a model of a physical device, which encapsulates both its `Architecture` and its gate noise characteristics. Ignoring the latter, we can construct a 'noise-free' `Device` directly from an `Architecture`:

from pytket.device import Device

dev = Device(arc)

# Suppose we have a circuit that we wish to run on this device:

circ = Circuit(5)
circ.CX(0, 1)
circ.H(0)
circ.Z(1)
circ.CX(0, 3)
circ.Rx(1.5, 3)
Exemple #20
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),
        )
Exemple #21
0
    def __init__(
        self,
        backend_name: str,
        hub: Optional[str] = None,
        group: Optional[str] = None,
        project: Optional[str] = None,
        monitor: bool = True,
    ):
        """A backend for running circuits on remote IBMQ devices.

        :param backend_name: Name of the IBMQ device, e.g. `ibmqx4`,
         `ibmq_16_melbourne`.
        :type backend_name: str
        :param hub: Name of the IBMQ hub to use for the provider.
         If None, just uses the first hub found. Defaults to None.
        :type hub: Optional[str], optional
        :param group: Name of the IBMQ group to use for the provider. Defaults to None.
        :type group: Optional[str], optional
        :param project: Name of the IBMQ project to use for the provider.
         Defaults to None.
        :type project: Optional[str], optional
        :param monitor: Use the IBM job monitor. Defaults to True.
        :type monitor: bool, optional
        :raises ValueError: If no IBMQ account is loaded and none exists on the disk.
        """
        super().__init__()
        if not IBMQ.active_account():
            if IBMQ.stored_account():
                IBMQ.load_account()
            else:
                raise NoIBMQAccountError()
        provider_kwargs = {}
        if hub:
            provider_kwargs["hub"] = hub
        if group:
            provider_kwargs["group"] = group
        if project:
            provider_kwargs["project"] = project

        try:
            if provider_kwargs:
                provider = IBMQ.get_provider(**provider_kwargs)
            else:
                provider = IBMQ.providers()[0]
        except qiskit.providers.ibmq.exceptions.IBMQProviderError as err:
            logging.warn(
                ("Provider was not specified enough, specify hub,"
                 "group and project correctly (check your IBMQ account)."))
            raise err
        self._backend: "_QiskIBMQBackend" = provider.get_backend(backend_name)
        self._config: "QasmBackendConfiguration" = self._backend.configuration(
        )
        self._gate_set: Set[OpType]
        # simulator i.e. "ibmq_qasm_simulator" does not have `supported_instructions`
        # attribute
        self._gate_set = _tk_gate_set(self._backend)

        self._mid_measure = self._config.simulator or self._config.multi_meas_enabled

        self._legacy_gateset = OpType.V not in self._gate_set

        if self._legacy_gateset:
            if not self._gate_set >= {
                    OpType.U1, OpType.U2, OpType.U3, OpType.CX
            }:
                raise NotImplementedError(
                    f"Gate set {self._gate_set} unsupported")
            self._rebase_pass = RebaseIBM()
        else:
            if not self._gate_set >= {
                    OpType.X, OpType.V, OpType.Rz, OpType.CX
            }:
                raise NotImplementedError(
                    f"Gate set {self._gate_set} unsupported")
            self._rebase_pass = RebaseCustom(
                {OpType.CX},
                Circuit(2).CX(0, 1),
                {OpType.X, OpType.V, OpType.Rz},
                _tk1_to_x_v_rz,
            )

        if hasattr(self._config, "max_experiments"):
            self._max_per_job = self._config.max_experiments
        else:
            self._max_per_job = 1

        self._characterisation: Dict[str, Any] = process_characterisation(
            self._backend)
        self._device = Device(
            self._characterisation.get("NodeErrors", {}),
            self._characterisation.get("EdgeErrors", {}),
            self._characterisation.get("Architecture", Architecture([])),
        )
        self._monitor = monitor

        self._MACHINE_DEBUG = False
Exemple #22
0
                [18, 15], [19, 20], [19, 16], [20, 21], [20, 19], [21, 28],
                [21, 22], [21, 20], [22, 23], [22, 21], [23, 24], [23, 22],
                [23, 17], [24, 25], [24, 23], [25, 29], [25, 26], [25, 24],
                [26, 27], [26, 25], [27, 26], [27, 18], [28, 32], [28, 21],
                [29, 36], [29, 25], [30, 39], [30, 31], [31, 32], [31, 30],
                [32, 33], [32, 31], [32, 28], [33, 34], [33, 32], [34, 40],
                [34, 35], [34, 33], [35, 36], [35, 34], [36, 37], [36, 35],
                [36, 29], [37, 38], [37, 36], [38, 41], [38, 37], [39, 42],
                [39, 30], [40, 46], [40, 34], [41, 50], [41, 38], [42, 43],
                [42, 39], [43, 44], [43, 42], [44, 51], [44, 45], [44, 43],
                [45, 46], [45, 44], [46, 47], [46, 45], [46, 40], [47, 48],
                [47, 46], [48, 52], [48, 49], [48, 47], [49, 50], [49, 48],
                [50, 49], [50, 41], [51, 44], [52, 48]]

### devices:
rigetti_device = Device(Architecture(rigetti_coupling))
google_sycamore_device = Device(Architecture(google_coupling))
ibm_rochester_device = Device(Architecture(ibm_coupling))
all_device = Device(Architecture(all_to_all_coupling))


def gen_tket_pass(optimisepass, backend: str):
    if backend == _BACKEND_FULL:
        return optimisepass
    elif backend == _BACKEND_RIGETTI:
        final_pass = RebaseQuil()
        device = rigetti_device
    elif backend == _BACKEND_GOOGLE:
        final_pass = RebaseCirq()
        device = google_sycamore_device
    elif backend == _BACKEND_IBM:
Exemple #23
0
# The Architecture class is used in ```pytket``` to hold information about a quantum architectures connectivity constraints. An Architecture object requires a coupling map to be created i.e. a list of edges between qubits which defines where two-qubit primitives may be executed. A coupling map can be produced naively by the integer indexing of nodes and edges in your architecture. We also use networkx and matplotlib to draw a graph representation of our Architecture.

import networkx as nx
import matplotlib.pyplot as plt


def draw_graph(coupling_map):
    coupling_graph = nx.Graph(coupling_map)
    nx.draw(coupling_graph,
            labels={node: node
                    for node in coupling_graph.nodes()})


simple_coupling_map = [(0, 1), (1, 2), (2, 3)]
simple_architecture = Architecture(simple_coupling_map)
draw_graph(simple_coupling_map)

# Alternatively we could use the `Node` class to assign our nodes - you will see why this can be helpful later. Lets create an Architecture with an identical graph in this manner.

from pytket.circuit import Node

node_0 = Node("example_register", 0)
node_1 = Node("example_register", 1)
node_2 = Node("example_register", 2)
node_3 = Node("example_register", 3)

id_coupling_map = [(node_0, node_1), (node_1, node_2), (node_2, node_3)]
id_architecture = Architecture(id_coupling_map)
draw_graph(id_coupling_map)
Exemple #24
0
def process_characterisation(backend: BaseBackend) -> Dict[str, Any]:
    """Convert a :py:class:`qiskit.BaseBackend` to a dictionary
     containing device Characteristics

    :param backend: A backend to be converted
    :type backend: BaseBackend
    :return: A dictionary containing device characteristics
    :rtype: dict
    """
    gate_set = _tk_gate_set(backend)
    assert OpType.CX in gate_set
    # TODO explicitly check for and separate 1 and 2 qubit gates
    properties = cast("BackendProperties", backend.properties())

    def return_value_if_found(iterator: Iterable["Nduv"],
                              name: str) -> Optional[Any]:
        try:
            first_found = next(filter(lambda item: item.name == name,
                                      iterator))
        except StopIteration:
            return None
        if hasattr(first_found, "value"):
            return first_found.value
        return None

    config = backend.configuration()
    coupling_map = config.coupling_map
    n_qubits = config.n_qubits
    if coupling_map is None:
        # Assume full connectivity
        arc = FullyConnected(n_qubits)
        link_ers_dict = {}
    else:
        arc = Architecture(coupling_map)
        link_ers_dict = {
            tuple(pair): QubitErrorContainer({OpType.CX})
            for pair in coupling_map
        }

    node_ers_dict = {}
    supported_single_optypes = gate_set.difference({OpType.CX})

    t1_times_dict = {}
    t2_times_dict = {}
    frequencies_dict = {}
    gate_times_dict = {}

    if properties is not None:
        for index, qubit_info in enumerate(properties.qubits):
            error_cont = QubitErrorContainer(supported_single_optypes)
            error_cont.add_readout(
                return_value_if_found(qubit_info, "readout_error"))

            t1_times_dict[index] = return_value_if_found(qubit_info, "T1")
            t2_times_dict[index] = return_value_if_found(qubit_info, "T2")
            frequencies_dict[index] = return_value_if_found(
                qubit_info, "frequency")

            node_ers_dict[index] = error_cont

        for gate in properties.gates:
            name = gate.gate
            if name in _gate_str_2_optype:
                optype = _gate_str_2_optype[name]
                qubits = gate.qubits
                gate_error = return_value_if_found(gate.parameters,
                                                   "gate_error")
                gate_error = gate_error if gate_error else 0.0
                gate_length = return_value_if_found(gate.parameters,
                                                    "gate_length")
                gate_length = gate_length if gate_length else 0.0
                gate_times_dict[(optype, tuple(qubits))] = gate_length
                # add gate fidelities to their relevant lists
                if len(qubits) == 1:
                    node_ers_dict[qubits[0]].add_error((optype, gate_error))
                elif len(qubits) == 2:
                    link_ers_dict[tuple(qubits)].add_error(
                        (optype, gate_error))
                    opposite_link = tuple(qubits[::-1])
                    if opposite_link not in coupling_map:
                        # to simulate a worse reverse direction square the fidelity
                        link_ers_dict[opposite_link] = QubitErrorContainer(
                            {OpType.CX})
                        link_ers_dict[opposite_link].add_error(
                            (optype, 2 * gate_error))

    # convert qubits to architecture Nodes
    node_ers_dict = {
        Node(q_index): ers
        for q_index, ers in node_ers_dict.items()
    }
    link_ers_dict = {(Node(q_indices[0]), Node(q_indices[1])): ers
                     for q_indices, ers in link_ers_dict.items()}

    characterisation: Dict[str, Any] = dict()
    characterisation["NodeErrors"] = node_ers_dict
    characterisation["EdgeErrors"] = link_ers_dict
    characterisation["Architecture"] = arc
    characterisation["t1times"] = t1_times_dict
    characterisation["t2times"] = t2_times_dict
    characterisation["Frequencies"] = frequencies_dict
    characterisation["GateTimes"] = gate_times_dict

    return characterisation