Source code for pyquil.quantum_processor.transformers.graph_to_compiler_isa

from typing import Union

import numpy as np
from typing import List, Optional, cast
from pyquil.external.rpcq import (
    GateInfo,
    MeasureInfo,
    Supported1QGate,
    Supported2QGate,
    CompilerISA,
    add_qubit,
    add_edge,
)

import networkx as nx


DEFAULT_1Q_GATES = [
    Supported1QGate.I,
    Supported1QGate.RX,
    Supported1QGate.RZ,
    Supported1QGate.MEASURE,
]
DEFAULT_2Q_GATES = [
    Supported2QGate.CZ,
    Supported2QGate.XY,
]


[docs]def graph_to_compiler_isa( graph: nx.Graph, gates_1q: Optional[List[str]] = None, gates_2q: Optional[List[str]] = None ) -> CompilerISA: """ Generate an ``CompilerISA`` object from a NetworkX graph and list of 1Q and 2Q gates. May raise ``GraphGateError`` if the specified gates are not supported. :param graph: The graph topology of the quantum_processor. :param gates_1q: A list of 1Q gate names to be made available for all qubits in the quantum_processor. Defaults to ``DEFAULT_1Q_GATES``. :param gates_2q: A list of 2Q gate names to be made available for all edges in the quantum_processor. Defaults to ``DEFAULT_2Q_GATES``. """ gates_1q = gates_1q or DEFAULT_1Q_GATES.copy() gates_2q = gates_2q or DEFAULT_2Q_GATES.copy() quantum_processor = CompilerISA() qubit_gates = [] for gate in gates_1q: qubit_gates.extend(_transform_qubit_operation_to_gates(gate)) all_qubits = list(range(max(graph.nodes) + 1)) for i in all_qubits: qubit = add_qubit(quantum_processor, i) qubit.gates = qubit_gates qubit.dead = i not in graph.nodes edge_gates = [] for gate in gates_2q: edge_gates.extend(_transform_edge_operation_to_gates(gate)) for a, b in graph.edges: edge = add_edge(quantum_processor, a, b) edge.gates = edge_gates return quantum_processor
[docs]def compiler_isa_to_graph(compiler_isa: CompilerISA) -> nx.Graph: """ Generate an ``nx.Graph`` based on the qubits and edges of any ``CompilerISA``. """ return nx.from_edgelist([int(i) for i in edge.ids] for edge in compiler_isa.edges.values())
[docs]class GraphGateError(ValueError): """ Signals an error when creating a ``CompilerISA`` from an ``nx.Graph``. This may raise as a consequence of unsupported gates. """ pass
def _make_i_gates() -> List[GateInfo]: return [GateInfo(operator=Supported1QGate.I, parameters=[], arguments=["_"])] def _make_measure_gates() -> List[MeasureInfo]: return [ MeasureInfo(operator=Supported1QGate.MEASURE, qubit="_", target="_"), MeasureInfo(operator=Supported1QGate.MEASURE, qubit="_", target=None), ] def _make_rx_gates() -> List[GateInfo]: gates = [] for param in [0.0, np.pi, -np.pi, np.pi / 2, -np.pi / 2]: gates.append(GateInfo(operator=Supported1QGate.RX, parameters=[param], arguments=["_"])) return gates def _make_rz_gates() -> List[GateInfo]: return [GateInfo(operator=Supported1QGate.RZ, parameters=["theta"], arguments=["_"])] def _make_wildcard_1q_gates() -> List[GateInfo]: return [GateInfo(operator="_", parameters=["_"], arguments=["_"])] def _transform_qubit_operation_to_gates( operation_name: str, ) -> List[Union[GateInfo, MeasureInfo]]: if operation_name == Supported1QGate.I: return cast(List[Union[GateInfo, MeasureInfo]], _make_i_gates()) elif operation_name == Supported1QGate.RX: return cast(List[Union[GateInfo, MeasureInfo]], _make_rx_gates()) elif operation_name == Supported1QGate.RZ: return cast(List[Union[GateInfo, MeasureInfo]], _make_rz_gates()) elif operation_name == Supported1QGate.MEASURE: return cast(List[Union[GateInfo, MeasureInfo]], _make_measure_gates()) elif operation_name == Supported1QGate.WILDCARD: return cast(List[Union[GateInfo, MeasureInfo]], _make_wildcard_1q_gates()) else: raise GraphGateError("Unsupported graph qubit operation: {}".format(operation_name)) def _make_cz_gates() -> List[GateInfo]: return [GateInfo(operator=Supported2QGate.CZ, parameters=[], arguments=["_", "_"])] def _make_iswap_gates() -> List[GateInfo]: return [GateInfo(operator=Supported2QGate.ISWAP, parameters=[], arguments=["_", "_"])] def _make_cphase_gates() -> List[GateInfo]: return [GateInfo(operator=Supported2QGate.CPHASE, parameters=["theta"], arguments=["_", "_"])] def _make_xy_gates() -> List[GateInfo]: return [GateInfo(operator=Supported2QGate.XY, parameters=["theta"], arguments=["_", "_"])] def _make_wildcard_2q_gates() -> List[GateInfo]: return [GateInfo(operator="_", parameters=["_"], arguments=["_", "_"])] def _transform_edge_operation_to_gates(operation_name: str) -> List[GateInfo]: if operation_name == Supported2QGate.CZ: return _make_cz_gates() elif operation_name == Supported2QGate.ISWAP: return _make_iswap_gates() elif operation_name == Supported2QGate.CPHASE: return _make_cphase_gates() elif operation_name == Supported2QGate.XY: return _make_xy_gates() elif operation_name == Supported2QGate.WILDCARD: return _make_wildcard_2q_gates() else: raise GraphGateError("Unsupported graph edge operation: {}".format(operation_name))