Skip to content

Commit

Permalink
Placement and gate optimisation for QIR via TKET (#78)
Browse files Browse the repository at this point in the history
GitOrigin-RevId: a3df19b390fd5204bf13cde9551317c26a602d48
  • Loading branch information
lcauser-oqc authored and copybara-bot committed Feb 19, 2025
1 parent 37455c6 commit 51d60d0
Show file tree
Hide file tree
Showing 10 changed files with 504 additions and 64 deletions.
16 changes: 0 additions & 16 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/qat/compiler/transform_passes.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
Pulse,
)
from qat.purr.integrations.qasm import CloudQasmParser, Qasm3Parser
from qat.purr.integrations.tket import run_tket_optimizations
from qat.purr.integrations.tket import run_tket_optimizations_qasm


class PhaseOptimisation(TransformPass):
Expand Down Expand Up @@ -194,7 +194,7 @@ def run_qasm_optimisation(self, qasm_string, optimizations, met_mgr, *args, **kw
isinstance(optimizations, Tket)
and optimizations.tket_optimizations != TketOptimizations.Empty
):
qasm_string = run_tket_optimizations(
qasm_string = run_tket_optimizations_qasm(
qasm_string, optimizations.tket_optimizations, self.hardware
)

Expand Down
36 changes: 30 additions & 6 deletions src/qat/purr/compiler/frontends.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
from typing import Tuple

import regex
from compiler_config.config import CompilerConfig, Languages, get_optimizer_config
from compiler_config.config import (
CompilerConfig,
Languages,
Tket,
TketOptimizations,
get_optimizer_config,
)

from qat.purr.backends.calibrations.remote import find_calibration
from qat.purr.backends.realtime_chip_simulator import get_default_RTCS_hardware
Expand Down Expand Up @@ -94,15 +100,33 @@ def _parse_from_file(
metrics = CompilationMetrics()
metrics.enable(compiler_config.metrics)

parser = QIRParser(hardware)
if compiler_config.optimizations is None:
compiler_config.optimizations = get_optimizer_config(Languages.QIR)

if compiler_config.results_format.format is not None:
parser.results_format = compiler_config.results_format.format
with log_duration("Compilation completed, took {} seconds."):
log.info(f"Processing QIR as parser and {str(hardware)} as hardware.")

optimizations = compiler_config.optimizations
if (
isinstance(optimizations, Tket)
and optimizations.tket_optimizations != TketOptimizations.Empty
):
quantum_builder = DefaultOptimizers(metrics).optimize_qir(
path_or_str,
get_model(hardware),
compiler_config.optimizations,
compiler_config.results_format.format,
)
else:
parser = QIRParser(
hardware, results_format=compiler_config.results_format.format
)
quantum_builder = parser.parse(path_or_str)

quantum_builder = parser.parse(path_or_str)
return self._build_instructions(quantum_builder, hardware, compiler_config), metrics
return (
self._build_instructions(quantum_builder, hardware, compiler_config),
metrics,
)

def parse(
self, path_or_str: str, hardware=None, compiler_config: CompilerConfig = None
Expand Down
22 changes: 20 additions & 2 deletions src/qat/purr/compiler/optimisers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2023-2024 Oxford Quantum Circuits Ltd
from compiler_config.config import (
InlineResultsProcessing,
MetricsType,
OptimizationConfig,
Qiskit,
Expand All @@ -13,7 +14,10 @@

from qat.purr.compiler.hardware_models import QuantumHardwareModel
from qat.purr.compiler.metrics import MetricsMixin
from qat.purr.integrations.tket import run_tket_optimizations
from qat.purr.integrations.tket import (
run_tket_optimizations_qasm,
run_tket_optimizations_qir,
)
from qat.purr.utils.logger import get_default_logger
from qat.purr.utils.logging_utils import log_duration

Expand All @@ -37,7 +41,7 @@ def optimize_qasm(
isinstance(optimizations, Tket)
and optimizations.tket_optimizations != TketOptimizations.Empty
):
qasm_string = run_tket_optimizations(
qasm_string = run_tket_optimizations_qasm(
qasm_string, optimizations.tket_optimizations, hardware
)

Expand All @@ -54,6 +58,20 @@ def optimize_qasm(
self.record_metric(MetricsType.OptimizedCircuit, qasm_string)
return qasm_string

def optimize_qir(
self,
qir_string: str,
hardware: QuantumHardwareModel,
optimizations: OptimizationConfig,
results_format: InlineResultsProcessing = None,
):
"""Run TKET optimizers on QIR input, returning the circuit as a QASM file."""
with log_duration("QIR optimization took {} seconds."):
builder = run_tket_optimizations_qir(
qir_string, optimizations.tket_optimizations, hardware, results_format
)
return builder

def run_qiskit_optimization(self, qasm_string, level):
"""
TODO: [QK] Current setup is unlikely to provide much benefit, refine settings
Expand Down
15 changes: 11 additions & 4 deletions src/qat/purr/integrations/qir.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ def __init__(
self,
hardware: Union[QuantumHardwareModel, InstructionExecutionEngine],
builder=None,
results_format=None,
):
if isinstance(hardware, InstructionExecutionEngine):
hardware = hardware.model

self.hardware: QuantumHardwareModel = hardware
self.builder: InstructionBuilder = builder or get_builder(hardware)
self.results_format = InlineResultsProcessing.Program
self.results_format = results_format or InlineResultsProcessing.Program
self.result_variables = []

def _get_qubit(self, id_: int):
Expand Down Expand Up @@ -101,6 +102,12 @@ def y(self, qubit: int):
def z(self, qubit: int):
self.builder.Z(self._get_qubit(qubit))

def returns(self, result_name=None):
self.builder.returns(result_name)

def assign(self, name, value):
self.builder.assign(name, value)

def process_instructions(self, instructions):
for inst in instructions:
if isinstance(inst, Call):
Expand Down Expand Up @@ -219,10 +226,10 @@ def parse(self, qir_file: str):
else:
result_name = "_".join(potential_names)

self.builder.assign(result_name, [val[0] for val in self.result_variables])
self.builder.returns(result_name)
self.assign(result_name, [val[0] for val in self.result_variables])
self.returns(result_name)
else:
self.builder.returns()
self.returns()

complete_builder = self.builder
self.builder = get_builder(self.hardware)
Expand Down
Loading

0 comments on commit 51d60d0

Please sign in to comment.