Skip to content

Commit

Permalink
Merge branch 'main' into dqc
Browse files Browse the repository at this point in the history
  • Loading branch information
edyounis committed Sep 11, 2024
2 parents 5f219aa + e4b212e commit b9791e6
Show file tree
Hide file tree
Showing 19 changed files with 318 additions and 73 deletions.
57 changes: 50 additions & 7 deletions bqskit/compiler/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
from bqskit.compiler.compiler import Compiler
from bqskit.compiler.machine import MachineModel
from bqskit.compiler.passdata import PassData
from bqskit.compiler.registry import _compile_registry
from bqskit.compiler.registry import _compile_circuit_registry
from bqskit.compiler.registry import _compile_statemap_registry
from bqskit.compiler.registry import _compile_stateprep_registry
from bqskit.compiler.registry import _compile_unitary_registry
from bqskit.compiler.registry import model_registered_target_types
from bqskit.compiler.workflow import Workflow
from bqskit.compiler.workflow import WorkflowLike
from bqskit.ir.circuit import Circuit
Expand Down Expand Up @@ -622,8 +626,11 @@ def type_and_check_input(input: CompilationInputLike) -> CompilationInput:
if isinstance(typed_input, Circuit):
in_circuit = typed_input

elif isinstance(typed_input, UnitaryMatrix):
in_circuit = Circuit.from_unitary(typed_input)

else:
in_circuit = Circuit(1)
in_circuit = Circuit(typed_input.num_qudits, typed_input.radixes)

# Perform the compilation
out, data = compiler.compile(in_circuit, workflow, True)
Expand Down Expand Up @@ -669,11 +676,7 @@ def build_workflow(
if model is None:
model = MachineModel(input.num_qudits, radixes=input.radixes)

# Use a registered workflow if model is found in the registry for a given
# optimization_level
if model in _compile_registry:
if optimization_level in _compile_registry[model]:
return _compile_registry[model][optimization_level]
model_registered_types = model_registered_target_types(model)

if isinstance(input, Circuit):
if input.num_qudits > max_synthesis_size:
Expand All @@ -691,6 +694,16 @@ def build_workflow(
'Unable to compile circuit with gate larger than'
' max_synthesis_size.\nConsider adjusting it.',
)
# Use a registered workflow if model is found in the circuit registry
# for a given optimization_level
if model in _compile_circuit_registry:
if optimization_level in _compile_circuit_registry[model]:
return _compile_circuit_registry[model][optimization_level]
elif len(model_registered_types) > 0:
m = f'MachineModel {model} is registered for inputs of type in '
m += f'{model_registered_types}, but input is {type(input)}. '
m += f'You may need to register a Workflow for type {type(input)}.'
warnings.warn(m)

return _circuit_workflow(
model,
Expand All @@ -708,6 +721,16 @@ def build_workflow(
'Unable to compile unitary with size larger than'
' max_synthesis_size.\nConsider adjusting it.',
)
# Use a registered workflow if model is found in the unitary registry
# for a given optimization_level
if model in _compile_unitary_registry:
if optimization_level in _compile_unitary_registry[model]:
return _compile_unitary_registry[model][optimization_level]
elif len(model_registered_types) > 0:
m = f'MachineModel {model} is registered for inputs of type in '
m += f'{model_registered_types}, but input is {type(input)}. '
m += f'You may need to register a Workflow for type {type(input)}.'
warnings.warn(m)

return _synthesis_workflow(
input,
Expand All @@ -726,6 +749,16 @@ def build_workflow(
'Unable to compile states with size larger than'
' max_synthesis_size.\nConsider adjusting it.',
)
# Use a registered workflow if model is found in the stateprep registry
# for a given optimization_level
if model in _compile_stateprep_registry:
if optimization_level in _compile_stateprep_registry[model]:
return _compile_stateprep_registry[model][optimization_level]
elif len(model_registered_types) > 0:
m = f'MachineModel {model} is registered for inputs of type in '
m += f'{model_registered_types}, but input is {type(input)}. '
m += f'You may need to register a Workflow for type {type(input)}.'
warnings.warn(m)

return _stateprep_workflow(
input,
Expand All @@ -744,6 +777,16 @@ def build_workflow(
'Unable to compile state systems with size larger than'
' max_synthesis_size.\nConsider adjusting it.',
)
# Use a registered workflow if model is found in the statemap registry
# for a given optimization_level
if model in _compile_statemap_registry:
if optimization_level in _compile_statemap_registry[model]:
return _compile_statemap_registry[model][optimization_level]
elif len(model_registered_types) > 0:
m = f'MachineModel {model} is registered for inputs of type in '
m += f'{model_registered_types}, but input is {type(input)}. '
m += f'You may need to register a Workflow for type {type(input)}.'
warnings.warn(m)

return _statemap_workflow(
input,
Expand Down
30 changes: 25 additions & 5 deletions bqskit/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import atexit
import functools
import logging
import pickle
import signal
import subprocess
import sys
Expand Down Expand Up @@ -312,7 +313,15 @@ def submit(
return task.task_id

def status(self, task_id: uuid.UUID) -> CompilationStatus:
"""Retrieve the status of the specified task."""
"""
Retrieve the status of the specified task.
Args:
task_id (uuid.UUID): The ID of the task to check.
Returns:
CompilationStatus: The status of the task.
"""
msg, payload = self._send_recv(RuntimeMessage.STATUS, task_id)
if msg != RuntimeMessage.STATUS:
raise RuntimeError(f'Unexpected message type: {msg}.')
Expand Down Expand Up @@ -406,7 +415,12 @@ def _send(self, msg: RuntimeMessage, payload: Any) -> None:
except Exception as e:
self.conn = None
self.close()
raise RuntimeError('Server connection unexpectedly closed.') from e
if isinstance(e, (EOFError, ConnectionResetError)):
raise RuntimeError('Server connection unexpectedly closed.')
else:
raise RuntimeError(
'Server connection unexpectedly closed.',
) from e

def _send_recv(
self,
Expand Down Expand Up @@ -439,9 +453,15 @@ def _recv_handle_log_error(self) -> tuple[RuntimeMessage, Any]:
msg, payload = self.conn.recv()

if msg == RuntimeMessage.LOG:
logger = logging.getLogger(payload.name)
if logger.isEnabledFor(payload.levelno):
logger.handle(payload)
record = pickle.loads(payload)
if isinstance(record, logging.LogRecord):
logger = logging.getLogger(record.name)
if logger.isEnabledFor(record.levelno):
logger.handle(record)
else:
name, levelno, msg = record
logger = logging.getLogger(name)
logger.log(levelno, msg)

elif msg == RuntimeMessage.ERROR:
raise RuntimeError(payload)
Expand Down
73 changes: 64 additions & 9 deletions bqskit/compiler/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,44 @@
from bqskit.compiler.workflow import WorkflowLike


_compile_registry: dict[MachineModel, dict[int, Workflow]] = {}
_compile_circuit_registry: dict[MachineModel, dict[int, Workflow]] = {}
_compile_unitary_registry: dict[MachineModel, dict[int, Workflow]] = {}
_compile_stateprep_registry: dict[MachineModel, dict[int, Workflow]] = {}
_compile_statemap_registry: dict[MachineModel, dict[int, Workflow]] = {}


def model_registered_target_types(key: MachineModel) -> list[str]:
"""
Return a list of target_types for which key is registered.
Args:
key (MachineModel): A MachineModel to check for.
Returns:
(list[str]): If `key` has been registered in any of the registry, the
name of that target type will be contained in this list.
"""
global _compile_circuit_registry
global _compile_unitary_registry
global _compile_stateprep_registry
global _compile_statemap_registry
registered_types = []
if key in _compile_circuit_registry:
registered_types.append('circuit')
if key in _compile_unitary_registry:
registered_types.append('unitary')
if key in _compile_stateprep_registry:
registered_types.append('stateprep')
if key in _compile_statemap_registry:
registered_types.append('statemap')
return registered_types


def register_workflow(
key: MachineModel,
workflow: WorkflowLike,
optimization_level: int,
target_type: str = 'circuit',
) -> None:
"""
Register a workflow for a given MachineModel.
Expand All @@ -34,30 +65,54 @@ def register_workflow(
be executed if the MachineModel in a call to `compile` matches
`key`. If `key` is already registered, a warning will be logged.
optimization_level ptional[int): The optimization level with which
to register the workflow. If no level is provided, the Workflow
will be registered as level 1.
optimization_level (int): The optimization level with which to
register the workflow.
target_type (str): Register a workflow for targets of this type. Must
be 'circuit', 'unitary', 'stateprep', or 'statemap'.
(Default: 'circuit')
Example:
model_t = SpecificMachineModel(num_qudits, radixes)
workflow = [QuickPartitioner(3), NewFangledOptimization()]
register_workflow(model_t, workflow, level)
register_workflow(model_t, workflow, level, 'circuit')
...
new_circuit = compile(circuit, model_t, optimization_level=level)
Raises:
Warning: If a workflow for a given optimization_level is overwritten.
ValueError: If `target_type` is not 'circuit', 'unitary', 'stateprep',
or 'statemap'.
"""
if target_type not in ['circuit', 'unitary', 'stateprep', 'statemap']:
m = 'target_type must be "circuit", "unitary", "stateprep", or '
m += f'"statemap", got {target_type}.'
raise ValueError(m)

if target_type == 'circuit':
global _compile_circuit_registry
_compile_registry = _compile_circuit_registry
elif target_type == 'unitary':
global _compile_unitary_registry
_compile_registry = _compile_unitary_registry
elif target_type == 'stateprep':
global _compile_stateprep_registry
_compile_registry = _compile_stateprep_registry
else:
global _compile_statemap_registry
_compile_registry = _compile_statemap_registry

workflow = Workflow(workflow)

global _compile_registry
new_workflow = {optimization_level: workflow}
if key in _compile_registry:
if optimization_level in _compile_registry[key]:
m = f'Overwritting workflow for {key} at level '
m += f'{optimization_level}. If multiple Namespace packages are '
m += 'installed, ensure that their __init__.py files do not '
m += 'attempt to overwrite the same default Workflows.'
m += f'{optimization_level} for target type {target_type}.'
m += 'If multiple Namespace packages are installed, ensure'
m += 'that their __init__.py files do not attempt to'
m += 'overwrite the same default Workflows.'
warnings.warn(m)
_compile_registry[key].update(new_workflow)
else:
Expand Down
9 changes: 9 additions & 0 deletions bqskit/ext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
Aspen11Model
AspenM2Model
ANKAA2Model
ANKAA9Q3Model
H1_1Model
H1_2Model
H2_1Model
Sycamore23Model
SycamoreModel
model_from_backend
Expand Down Expand Up @@ -64,8 +67,11 @@
from bqskit.ext.qiskit.translate import qiskit_to_bqskit
from bqskit.ext.quantinuum import H1_1Model
from bqskit.ext.quantinuum import H1_2Model
from bqskit.ext.quantinuum import H2_1Model
from bqskit.ext.qutip.translate import bqskit_to_qutip
from bqskit.ext.qutip.translate import qutip_to_bqskit
from bqskit.ext.rigetti import ANKAA2Model
from bqskit.ext.rigetti import ANKAA9Q3Model
from bqskit.ext.rigetti import Aspen11Model
from bqskit.ext.rigetti import AspenM2Model
from bqskit.ext.supermarq import supermarq_critical_depth
Expand Down Expand Up @@ -95,6 +101,9 @@
'AspenM2Model',
'H1_1Model',
'H1_2Model',
'H2_1Model',
'ANKAA2Model',
'ANKAA9Q3Model',
'Sycamore23Model',
'SycamoreModel',
]
23 changes: 0 additions & 23 deletions bqskit/ext/honeywell.py

This file was deleted.

5 changes: 3 additions & 2 deletions bqskit/ext/quantinuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

from bqskit.compiler.machine import MachineModel
from bqskit.ir.gate import Gate
from bqskit.ir.gates.constant.zz import ZZGate
from bqskit.ir.gates.parameterized.rz import RZGate
from bqskit.ir.gates.parameterized.rzz import RZZGate
from bqskit.ir.gates.parameterized.u1q import U1qPi2Gate
from bqskit.ir.gates.parameterized.u1q import U1qPiGate

quantinuum_gate_set: set[Gate] = {U1qPiGate, U1qPi2Gate, RZGate(), ZZGate()}
quantinuum_gate_set: set[Gate] = {U1qPiGate, U1qPi2Gate, RZGate(), RZZGate()}

H1_1Model = MachineModel(20, None, quantinuum_gate_set)
H1_2Model = MachineModel(20, None, quantinuum_gate_set)
H2_1Model = MachineModel(56, None, quantinuum_gate_set)
13 changes: 13 additions & 0 deletions bqskit/ext/rigetti.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@

from bqskit.compiler.machine import MachineModel
from bqskit.ir.gates.constant.cz import CZGate
from bqskit.ir.gates.constant.iswap import ISwapGate
from bqskit.ir.gates.constant.sx import SXGate
from bqskit.ir.gates.constant.x import XGate
from bqskit.ir.gates.parameterized.rz import RZGate
from bqskit.qis.graph import CouplingGraph

rigetti_gate_set = {SXGate(), XGate(), RZGate(), CZGate()}

ankaa_gate_set = {SXGate(), XGate(), RZGate(), CZGate(), ISwapGate()}

_aspen_11_coupling_graph = CouplingGraph([
# Ring 1
(0, 1), (1, 2), (2, 3), (3, 4),
Expand Down Expand Up @@ -79,10 +82,20 @@
_aspen_m2_coupling_graph = CouplingGraph(_links)
"""Retrieved August 31, 2022: https://qcs.rigetti.com/qpus."""

_ankaa_9q_3_coupling_graph = CouplingGraph.grid(3, 3)
"""Retrieved September 11, 2024: https://qcs.rigetti.com/qpus."""

_ankaa_2_coupling_graph = CouplingGraph.grid(7, 12)
"""Retrieved September 11, 2024: https://qcs.rigetti.com/qpus."""

Aspen11Model = MachineModel(40, _aspen_11_coupling_graph, rigetti_gate_set)
"""A BQSKit MachineModel for Rigetti's Aspen-11 quantum processor."""

AspenM2Model = MachineModel(80, _aspen_m2_coupling_graph, rigetti_gate_set)
"""A BQSKit MachineModel for Rigetti's Aspen-M-2 quantum processor."""

ANKAA2Model = MachineModel(84, _ankaa_2_coupling_graph, ankaa_gate_set)

ANKAA9Q3Model = MachineModel(9, _ankaa_9q_3_coupling_graph, ankaa_gate_set)

__all__ = ['Aspen11Model', 'AspenM2Model']
1 change: 1 addition & 0 deletions bqskit/ir/gates/circuitgate.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ def get_qasm_gate_def(self) -> str:
', '.join([str(p) for p in params]),
', q'.join([str(q) for q in op.location]),
).replace('()', '')
param_index += op.num_params
ret += '}\n'
return ret

Expand Down
Loading

0 comments on commit b9791e6

Please sign in to comment.