Skip to content

Commit

Permalink
add azure option in result recording
Browse files Browse the repository at this point in the history
  • Loading branch information
cqc-melf committed Dec 4, 2024
1 parent b939394 commit 2b93b16
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 5 deletions.
2 changes: 1 addition & 1 deletion _metadata.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__extension_version__ = "0.18.0rc0"
__extension_version__ = "0.18.0rc1"
__extension_name__ = "pytket-qir"
2 changes: 1 addition & 1 deletion docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ API documentation

.. automodule:: pytket.qir
:special-members:
:members: pytket_to_qir, QIRFormat
:members: pytket_to_qir, QIRFormat, QIRProfile
25 changes: 22 additions & 3 deletions pytket/qir/conversion/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
scratch_reg_resize_pass,
)

from .azurebaseprofileqirgenerator import AzureBaseProfileQirGenerator
from .azureprofileqirgenerator import AzureAdaptiveProfileQirGenerator
from .baseprofileqirgenerator import BaseProfileQirGenerator
from .module import tketqirModule
from .profileqirgenerator import AdaptiveProfileQirGenerator
Expand All @@ -48,9 +50,11 @@ class QIRProfile(Enum):
"""Profile for the QIR generation"""

BASE = 0
ADAPTIVE = 1
ADAPTIVE_CREGSIZE = 2
PYTKET = 3
AZUREBASE = 1
ADAPTIVE = 2
AZUREADAPTIVE = 3
ADAPTIVE_CREGSIZE = 4
PYTKET = 5


def pytket_to_qir(
Expand Down Expand Up @@ -107,6 +111,13 @@ def pytket_to_qir(
wasm_int_type=int_type,
qir_int_type=int_type,
)
elif profile == QIRProfile.AZUREBASE:
qir_generator: AbstractQirGenerator = AzureBaseProfileQirGenerator(
circuit=circ,
module=m,
wasm_int_type=int_type,
qir_int_type=int_type,
)
elif profile == QIRProfile.PYTKET:
qir_generator = PytketQirGenerator(
circuit=circ,
Expand All @@ -122,6 +133,14 @@ def pytket_to_qir(
qir_int_type=int_type,
trunc=trunc,
)
elif profile == QIRProfile.AZUREADAPTIVE:
qir_generator = AzureAdaptiveProfileQirGenerator(
circuit=circ,
module=m,
wasm_int_type=int_type,
qir_int_type=int_type,
trunc=trunc,
)
else:
raise NotImplementedError("unexpected profile")

Expand Down
91 changes: 91 additions & 0 deletions pytket/qir/conversion/azurebaseprofileqirgenerator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Copyright 2019-2024 Quantinuum
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import pyqir

from pytket.circuit import (
Bit,
Circuit,
Qubit,
)

from .baseprofileqirgenerator import (
BaseProfileQirGenerator,
)
from .module import tketqirModule


class AzureBaseProfileQirGenerator(BaseProfileQirGenerator):
"""Generate QIR from a pytket circuit."""

def __init__(
self,
circuit: Circuit,
module: tketqirModule,
wasm_int_type: int,
qir_int_type: int,
) -> None:

super().__init__(circuit, module, wasm_int_type, qir_int_type)

# void @__quantum__rt__array_record_output(result)
self.record_output_array = self.module.module.add_external_function(
"__quantum__rt__array_record_output",
pyqir.FunctionType(
pyqir.Type.void(self.module.module.context),
[
self.qir_int_type,
pyqir.PointerType(pyqir.IntType(self.module.module.context, 8)),
],
),
)

def conv_measure(self, bits: list[Bit], qubits: list[Qubit]) -> None:
assert len(bits) == 1
assert len(qubits) == 1

pass

def record_output(self) -> None:

# this will measure all qubits at the end of the circuit
# the result of the measurement will be added to an array and recorded togeather

for i in range(len(self.circuit.qubits)):
self.module.qis.mz(
self.module.module.qubits[i],
self.module.module.results[i],
)

self.module.builder.call(
self.record_output_array,
[
pyqir.const(self.qir_int_type, len(self.circuit.qubits)),
pyqir.Constant.null(
pyqir.PointerType(pyqir.IntType(self.module.module.context, 8))
),
],
)

for i in range(len(self.circuit.qubits)):
self.module.builder.call(
self.record_output_res,
[
self.module.module.results[i],
pyqir.Constant.null(
pyqir.PointerType(pyqir.IntType(self.module.module.context, 8))
),
],
)
99 changes: 99 additions & 0 deletions pytket/qir/conversion/azureprofileqirgenerator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright 2019-2024 Quantinuum
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import pyqir

from pytket.circuit import (
Bit,
Circuit,
Qubit,
)

from .module import tketqirModule
from .profileqirgenerator import (
AdaptiveProfileQirGenerator,
)


class AzureAdaptiveProfileQirGenerator(AdaptiveProfileQirGenerator):
"""Generate QIR from a pytket circuit."""

def __init__(
self,
circuit: Circuit,
module: tketqirModule,
wasm_int_type: int,
qir_int_type: int,
trunc: bool,
) -> None:

super().__init__(circuit, module, wasm_int_type, qir_int_type, trunc)

# void @__quantum__rt__array_record_output(result)
self.record_output_array = self.module.module.add_external_function(
"__quantum__rt__array_record_output",
pyqir.FunctionType(
pyqir.Type.void(self.module.module.context),
[
self.qir_int_type,
pyqir.PointerType(pyqir.IntType(self.module.module.context, 8)),
],
),
)

def conv_measure(self, bits: list[Bit], qubits: list[Qubit]) -> None:

assert len(bits) == 1
assert len(qubits) == 1

qubit_index = qubits[0].index[0]

self.module.qis.mz(
self.module.module.qubits[qubit_index],
self.module.module.results[qubit_index],
)

ssa_measureresult = self.module.builder.call(
self.read_bit_from_result,
[
self.module.module.results[qubit_index],
],
)

self._set_bit_in_creg(bits[0].reg_name, bits[0].index[0], ssa_measureresult)

def record_output(self) -> None:

self.module.builder.call(
self.record_output_array,
[
pyqir.const(self.qir_int_type, len(self.circuit.qubits)),
pyqir.Constant.null(
pyqir.PointerType(pyqir.IntType(self.module.module.context, 8))
),
],
)

for creg in self.circuit.c_registers:
reg_name = creg[0].reg_name
self.module.builder.call(
self.record_output_i64,
[
self._get_i64_ssa_reg(reg_name),
pyqir.Constant.null(
pyqir.PointerType(pyqir.IntType(self.module.module.context, 8))
),
],
)

0 comments on commit 2b93b16

Please sign in to comment.