-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR moves the QASM2 implementation into this new namespace package with some minor cleanups: - qrack is no longer living with dialects, it is in independent module so we can install it conditionally with extra `qrack` - implement qrack interpreter for QASM2 Co-authored-by: Roger-luo <rluo@quera.com> Co-authored-by: kaihsin <khwu@quera.com> Co-authored-by: weinbe58 <pweinberg@quera.com> Co-authored-by: johnzl-777 <jlong@quera.com>
- Loading branch information
1 parent
39bd1c8
commit 0e578fc
Showing
79 changed files
with
5,017 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -185,3 +185,4 @@ main.py | |
.ruff_cache | ||
.python-version | ||
!package.json | ||
!src/**/**/main.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# See https://pre-commit.com for more information | ||
# See https://pre-commit.com/hooks.html for more hooks | ||
repos: | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v5.0.0 | ||
hooks: | ||
- id: check-yaml | ||
args: ['--unsafe'] | ||
- id: end-of-file-fixer | ||
- id: trailing-whitespace | ||
- repo: https://github.com/pycqa/isort | ||
rev: 5.13.2 | ||
hooks: | ||
- id: isort | ||
name: isort (python) | ||
- repo: https://github.com/psf/black | ||
rev: 24.10.0 | ||
hooks: | ||
- id: black | ||
- repo: https://github.com/charliermarsh/ruff-pre-commit | ||
# Ruff version. | ||
rev: "v0.9.2" | ||
hooks: | ||
- id: ruff |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
coverage-run: | ||
coverage run -m pytest test | ||
|
||
coverage-xml: | ||
coverage xml | ||
|
||
coverage-html: | ||
coverage html | ||
|
||
coverage-report: | ||
coverage report | ||
|
||
coverage-open: | ||
open htmlcov/index.html | ||
|
||
coverage: coverage-run coverage-xml coverage-report | ||
|
||
doc: | ||
mkdocs serve | ||
|
||
doc-build: | ||
mkdocs build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from . import impls as impls | ||
from .lattice import ( | ||
Address as Address, | ||
NotQubit as NotQubit, | ||
AddressReg as AddressReg, | ||
AnyAddress as AnyAddress, | ||
AddressQubit as AddressQubit, | ||
AddressTuple as AddressTuple, | ||
) | ||
from .analysis import AddressAnalysis as AddressAnalysis |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
from typing import TypeVar, Iterable | ||
|
||
from kirin import ir, types, interp | ||
from bloqade.types import QubitType | ||
from kirin.analysis import Forward, const | ||
from kirin.dialects import cf, py, func, ilist | ||
from kirin.exceptions import InterpreterError | ||
from kirin.analysis.forward import ForwardFrame | ||
|
||
from .lattice import Address | ||
|
||
|
||
class AddressAnalysis(Forward[Address]): | ||
keys = ["qubit.address"] | ||
lattice = Address | ||
|
||
def __init__( | ||
self, | ||
dialects: ir.DialectGroup | Iterable[ir.Dialect], | ||
*, | ||
fuel: int | None = None, | ||
save_all_ssa: bool = False, | ||
max_depth: int = 128, | ||
max_python_recursion_depth: int = 8192, | ||
): | ||
super().__init__( | ||
dialects, | ||
fuel=fuel, | ||
save_all_ssa=save_all_ssa, | ||
max_depth=max_depth, | ||
max_python_recursion_depth=max_python_recursion_depth, | ||
) | ||
self.next_address: int = 0 | ||
self.constprop_results: dict[ir.SSAValue, const.JointResult] = {} | ||
|
||
def clear(self): | ||
self.next_address = 0 | ||
self.constprop_results.clear() | ||
|
||
@property | ||
def qubit_count(self) -> int: | ||
return self.next_address | ||
|
||
T = TypeVar("T") | ||
|
||
def get_const_value(self, typ: type[T], value: ir.SSAValue) -> T: | ||
if isinstance(value.type, types.Hinted) and isinstance( | ||
value.type.data, const.Value | ||
): | ||
data = value.type.data.data | ||
if isinstance(data, typ): | ||
return value.type.data.data | ||
raise InterpreterError( | ||
f"Expected constant value <type = {typ}>, got {data}" | ||
) | ||
raise InterpreterError(f"Expected constant value <type = {typ}>, got {value}") | ||
|
||
def run_stmt_fallback( | ||
self, frame: ForwardFrame[Address, None], stmt: ir.Statement | ||
) -> tuple[Address, ...] | interp.SpecialResult[Address]: | ||
return tuple( | ||
( | ||
self.lattice.top() | ||
if result.type.is_subseteq(QubitType) | ||
else self.lattice.bottom() | ||
) | ||
for result in stmt.results | ||
) | ||
|
||
def should_exec_stmt(self, stmt: ir.Statement): | ||
return ( | ||
stmt.has_trait(ir.ConstantLike) | ||
or stmt.dialect in self.dialects.data | ||
or isinstance( | ||
stmt, | ||
( | ||
func.Return, | ||
func.Invoke, | ||
py.tuple.New, | ||
ilist.New, | ||
py.GetItem, | ||
py.Alias, | ||
py.Add, | ||
cf.Branch, | ||
cf.ConditionalBranch, | ||
), | ||
) | ||
) | ||
|
||
def run_method( | ||
self, method: ir.Method, args: tuple[Address, ...] | ||
) -> Address | interp.Err[Address]: | ||
if len(self.state.frames) >= self.max_depth: | ||
raise InterpreterError("maximum recursion depth exceeded") | ||
# NOTE: we do not support dynamic calls here, thus no need to propagate method object | ||
return self.run_callable(method.code, (self.lattice.bottom(),) + args) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
""" | ||
qubit.address method table for a few builtin dialects. | ||
""" | ||
|
||
from kirin import interp | ||
from kirin.dialects import cf, py, func, ilist | ||
|
||
from .lattice import NotQubit, AddressReg, AddressQubit, AddressTuple | ||
from .analysis import AddressAnalysis | ||
|
||
|
||
@py.binop.dialect.register(key="qubit.address") | ||
class PyBinOp(interp.MethodTable): | ||
|
||
@interp.impl(py.Add) | ||
def add(self, interp: AddressAnalysis, frame: interp.Frame, stmt: py.Add): | ||
lhs = frame.get(stmt.lhs) | ||
rhs = frame.get(stmt.rhs) | ||
|
||
if isinstance(lhs, AddressTuple) and isinstance(rhs, AddressTuple): | ||
return (AddressTuple(data=lhs.data + rhs.data),) | ||
else: | ||
return (NotQubit(),) | ||
|
||
|
||
@py.tuple.dialect.register(key="qubit.address") | ||
class PyTuple(interp.MethodTable): | ||
@interp.impl(py.tuple.New) | ||
def new_tuple( | ||
self, | ||
interp: AddressAnalysis, | ||
frame: interp.Frame, | ||
stmt: py.tuple.New, | ||
): | ||
return (AddressTuple(frame.get_values(stmt.args)),) | ||
|
||
|
||
@ilist.dialect.register(key="qubit.address") | ||
class IList(interp.MethodTable): | ||
@interp.impl(ilist.New) | ||
def new_ilist( | ||
self, | ||
interp: AddressAnalysis, | ||
frame: interp.Frame, | ||
stmt: ilist.New, | ||
): | ||
return (AddressTuple(frame.get_values(stmt.args)),) | ||
|
||
|
||
@py.list.dialect.register(key="qubit.address") | ||
class PyList(interp.MethodTable): | ||
@interp.impl(py.list.New) | ||
def new_ilist( | ||
self, | ||
interp: AddressAnalysis, | ||
frame: interp.Frame, | ||
stmt: py.list.New, | ||
): | ||
return (AddressTuple(frame.get_values(stmt.args)),) | ||
|
||
|
||
@py.indexing.dialect.register(key="qubit.address") | ||
class PyIndexing(interp.MethodTable): | ||
@interp.impl(py.GetItem) | ||
def getitem(self, interp: AddressAnalysis, frame: interp.Frame, stmt: py.GetItem): | ||
idx = interp.get_const_value(int, stmt.index) | ||
obj = frame.get(stmt.obj) | ||
if isinstance(obj, AddressTuple): | ||
return (obj.data[idx],) | ||
elif isinstance(obj, AddressReg): | ||
return (AddressQubit(obj.data[idx]),) | ||
else: | ||
return (NotQubit(),) | ||
|
||
|
||
@py.assign.dialect.register(key="qubit.address") | ||
class PyAssign(interp.MethodTable): | ||
@interp.impl(py.Alias) | ||
def alias(self, interp: AddressAnalysis, frame: interp.Frame, stmt: py.Alias): | ||
return (frame.get(stmt.value),) | ||
|
||
|
||
@func.dialect.register(key="qubit.address") | ||
class Func(interp.MethodTable): | ||
@interp.impl(func.Return) | ||
def return_(self, _: AddressAnalysis, frame: interp.Frame, stmt: func.Return): | ||
return interp.ReturnValue(frame.get(stmt.value)) | ||
|
||
|
||
@cf.dialect.register(key="qubit.address") | ||
class Cf(cf.typeinfer.TypeInfer): | ||
# NOTE: cf just re-use the type infer method table | ||
# it's the same process as type infer. | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
from typing import Sequence, final | ||
from dataclasses import dataclass | ||
|
||
from kirin.lattice import ( | ||
SingletonMeta, | ||
BoundedLattice, | ||
SimpleJoinMixin, | ||
SimpleMeetMixin, | ||
) | ||
|
||
|
||
@dataclass | ||
class Address( | ||
SimpleJoinMixin["Address"], | ||
SimpleMeetMixin["Address"], | ||
BoundedLattice["Address"], | ||
): | ||
|
||
@classmethod | ||
def bottom(cls) -> "Address": | ||
return NotQubit() | ||
|
||
@classmethod | ||
def top(cls) -> "Address": | ||
return AnyAddress() | ||
|
||
|
||
@final | ||
@dataclass | ||
class NotQubit(Address, metaclass=SingletonMeta): | ||
|
||
def is_subseteq(self, other: Address) -> bool: | ||
return True | ||
|
||
|
||
@final | ||
@dataclass | ||
class AnyAddress(Address, metaclass=SingletonMeta): | ||
|
||
def is_subseteq(self, other: Address) -> bool: | ||
return isinstance(other, AnyAddress) | ||
|
||
|
||
@final | ||
@dataclass | ||
class AddressTuple(Address): | ||
data: tuple[Address, ...] | ||
|
||
def is_subseteq(self, other: Address) -> bool: | ||
if isinstance(other, AddressTuple): | ||
return all(a.is_subseteq(b) for a, b in zip(self.data, other.data)) | ||
return False | ||
|
||
|
||
@final | ||
@dataclass | ||
class AddressReg(Address): | ||
data: Sequence[int] | ||
|
||
def is_subseteq(self, other: Address) -> bool: | ||
if isinstance(other, AddressReg): | ||
return self.data == other.data | ||
return False | ||
|
||
|
||
@final | ||
@dataclass | ||
class AddressQubit(Address): | ||
data: int | ||
|
||
def is_subseteq(self, other: Address) -> bool: | ||
if isinstance(other, AddressQubit): | ||
return self.data == other.data | ||
return False |
Oops, something went wrong.