from typing import List, Optional
import httpx
import networkx as nx
from qcs_api_client.models import InstructionSetArchitecture
from qcs_api_client.operations.sync import get_instruction_set_architecture
from pyquil.api import QCSClientConfiguration
from pyquil.api._qcs_client import qcs_client
from pyquil.external.rpcq import CompilerISA
from pyquil.noise import NoiseModel
from pyquil.quantum_processor import AbstractQuantumProcessor
from pyquil.quantum_processor.transformers import qcs_isa_to_compiler_isa, qcs_isa_to_graph
[docs]class QCSQuantumProcessor(AbstractQuantumProcessor):
"""
An AbstractQuantumProcessor initialized with an ``InstructionSetArchitecture`` returned
from the QCS API. Notably, this class is able to serialize a ``CompilerISA`` based
on the architecture instructions.
"""
quantum_processor_id: str
_isa: InstructionSetArchitecture
noise_model: Optional[NoiseModel]
def __init__(
self,
quantum_processor_id: str,
isa: InstructionSetArchitecture,
noise_model: Optional[NoiseModel] = None,
):
"""
Initialize a new QCSQuantumProcessor.
:param quantum_processor_id: The id of the quantum processor.
:param isa: The QCS API ``InstructionSetArchitecture``.
:param noise_model: An optional ``NoiseModel`` for configuring a noisy quantum_processor on the ``QVM``.
"""
self.quantum_processor_id = quantum_processor_id
self._isa = isa
self.noise_model = noise_model
[docs] def qubits(self) -> List[int]:
return sorted(node.node_id for node in self._isa.architecture.nodes)
[docs] def qubit_topology(self) -> nx.Graph:
return qcs_isa_to_graph(self._isa)
[docs] def to_compiler_isa(self) -> CompilerISA:
return qcs_isa_to_compiler_isa(self._isa)
def __str__(self) -> str:
return "<QCSQuantumProcessor {}>".format(self.quantum_processor_id)
def __repr__(self) -> str:
return str(self)
[docs]def get_qcs_quantum_processor(
quantum_processor_id: str,
client_configuration: Optional[QCSClientConfiguration] = None,
timeout: float = 10.0,
) -> QCSQuantumProcessor:
"""
Retrieve an instruction set architecture for the specified ``quantum_processor_id`` and initialize a
``QCSQuantumProcessor`` with it.
:param quantum_processor_id: QCS ID for the quantum processor.
:param timeout: Time limit for request, in seconds.
:param client_configuration: Optional client configuration. If none is provided, a default one will
be loaded.
:return: A ``QCSQuantumProcessor`` with the requested ISA.
"""
client_configuration = client_configuration or QCSClientConfiguration.load()
with qcs_client(client_configuration=client_configuration, request_timeout=timeout) as client: # type: httpx.Client
isa = get_instruction_set_architecture(client=client, quantum_processor_id=quantum_processor_id).parsed
return QCSQuantumProcessor(quantum_processor_id=quantum_processor_id, isa=isa)