From f40f340442abb0de19b714f0251eb0b654f49b96 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Thu, 18 Jun 2026 13:01:40 -0400 Subject: [PATCH 01/20] clean: Move math into atomic compiler --- src/oqd_core/compiler/atomic/canonicalize.py | 4 +- src/oqd_core/compiler/atomic/math/__init__.py | 17 + src/oqd_core/compiler/atomic/math/passes.py | 72 +++ src/oqd_core/compiler/atomic/math/rules.py | 527 ++++++++++++++++++ 4 files changed, 618 insertions(+), 2 deletions(-) create mode 100644 src/oqd_core/compiler/atomic/math/__init__.py create mode 100644 src/oqd_core/compiler/atomic/math/passes.py create mode 100644 src/oqd_core/compiler/atomic/math/rules.py diff --git a/src/oqd_core/compiler/atomic/canonicalize.py b/src/oqd_core/compiler/atomic/canonicalize.py index 5f41d9c3..e203986b 100644 --- a/src/oqd_core/compiler/atomic/canonicalize.py +++ b/src/oqd_core/compiler/atomic/canonicalize.py @@ -16,9 +16,9 @@ from oqd_compiler_infrastructure import Chain, Post, Pre, RewriteRule -from oqd_core.compiler.math.rules import SubstituteMathVar +from oqd_core.compiler.atomic.math.rules import SubstituteMathVar from oqd_core.interface.atomic import Level, Transition -from oqd_core.interface.math import MathVar +from oqd_core.interface.atomic import MathVar ######################################################################################## diff --git a/src/oqd_core/compiler/atomic/math/__init__.py b/src/oqd_core/compiler/atomic/math/__init__.py new file mode 100644 index 00000000..92906e43 --- /dev/null +++ b/src/oqd_core/compiler/atomic/math/__init__.py @@ -0,0 +1,17 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +from . import passes, rules + +__all__ = ["passes", "rules"] diff --git a/src/oqd_core/compiler/atomic/math/passes.py b/src/oqd_core/compiler/atomic/math/passes.py new file mode 100644 index 00000000..439e6028 --- /dev/null +++ b/src/oqd_core/compiler/atomic/math/passes.py @@ -0,0 +1,72 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +######################################################################################## + +from oqd_compiler_infrastructure import Chain, FixedPoint, Post + +from oqd_core.compiler.atomic.math.rules import ( + DistributeMathExpr, + EvaluateMathExpr, + PartitionMathExpr, + PrintMathExpr, + ProperOrderMathExpr, + PruneMathExpr, + SimplifyMathExpr, +) + +######################################################################################## + +__all__ = [ + "evaluate_math_expr", + "simplify_math_expr", + "print_math_expr", + "canonicalize_math_expr", +] + +######################################################################################## + +evaluate_math_expr = Post(EvaluateMathExpr()) +""" +Pass for evaluating math expression +""" + +simplify_math_expr = Post(SimplifyMathExpr()) +""" +Pass for simplifying math expression +""" + +print_math_expr = Post(PrintMathExpr()) +""" +Pass for printing math expression +""" + +canonicalize_math_expr = Chain( + FixedPoint( + Post( + Chain( + PruneMathExpr(), + SimplifyMathExpr(), + DistributeMathExpr(), + ProperOrderMathExpr(), + ) + ) + ), + FixedPoint(Post(PartitionMathExpr())), + simplify_math_expr, +) + +""" +Pass for canonicalizing math expression +""" diff --git a/src/oqd_core/compiler/atomic/math/rules.py b/src/oqd_core/compiler/atomic/math/rules.py new file mode 100644 index 00000000..84db333b --- /dev/null +++ b/src/oqd_core/compiler/atomic/math/rules.py @@ -0,0 +1,527 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +from typing import Union + +import numpy as np +from oqd_compiler_infrastructure import ConversionRule, Post, RewriteRule +from pydantic import TypeAdapter, ValidationError + +from oqd_core.interface.atomic import ( + ConstantMathExpr, + MathAdd, + MathBinaryOp, + MathDiv, + MathExpr, + MathFunc, + MathImag, + MathMul, + MathNum, + MathPow, + MathSub, + MathTerminal, + MathVar, + Access, +) + +######################################################################################## + +__all__ = [ + "PrintMathExpr", + "DistributeMathExpr", + "PartitionMathExpr", + "ProperOrderMathExpr", + "PruneMathExpr", + "SimplifyMathExpr", + "EvaluateMathExpr", + "PruneMathExpr", +] + +######################################################################################## + + +class PrintMathExpr(ConversionRule): + """ + This prints [`MathExpr`][oqd_core.interface.math.MathExpr] objects. Verbosity level can be given as an attribute. + + Args: + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Returns: + string (str): + + Assumptions: + None + + Example: + MathAdd(expr1 = 2, expr2 = 3) => str(2 + 3) + """ + + def __init__(self, *, verbose=False): + super().__init__() + + self.verbose = verbose + + def map_MathVar(self, model: MathVar, operands): + string = "{}".format(model.name) + return string + + def map_MathNum(self, model: MathNum, operands): + string = "{}".format(model.value) + return string + + def map_MathImag(self, model: MathImag, operands): + string = "1j" + return string + + def map_MathFunc(self, model: MathFunc, operands): + string = "{}({})".format(model.func, operands["expr"]) + return string + + def map_MathAdd(self, model: MathAdd, operands): + if self.verbose: + return self._map_MathBinaryOp(model, operands) + string = "{} + {}".format(operands["expr1"], operands["expr2"]) + return string + + def map_MathSub(self, model: MathSub, operands): + if self.verbose: + return self._map_MathBinaryOp(model, operands) + s2 = ( + f"({operands['expr2']})" + if isinstance(model.expr2, (MathAdd, MathSub)) + else operands["expr2"] + ) + string = "{} - {}".format(operands["expr1"], s2) + return string + + def map_MathMul(self, model: MathMul, operands): + if self.verbose: + return self._map_MathBinaryOp(model, operands) + s1 = ( + f"({operands['expr1']})" + if isinstance(operands["expr1"], (MathAdd, MathSub)) + else operands["expr1"] + ) + s2 = ( + f"({operands['expr2']})" + if isinstance(model.expr2, (MathAdd, MathSub)) + else operands["expr2"] + ) + + string = "{} * {}".format(s1, s2) + return string + + def map_MathDiv(self, model: MathDiv, operands): + if self.verbose: + return self._map_MathBinaryOp(model, operands) + s1 = ( + f"({operands['expr1']})" + if isinstance(model.expr1, (MathAdd, MathSub)) + else operands["expr1"] + ) + s2 = ( + f"({operands['expr2']})" + if isinstance(model.expr2, (MathAdd, MathSub)) + else operands["expr2"] + ) + + string = "{} / {}".format(s1, s2) + return string + + def map_MathPow(self, model: MathPow, operands): + if self.verbose: + return self._map_MathBinaryOp(model, operands) + s1 = ( + f"({operands['expr1']})" + if isinstance(model.expr1, (MathAdd, MathSub, MathMul, MathDiv)) + else operands["expr1"] + ) + s2 = ( + f"({operands['expr2']})" + if isinstance(model.expr2, (MathAdd, MathSub, MathMul, MathDiv)) + else operands["expr2"] + ) + + string = "{} ** {}".format(s1, s2) + return string + + def _map_MathBinaryOp(self, model: MathBinaryOp, operands): + s1 = ( + f"({operands['expr1']})" + if not isinstance(model.expr1, (MathTerminal, MathFunc)) + else operands["expr1"] + ) + s2 = ( + f"({operands['expr2']})" + if not isinstance(model.expr2, (MathTerminal, MathFunc)) + else operands["expr2"] + ) + operator_dict = dict( + MathAdd="+", MathSub="-", MathMul="*", MathDiv="/", MathPow="**" + ) + string = f"{s1} {operator_dict[model.__class__.__name__]} {s2}" + return string + + +######################################################################################## + + +class DistributeMathExpr(RewriteRule): + """ + This distributes [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Args: + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Returns: + model (MathExpr): + + Assumptions: + None + + Example: + MathStr(string = '3 * (2 + 1)') => MathStr(string = '3 * 2 + 3 * 1') + """ + + def map_MathMul(self, model: MathMul): + if isinstance(model.expr1, (MathAdd, MathSub)): + return model.expr1.__class__( + expr1=MathMul(expr1=model.expr1.expr1, expr2=model.expr2), + expr2=MathMul(expr1=model.expr1.expr2, expr2=model.expr2), + ) + if isinstance(model.expr2, (MathAdd, MathSub)): + return model.expr2.__class__( + expr1=MathMul(expr1=model.expr1, expr2=model.expr2.expr1), + expr2=MathMul(expr1=model.expr1, expr2=model.expr2.expr2), + ) + pass + + def map_MathSub(self, model: MathSub): + return MathAdd( + expr1=model.expr1, + expr2=MathMul(expr1=MathNum(value=-1), expr2=model.expr2), + ) + + def map_MathDiv(self, model: MathDiv): + return MathMul( + expr1=model.expr1, + expr2=MathPow(expr1=model.expr2, expr2=MathNum(value=-1)), + ) + + +class PartitionMathExpr(RewriteRule): + """ + This separates real and complex portions of [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Args: + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Returns: + model (MathExpr): + + Assumptions: + [`DistributeMathExpr`][oqd_core.compiler.math.rules.DistributeMathExpr], + [`ProperOrderMathExpr`][oqd_core.compiler.math.rules.ProperOrderMathExpr] + + Example: + - MathStr(string = '1 + 1j + 2') => MathStr(string = '1 + 2 + 1j') + - MathStr(string = '1 * 1j * 2') => MathStr(string = '1j * 1 * 2') + """ + + def map_MathAdd(self, model): + priority = dict( + MathImag=6, MathNum=5, MathVar=4, Access=3, MathFunc=2, MathPow=1, MathMul=0 + ) + + if isinstance( + model.expr2, (MathImag, MathNum, MathVar, Access, MathFunc, MathPow, MathMul) + ): + if isinstance(model.expr1, MathAdd): + if ( + priority[model.expr2.__class__.__name__] + > priority[model.expr1.expr2.__class__.__name__] + ): + return MathAdd( + expr1=MathAdd(expr1=model.expr1.expr1, expr2=model.expr2), + expr2=model.expr1.expr2, + ) + else: + if ( + priority[model.expr2.__class__.__name__] + > priority[model.expr1.__class__.__name__] + ): + return MathAdd( + expr1=model.expr2, + expr2=model.expr1, + ) + + def map_MathMul(self, model: MathMul): + priority = dict(MathImag=5, MathNum=4, MathVar=3, Access=2, MathFunc=1, MathPow=0) + + if isinstance(model.expr2, (MathImag, MathNum, MathVar, Access, MathFunc, MathPow)): + if isinstance(model.expr1, MathMul): + if ( + priority[model.expr2.__class__.__name__] + > priority[model.expr1.expr2.__class__.__name__] + ): + return MathMul( + expr1=MathMul(expr1=model.expr1.expr1, expr2=model.expr2), + expr2=model.expr1.expr2, + ) + else: + if ( + priority[model.expr2.__class__.__name__] + > priority[model.expr1.__class__.__name__] + ): + return MathMul( + expr1=model.expr2, + expr2=model.expr1, + ) + + +class ProperOrderMathExpr(RewriteRule): + """ + This rearranges bracketing of [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Args: + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Returns: + model (MathExpr): + + Assumptions: + [`DistributeMathExpr`][oqd_core.compiler.math.rules.DistributeMathExpr] + + Example: + - MathStr(string = '2 * (3 * 5)') => MathStr(string = '(2 * 3) * 5') + """ + + def map_MathAdd(self, model: MathAdd): + return self._MathAddMul(model) + + def map_MathMul(self, model: MathMul): + return self._MathAddMul(model) + + def _MathAddMul(self, model: Union[MathAdd, MathMul]): + if isinstance(model.expr2, model.__class__): + return model.__class__( + expr1=model.__class__(expr1=model.expr1, expr2=model.expr2.expr1), + expr2=model.expr2.expr2, + ) + pass + + +class PruneMathExpr(RewriteRule): + """ + This is constant fold operation where scalar addition, multiplication and power are simplified + + Args: + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Returns: + model (MathExpr): + + Assumptions: + None + + """ + + def map_MathAdd(self, model): + if model.expr1 == MathNum(value=0): + return model.expr2 + if model.expr2 == MathNum(value=0): + return model.expr1 + + def map_MathMul(self, model): + if model.expr1 == MathNum(value=1): + return model.expr2 + if model.expr2 == MathNum(value=1): + return model.expr1 + + if model.expr1 == MathNum(value=0) or model.expr2 == MathNum(value=0): + return MathNum(value=0) + + def map_MathPow(self, model): + if model.expr1 == MathNum(value=1) or model.expr2 == MathNum(value=1): + return model.expr1 + + if model.expr2 == MathNum(value=0): + return MathNum(value=1) + + if model.expr1 == MathNum(value=0): + return MathNum(value=0) + + +######################################################################################## + + +class SubstituteMathVar(RewriteRule): + """ + This rule substitutes a MathVar with another MathExpr + + Args: + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Returns: + model (MathExpr): + + Assumptions: + None + + """ + + def __init__(self, variable, substitution): + super().__init__() + + if not isinstance(variable, MathVar): + raise TypeError("Variable must be a MathVar") + + if not isinstance(variable, MathExpr): + raise TypeError("Substituted value must be a MathExpr") + + self.variable = variable + self.substitution = substitution + + def map_MathVar(self, model): + if model == self.variable: + return self.substitution + + +######################################################################################## + + +class EvaluateMathExpr(ConversionRule): + """ + This evaluates MathExpr objects and raises a type error if a MathVar exist in the AST. + + Args: + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Returns: + model (MathExpr): + + Assumptions: + None + """ + + def map_MathVar(self, model: MathVar, operands): + raise TypeError( + "Evaluation requires the substitution of all MathVar to constants" + ) + + def map_Access(self, model: Access, operands): + raise TypeError( + "Evaluation requires Access to be resolved" + ) + + def map_MathNum(self, model: MathNum, operands): + return model.value + + def map_MathImag(self, model: MathImag, operands): + return complex("1j") + + def map_MathFunc(self, model: MathFunc, operands): + if model.func in [ + "abs", + "sin", + "cos", + "tan", + "exp", + "log", + "sinh", + "cosh", + "tanh", + "atan", + "acos", + "asin", + "atanh", + "asinh", + "acosh", + "conj", + "real", + "imag", + "atan2", + ]: + if isinstance(operands["expr"], list): + return getattr(np, model.func)(*operands["expr"]) + + return getattr(np, model.func)(operands["expr"]) + + if model.func == "heaviside": + return np.heaviside(operands["expr"], 1) + + raise ValueError("Unsupported function") + + def map_MathAdd(self, model: MathAdd, operands): + return operands["expr1"] + operands["expr2"] + + def map_MathSub(self, model: MathSub, operands): + return operands["expr1"] - operands["expr2"] + + def map_MathMul(self, model: MathMul, operands): + return operands["expr1"] * operands["expr2"] + + def map_MathDiv(self, model: MathDiv, operands): + return operands["expr1"] / operands["expr2"] + + def map_MathPow(self, model: MathPow, operands): + return operands["expr1"] ** operands["expr2"] + + +######################################################################################## + + +class SimplifyMathExpr(RewriteRule): + """ + This simplifies MathExpr objects by evaluating all constants in the AST. + + Args: + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + + Returns: + model (MathExpr): + + Assumptions: + None + + """ + + def map_MathNum(self, model): + # This empty function overrides the map_MathExpr definition for child class MathNum + pass + + def map_MathImag(self, model): + # This empty function overrides the map_MathExpr definition for child class MathImag + pass + + def map_MathExpr(self, model): + try: + TypeAdapter(ConstantMathExpr).validate_python(model) + + value = Post(EvaluateMathExpr())(model) + + if isinstance(value, (int, float)): + return MathNum(value=value) + elif value == 1j: + return MathImag() + elif value.real == 0: + return MathImag() * MathNum(value=value.imag) + else: + return MathNum(value=value.real) + MathImag() * MathNum( + value=value.imag + ) + + except (ValidationError, TypeError, ValueError): + return model From 8232c4cb29e2a49e9ef572d3a81c4b36075e4884 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Fri, 19 Jun 2026 16:22:38 -0400 Subject: [PATCH 02/20] feat: Fix atomic canonicalization passes --- .github/workflows/pytest.yml | 2 +- examples/analog/test.analog | 4 +- examples/analog/test.ipynb | 199 ++++++----- examples/atomic/test.atomic | 1 + examples/atomic/test.ipynb | 47 ++- src/oqd_core/analysis/analog/types.py | 6 +- src/oqd_core/compiler/atomic/canonicalize.py | 326 +++++++----------- .../compiler/atomic/cfg_passes/__init__.py | 6 + .../compiler/atomic/cfg_passes/walk.py | 89 +++++ src/oqd_core/compiler/atomic/error.py | 27 ++ src/oqd_core/compiler/atomic/math/rules.py | 4 +- tests/test_atomic/test_beam.py | 162 ++++----- tests/test_atomic/test_unroll.py | 265 -------------- tests/test_serialization.py | 257 -------------- 14 files changed, 491 insertions(+), 904 deletions(-) create mode 100644 src/oqd_core/compiler/atomic/cfg_passes/__init__.py create mode 100644 src/oqd_core/compiler/atomic/cfg_passes/walk.py create mode 100644 src/oqd_core/compiler/atomic/error.py delete mode 100644 tests/test_atomic/test_unroll.py delete mode 100644 tests/test_serialization.py diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 65838077..12ff5ddb 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -39,4 +39,4 @@ jobs: uv sync --extra tests - name: Run tests run: | - uv run pytest tests/test_frontend tests/test_analog tests/test_analysis -v + uv run pytest tests/ -v diff --git a/examples/analog/test.analog b/examples/analog/test.analog index d452fbac..0650e435 100644 --- a/examples/analog/test.analog +++ b/examples/analog/test.analog @@ -35,7 +35,7 @@ if (x > 0){ initialize(r) } if (x == 1) { - evolve(H_single, 1.0, r) + evolve(H_single, 1.0, q0) } else { evolve(H_pair, 0.5, r) } n = 3 @@ -67,7 +67,7 @@ if (a > b) { initialize(r) // evolve(hamiltonian, duration, target) -evolve(H_single, 2.0, r) +evolve(H_single, 2.0, q1) evolve(H_pair, 1.0, targets) evolve(%X %* 0.5, pi, q0) diff --git a/examples/analog/test.ipynb b/examples/analog/test.ipynb index e4db5684..0f231658 100644 --- a/examples/analog/test.ipynb +++ b/examples/analog/test.ipynb @@ -34,111 +34,152 @@ "execution_count": 2, "id": "1c5481c1", "metadata": {}, + "outputs": [], + "source": [ + "from oqd_compiler_infrastructure import Post, PrettyPrint\n", + "\n", + "from oqd_core.analysis.analog.cfg import AnalogCFGBuilder\n", + "from oqd_core.analysis.analog.type_checker import AnalogTypeChecker\n", + "from oqd_core.frontend.analog import parse_analog\n", + "\n", + "printer = Post(PrettyPrint())\n", + "\n", + "with open(\"test.analog\", mode=\"r\", encoding=\"utf8\") as f:\n", + " source = f.read()\n", + "\n", + "circuit = parse_analog(source)\n", + "cfg = AnalogCFGBuilder().run(circuit)\n", + "checker = AnalogTypeChecker(cfg)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "08b33d2c", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "line 1:8 no viable alternative at input 'r = qreg['\n" + ] + } + ], + "source": [ + "from oqd_core.frontend.analog import parse_analog\n", + "\n", + "program = \"r = qreg[2] \\n H_single = 0.5 %* %X %+ 0.5 %* %Z \\n evolve(H_single, 1.0, r[0])\"\n", + "circuit = parse_analog(program)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f628d79e", + "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "r = qreg(2)\n", - "s = qmode(3)\n", - "q0 = r[0]\n", - "q1 = r[1]\n", - "targets = [q0, q1]\n", - "pi = 3.14159\n", - "tau = 2 * pi\n", - "omega = #omega\n", - "phase = #t * omega + #phi\n", - "neg = -1\n", - "cubed = 2 ^ 3\n", - "sine = sin(0.5)\n", - "cosed = cos(phase)\n", - "cplx = 1.0 + 1j * 0.5\n", - "X = %X\n", - "Y = %Y\n", - "Z = %Z\n", - "I = %I\n", - "C = %C\n", - "A = %A\n", - "J = %J\n", - "H_single = 0.5 * %X + 0.5 * %Z\n", - "H_pair = %X %@ %I %+ %I %@ %X\n", - "H_rabi = 0.5 * #t * %X %@ %I %+ 0.5 * %I %@ %Y\n", - "x = 1\n", - "if (x > 0) {\n", - "initialize(r)\n", - "}\n", - "if (x == 1) {\n", - "evolve(H_single, 1.0, r)\n", - "} else {\n", - "evolve(H_pair, 0.5, r)\n", - "}\n", - "n = 3\n", - "while (n > 0) {\n", - "evolve(H_rabi, 0.1, targets)\n", - "n = n - 1\n", - "}\n", - "while (true) {\n", - "if (x == 1) {\n", - "break\n", - "}\n", - "}\n", - "a = 5\n", - "b = 3\n", - "if (a > b) {\n", - "if (b > 0) {\n", - "initialize(targets)\n", - "} else {\n", - "measure(r)\n", - "}\n", - "}\n", - "initialize(r)\n", - "evolve(H_single, 2.0, r)\n", - "evolve(H_pair, 1.0, targets)\n", - "evolve(%X * 0.5, pi, q0)\n", - "measure(r)\n", - "measurement = measure(q0)\n", - "flag = 1\n", - "if (flag != 0) {\n", - "x = 0\n", - "}\n", - "if (x <= 1) {\n", - "x = 1\n", - "}\n", - "if (x >= 0) {\n", - "x = 0\n", - "}\n", - "a = true\n", - "if (a) {\n", - "b = 5\n", - "}\n", - "\n" + "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4492982736: 1, 4492977376: 2, 4492983696: 3, 4492979216: 4, 4492981776: 5, 4474730720: 6, 4493035552: 7, 4493036512: 8, 4493038112: 9, 4493038432: 10, 4493038752: 11, 4493038912: 12, 4493039312: 13, 4493039952: 14, 4493040112: 15, 4493040272: 16, 4493040352: 17, 4493040512: 18, 4493040672: 19, 4493040832: 20, 4493040992: 21, 4493042112: 22, 4493043312: 23, 4493044672: 24, 4493044832: 25, 4493045072: 26, 4493045392: 27, 4493045712: 28, 4493046032: 29, 4493046512: 30, 4493046752: 31, 4493046992: 32, 4493047312: 33, 4493047632: 34, 4485421872: 35, 4493048112: 36, 4493048272: 37, 4493048512: 38, 4493048672: 39, 4493048912: 40, 4493049152: 41, 4493049312: 42, 4493049472: 43, 4497948752: 44, 4497949072: 45, 4497949392: 46, 4497949872: 47, 4497950032: 48, 4497950272: 49, 4497950432: 50, 4497950672: 51, 4497950912: 52, 4497951152: 53, 4497951392: 54, 4497951792: 55, 4497951952: 56, 4497952272: 57, 4497952192: 58, 4497952432: 59}\"\n" ] } ], "source": [ - "from oqd_core.frontend.analog import parse_analog, serialize_analog\n", + "from oqd_core.analysis.analog.symbol_table import AnalogSymbolTableBuilder\n", + "\n", + "symbol_analysis = AnalogSymbolTableBuilder(cfg, checker.dataflow_result)\n", + "symbol_table = symbol_analysis.symbol_table\n", + "import json\n", + "\n", + "symbol_table = str(symbol_table)\n", + "print(json.dumps(symbol_table, indent=2))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ec743f9f", + "metadata": {}, + "outputs": [ + { + "ename": "AnalogCompilerError", + "evalue": "Inconsistent Hilbert space dimensions between Evolve statements", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mAnalogCompilerError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[5]\u001b[39m\u001b[32m, line 17\u001b[39m\n\u001b[32m 15\u001b[39m symbol_analysis = AnalogSymbolTableBuilder(cfg, dataflow_result)\n\u001b[32m 16\u001b[39m symbol_table = symbol_analysis.symbol_table\n\u001b[32m---> \u001b[39m\u001b[32m17\u001b[39m \u001b[43mcompile_analog_circuit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcircuit\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcfg\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msymbol_table\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/Documents/OQD/oqd-core/src/oqd_core/compiler/analog/passes/compile.py:46\u001b[39m, in \u001b[36mcompile_analog_circuit\u001b[39m\u001b[34m(model, cfg, symbol_table, args)\u001b[39m\n\u001b[32m 43\u001b[39m verify_register_access_dim(cfg, symbol_table)\n\u001b[32m 44\u001b[39m verify_hamiltonian_target_dim(cfg, symbol_table)\n\u001b[32m---> \u001b[39m\u001b[32m46\u001b[39m n_qreg, n_qmode = \u001b[43minfer_analog_circuit_dim_cfg\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcfg\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 47\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m args \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[32m 48\u001b[39m canonicalize_args_metrics(args)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/Documents/OQD/oqd-core/src/oqd_core/compiler/analog/passes/assign.py:52\u001b[39m, in \u001b[36minfer_analog_circuit_dim_cfg\u001b[39m\u001b[34m(cfg)\u001b[39m\n\u001b[32m 50\u001b[39m dim = d\n\u001b[32m 51\u001b[39m \u001b[38;5;28;01melif\u001b[39;00m dim != d:\n\u001b[32m---> \u001b[39m\u001b[32m52\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m AnalogCompilerError(\u001b[33m\"\u001b[39m\u001b[33mInconsistent Hilbert space dimensions between Evolve statements\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m 53\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m dim \u001b[38;5;129;01mor\u001b[39;00m (\u001b[32m0\u001b[39m, \u001b[32m0\u001b[39m)\n", + "\u001b[31mAnalogCompilerError\u001b[39m: Inconsistent Hilbert space dimensions between Evolve statements" + ] + } + ], + "source": [ + "from oqd_core.analysis.analog import (\n", + " AnalogCFGBuilder,\n", + " AnalogSymbolTableBuilder,\n", + " AnalogTypeChecker,\n", + ")\n", + "from oqd_core.compiler.analog.passes.compile import compile_analog_circuit\n", "\n", "with open(\"test.analog\", mode=\"r\", encoding=\"utf8\") as f:\n", " source = f.read()\n", "\n", "circuit = parse_analog(source)\n", - "\n", - "\n", - "print(serialize_analog(circuit))" + "cfg = AnalogCFGBuilder().run(circuit)\n", + "type_checker = AnalogTypeChecker(cfg)\n", + "dataflow_result = type_checker.dataflow_result\n", + "symbol_analysis = AnalogSymbolTableBuilder(cfg, dataflow_result)\n", + "symbol_table = symbol_analysis.symbol_table\n", + "compile_analog_circuit(circuit, cfg, symbol_table)\n" ] }, { "cell_type": "code", "execution_count": null, - "id": "b5a6b113", + "id": "34b5e170", "metadata": {}, "outputs": [], "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8303ca3d", + "metadata": {}, + "outputs": [], + "source": [ + "# from oqd_core.compiler.analog.passes.compile import compile_analog_circuit\n", + "# out, (n_qreg, n_qmode) = compile_analog_circuit(circuit)\n", + "# print(printer(out))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5a6b113", + "metadata": {}, + "outputs": [], + "source": [ + "# cfg = AnalogCFGBuilder().run(circuit)\n", + "# out = json.dumps({node_id: node.to_dict() for node_id, node in cfg.items()}, indent=2)\n", + "# print(out)\n", + "\n", + "\n", + "# print(symbol_table)\n", + "# symbol_table = str(symbol_table)\n", + "# tree = symbol_table.model_dump_json(indent=2, serialize_as_any=True)\n", + "# print(json.dumps(cfg, indent=2))" + ] } ], "metadata": { "kernelspec": { - "display_name": "oqd-core (3.11.11)", + "display_name": "oqd-core (3.11.11.final.0)", "language": "python", "name": "python3" }, diff --git a/examples/atomic/test.atomic b/examples/atomic/test.atomic index 2ca08c07..30c08182 100644 --- a/examples/atomic/test.atomic +++ b/examples/atomic/test.atomic @@ -11,6 +11,7 @@ phi = #phi t_gate = 10e-6 flag = true n = 3 +r = ionreg(2) // beam(frequency, rabi, phase, polarization, wavevector) beam_mw = beam(2.0 * pi * 1e6, omega, phi, [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]) diff --git a/examples/atomic/test.ipynb b/examples/atomic/test.ipynb index 17d1368a..d7645db1 100644 --- a/examples/atomic/test.ipynb +++ b/examples/atomic/test.ipynb @@ -82,6 +82,7 @@ "t_gate = 1e-5\n", "flag = true\n", "n = 3\n", + "r = ionreg(2)\n", "beam_mw = beam(2.0 * pi * 1000000.0, omega, phi, [1.0, 0.0, 0.0], [0.0, 0.0, 1.0])\n", "beam_det = beam(2.0 * pi * 2000000.0, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0])\n", "pulse(beam_mw, t_gate, q0, false)\n", @@ -138,16 +139,56 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "89124808", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "from oqd_compiler_infrastructure import Post, PrettyPrint\n", + "\n", + "from oqd_core.analysis.atomic.cfg import AtomicCFGBuilder\n", + "from oqd_core.analysis.atomic.type_checker import AtomicTypeChecker\n", + "from oqd_core.frontend.atomic import parse_atomic\n", + "\n", + "printer = Post(PrettyPrint())\n", + "\n", + "with open(\"test.atomic\", mode=\"r\", encoding=\"utf8\") as f:\n", + " source = f.read()\n", + "\n", + "circuit = parse_atomic(source)\n", + "cfg = AtomicCFGBuilder().run(circuit)\n", + "checker = AtomicTypeChecker(cfg)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "9314af17", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AtomicCircuit(class_='AtomicCircuit', statements=[Declaration(class_='Declaration', name='ions', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=1)), Declaration(class_='Declaration', name='targets', value=AtomicList(class_='AtomicList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phi', value=MathVar(class_='MathVar', name='#phi')), Declaration(class_='Declaration', name='t_gate', value=MathNum(class_='MathNum', value=1e-05)), Declaration(class_='Declaration', name='flag', value=Bool(class_='Bool', value=True)), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), Declaration(class_='Declaration', name='r', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='beam_mw', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=2000000.0), expr2=Access(class_='Access', name='pi')), rabi=Access(class_='Access', name='omega'), phase=Access(class_='Access', name='phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Declaration(class_='Declaration', name='beam_det', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=4000000.0), expr2=Access(class_='Access', name='pi')), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=Access(class_='Access', name='t_gate'), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=3e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=Access(class_='Access', name='t_gate'), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=3e-06), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=False))])]), IfElse(class_='IfElse', condition=Access(class_='Access', name='flag'), then_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))])], else_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-05), target=Access(class_='Access', name='targets'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=True))])]), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=1e-06), target=Access(class_='Access', name='targets'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))])]), Declaration(class_='Declaration', name='n', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=-1), expr2=Access(class_='Access', name='n'))), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Continue(class_='Continue')], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Break(class_='Break')], else_branch=[])])])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from oqd_core.compiler.atomic.canonicalize import canonicalize_atomic_circuit_factory\n", + "from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_math_cfg\n", + "\n", + "canonicalize_math_cfg(cfg)\n", + "canonicalize_atomic_circuit_factory()(circuit)" + ] } ], "metadata": { "kernelspec": { - "display_name": "oqd-core (3.11.11)", + "display_name": "oqd-core (3.11.11.final.0)", "language": "python", "name": "python3" }, diff --git a/src/oqd_core/analysis/analog/types.py b/src/oqd_core/analysis/analog/types.py index bfbdc008..63253e74 100644 --- a/src/oqd_core/analysis/analog/types.py +++ b/src/oqd_core/analysis/analog/types.py @@ -15,7 +15,6 @@ from __future__ import annotations -from dataclasses import dataclass from typing import Union from oqd_compiler_infrastructure.lattice import ( @@ -23,6 +22,7 @@ LatticeBottom, LatticeTop, ) +from pydantic import BaseModel, ConfigDict from oqd_core.interface.analog import ( BoolAnd, @@ -48,9 +48,9 @@ class AnalogTypeError(TypeError): """Type Error class for Analog.""" pass -@dataclass -class TList(LatticeTop): +class TList(LatticeTop, BaseModel): """Lattice value representing a list.""" + model_config = ConfigDict(frozen=True) elem: TLatticeValue TLatticeValue = Union[TList, type[LatticeTop]] diff --git a/src/oqd_core/compiler/atomic/canonicalize.py b/src/oqd_core/compiler/atomic/canonicalize.py index e203986b..fd0b650e 100644 --- a/src/oqd_core/compiler/atomic/canonicalize.py +++ b/src/oqd_core/compiler/atomic/canonicalize.py @@ -14,98 +14,23 @@ from functools import partial, reduce -from oqd_compiler_infrastructure import Chain, Post, Pre, RewriteRule +from oqd_compiler_infrastructure import Chain, Post, RewriteRule +from oqd_core.interface.atomic.expr import MathNum, MathSub, Pulse +from oqd_core.interface.atomic import Declaration, IfElse, While +from oqd_core.compiler.atomic.math.passes import simplify_math_expr +from oqd_core.compiler.atomic.error import AtomicCompilerError +from oqd_core.interface.atomic.statement import SerialProtocol, ParallelProtocol -from oqd_core.compiler.atomic.math.rules import SubstituteMathVar -from oqd_core.interface.atomic import Level, Transition -from oqd_core.interface.atomic import MathVar ######################################################################################## +PROTOCOL_STMT_TYPES = (Pulse, ParallelProtocol, SerialProtocol) -class UnrollLevelLabel(RewriteRule): - """ - Unrolls the [`Level`][oqd_core.interface.atomic.system.Level] labels present in [`Transitions`][oqd_core.interface.atomic.system.Transition]. - - Args: - model (AtomicCircuit): The rule only acts on [`AtomicCircuit`][oqd_core.interface.atomic.AtomicCircuit] objects. - - Returns: - model (AtomicCircuit): - - Assumptions: - None - - """ - - def map_Ion(self, model): - self.ion_levels = {level.label: level for level in model.levels} - - def map_Transition(self, model): - if isinstance(model.level1, Level) and isinstance(model.level2, Level): - return - - level1 = ( - self.ion_levels[model.level1] - if isinstance(model.level1, str) - else model.level1 - ) - level2 = ( - self.ion_levels[model.level2] - if isinstance(model.level2, str) - else model.level2 - ) - return model.__class__( - label=model.label, - level1=level1, - level2=level2, - einsteinA=model.einsteinA, - multipole=model.multipole, - ) - - -class UnrollTransitionLabel(RewriteRule): - """ - Unrolls the [`Transition`][oqd_core.interface.atomic.system.Transition] labels present in [`Beams`][oqd_core.interface.atomic.protocol.Beam]. - - Args: - model (AtomicCircuit): The rule only acts on [`AtomicCircuit`][oqd_core.interface.atomic.AtomicCircuit] objects. - - Returns: - model (AtomicCircuit): - - Assumptions: - None - """ - - def map_System(self, model): - self.ions_transitions = [ - {transition.label: transition for transition in ion.transitions} - for ion in model.ions - ] - - def map_Beam(self, model): - if isinstance(model.transition, Transition): - return - - if isinstance(model.transition, str): - transition_label = model.transition - reference_ion = model.target - else: - transition_label = model.transition[0] - reference_ion = model.transition[1] - - transition = self.ions_transitions[reference_ion][transition_label] - return model.__class__( - transition=transition, - rabi=model.rabi, - detuning=model.detuning, - phase=model.phase, - polarization=model.polarization, - wavevector=model.wavevector, - target=model.target, - ) - +def _as_numeric_duration(duration): + simplified = simplify_math_expr(duration) + if isinstance(simplified, MathNum): + return simplified.value + raise AtomicCompilerError(f"Duration must be constant: {duration}") class ResolveNestedProtocol(RewriteRule): """ @@ -129,15 +54,19 @@ def __init__(self): @classmethod def _get_continuous_duration(self, model): if isinstance(model, ParallelProtocol): - if len(model.sequence) == 1: - return model.sequence[0].duration + if not model.pulses: + raise AtomicCompilerError(f"Parallel block is empty.") + if len(model.pulses) == 1: + return self._get_continuous_duration(model.pulses[0]) - return min(map(lambda x: x.duration, model.sequence)) + return min(map(lambda x: self._get_continuous_duration, model.pulses)) - if isinstance(model, SequentialProtocol): - return self._get_continuous_duration(model.sequence[0]) + if isinstance(model, SerialProtocol): + if not model.pulses: + raise AtomicCompilerError(f"Serial block is empty.") + return self._get_continuous_duration(model.pulses[0]) - return model.duration + return _as_numeric_duration(model.duration) @classmethod def _cut_protocol(cls, model, continuous_duration): @@ -145,7 +74,7 @@ def _cut_protocol(cls, model, continuous_duration): pairs = list( map( partial(cls._cut_protocol, continuous_duration=continuous_duration), - model.sequence, + model.pulses, ) ) @@ -154,158 +83,164 @@ def _cut_protocol(cls, model, continuous_duration): remainder = [r for r in map(lambda x: x[1], pairs) if r is not None] if remainder: - return cut, ParallelProtocol(sequence=remainder) + return cut, ParallelProtocol(pulses=remainder) return cut, None - if isinstance(model, SequentialProtocol): + if isinstance(model, SerialProtocol): cut, remainder = cls._cut_protocol( - model.sequence[0], continuous_duration=continuous_duration + model.pulses[0], continuous_duration=continuous_duration ) if remainder: - return cut, SequentialProtocol( - sequence=[remainder, *model.sequence[1:]] + return cut, SerialProtocol( + pulses=[remainder, *model.pulses[1:]] ) - if model.sequence[1:]: - return cut, SequentialProtocol(sequence=model.sequence[1:]) + if model.pulses[1:]: + return cut, SerialProtocol(pulses=model.pulses[1:]) return cut, None + total = _as_numeric_duration(model.duration) cut = model.model_copy(deep=True) - if cut.duration == continuous_duration: + + if total == continuous_duration: return [cut], None - cut.duration = continuous_duration - + cut.duration = MathNum(value=continuous_duration) remainder = model.model_copy(deep=True) - remainder.duration = remainder.duration - continuous_duration + remainder.duration = MathSub( + expr1=model.duration, + expr2=MathNum(value=continuous_duration), + ) return [cut], remainder def map_ParallelProtocol(self, model): - sequence = model.sequence + statements = model.pulses protocols = [] - while sequence: - continuous_duration = min(map(self._get_continuous_duration, sequence)) + while statements: + continuous_duration = min(map(self._get_continuous_duration, statements)) pairs = list( map( partial( self._cut_protocol, continuous_duration=continuous_duration ), - sequence, + statements, ) ) protocols.append( ParallelProtocol( - sequence=reduce(lambda x, y: x + y, map(lambda x: x[0], pairs)) + pulses=reduce(lambda x, y: x + y, map(lambda x: x[0], pairs)) ) ) - sequence = [r for r in map(lambda x: x[1], pairs) if r is not None] + statements = [r for r in map(lambda x: x[1], pairs) if r is not None] - return SequentialProtocol(sequence=protocols) + return SerialProtocol(pulses=protocols) - def map_SequentialProtocol(self, model): - if len(model.sequence) == 1: - return model.sequence[0] + def map_SerialProtocol(self, model): + if len(model.pulses) == 1: + return model.pulses[0] - new_sequence = [] - for subprotocol in model.sequence: - if isinstance(subprotocol, SequentialProtocol): - new_sequence.extend( + new_statements = [] + for subprotocol in model.pulses: + if isinstance(subprotocol, SerialProtocol): + new_statements.extend( list( map( lambda x: x if isinstance(x, ParallelProtocol) - else ParallelProtocol(sequence=[x]), - subprotocol.sequence, + else ParallelProtocol(pulses=[x]), + subprotocol.pulses, ) ) ) elif isinstance(subprotocol, ParallelProtocol): - new_sequence.append(subprotocol) + new_statements.append(subprotocol) else: - new_sequence.append(ParallelProtocol(sequence=[subprotocol])) - return model.__class__(sequence=new_sequence) + new_statements.append(ParallelProtocol(pulses=[subprotocol])) + return model.__class__(pulses=new_statements) def map_Pulse(self, model): - return SequentialProtocol(sequence=[model]) - - -class ResolveRelativeTime(RewriteRule): - """ - Handles conversion of relative time to absolute time. - - Args: - model (AtomicCircuit): The rule only acts on [`AtomicCircuit`][oqd_core.interface.atomic.AtomicCircuit] objects. - - Returns: - model (AtomicCircuit): - - Assumptions: - None - """ - - def __init__(self): - super().__init__() - - def map_AtomicCircuit(self, model): - protocol = Post( - SubstituteMathVar( - variable=MathVar(name="s"), substitution=MathVar(name="t") - ) - )(model.protocol) - - return model.__class__(system=model.system, protocol=protocol) - - @classmethod - def _get_duration(cls, model): - if isinstance(model, SequentialProtocol): - return reduce( - lambda x, y: x + y, - [cls._get_duration(p) for p in model.sequence], - ) - if isinstance(model, ParallelProtocol): - if len(model.sequence) == 1: - return cls._get_duration(model.sequence[0]) - - return max( - *[cls._get_duration(p) for p in model.sequence], - ) - return model.duration - - def map_SequentialProtocol(self, model): - current_time = 0 - - new_sequence = [] - for p in model.sequence: - duration = self._get_duration(p) - - new_p = Post( - SubstituteMathVar( - variable=MathVar(name="s"), - substitution=MathVar(name="s") - current_time, - ) - )(p) - new_sequence.append(new_p) - - current_time += duration - - return model.__class__(sequence=new_sequence) + return SerialProtocol(pulses=[model]) + + def map_Declaration(self, model: Declaration): + pass + + def map_IfElse(self, model: IfElse): + pass + + def map_While(self, model: While): + pass + + +# class ResolveRelativeTime(RewriteRule): +# """ +# Handles conversion of relative time to absolute time. + +# Args: +# model (AtomicCircuit): The rule only acts on [`AtomicCircuit`][oqd_core.interface.atomic.AtomicCircuit] objects. + +# Returns: +# model (AtomicCircuit): + +# Assumptions: +# None +# """ + +# def __init__(self): +# super().__init__() + +# def map_AtomicCircuit(self, model): +# protocol = Post( +# SubstituteMathVar( +# variable=MathVar(name="#s"), substitution=MathVar(name="#t") +# ) +# )(model.statements) + +# return model.__class__(statements=protocol) + +# @classmethod +# def _get_duration(cls, model): +# if isinstance(model, SerialProtocol): +# return reduce( +# lambda x, y: x + y, +# [cls._get_duration(p) for p in model.pulses], +# ) +# if isinstance(model, ParallelProtocol): +# if len(model.pulses) == 1: +# return cls._get_duration(model.pulses[0]) + +# return max( +# *[cls._get_duration(p) for p in model.pulses], +# ) +# return model.duration + +# def map_SerialProtocol(self, model): +# current_time = 0 + +# new_statements = [] +# for p in model.pulses: +# duration = self._get_duration(p) + +# new_p = Post( +# SubstituteMathVar( +# variable=MathVar(name="#s"), +# substitution=MathVar(name="#s") - current_time, +# ) +# )(p) +# new_statements.append(new_p) + +# current_time += duration + +# return model.__class__(pulses=new_statements) ######################################################################################## -unroll_label_pass = Chain( - Pre(UnrollLevelLabel()), - Pre(UnrollTransitionLabel()), -) -""" -Pass that unrolls the references to levels and transitions -""" def canonicalize_atomic_circuit_factory(): @@ -313,7 +248,6 @@ def canonicalize_atomic_circuit_factory(): Factory for creating a pass for canonicalizing an atomic circuit. """ return Chain( - unroll_label_pass, - Post(ResolveRelativeTime()), + # Post(ResolveRelativeTime()), Post(ResolveNestedProtocol()), ) diff --git a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py new file mode 100644 index 00000000..ea701c32 --- /dev/null +++ b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py @@ -0,0 +1,6 @@ +from .walk import canonicalize_math_block, canonicalize_math_cfg, iter_stmt_blocks +__all__ = [ + "iter_stmt_blocks", + "canonicalize_math_block", + "canonicalize_math_cfg", +] diff --git a/src/oqd_core/compiler/atomic/cfg_passes/walk.py b/src/oqd_core/compiler/atomic/cfg_passes/walk.py new file mode 100644 index 00000000..3762710f --- /dev/null +++ b/src/oqd_core/compiler/atomic/cfg_passes/walk.py @@ -0,0 +1,89 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + + +from __future__ import annotations + + +from oqd_core.analysis.utils.control_flow import Block, ControlFlowGraph +from oqd_core.compiler.atomic.math.passes import canonicalize_math_expr +from oqd_core.interface.atomic import ( + AtomicList, + Beam, + Declaration, + ParallelProtocol, + Pulse, + SerialProtocol, +) +from oqd_core.interface.atomic.expr import AtomicExpr + +def iter_stmt_blocks(cfg: ControlFlowGraph): + for node_id, block in cfg.blocks.items(): + if isinstance(block.stmt, str): + continue + yield node_id, block + +def canonicalize_expr(expr): + if isinstance(expr, AtomicExpr): + return canonicalize_math_expr(expr) + return expr + +def canonicalize_beam(beam: Beam) -> Beam: + beam.frequency = canonicalize_expr(beam.frequency) + beam.rabi = canonicalize_expr(beam.rabi) + beam.phase = canonicalize_expr(beam.phase) + beam.polarization = canonicalize_expr(beam.polarization) + beam.wavevector = canonicalize_expr(beam.wavevector) + return beam + +def canonicalize_atomic_list(values: AtomicList) -> AtomicList: + values.values = [canonicalize_expr(v) for v in values.values] + return values + +def canonicalize_math_block(block: Block): + stmt = block.stmt + + if block.kind == "branch": + block.stmt = canonicalize_expr(stmt) + return + + if isinstance(stmt, Pulse): + stmt.duration = canonicalize_expr(stmt.duration) + stmt.target = canonicalize_expr(stmt.target) + stmt.measured = canonicalize_expr(stmt.measured) + if isinstance(stmt.beam, Beam): + stmt.beam = canonicalize_beam(stmt.beam) + else: + stmt.beam = canonicalize_expr(stmt.beam) + return + + if isinstance(stmt, Declaration): + if isinstance(stmt.value, Beam): + stmt.value = canonicalize_beam(stmt.value) + elif isinstance(stmt.value, AtomicList): + stmt.value = canonicalize_atomic_list(stmt.value) + else: + stmt.value = canonicalize_expr(stmt.value) + return + + if isinstance(stmt, (ParallelProtocol, SerialProtocol)): + return + + +def canonicalize_math_cfg(cfg: ControlFlowGraph): + for _, block in iter_stmt_blocks(cfg): + canonicalize_math_block(block) + return cfg + + diff --git a/src/oqd_core/compiler/atomic/error.py b/src/oqd_core/compiler/atomic/error.py new file mode 100644 index 00000000..3ad24ab1 --- /dev/null +++ b/src/oqd_core/compiler/atomic/error.py @@ -0,0 +1,27 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +__all__ = [ + "AtomicCompilerError", +] + +######################################################################################## + + +class AtomicCompilerError(Exception): + """ + Error class for Atomic compiler + """ + + pass diff --git a/src/oqd_core/compiler/atomic/math/rules.py b/src/oqd_core/compiler/atomic/math/rules.py index 84db333b..ab2012ce 100644 --- a/src/oqd_core/compiler/atomic/math/rules.py +++ b/src/oqd_core/compiler/atomic/math/rules.py @@ -19,7 +19,7 @@ from pydantic import TypeAdapter, ValidationError from oqd_core.interface.atomic import ( - ConstantMathExpr, + # CastMathExpr, MathAdd, MathBinaryOp, MathDiv, @@ -508,7 +508,7 @@ def map_MathImag(self, model): def map_MathExpr(self, model): try: - TypeAdapter(ConstantMathExpr).validate_python(model) + # TypeAdapter(CastMathExpr).validate_python(model) value = Post(EvaluateMathExpr())(model) diff --git a/tests/test_atomic/test_beam.py b/tests/test_atomic/test_beam.py index 76525ba9..884761b8 100644 --- a/tests/test_atomic/test_beam.py +++ b/tests/test_atomic/test_beam.py @@ -15,179 +15,149 @@ import numpy as np import pytest -from oqd_core.interface.atomic import Beam -from oqd_core.interface.atomic.species import Yb171IIBuilder -from oqd_core.interface.math import MathStr +from oqd_core.interface.atomic import ( + Beam, + MathVar, + AtomicList, + MathFunc, + MathMul, + MathImag, + MathNum, +) ######################################################################################## - -@pytest.fixture -def ion(): - return Yb171IIBuilder().build() - +T = MathVar(name="#t") +A = MathVar(name="#A") +DEFAULT_WV = AtomicList(values=[1, 0, 0]) +DEFAULT_POL = AtomicList(values=[0, 0, 1]) class TestBeam: - def test_zero_beam(self, ion): + def test_zero_beam(self): Beam( - transition=ion.transitions[0], - detuning=0, + frequency=0, rabi=0, phase=0, - polarization=[0, 0, 1], - wavevector=[1, 0, 0], - target=0, + polarization=DEFAULT_POL, + wavevector=DEFAULT_WV, ) - def test_constant_beam(self, ion): + def test_constant_beam(self): Beam( - transition=ion.transitions[0], - detuning=0, + frequency=0, rabi=1, phase=np.pi, - polarization=[0, 0, 1], - wavevector=[1, 0, 0], - target=0, + polarization=DEFAULT_POL, + wavevector=DEFAULT_WV, ) @pytest.mark.parametrize( "rabi", [ - MathStr(string="t"), - MathStr(string="sin(t)"), - MathStr(string="A*sin(t)"), + T, + MathFunc(func="sin", expr=T), + MathMul(expr1=A, expr2=MathFunc(func="sin", expr=T)), ], ) - def test_time_dependent_rabi(self, ion, rabi): + def test_time_dependent_rabi(self, rabi): Beam( - transition=ion.transitions[0], - detuning=0, + frequency=0, rabi=rabi, phase=0, - polarization=[0, 0, 1], - wavevector=[1, 0, 0], - target=0, - ) - - @pytest.mark.parametrize( - "detuning", - [ - MathStr(string="t"), - MathStr(string="sin(t)"), - MathStr(string="A*sin(t)"), - ], - ) - def test_time_dependent_detuning(self, ion, detuning): - Beam( - transition=ion.transitions[0], - detuning=detuning, - rabi=1, - phase=0, - polarization=[0, 0, 1], - wavevector=[1, 0, 0], - target=0, + polarization=DEFAULT_POL, + wavevector=DEFAULT_WV, ) @pytest.mark.parametrize( "phase", [ - MathStr(string="t"), - MathStr(string="sin(t)"), - MathStr(string="A*sin(t)"), + T, + MathFunc(func="sin", expr=T), + MathMul(expr1=A, expr2=MathFunc(func="sin", expr=T)), ], ) - def test_time_dependent_phase(self, ion, phase): + def test_time_dependent_phase(self, phase): Beam( - transition=ion.transitions[0], - detuning=0, + frequency=0, rabi=1, phase=phase, - polarization=[0, 0, 1], - wavevector=[1, 0, 0], - target=0, + polarization=DEFAULT_POL, + wavevector=DEFAULT_WV, ) @pytest.mark.parametrize( "polarization", [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1], - [1, 1, 0], - [1, 1j, 0], - [1, -1j, 0], - [1, -1j, 0], - [0, 0, MathStr(string="exp(1j*3.1415926535)")], + AtomicList(values=[1, 0, 0]), + AtomicList(values=[0, 1, 0]), + AtomicList(values=[0, 0, 1]), + AtomicList(values=[1, 1, 0]), + AtomicList(values=[1, 1j, 0]), + AtomicList(values=[1, -1j, 0]), + AtomicList(values=[1, -1j, 0]), + AtomicList(values=[0, 0, MathFunc(func="exp", expr=MathMul(expr1=MathImag(), expr2=MathNum(value=3.1415926535)),),]), ], ) - def test_polarization(self, ion, polarization): + def test_polarization(self, polarization): Beam( - transition=ion.transitions[0], - detuning=0, + frequency=0, rabi=1, phase=0, polarization=polarization, - wavevector=[1, 0, 0], - target=0, + wavevector=DEFAULT_WV, ) @pytest.mark.xfail @pytest.mark.parametrize( "polarization", [ - [0, 0, MathStr(string="t")], - [0, 0, MathStr(string="sin(t)")], - [0, 0, MathStr(string="A*sin(t)")], + AtomicList(values=[0, 0, T]), + AtomicList(values=[0, 0, MathFunc(func="sin", expr=T)]), + AtomicList(values=[0, 0, MathMul(expr1=A, expr2=MathFunc(func="sin", expr=T))]), ], ) - def test_non_constant_polarization(self, ion, polarization): + def test_non_constant_polarization(self, polarization): Beam( - transition=ion.transitions[0], - detuning=0, + frequency=0, rabi=1, phase=0, polarization=polarization, - wavevector=[1, 0, 0], - target=0, + wavevector=DEFAULT_WV, ) @pytest.mark.parametrize( "wavevector", [ - [1, 0, 0], - [0, 1, 0], - [0, 0, 1], - [1, 1, 0], - [0, 0, MathStr(string="exp(1j*3.1415926535)")], + AtomicList(values=[1, 0, 0]), + AtomicList(values=[0, 1, 0]), + AtomicList(values=[0, 0, 1]), + AtomicList(values=[1, 1, 0]), + AtomicList(values=[0, 0, MathFunc(func="exp", expr=MathMul(expr1=MathImag(), expr2=MathNum(value=3.1415926535)),),]), ], ) - def test_wavevector(self, ion, wavevector): + def test_wavevector(self, wavevector): Beam( - transition=ion.transitions[0], - detuning=0, + frequency=0, rabi=1, phase=0, - polarization=[0, 0, 1], + polarization=DEFAULT_POL, wavevector=wavevector, - target=0, ) @pytest.mark.xfail @pytest.mark.parametrize( "wavevector", [ - [0, 0, MathStr(string="t")], - [0, 0, MathStr(string="sin(t)")], - [0, 0, MathStr(string="A*sin(t)")], + AtomicList(values=[0, 0, T]), + AtomicList(values=[0, 0, MathFunc(func="sin", expr=T)]), + AtomicList(values=[0, 0, MathMul(expr1=A, expr2=MathFunc(func="sin", expr=T))]), ], ) - def test_non_constant_wavevector(self, ion, wavevector): + def test_non_constant_wavevector(self, wavevector): Beam( - transition=ion.transitions[0], - detuning=0, + frequency=0, rabi=1, phase=0, - polarization=[0, 0, 1], + polarization=DEFAULT_POL, wavevector=wavevector, - target=0, ) diff --git a/tests/test_atomic/test_unroll.py b/tests/test_atomic/test_unroll.py deleted file mode 100644 index 67a27746..00000000 --- a/tests/test_atomic/test_unroll.py +++ /dev/null @@ -1,265 +0,0 @@ -# Copyright 2024-2025 Open Quantum Design - -# 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 numpy as np - -from oqd_core.compiler.atomic.canonicalize import unroll_label_pass - -######################################################################################## -from oqd_core.interface.atomic import ( - AtomicCircuit, - Beam, - Ion, - Level, - Pulse, - SequentialProtocol, - System, - Transition, -) - -######################################################################################## - - -def test_unroll_string_labels(): - downstate = Level( - label="q0", - principal=6, - spin=1 / 2, - orbital=0, - nuclear=1 / 2, - spin_orbital=1 / 2, - spin_orbital_nuclear=0, - spin_orbital_nuclear_magnetization=0, - energy=2 * np.pi * 0, - ) - estate = Level( - label="e0", - principal=5, - spin=1 / 2, - orbital=1, - nuclear=1 / 2, - spin_orbital=1 / 2, - spin_orbital_nuclear=1, - spin_orbital_nuclear_magnetization=-1, - energy=2 * np.pi * 100, - ) - - transitions = [ - Transition( - label="q0->e0", - level1="q0", - level2="e0", - einsteinA=1, - multipole="E1", - ), - ] - - ion = Ion( - mass=171, - charge=1, - position=[0, 0, 0], - levels=[downstate, estate], - transitions=transitions, - ) - - system = System( - ions=[ - ion, - ], - modes=[], - ) - - beam = Beam( - transition="q0->e0", - rabi=2 * np.pi * 1, - detuning=0, - phase=0, - polarization=[1, 0, 0], - wavevector=[0, 1, 0], - target=0, - ) - - protocol = SequentialProtocol( - sequence=[ - Pulse(beam=beam, duration=1), - ] - ) - - atomic_circuit = AtomicCircuit(system=system, protocol=protocol) - - ######################################################################################## - - unrolled_transitions = [ - Transition( - label="q0->e0", - level1=downstate, - level2=estate, - einsteinA=1, - multipole="E1", - ), - ] - - unrolled_ion = Ion( - mass=171, - charge=1, - position=[0, 0, 0], - levels=[downstate, estate], - transitions=unrolled_transitions, - ) - - unrolled_system = System( - ions=[ - unrolled_ion, - ], - modes=[], - ) - - unrolled_beam = Beam( - transition=unrolled_transitions[0], - rabi=2 * np.pi * 1, - detuning=0, - phase=0, - polarization=[1, 0, 0], - wavevector=[0, 1, 0], - target=0, - ) - - unrolled_protocol = SequentialProtocol( - sequence=[ - Pulse(beam=unrolled_beam, duration=1), - ] - ) - - unrolled_atomic_circuit = AtomicCircuit( - system=unrolled_system, protocol=unrolled_protocol - ) - - assert unroll_label_pass(atomic_circuit) == unrolled_atomic_circuit - - -def test_unroll_tuple_labels(): - downstate = Level( - label="q0", - principal=6, - spin=1 / 2, - orbital=0, - nuclear=1 / 2, - spin_orbital=1 / 2, - spin_orbital_nuclear=0, - spin_orbital_nuclear_magnetization=0, - energy=2 * np.pi * 0, - ) - estate = Level( - label="e0", - principal=5, - spin=1 / 2, - orbital=1, - nuclear=1 / 2, - spin_orbital=1 / 2, - spin_orbital_nuclear=1, - spin_orbital_nuclear_magnetization=-1, - energy=2 * np.pi * 100, - ) - - transitions = [ - Transition( - label="q0->e0", - level1="q0", - level2="e0", - einsteinA=1, - multipole="E1", - ), - ] - - ion = Ion( - mass=171, - charge=1, - position=[0, 0, 0], - levels=[downstate, estate], - transitions=transitions, - ) - - system = System( - ions=[ - ion, - ], - modes=[], - ) - - beam = Beam( - transition=("q0->e0", 0), - rabi=2 * np.pi * 1, - detuning=0, - phase=0, - polarization=[1, 0, 0], - wavevector=[0, 1, 0], - target=0, - ) - - protocol = SequentialProtocol( - sequence=[ - Pulse(beam=beam, duration=1), - ] - ) - - atomic_circuit = AtomicCircuit(system=system, protocol=protocol) - - ######################################################################################## - - unrolled_transitions = [ - Transition( - label="q0->e0", - level1=downstate, - level2=estate, - einsteinA=1, - multipole="E1", - ), - ] - - unrolled_ion = Ion( - mass=171, - charge=1, - position=[0, 0, 0], - levels=[downstate, estate], - transitions=unrolled_transitions, - ) - - unrolled_system = System( - ions=[ - unrolled_ion, - ], - modes=[], - ) - - unrolled_beam = Beam( - transition=unrolled_transitions[0], - rabi=2 * np.pi * 1, - detuning=0, - phase=0, - polarization=[1, 0, 0], - wavevector=[0, 1, 0], - target=0, - ) - - unrolled_protocol = SequentialProtocol( - sequence=[ - Pulse(beam=unrolled_beam, duration=1), - ] - ) - - unrolled_atomic_circuit = AtomicCircuit( - system=unrolled_system, protocol=unrolled_protocol - ) - - assert unroll_label_pass(atomic_circuit) == unrolled_atomic_circuit diff --git a/tests/test_serialization.py b/tests/test_serialization.py deleted file mode 100644 index 14d68730..00000000 --- a/tests/test_serialization.py +++ /dev/null @@ -1,257 +0,0 @@ -# Copyright 2024-2025 Open Quantum Design - -# 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 numpy as np -import pytest - -from oqd_core.interface.analog import ( - AnalogCircuit, - AnalogGate, - Annihilation, - Creation, - Identity, - PauliI, - PauliX, - PauliY, - PauliZ, -) -from oqd_core.interface.atomic import ( - AtomicCircuit, - Beam, - Ion, - Level, - ParallelProtocol, - Phonon, - Pulse, - SequentialProtocol, - System, - Transition, -) - -######################################################################################## -from oqd_core.interface.math import MathStr - -######################################################################################## - -X, Y, Z, PI, A, C, LI = ( - PauliX(), - PauliY(), - PauliZ(), - PauliI(), - Annihilation(), - Creation(), - Identity(), -) - - -Hx = AnalogGate(hamiltonian=-(np.pi / 4) * X) -analog_circuit = AnalogCircuit() -analog_circuit.evolve(duration=1, gate=Hx) -analog_circuit.evolve(duration=1, gate=Hx) -analog_circuit.evolve(duration=1, gate=Hx) -analog_circuit.measure() - -######################################################################################## - -downstate = Level( - label="q0", - principal=6, - spin=1 / 2, - orbital=0, - nuclear=1 / 2, - spin_orbital=1 / 2, - spin_orbital_nuclear=0, - spin_orbital_nuclear_magnetization=0, - energy=2 * np.pi * 0, -) -upstate = Level( - label="q1", - principal=6, - spin=1 / 2, - orbital=0, - nuclear=1 / 2, - spin_orbital=1 / 2, - spin_orbital_nuclear=1, - spin_orbital_nuclear_magnetization=0, - energy=2 * np.pi * 10, -) -estate = Level( - label="e0", - principal=5, - spin=1 / 2, - orbital=1, - nuclear=1 / 2, - spin_orbital=1 / 2, - spin_orbital_nuclear=1, - spin_orbital_nuclear_magnetization=-1, - energy=2 * np.pi * 100, -) -estate2 = Level( - label="e1", - principal=5, - spin=1 / 2, - orbital=1, - nuclear=1 / 2, - spin_orbital=1 / 2, - spin_orbital_nuclear=1, - spin_orbital_nuclear_magnetization=1, - energy=2 * np.pi * 110, -) - -transitions = [ - Transition( - label="q0->e0", - level1="q0", - level2="e0", - einsteinA=1, - multipole="E1", - ), - Transition( - label="q0->e1", - level1="q0", - level2="e1", - einsteinA=1, - multipole="E1", - ), - Transition( - label="q1->e0", - level1="q1", - level2="e0", - einsteinA=1, - multipole="E1", - ), - Transition( - label="q1->e1", - level1="q1", - level2="e1", - einsteinA=1, - multipole="E1", - ), -] - -ion = Ion( - mass=171, - charge=1, - position=[0, 0, 0], - levels=[downstate, upstate, estate, estate2], - transitions=transitions, -) - -COM_x = Phonon(energy=0.1, eigenvector=[1, 0, 0]) - -system = System( - ions=[ - ion, - ], - modes=[ - COM_x, - ], -) - -beam = Beam( - transition="q0->e0", - rabi=2 * np.pi * 1, - detuning=0, - phase=0, - polarization=[1, 0, 0], - wavevector=[0, 1, 0], - target=0, -) - -beam2 = Beam( - transition="q0->e0", - rabi=2 * np.pi * 5, - detuning=2 * np.pi * 25, - phase=0, - polarization=[1, 0, 0], - wavevector=[0, 1, 0], - target=0, -) - -beam3 = Beam( - transition="q1->e0", - rabi=2 * np.pi * 5, - detuning=2 * np.pi * 25, - phase=0, - polarization=[1, 0, 0], - wavevector=[0, 1, 0], - target=0, -) - -protocol1 = SequentialProtocol( - sequence=[ - Pulse(beam=beam, duration=10), - ] -) -protocol2 = ParallelProtocol( - sequence=[ - Pulse(beam=beam2, duration=10), - Pulse(beam=beam3, duration=10), - ] -) - -protocol = SequentialProtocol( - sequence=[ - protocol1, - protocol2, - ] -) - -atomic_circuit = AtomicCircuit(system=system, protocol=protocol) - -######################################################################################## - - -@pytest.mark.parametrize( - "model", - [ - MathStr(string="1"), - MathStr(string="t"), - MathStr(string="1+2"), - MathStr(string="1*2"), - MathStr(string="1**2"), - MathStr(string="sin(t)"), - MathStr(string="exp(t)"), - X, - Y @ Y @ X, - X + Y + Z + PI, - A + C + LI, - Hx, - analog_circuit, - downstate, - upstate, - estate, - estate2, - transitions[0], - transitions[1], - transitions[2], - transitions[3], - ion, - COM_x, - system, - beam, - beam2, - beam3, - Pulse(beam=beam, duration=10), - Pulse(beam=beam2, duration=10), - Pulse(beam=beam3, duration=10), - protocol1, - protocol2, - protocol, - atomic_circuit, - ], -) -def test_serialize_deserialize(model): - assert model.model_validate(model.model_dump()) == model - assert model.model_validate_json(model.model_dump_json()) == model From f5c87f757c0a3eb38ba759dfa6c5ef3e5c5d9027 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Mon, 29 Jun 2026 12:55:30 -0400 Subject: [PATCH 03/20] fix: minor bugs in atomic compiler passes --- examples/atomic/test.ipynb | 2 +- src/oqd_core/compiler/atomic/canonicalize.py | 2 +- src/oqd_core/compiler/atomic/math/rules.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/atomic/test.ipynb b/examples/atomic/test.ipynb index d7645db1..00cf48fc 100644 --- a/examples/atomic/test.ipynb +++ b/examples/atomic/test.ipynb @@ -188,7 +188,7 @@ ], "metadata": { "kernelspec": { - "display_name": "oqd-core (3.11.11.final.0)", + "display_name": "oqd-core (3.11.11)", "language": "python", "name": "python3" }, diff --git a/src/oqd_core/compiler/atomic/canonicalize.py b/src/oqd_core/compiler/atomic/canonicalize.py index fd0b650e..785f1e3f 100644 --- a/src/oqd_core/compiler/atomic/canonicalize.py +++ b/src/oqd_core/compiler/atomic/canonicalize.py @@ -59,7 +59,7 @@ def _get_continuous_duration(self, model): if len(model.pulses) == 1: return self._get_continuous_duration(model.pulses[0]) - return min(map(lambda x: self._get_continuous_duration, model.pulses)) + return min(map(self._get_continuous_duration, model.pulses)) if isinstance(model, SerialProtocol): if not model.pulses: diff --git a/src/oqd_core/compiler/atomic/math/rules.py b/src/oqd_core/compiler/atomic/math/rules.py index ab2012ce..29182633 100644 --- a/src/oqd_core/compiler/atomic/math/rules.py +++ b/src/oqd_core/compiler/atomic/math/rules.py @@ -388,7 +388,7 @@ def __init__(self, variable, substitution): if not isinstance(variable, MathVar): raise TypeError("Variable must be a MathVar") - if not isinstance(variable, MathExpr): + if not isinstance(substitution, MathExpr): raise TypeError("Substituted value must be a MathExpr") self.variable = variable From 60e6f90c974ba8c86fe2380fa9ff24d64dbef7c7 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Mon, 29 Jun 2026 13:58:16 -0400 Subject: [PATCH 04/20] Add resolution of relative time in atomic compiler pass --- src/oqd_core/compiler/atomic/canonicalize.py | 108 +++++++++---------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/oqd_core/compiler/atomic/canonicalize.py b/src/oqd_core/compiler/atomic/canonicalize.py index 785f1e3f..1080bdce 100644 --- a/src/oqd_core/compiler/atomic/canonicalize.py +++ b/src/oqd_core/compiler/atomic/canonicalize.py @@ -15,9 +15,10 @@ from functools import partial, reduce from oqd_compiler_infrastructure import Chain, Post, RewriteRule -from oqd_core.interface.atomic.expr import MathNum, MathSub, Pulse +from oqd_core.interface.atomic.expr import MathNum, MathSub, MathVar, Pulse from oqd_core.interface.atomic import Declaration, IfElse, While from oqd_core.compiler.atomic.math.passes import simplify_math_expr +from oqd_core.compiler.atomic.math.rules import SubstituteMathVar from oqd_core.compiler.atomic.error import AtomicCompilerError from oqd_core.interface.atomic.statement import SerialProtocol, ParallelProtocol @@ -177,66 +178,65 @@ def map_While(self, model: While): pass -# class ResolveRelativeTime(RewriteRule): -# """ -# Handles conversion of relative time to absolute time. - -# Args: -# model (AtomicCircuit): The rule only acts on [`AtomicCircuit`][oqd_core.interface.atomic.AtomicCircuit] objects. - -# Returns: -# model (AtomicCircuit): - -# Assumptions: -# None -# """ - -# def __init__(self): -# super().__init__() - -# def map_AtomicCircuit(self, model): -# protocol = Post( -# SubstituteMathVar( -# variable=MathVar(name="#s"), substitution=MathVar(name="#t") -# ) -# )(model.statements) +class ResolveRelativeTime(RewriteRule): + """ + Handles conversion of relative time to absolute time. -# return model.__class__(statements=protocol) + Args: + model (AtomicCircuit): The rule only acts on [`AtomicCircuit`][oqd_core.interface.atomic.AtomicCircuit] objects. -# @classmethod -# def _get_duration(cls, model): -# if isinstance(model, SerialProtocol): -# return reduce( -# lambda x, y: x + y, -# [cls._get_duration(p) for p in model.pulses], -# ) -# if isinstance(model, ParallelProtocol): -# if len(model.pulses) == 1: -# return cls._get_duration(model.pulses[0]) + Returns: + model (AtomicCircuit): -# return max( -# *[cls._get_duration(p) for p in model.pulses], -# ) -# return model.duration + Assumptions: + None + """ -# def map_SerialProtocol(self, model): -# current_time = 0 + def __init__(self): + super().__init__() -# new_statements = [] -# for p in model.pulses: -# duration = self._get_duration(p) + def _get_segment_duration(self, model): + if isinstance(model, SerialProtocol): + if not model.pulses: + raise AtomicCompilerError("Serial block is empty.") + return sum(self._get_segment_duration(p) for p in model.pulses) + + if isinstance(model, ParallelProtocol): + if not model.pulses: + raise AtomicCompilerError("Parallel block is empty.") + return max(self._get_segment_duration(p) for p in model.pulses) + + if isinstance(model, Pulse): + return _as_numeric_duration(model.duration) + + return 0 + + def _substitute_at(self, offset): + return SubstituteMathVar( + variable=MathVar(name="#s"), + substitution=MathSub( + expr1=MathVar(name="#t"), + expr2=MathNum(value=offset), + ), + ) -# new_p = Post( -# SubstituteMathVar( -# variable=MathVar(name="#s"), -# substitution=MathVar(name="#s") - current_time, -# ) -# )(p) -# new_statements.append(new_p) + def map_SerialProtocol(self, model): + current_time = 0 -# current_time += duration + new_pulses = [] + for p in model.pulses: + new_pulses.append(Post(self._substitute_at(current_time))(p)) + current_time += self._get_segment_duration(p) -# return model.__class__(pulses=new_statements) + return SerialProtocol(pulses=new_pulses) + + def map_ParallelProtocol(self, model): + return ParallelProtocol( + pulses=[Post(self._substitute_at(0))(p) for p in model.pulses] + ) + + def map_Pulse(self, model): + return Post(self._substitute_at(0))(model) ######################################################################################## @@ -248,6 +248,6 @@ def canonicalize_atomic_circuit_factory(): Factory for creating a pass for canonicalizing an atomic circuit. """ return Chain( - # Post(ResolveRelativeTime()), Post(ResolveNestedProtocol()), + Post(ResolveRelativeTime()), ) From a5ef201ba25040bd709263174ac48ab436694bfb Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Mon, 6 Jul 2026 22:14:52 -0400 Subject: [PATCH 05/20] feat: Add compiler passes for atomic interface --- src/oqd_core/analysis/atomic/__init__.py | 23 ++ src/oqd_core/analysis/atomic/symbol_table.py | 238 ++++++++++++++++++ src/oqd_core/compiler/atomic/canonicalize.py | 9 + .../compiler/atomic/cfg_passes/__init__.py | 5 + .../compiler/atomic/cfg_passes/scalar_env.py | 236 +++++++++++++++++ .../compiler/atomic/passes/__init__.py | 3 + .../compiler/atomic/passes/compile.py | 40 +++ src/oqd_core/compiler/atomic/verify/passes.py | 40 +++ tests/test_analysis/test_analysis_atomic.py | 37 +++ 9 files changed, 631 insertions(+) create mode 100644 src/oqd_core/analysis/atomic/symbol_table.py create mode 100644 src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py create mode 100644 src/oqd_core/compiler/atomic/passes/__init__.py create mode 100644 src/oqd_core/compiler/atomic/passes/compile.py create mode 100644 src/oqd_core/compiler/atomic/verify/passes.py diff --git a/src/oqd_core/analysis/atomic/__init__.py b/src/oqd_core/analysis/atomic/__init__.py index e69de29b..096b3917 100644 --- a/src/oqd_core/analysis/atomic/__init__.py +++ b/src/oqd_core/analysis/atomic/__init__.py @@ -0,0 +1,23 @@ +from .cfg import AtomicCFGBuilder +from .symbol_table import ( + AtomicSymbolError, + AtomicSymbolTable, + AtomicSymbolTableBuilder, + RegisterEnv, + SymbolBinding, + target_dim, +) +from .type_checker import AtomicTypeChecker +from .types import AtomicTypeError + +__all__ = [ + "AtomicCFGBuilder", + "AtomicTypeChecker", + "AtomicTypeError", + "AtomicSymbolError", + "AtomicSymbolTable", + "AtomicSymbolTableBuilder", + "RegisterEnv", + "SymbolBinding", + "target_dim", +] \ No newline at end of file diff --git a/src/oqd_core/analysis/atomic/symbol_table.py b/src/oqd_core/analysis/atomic/symbol_table.py new file mode 100644 index 00000000..e5801c01 --- /dev/null +++ b/src/oqd_core/analysis/atomic/symbol_table.py @@ -0,0 +1,238 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +from __future__ import annotations + +from typing import Iterable, Union + +from oqd_compiler_infrastructure.dataflow import ( + DataflowResult, + ForwardDataflowAnalysis, +) +from oqd_compiler_infrastructure.lattice import ( + Lattice, + LatticeBottom, + LatticeTop, + maplattice, +) +from pydantic import BaseModel, ConfigDict + +from oqd_core.analysis.atomic.types import ( + TIonRef, + TIonReg, + TLatticeValue, + TList, + TTargetRef, + TypeEnv, +) +from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.interface.atomic import ( + Access, + AtomicList, + Declaration, + Extract, + IonRegister, +) + +######################################################################################## + + +class AtomicSymbolError(TypeError): + """Symbol table error class for Atomic.""" + pass + + +class SymbolBinding(BaseModel): + lattice_type: TLatticeValue + target_dim: tuple[int, int] + list_elem: SymbolBinding | None = None + model_config = ConfigDict(frozen=True) + +RegisterEnv = dict[str, SymbolBinding] + +class AtomicSymbolTable(BaseModel): + in_env: dict[int, RegisterEnv] + stmt_index: dict[int, int] + + +class SymbolBindingLattice(Lattice[Union[SymbolBinding, type[LatticeTop]]]): + def top(self) -> type[LatticeTop]: + return LatticeTop + + def bottom(self) -> type[LatticeTop]: + return LatticeBottom + + def leq(self, t1, t2) -> bool: + if t1 is LatticeBottom: + return True + if t2 is LatticeTop: + return True + if t1 is LatticeTop: + return t2 is LatticeTop + if t2 is LatticeBottom: + return False + return t1 == t2 + + def join(self, t1, t2): + if t1 is LatticeTop or t2 is LatticeTop: + return LatticeTop + if t1 is LatticeBottom: + return t2 + if t2 is LatticeBottom: + return t1 + if t1 == t2: + return t1 + return LatticeTop + + def meet(self, t1, t2): + if t1 is LatticeBottom or t2 is LatticeBottom: + return LatticeBottom + if t1 is LatticeTop: + return t2 + if t2 is LatticeTop: + return t1 + if t1 == t2: + return t1 + return LatticeBottom + + +def is_target_lattice_type(t: TLatticeValue) -> bool: + if t in (TIonReg, TIonRef, TTargetRef): + return True + if isinstance(t, TList): + return is_target_lattice_type(t.elem) + return False + + +def bind_target_value(expr, t: TLatticeValue, env: RegisterEnv) -> SymbolBinding: + + if isinstance(expr, Access): + if expr.name not in env: + raise AtomicSymbolError(f"Undefined variable: {expr.name}") + return env[expr.name] + + if t is TIonReg: + return SymbolBinding(lattice_type=TIonReg, target_dim=(expr.size, 0)) + + if isinstance(expr, Extract): + if expr.access.name not in env: + raise AtomicSymbolError(f"Undefined variable: {expr.access.name}") + base = env[expr.access.name] + n_qreg, _ = base.target_dim + if n_qreg <= 0 or expr.index >= n_qreg: + raise AtomicSymbolError("Extract index out of range") + return SymbolBinding(lattice_type=TIonRef, target_dim=(1, 0)) + + if isinstance(expr, AtomicList): + if not isinstance(t, TList) or not is_target_lattice_type(t): + raise AtomicSymbolError("target list expected") + elem_bindings = [bind_target_value(v, t.elem, env) for v in expr.values] + target_dim = (0, 0) + for binding in elem_bindings: + target_dim = ( + target_dim[0] + binding.target_dim[0], + target_dim[1] + binding.target_dim[1], + ) + return SymbolBinding( + lattice_type=t, + target_dim=target_dim, + list_elem=elem_bindings[0], + ) + raise AtomicSymbolError(f"Unsupported target expression: {type(expr).__name__}") + + +def target_dim(expr, env: RegisterEnv): + if isinstance(expr, Access): + if expr.name not in env: + raise AtomicSymbolError(f"Undefined Variable: {expr.name}") + return env[expr.name].target_dim + + if isinstance(expr, Extract): + if expr.access.name not in env: + raise AtomicSymbolError(f"Undefined Variable: {expr.access.name}") + base = env[expr.access.name] + n_qreg, n_qmode = base.target_dim + if n_qreg > 0: + if expr.index >= n_qreg: + raise AtomicSymbolError("Extract index out of range") + return (1, 0) + if n_qmode > 0: + if expr.index >= n_qmode: + raise AtomicSymbolError("Extract index out of range") + return (0,1) + raise AtomicSymbolError("Extract index out of range") + + if isinstance(expr, AtomicList): + dim = (0, 0) + for value in expr.values: + new = target_dim(value, env) + dim = (dim[0] + new[0], dim[1] + new[1]) + return dim + + if isinstance(expr, IonRegister): + return (expr.size, 0) + + raise AtomicSymbolError(f"Invalid target: {type(expr).__name__} ") + + +class AtomicSymbolTableBuilder(ForwardDataflowAnalysis[int, RegisterEnv]): + """Forward dataflow symbol table for register / target dimension checking.""" + def __init__(self, graph: ControlFlowGraph, type_result: DataflowResult[int, TypeEnv]) -> None: + self.type_out_states = type_result.out_states + self.lattice = maplattice(SymbolBindingLattice)() + self.blocks = graph.blocks + + self.dataflow_result = self.analyze(graph, self.merge_symbol_env) + + self.symbol_table = AtomicSymbolTable( + in_env={ + node_id: {} if state is LatticeBottom else dict(state) + for node_id, state in self.dataflow_result.in_states.items() + }, + stmt_index={ + id(block.stmt): node_id + for node_id, block in graph.blocks.items() + if not isinstance(block.stmt, str) + }, + ) + + def merge_symbol_env(self, states: Iterable[RegisterEnv]) -> RegisterEnv: + states_list = list(states) + if not states_list: + return self.lattice.bottom() + merged = {} if states_list[0] is LatticeBottom else dict(states_list[0]) + for state in states_list[1:]: + if state is LatticeBottom: + continue + for name in set(merged).union(state): + b1 = merged.get(name) + b2 = state.get(name) + if b1 is None: + merged[name] = b2 + elif b2 is None: + continue + elif b1 != b2: + raise AtomicSymbolError(f"Incompatible register bindings for {name}") + return merged + + def transfer(self, node_id: int, state_in: RegisterEnv) -> RegisterEnv: + env = {} if state_in is LatticeBottom else dict(state_in) + stmt = self.blocks[node_id].stmt + if isinstance(stmt, Declaration): + t = self.type_out_states[node_id].get(stmt.name) + if t is not None and is_target_lattice_type(t): + state_out = dict(env) + state_out[stmt.name] = bind_target_value(stmt.value, t, env) + return state_out + return env diff --git a/src/oqd_core/compiler/atomic/canonicalize.py b/src/oqd_core/compiler/atomic/canonicalize.py index 1080bdce..0907296f 100644 --- a/src/oqd_core/compiler/atomic/canonicalize.py +++ b/src/oqd_core/compiler/atomic/canonicalize.py @@ -237,6 +237,15 @@ def map_ParallelProtocol(self, model): def map_Pulse(self, model): return Post(self._substitute_at(0))(model) + + def map_Declaration(self, model: Declaration): + pass + + def map_IfElse(self, model: IfElse): + pass + + def map_While(self, model: While): + pass ######################################################################################## diff --git a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py index ea701c32..88ccf647 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py @@ -1,6 +1,11 @@ from .walk import canonicalize_math_block, canonicalize_math_cfg, iter_stmt_blocks +from .scalar_env import canonicalize_scalar_expr, canonicalize_scalars_cfg, resolve_scalar_expr + __all__ = [ "iter_stmt_blocks", "canonicalize_math_block", "canonicalize_math_cfg", + "canonicalize_scalar_expr", + "canonicalize_scalars_cfg", + "resolve_scalar_expr", ] diff --git a/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py b/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py new file mode 100644 index 00000000..3a455d59 --- /dev/null +++ b/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py @@ -0,0 +1,236 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +from __future__ import annotations + +from typing import Iterable, Union + +from oqd_compiler_infrastructure.dataflow import DataflowResult, ForwardDataflowAnalysis +from oqd_compiler_infrastructure.lattice import Lattice, LatticeBottom, LatticeTop, maplattice + +from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_beam +from oqd_core.analysis.atomic.types import TBeam, TBool, TScalar, TLatticeValue, TypeEnv +from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.compiler.atomic.error import AtomicCompilerError +from oqd_core.compiler.atomic.math.passes import canonicalize_math_expr +from oqd_core.interface.atomic import ( + Access, + Bool, + BoolAnd, + BoolEq, + BoolGreaterThan, + BoolGreaterThanEq, + BoolLessThan, + BoolLessThanEq, + BoolNot, + BoolNotEq, + BoolOr, + Declaration, + MathAdd, + MathDiv, + MathFunc, + MathImag, + MathMul, + MathNum, + MathPow, + MathSub, + MathVar, + Pulse, + Beam, + AtomicList +) + +ScalarEnv = dict[str, object] + +MATH_BOOL_TYPES = (MathAdd, MathSub, MathMul, MathDiv, MathPow, + BoolAnd, BoolOr, BoolEq, BoolNotEq, BoolLessThan, + BoolLessThanEq, BoolGreaterThan, BoolGreaterThanEq) + +class ScalarExprLattice(Lattice[Union[object, type[LatticeTop]]]): + def top(self): + return LatticeTop + + def bottom(self): + return LatticeBottom + + def leq(self, t1, t2) -> bool: + if t1 is LatticeBottom or t2 is LatticeTop: + return True + if t1 is LatticeTop or t2 is LatticeBottom: + return t2 is LatticeTop + return t1 == t2 + + def join(self, t1, t2): + if t1 is LatticeTop or t2 is LatticeTop: + return LatticeTop + if t1 is LatticeBottom: + return t2 + if t2 is LatticeBottom: + return t1 + if t1 == t2: + return t1 + return LatticeTop + + def meet(self, t1, t2): + if t1 is LatticeBottom or t2 is LatticeBottom: + return LatticeBottom + if t1 is LatticeTop: + return t2 + if t2 is LatticeTop: + return t1 + if t1 == t2: + return t1 + return LatticeBottom + + +def resolve_scalar_expr(expr, env: ScalarEnv): + if isinstance(expr, Access): + if expr.name not in env: + raise AtomicCompilerError(f"Undefined variable: {expr.name}") + bound = env[expr.name] + if bound is LatticeTop: + return expr + if isinstance(bound, Access): + return resolve_scalar_expr(bound, env) + return bound + + if isinstance(expr, MATH_BOOL_TYPES): + return expr.__class__( + expr1=resolve_scalar_expr(expr.expr1, env), + expr2=resolve_scalar_expr(expr.expr2, env), + ) + + if isinstance(expr, MathFunc): + if isinstance(expr.expr, list): + return MathFunc( + func=expr.func, + expr=[resolve_scalar_expr(e, env) for e in expr.expr], + ) + return MathFunc(func=expr.func, expr=resolve_scalar_expr(expr.expr, env)) + + if isinstance(expr, BoolNot): + return BoolNot(expr=resolve_scalar_expr(expr.expr, env)) + + if isinstance(expr, (MathNum, MathVar, MathImag, Bool)): + return expr + + raise AtomicCompilerError(f"Cannot resolve scalar expression: {type(expr).__name__}") + + +def resolve_beam_expr(beam: Beam, env: ScalarEnv) -> Beam: + pol, wv = beam.polarization, beam.wavevector + return Beam( + frequency=resolve_scalar_expr(beam.frequency, env), + rabi=resolve_scalar_expr(beam.rabi, env), + phase=resolve_scalar_expr(beam.phase, env), + polarization=AtomicList(values=[resolve_scalar_expr(v, env) for v in pol.values]) + if isinstance(pol, AtomicList) else resolve_scalar_expr(pol, env), + wavevector=AtomicList(values=[resolve_scalar_expr(v, env) for v in wv.values]) + if isinstance(wv, AtomicList) else resolve_scalar_expr(wv, env), + ) + +def resolve_beam_ref(expr, env: ScalarEnv): + if isinstance(expr, Access): + if expr.name not in env: + raise AtomicCompilerError(f"Undefined variable: {expr.name}") + bound = env[expr.name] + if isinstance(bound, Access): + return resolve_beam_ref(bound, env) + if not isinstance(bound, Beam): + raise AtomicCompilerError(f"Access {expr.name} is not a beam") + return bound.model_copy(deep=True) + if isinstance(expr, Beam): + return resolve_beam_expr(expr, env) + raise AtomicCompilerError(f"Cannot resolve beam expression: {type(expr).__name__}") + + +def canonicalize_scalar_expr(expr): + if isinstance(expr, Bool): + return expr + return canonicalize_math_expr(expr) + + +class ScalarEnvBuilder(ForwardDataflowAnalysis[int, ScalarEnv]): + def __init__( + self, + graph: ControlFlowGraph, + type_result: DataflowResult[int, TypeEnv], + ) -> None: + self.type_out_states = type_result.out_states + self.lattice = maplattice(ScalarExprLattice)() + self.blocks = graph.blocks + self.analyze(graph, self.merge_scalar_env) + + def merge_scalar_env(self, states: Iterable[ScalarEnv]) -> ScalarEnv: + states_list = list(states) + if not states_list: + return self.lattice.bottom() + + merged = {} if states_list[0] is LatticeBottom else dict(states_list[0]) + for state in states_list[1:]: + if state is LatticeBottom: + continue + for name in set(merged).union(state): + v1, v2 = merged.get(name), state.get(name) + if v1 is None: + merged[name] = v2 + elif v2 is None: + continue + elif v1 is LatticeTop or v2 is LatticeTop or v1 != v2: + merged[name] = LatticeTop + return merged + + def transfer(self, node_id: int, state_in: ScalarEnv) -> ScalarEnv: + env = {} if state_in is LatticeBottom else dict(state_in) + stmt = self.blocks[node_id].stmt + + if isinstance(stmt, Declaration): + t: TLatticeValue | None = self.type_out_states[node_id].get(stmt.name) + if t is TScalar: + value = canonicalize_scalar_expr( + resolve_scalar_expr(stmt.value, env) + ) + stmt.value = value + out = dict(env) + out[stmt.name] = value + return out + if t is TBool: + value = resolve_scalar_expr(stmt.value, env) + stmt.value = value + out = dict(env) + out[stmt.name] = value + return out + if t is TBeam: + beam = canonicalize_beam(resolve_beam_expr(stmt.value, env)) + stmt.value = beam + out = dict(env) + out[stmt.name] = beam + return out + return env + + if isinstance(stmt, Pulse): + stmt.duration = canonicalize_scalar_expr(resolve_scalar_expr(stmt.duration, env)) + stmt.beam = canonicalize_beam(resolve_beam_ref(stmt.beam, env)) + return env + + return env + + +def canonicalize_scalars_cfg( + cfg: ControlFlowGraph, + type_result: DataflowResult[int, TypeEnv], +) -> ControlFlowGraph: + ScalarEnvBuilder(cfg, type_result) + return cfg + diff --git a/src/oqd_core/compiler/atomic/passes/__init__.py b/src/oqd_core/compiler/atomic/passes/__init__.py new file mode 100644 index 00000000..f656b5db --- /dev/null +++ b/src/oqd_core/compiler/atomic/passes/__init__.py @@ -0,0 +1,3 @@ +from .compile import compile_atomic_circuit + +__all__ = ["compile_atomic_circuit"] diff --git a/src/oqd_core/compiler/atomic/passes/compile.py b/src/oqd_core/compiler/atomic/passes/compile.py new file mode 100644 index 00000000..2c8bf210 --- /dev/null +++ b/src/oqd_core/compiler/atomic/passes/compile.py @@ -0,0 +1,40 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +from oqd_compiler_infrastructure.dataflow import DataflowResult +from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable +from oqd_core.analysis.atomic.types import TypeEnv +from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.compiler.atomic.canonicalize import canonicalize_atomic_circuit_factory +from oqd_core.compiler.atomic.cfg_passes.scalar_env import canonicalize_scalars_cfg +from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_math_cfg +from oqd_core.compiler.atomic.verify.passes import verify_pulse_target_dim +from oqd_core.interface.atomic import AtomicCircuit + +__all__ = ["compile_atomic_circuit"] + + +def compile_atomic_circuit( + model: AtomicCircuit, + cfg: ControlFlowGraph, + type_result: DataflowResult[int, TypeEnv], + symbol_table: AtomicSymbolTable, +): + canonicalize_scalars_cfg(cfg, type_result) + canonicalize_math_cfg(cfg) + verify_pulse_target_dim(cfg, symbol_table) + + model = canonicalize_atomic_circuit_factory()(model) + return model + diff --git a/src/oqd_core/compiler/atomic/verify/passes.py b/src/oqd_core/compiler/atomic/verify/passes.py new file mode 100644 index 00000000..09bc743c --- /dev/null +++ b/src/oqd_core/compiler/atomic/verify/passes.py @@ -0,0 +1,40 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +from __future__ import annotations +from collections.abc import Iterator +from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable, target_dim +from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.compiler.atomic.cfg_passes.walk import iter_stmt_blocks +from oqd_core.interface.atomic import Declaration, Pulse + + +def iter_pulse_targets(stmt) -> Iterator: + if isinstance(stmt, Pulse): + yield stmt.target + elif isinstance(stmt, Declaration) and isinstance(stmt.value, Pulse): + yield stmt.value.target + + +def verify_pulse_target_dim(cfg: ControlFlowGraph, symbol_table: AtomicSymbolTable): + """ + Check pulse targets are in range at each use. + """ + for node_id, block in iter_stmt_blocks(cfg): + stmt = block.stmt + env = symbol_table.in_env[node_id] + for target in iter_pulse_targets(stmt): + target_dim(target, env) + return cfg + diff --git a/tests/test_analysis/test_analysis_atomic.py b/tests/test_analysis/test_analysis_atomic.py index 1dddcddb..e450482c 100644 --- a/tests/test_analysis/test_analysis_atomic.py +++ b/tests/test_analysis/test_analysis_atomic.py @@ -15,9 +15,46 @@ import pytest from oqd_core.analysis.atomic.cfg import AtomicCFGBuilder +from oqd_core.analysis.atomic.symbol_table import ( + AtomicSymbolError, + AtomicSymbolTableBuilder, +) from oqd_core.analysis.atomic.type_checker import AtomicTypeChecker from oqd_core.analysis.atomic.types import AtomicTypeError +from oqd_core.compiler.atomic.verify.passes import verify_pulse_target_dim from oqd_core.frontend.atomic.AtomicCircuitAST import parse_atomic +from oqd_core.interface.atomic import Pulse + +## Symbol Table ## + +def build_symbol_table(program: str): + circuit = parse_atomic(program) + cfg = AtomicCFGBuilder().run(circuit) + type_checker = AtomicTypeChecker(cfg) + symbol_table = AtomicSymbolTableBuilder( + cfg, type_checker.dataflow_result + ).symbol_table + return symbol_table, cfg, circuit + + +class TestAtomicSymbolTable: + def test_ionreg_binding(self): + symbol_table, _, circuit = build_symbol_table( + "r = ionreg(3)\n" + "pulse(beam(2e6, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]), 1e-5, r, true)" + ) + pulse = next(s for s in circuit.statements if isinstance(s, Pulse)) + node_id = symbol_table.stmt_index[id(pulse)] + assert symbol_table.in_env[node_id]["r"].target_dim == (3, 0) + + def test_extract_out_of_range(self): + symbol_table, cfg, _ = build_symbol_table( + "r = ionreg(2)\n" + "pulse(beam(2e6, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]), 1e-5, r[2], true)" + ) + with pytest.raises(AtomicSymbolError): + verify_pulse_target_dim(cfg, symbol_table) + ## Control Flow Graph ## From 49b4df1404d9859ef483bda6740a95ce8919952b Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Mon, 6 Jul 2026 22:22:50 -0400 Subject: [PATCH 06/20] clean: Update docs --- docs/analysis/atomic_analysis.md | 8 ++++++-- examples/atomic/test.ipynb | 10 +++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/analysis/atomic_analysis.md b/docs/analysis/atomic_analysis.md index a79afbbd..906456f3 100644 --- a/docs/analysis/atomic_analysis.md +++ b/docs/analysis/atomic_analysis.md @@ -10,6 +10,9 @@ The atomic Control Flow Graph (CFG) is implemented by the `AtomicCFGBuilder` cla The atomic type checker is implemented by the `AtomicTypeChecker` class in [`type_checker.py`](../../src/oqd_core/analysis/atomic/type_checker.py). The `AtomicTypeLattice` class defines a concrete lattice for atomic types with `leq`, `join`, and `meet` methods. Type inference rules are implemented by the `AtomicSemantics` class in [`semantics.py`](../../src/oqd_core/analysis/atomic/semantics.py). The type checker runs forward dataflow analysis over the CFG. +## Symbol Table + +The atomic symbol table is implemented in [`symbol_table.py`](../../src/oqd_core/analysis/atomic/symbol_table.py). The `AtomicSymbolTableBuilder` class runs a second forward dataflow pass over the CFG, using the type checker output to track register and target dimensions. The result is an `AtomicSymbolTable` with register environments per block and a statement index. ## Usage of the type checker @@ -19,7 +22,7 @@ The atomic type checker is implemented by the `AtomicTypeChecker` class in [`typ ```py from oqd_core.frontend.atomic import parse_atomic -from oqd_core.analysis.atomic import AtomicCFGBuilder, AtomicTypeChecker +from oqd_core.analysis.atomic import AtomicCFGBuilder, AtomicTypeChecker, AtomicSymbolTableBuilder source = """ ions = ionreg(1) @@ -30,8 +33,9 @@ pulse(mw, 1e-5, ions[0], true) circuit = parse_atomic(source) cfg = AtomicCFGBuilder().run(circuit) type_checker = AtomicTypeChecker(cfg) +symbol_table = AtomicSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table ``` /// -The output of the type checker is stored in `type_checker.dataflow_result`. +The type checker dataflow result is available at `type_checker.dataflow_result`. diff --git a/examples/atomic/test.ipynb b/examples/atomic/test.ipynb index 00cf48fc..56034ccd 100644 --- a/examples/atomic/test.ipynb +++ b/examples/atomic/test.ipynb @@ -147,6 +147,7 @@ "from oqd_compiler_infrastructure import Post, PrettyPrint\n", "\n", "from oqd_core.analysis.atomic.cfg import AtomicCFGBuilder\n", + "from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTableBuilder\n", "from oqd_core.analysis.atomic.type_checker import AtomicTypeChecker\n", "from oqd_core.frontend.atomic import parse_atomic\n", "\n", @@ -157,7 +158,8 @@ "\n", "circuit = parse_atomic(source)\n", "cfg = AtomicCFGBuilder().run(circuit)\n", - "checker = AtomicTypeChecker(cfg)\n" + "checker = AtomicTypeChecker(cfg)\n", + "symbol_table = AtomicSymbolTableBuilder(cfg, checker.dataflow_result).symbol_table" ] }, { @@ -169,7 +171,7 @@ { "data": { "text/plain": [ - "AtomicCircuit(class_='AtomicCircuit', statements=[Declaration(class_='Declaration', name='ions', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=1)), Declaration(class_='Declaration', name='targets', value=AtomicList(class_='AtomicList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phi', value=MathVar(class_='MathVar', name='#phi')), Declaration(class_='Declaration', name='t_gate', value=MathNum(class_='MathNum', value=1e-05)), Declaration(class_='Declaration', name='flag', value=Bool(class_='Bool', value=True)), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), Declaration(class_='Declaration', name='r', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='beam_mw', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=2000000.0), expr2=Access(class_='Access', name='pi')), rabi=Access(class_='Access', name='omega'), phase=Access(class_='Access', name='phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Declaration(class_='Declaration', name='beam_det', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=4000000.0), expr2=Access(class_='Access', name='pi')), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=Access(class_='Access', name='t_gate'), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=3e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=Access(class_='Access', name='t_gate'), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=3e-06), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=False))])]), IfElse(class_='IfElse', condition=Access(class_='Access', name='flag'), then_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))])], else_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-05), target=Access(class_='Access', name='targets'), beam=Access(class_='Access', name='beam_det'), measured=Bool(class_='Bool', value=True))])]), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=1e-06), target=Access(class_='Access', name='targets'), beam=Access(class_='Access', name='beam_mw'), measured=Bool(class_='Bool', value=False))])]), Declaration(class_='Declaration', name='n', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=-1), expr2=Access(class_='Access', name='n'))), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Continue(class_='Continue')], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Break(class_='Break')], else_branch=[])])])" + "AtomicCircuit(class_='AtomicCircuit', statements=[Declaration(class_='Declaration', name='ions', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=1)), Declaration(class_='Declaration', name='targets', value=AtomicList(class_='AtomicList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phi', value=MathVar(class_='MathVar', name='#phi')), Declaration(class_='Declaration', name='t_gate', value=MathNum(class_='MathNum', value=1e-05)), Declaration(class_='Declaration', name='flag', value=Bool(class_='Bool', value=True)), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), Declaration(class_='Declaration', name='r', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='beam_mw', value=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Declaration(class_='Declaration', name='beam_det', value=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=1e-05), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=3e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=1e-05), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=3e-06), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])]), IfElse(class_='IfElse', condition=Access(class_='Access', name='flag'), then_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])], else_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-05), target=Access(class_='Access', name='targets'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=True))])]), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=1e-06), target=Access(class_='Access', name='targets'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])]), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=2)), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Continue(class_='Continue')], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Break(class_='Break')], else_branch=[])])])" ] }, "execution_count": 5, @@ -179,8 +181,10 @@ ], "source": [ "from oqd_core.compiler.atomic.canonicalize import canonicalize_atomic_circuit_factory\n", + "from oqd_core.compiler.atomic.cfg_passes.scalar_env import canonicalize_scalars_cfg\n", "from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_math_cfg\n", "\n", + "canonicalize_scalars_cfg(cfg, checker.dataflow_result)\n", "canonicalize_math_cfg(cfg)\n", "canonicalize_atomic_circuit_factory()(circuit)" ] @@ -188,7 +192,7 @@ ], "metadata": { "kernelspec": { - "display_name": "oqd-core (3.11.11)", + "display_name": "oqd-core (3.11.11.final.0)", "language": "python", "name": "python3" }, From e8f970a2c590984a827b8d04bdd78d796a34a2fe Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Tue, 7 Jul 2026 02:04:31 -0400 Subject: [PATCH 07/20] fix: Modify Pulse as an AtomicExpr similar to Beam in Atomic interface. Clean up atomic compiler passes. --- src/oqd_core/analysis/atomic/symbol_table.py | 44 +++++------ src/oqd_core/analysis/atomic/type_checker.py | 49 +++++++++--- src/oqd_core/analysis/atomic/types.py | 4 +- src/oqd_core/compiler/atomic/canonicalize.py | 23 +----- .../compiler/atomic/cfg_passes/__init__.py | 4 +- .../compiler/atomic/cfg_passes/scalar_env.py | 78 +++++++++++++++++-- .../compiler/atomic/cfg_passes/walk.py | 43 +--------- src/oqd_core/compiler/atomic/math/rules.py | 17 ++++ .../compiler/atomic/passes/compile.py | 9 +-- src/oqd_core/compiler/atomic/verify/passes.py | 30 ++++++- src/oqd_core/interface/atomic/circuit.py | 4 +- src/oqd_core/interface/atomic/expr.py | 9 ++- 12 files changed, 194 insertions(+), 120 deletions(-) diff --git a/src/oqd_core/analysis/atomic/symbol_table.py b/src/oqd_core/analysis/atomic/symbol_table.py index e5801c01..72af0a92 100644 --- a/src/oqd_core/analysis/atomic/symbol_table.py +++ b/src/oqd_core/analysis/atomic/symbol_table.py @@ -55,7 +55,7 @@ class AtomicSymbolError(TypeError): class SymbolBinding(BaseModel): lattice_type: TLatticeValue - target_dim: tuple[int, int] + target_dim: int list_elem: SymbolBinding | None = None model_config = ConfigDict(frozen=True) @@ -123,27 +123,30 @@ def bind_target_value(expr, t: TLatticeValue, env: RegisterEnv) -> SymbolBinding return env[expr.name] if t is TIonReg: - return SymbolBinding(lattice_type=TIonReg, target_dim=(expr.size, 0)) + return SymbolBinding(lattice_type=TIonReg, target_dim=expr.size) if isinstance(expr, Extract): if expr.access.name not in env: raise AtomicSymbolError(f"Undefined variable: {expr.access.name}") base = env[expr.access.name] - n_qreg, _ = base.target_dim - if n_qreg <= 0 or expr.index >= n_qreg: + n_ion = base.target_dim + if n_ion <= 0 or expr.index >= n_ion: raise AtomicSymbolError("Extract index out of range") - return SymbolBinding(lattice_type=TIonRef, target_dim=(1, 0)) + return SymbolBinding(lattice_type=TIonRef, target_dim=1) if isinstance(expr, AtomicList): if not isinstance(t, TList) or not is_target_lattice_type(t): raise AtomicSymbolError("target list expected") + target_dim = 0 elem_bindings = [bind_target_value(v, t.elem, env) for v in expr.values] - target_dim = (0, 0) - for binding in elem_bindings: - target_dim = ( - target_dim[0] + binding.target_dim[0], - target_dim[1] + binding.target_dim[1], + if not elem_bindings: + return SymbolBinding( + lattice_type=t, + target_dim=target_dim, + list_elem=None, ) + for binding in elem_bindings: + target_dim += binding.target_dim return SymbolBinding( lattice_type=t, target_dim=target_dim, @@ -162,26 +165,21 @@ def target_dim(expr, env: RegisterEnv): if expr.access.name not in env: raise AtomicSymbolError(f"Undefined Variable: {expr.access.name}") base = env[expr.access.name] - n_qreg, n_qmode = base.target_dim - if n_qreg > 0: - if expr.index >= n_qreg: - raise AtomicSymbolError("Extract index out of range") - return (1, 0) - if n_qmode > 0: - if expr.index >= n_qmode: - raise AtomicSymbolError("Extract index out of range") - return (0,1) - raise AtomicSymbolError("Extract index out of range") + n_ion = base.target_dim + if n_ion <= 0 or expr.index >= n_ion: + raise AtomicSymbolError("Extract index out of range") + return 1 + if isinstance(expr, AtomicList): - dim = (0, 0) + dim = 0 for value in expr.values: new = target_dim(value, env) - dim = (dim[0] + new[0], dim[1] + new[1]) + dim += new return dim if isinstance(expr, IonRegister): - return (expr.size, 0) + return expr.size raise AtomicSymbolError(f"Invalid target: {type(expr).__name__} ") diff --git a/src/oqd_core/analysis/atomic/type_checker.py b/src/oqd_core/analysis/atomic/type_checker.py index 6ab7a595..be53147c 100644 --- a/src/oqd_core/analysis/atomic/type_checker.py +++ b/src/oqd_core/analysis/atomic/type_checker.py @@ -39,6 +39,8 @@ ######################################################################################## + + class AtomicTypeChecker(ForwardDataflowAnalysis[int, TypeEnv]): """Forward dataflow type checker over the Control Flow Graph.""" def __init__(self, graph: ControlFlowGraph) -> None: @@ -49,6 +51,41 @@ def __init__(self, graph: ControlFlowGraph) -> None: self.dataflow_result = self.analyze(graph, self.merge_union) + def check_protocol(self, protocol, env: TypeEnv) -> TypeEnv: + if isinstance(protocol, SerialProtocol): + curr_env = env + for child in protocol.pulses: + curr_env = self.check_protocol_stmt(child, curr_env) + return curr_env + + if isinstance(protocol, ParallelProtocol): + for child in protocol.pulses: + self.check_protocol_stmt(child, env) + return env + + raise AtomicTypeError(f"Unsupported protocol node: {type(protocol).__name__}") + + def check_protocol_stmt(self, stmt, env: TypeEnv) -> TypeEnv: + if isinstance(stmt, (ParallelProtocol, SerialProtocol)): + return self.check_protocol(stmt, env) + + if isinstance(stmt, Declaration): + t = self.semantics.infer_type(stmt.value, env) + if not self.value_lattice.leq(t, TPulse): + raise AtomicTypeError( + f"Parallel/Serial blocks expect only Pulse statements, got {type_name(t)}" + ) + out = dict(env) + out[stmt.name] = t + return out + + t = self.semantics.infer_type(stmt, env) + if not self.value_lattice.leq(t, TPulse): + raise AtomicTypeError( + f"Parallel/Serial blocks expect only Pulse statements, got {type_name(t)}" + ) + return env + def transfer(self, node_id: int, state_in: TypeEnv) -> TypeEnv: env = {} if state_in is LatticeBottom else dict(state_in) stmt = self.blocks[node_id].stmt @@ -62,17 +99,7 @@ def transfer(self, node_id: int, state_in: TypeEnv) -> TypeEnv: return env if isinstance(stmt, (ParallelProtocol, SerialProtocol)): - stack = [stmt] - while stack: - curr = stack.pop() - if isinstance(curr, (ParallelProtocol, SerialProtocol)): - stack.extend(reversed(curr.pulses)) - continue - t = self.semantics.infer_type(curr, env) - if not self.value_lattice.leq(t, TPulse): - raise AtomicTypeError( - f"Parallel/Serial blocks expect only Pulse statements, got {type_name(t)}" - ) + self.check_protocol(stmt, env) return env t = self.semantics.infer_type(stmt, env) diff --git a/src/oqd_core/analysis/atomic/types.py b/src/oqd_core/analysis/atomic/types.py index 93e3cadb..4421c9c9 100644 --- a/src/oqd_core/analysis/atomic/types.py +++ b/src/oqd_core/analysis/atomic/types.py @@ -109,7 +109,7 @@ def join(self, t1: TLatticeValue, t2: TLatticeValue) -> TLatticeValue: if self.leq(t2, t1): return t1 if isinstance(t1, TList) and isinstance(t2, TList): - return TList(elem=self.lattice.join(t1.elem, t2.elem)) + return TList(elem=self.join(t1.elem, t2.elem)) if isinstance(t1, TList) or isinstance(t2, TList): return TAtomic return super().join(t1, t2) @@ -120,7 +120,7 @@ def meet(self, t1: TLatticeValue, t2: TLatticeValue) -> TLatticeValue: if self.leq(t2, t1): return t2 if isinstance(t1, TList) and isinstance(t2, TList): - return TList(elem=self.lattice.meet(t1.elem, t2.elem)) + return TList(elem=self.meet(t1.elem, t2.elem)) return super().meet(t1, t2) diff --git a/src/oqd_core/compiler/atomic/canonicalize.py b/src/oqd_core/compiler/atomic/canonicalize.py index 0907296f..06f62e2a 100644 --- a/src/oqd_core/compiler/atomic/canonicalize.py +++ b/src/oqd_core/compiler/atomic/canonicalize.py @@ -25,8 +25,6 @@ ######################################################################################## -PROTOCOL_STMT_TYPES = (Pulse, ParallelProtocol, SerialProtocol) - def _as_numeric_duration(duration): simplified = simplify_math_expr(duration) if isinstance(simplified, MathNum): @@ -53,19 +51,19 @@ def __init__(self): self.durations = [] @classmethod - def _get_continuous_duration(self, model): + def _get_continuous_duration(cls, model): if isinstance(model, ParallelProtocol): if not model.pulses: raise AtomicCompilerError(f"Parallel block is empty.") if len(model.pulses) == 1: - return self._get_continuous_duration(model.pulses[0]) + return cls._get_continuous_duration(model.pulses[0]) - return min(map(self._get_continuous_duration, model.pulses)) + return min(map(cls._get_continuous_duration, model.pulses)) if isinstance(model, SerialProtocol): if not model.pulses: raise AtomicCompilerError(f"Serial block is empty.") - return self._get_continuous_duration(model.pulses[0]) + return cls._get_continuous_duration(model.pulses[0]) return _as_numeric_duration(model.duration) @@ -247,16 +245,3 @@ def map_IfElse(self, model: IfElse): def map_While(self, model: While): pass - -######################################################################################## - - - -def canonicalize_atomic_circuit_factory(): - """ - Factory for creating a pass for canonicalizing an atomic circuit. - """ - return Chain( - Post(ResolveNestedProtocol()), - Post(ResolveRelativeTime()), - ) diff --git a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py index 88ccf647..80ad99f1 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py @@ -1,10 +1,8 @@ -from .walk import canonicalize_math_block, canonicalize_math_cfg, iter_stmt_blocks +from .walk import iter_stmt_blocks from .scalar_env import canonicalize_scalar_expr, canonicalize_scalars_cfg, resolve_scalar_expr __all__ = [ "iter_stmt_blocks", - "canonicalize_math_block", - "canonicalize_math_cfg", "canonicalize_scalar_expr", "canonicalize_scalars_cfg", "resolve_scalar_expr", diff --git a/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py b/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py index 3a455d59..fce276d5 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py @@ -19,8 +19,8 @@ from oqd_compiler_infrastructure.dataflow import DataflowResult, ForwardDataflowAnalysis from oqd_compiler_infrastructure.lattice import Lattice, LatticeBottom, LatticeTop, maplattice -from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_beam -from oqd_core.analysis.atomic.types import TBeam, TBool, TScalar, TLatticeValue, TypeEnv +from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_beam, canonicalize_expr +from oqd_core.analysis.atomic.types import TBeam, TBool, TScalar, TLatticeValue, TypeEnv, TPulse from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.error import AtomicCompilerError from oqd_core.compiler.atomic.math.passes import canonicalize_math_expr @@ -48,7 +48,9 @@ MathVar, Pulse, Beam, - AtomicList + AtomicList, + ParallelProtocol, + SerialProtocol, ) ScalarEnv = dict[str, object] @@ -155,6 +157,46 @@ def resolve_beam_ref(expr, env: ScalarEnv): raise AtomicCompilerError(f"Cannot resolve beam expression: {type(expr).__name__}") +def resolve_pulse_expr(pulse: Pulse, env: ScalarEnv) -> Pulse: + return Pulse( + beam=canonicalize_beam(resolve_beam_ref(pulse.beam, env)), + duration=canonicalize_scalar_expr(resolve_scalar_expr(pulse.duration, env)), + target=canonicalize_expr(pulse.target), + measured=resolve_scalar_expr(pulse.measured, env), + ) + + +def resolve_pulse_ref(expr, env: ScalarEnv): + if isinstance(expr, Access): + if expr.name not in env: + raise AtomicCompilerError(f"Undefined variable: {expr.name}") + bound = env[expr.name] + if isinstance(bound, Access): + return resolve_pulse_ref(bound, env) + if not isinstance(bound, Pulse): + raise AtomicCompilerError(f"Access {expr.name} is not a pulse") + return bound.model_copy(deep=True) + + if isinstance(expr, Pulse): + return resolve_pulse_expr(expr, env) + raise AtomicCompilerError(f"Cannot resolve pulse expression: {type(expr).__name__}") + + +def resolve_protocol_pulses(pulses, env: ScalarEnv): + resolved = [] + for child in pulses: + if isinstance(child, Access): + child = resolve_pulse_ref(child, env) + elif isinstance(child, Pulse): + child = resolve_pulse_expr(child, env) + elif isinstance(child, (ParallelProtocol, SerialProtocol)): + child = child.__class__( + pulses=resolve_protocol_pulses(child.pulses, env) + ) + resolved.append(child) + return resolved + + def canonicalize_scalar_expr(expr): if isinstance(expr, Bool): return expr @@ -194,6 +236,11 @@ def merge_scalar_env(self, states: Iterable[ScalarEnv]) -> ScalarEnv: def transfer(self, node_id: int, state_in: ScalarEnv) -> ScalarEnv: env = {} if state_in is LatticeBottom else dict(state_in) stmt = self.blocks[node_id].stmt + block = self.blocks[node_id] + + if block.kind == "branch": + block.stmt = resolve_scalar_expr(stmt, env) + return env if isinstance(stmt, Declaration): t: TLatticeValue | None = self.type_out_states[node_id].get(stmt.name) @@ -217,15 +264,32 @@ def transfer(self, node_id: int, state_in: ScalarEnv) -> ScalarEnv: out = dict(env) out[stmt.name] = beam return out + if t is TPulse: + pulse = resolve_pulse_expr(stmt.value, env) + stmt.value = pulse + out = dict(env) + out[stmt.name] = pulse + return out return env - + if isinstance(stmt, Pulse): - stmt.duration = canonicalize_scalar_expr(resolve_scalar_expr(stmt.duration, env)) - stmt.beam = canonicalize_beam(resolve_beam_ref(stmt.beam, env)) + resolved = resolve_pulse_expr(stmt, env) + stmt.beam = resolved.beam + stmt.duration = resolved.duration + stmt.target = resolved.target + stmt.measured = resolved.measured + return env + + if isinstance(stmt, Access): + block.stmt = resolve_pulse_ref(stmt, env) + return env + + if isinstance(stmt, (ParallelProtocol, SerialProtocol)): + stmt.pulses = resolve_protocol_pulses(stmt.pulses, env) return env return env - + def canonicalize_scalars_cfg( cfg: ControlFlowGraph, diff --git a/src/oqd_core/compiler/atomic/cfg_passes/walk.py b/src/oqd_core/compiler/atomic/cfg_passes/walk.py index 3762710f..10231ea1 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/walk.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/walk.py @@ -16,15 +16,12 @@ from __future__ import annotations -from oqd_core.analysis.utils.control_flow import Block, ControlFlowGraph +from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.math.passes import canonicalize_math_expr from oqd_core.interface.atomic import ( AtomicList, Beam, - Declaration, - ParallelProtocol, Pulse, - SerialProtocol, ) from oqd_core.interface.atomic.expr import AtomicExpr @@ -35,6 +32,8 @@ def iter_stmt_blocks(cfg: ControlFlowGraph): yield node_id, block def canonicalize_expr(expr): + if isinstance(expr, (Beam, Pulse)): + return expr if isinstance(expr, AtomicExpr): return canonicalize_math_expr(expr) return expr @@ -51,39 +50,3 @@ def canonicalize_atomic_list(values: AtomicList) -> AtomicList: values.values = [canonicalize_expr(v) for v in values.values] return values -def canonicalize_math_block(block: Block): - stmt = block.stmt - - if block.kind == "branch": - block.stmt = canonicalize_expr(stmt) - return - - if isinstance(stmt, Pulse): - stmt.duration = canonicalize_expr(stmt.duration) - stmt.target = canonicalize_expr(stmt.target) - stmt.measured = canonicalize_expr(stmt.measured) - if isinstance(stmt.beam, Beam): - stmt.beam = canonicalize_beam(stmt.beam) - else: - stmt.beam = canonicalize_expr(stmt.beam) - return - - if isinstance(stmt, Declaration): - if isinstance(stmt.value, Beam): - stmt.value = canonicalize_beam(stmt.value) - elif isinstance(stmt.value, AtomicList): - stmt.value = canonicalize_atomic_list(stmt.value) - else: - stmt.value = canonicalize_expr(stmt.value) - return - - if isinstance(stmt, (ParallelProtocol, SerialProtocol)): - return - - -def canonicalize_math_cfg(cfg: ControlFlowGraph): - for _, block in iter_stmt_blocks(cfg): - canonicalize_math_block(block) - return cfg - - diff --git a/src/oqd_core/compiler/atomic/math/rules.py b/src/oqd_core/compiler/atomic/math/rules.py index 29182633..468d54be 100644 --- a/src/oqd_core/compiler/atomic/math/rules.py +++ b/src/oqd_core/compiler/atomic/math/rules.py @@ -50,6 +50,20 @@ ######################################################################################## +def _is_constant_math(model) -> bool: + if isinstance(model, (MathNum, MathImag)): + return True + if isinstance(model, (MathVar, Access)): + return False + if isinstance(model, MathFunc): + arg = model.expr + if isinstance(arg, list): + return all(_is_constant_math(a) for a in arg) + return _is_constant_math(arg) + if isinstance(model, (MathAdd, MathSub, MathMul, MathDiv, MathPow)): + return _is_constant_math(model.expr1) and _is_constant_math(model.expr2) + return False + class PrintMathExpr(ConversionRule): """ @@ -507,6 +521,9 @@ def map_MathImag(self, model): pass def map_MathExpr(self, model): + if not _is_constant_math(model): + return model + try: # TypeAdapter(CastMathExpr).validate_python(model) diff --git a/src/oqd_core/compiler/atomic/passes/compile.py b/src/oqd_core/compiler/atomic/passes/compile.py index 2c8bf210..45170d7a 100644 --- a/src/oqd_core/compiler/atomic/passes/compile.py +++ b/src/oqd_core/compiler/atomic/passes/compile.py @@ -16,10 +16,9 @@ from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable from oqd_core.analysis.atomic.types import TypeEnv from oqd_core.analysis.utils.control_flow import ControlFlowGraph -from oqd_core.compiler.atomic.canonicalize import canonicalize_atomic_circuit_factory from oqd_core.compiler.atomic.cfg_passes.scalar_env import canonicalize_scalars_cfg -from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_math_cfg -from oqd_core.compiler.atomic.verify.passes import verify_pulse_target_dim +from oqd_core.compiler.atomic.cfg_passes.protocol import canonicalize_protocol_cfg +from oqd_core.compiler.atomic.verify.passes import verify_pulse_target_dim, verify_constant_pulse_durations from oqd_core.interface.atomic import AtomicCircuit __all__ = ["compile_atomic_circuit"] @@ -32,9 +31,9 @@ def compile_atomic_circuit( symbol_table: AtomicSymbolTable, ): canonicalize_scalars_cfg(cfg, type_result) - canonicalize_math_cfg(cfg) + verify_constant_pulse_durations(cfg) + canonicalize_protocol_cfg(cfg, model) verify_pulse_target_dim(cfg, symbol_table) - model = canonicalize_atomic_circuit_factory()(model) return model diff --git a/src/oqd_core/compiler/atomic/verify/passes.py b/src/oqd_core/compiler/atomic/verify/passes.py index 09bc743c..1b0b86ad 100644 --- a/src/oqd_core/compiler/atomic/verify/passes.py +++ b/src/oqd_core/compiler/atomic/verify/passes.py @@ -17,14 +17,36 @@ from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable, target_dim from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.cfg_passes.walk import iter_stmt_blocks -from oqd_core.interface.atomic import Declaration, Pulse +from oqd_core.compiler.atomic.canonicalize import _as_numeric_duration +from oqd_core.compiler.atomic.error import AtomicCompilerError +from oqd_core.interface.atomic import Declaration, ParallelProtocol, Pulse, SerialProtocol -def iter_pulse_targets(stmt) -> Iterator: +def iter_pulses(stmt): if isinstance(stmt, Pulse): - yield stmt.target + yield stmt elif isinstance(stmt, Declaration) and isinstance(stmt.value, Pulse): - yield stmt.value.target + yield stmt.value + elif isinstance(stmt, (ParallelProtocol, SerialProtocol)): + for child in stmt.pulses: + yield from iter_pulses(child) + + +def iter_pulse_targets(stmt) -> Iterator: + for pulse in iter_pulses(stmt): + yield pulse.target + + +def verify_constant_pulse_durations(cfg: ControlFlowGraph): + for _, block in iter_stmt_blocks(cfg): + for pulse in iter_pulses(block.stmt): + try: + _as_numeric_duration(pulse.duration) + except AtomicCompilerError as exc: + raise AtomicCompilerError( + f"Non-constant pulse duration before protocol canonicalization: {pulse.duration}" + ) from exc + return cfg def verify_pulse_target_dim(cfg: ControlFlowGraph, symbol_table: AtomicSymbolTable): diff --git a/src/oqd_core/interface/atomic/circuit.py b/src/oqd_core/interface/atomic/circuit.py index d9d2d6a3..e3ef15fe 100644 --- a/src/oqd_core/interface/atomic/circuit.py +++ b/src/oqd_core/interface/atomic/circuit.py @@ -43,9 +43,9 @@ def beam(self, frequency, rabi, phase, polarization, wavevector): Beam(frequency = frequency, rabi = rabi, phase = phase, polarization = polarization, wavevector = wavevector) ) - def pulse(self, duration, target, beam, measured): + def pulse(self, beam, duration, target, measured): self.statements.append( - Pulse(duration=duration, target=target, beam=beam, measured=measured) + Pulse(beam=beam, duration=duration, target=target, measured=measured) ) def parallel(self, pulses): diff --git a/src/oqd_core/interface/atomic/expr.py b/src/oqd_core/interface/atomic/expr.py index 1106d057..8568f633 100644 --- a/src/oqd_core/interface/atomic/expr.py +++ b/src/oqd_core/interface/atomic/expr.py @@ -60,6 +60,7 @@ "AtomicList", "Extract", "Beam", + "Pulse", ] ######################################################################################## @@ -212,7 +213,7 @@ class Bool(BoolExpr): ######################################################################################## -class IonRegister(AtomicExpr): +class IonRegister(RegisterExpr): size: NonNegativeInt @@ -472,11 +473,11 @@ class BoolGreaterThanEq(ComparisonOp): ######################################################################################## -class AtomicList(AtomicExpr): +class AtomicList(CollectionExpr): values: List[CastAtomicExpr] -class Extract(AtomicExpr): +class Extract(IndexingExpr): access: Access index: NonNegativeInt @@ -502,7 +503,7 @@ class Beam(AtomicExpr): wavevector: CastAtomicExpr -class Pulse(TypeReflectBaseModel): +class Pulse(AtomicExpr): """ Class representing the application of the beam for some duration. From b840b30027443b5303a94ec98ffc4f269c00a235 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Tue, 7 Jul 2026 02:05:17 -0400 Subject: [PATCH 08/20] fix: Atomic tests --- tests/test_analysis/test_analysis_atomic.py | 6 ++++-- tests/test_atomic/test_beam.py | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_analysis/test_analysis_atomic.py b/tests/test_analysis/test_analysis_atomic.py index e450482c..e2c3d5f9 100644 --- a/tests/test_analysis/test_analysis_atomic.py +++ b/tests/test_analysis/test_analysis_atomic.py @@ -45,7 +45,7 @@ def test_ionreg_binding(self): ) pulse = next(s for s in circuit.statements if isinstance(s, Pulse)) node_id = symbol_table.stmt_index[id(pulse)] - assert symbol_table.in_env[node_id]["r"].target_dim == (3, 0) + assert symbol_table.in_env[node_id]["r"].target_dim == 3 def test_extract_out_of_range(self): symbol_table, cfg, _ = build_symbol_table( @@ -96,6 +96,8 @@ class TestAtomicTypeChecker: p2 = pulse(beam_mw, 5e-6, r[2]) \n parallel {\n p0\n serial {\n p1\n p2 \n}\n}", "r = ionreg(2) \n b = beam(2e6, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]) \n \ pulse(b, 1e-5, r[0], false)", + "r = ionreg(2) \n beam_mw = beam(2e6, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]) \n \ + parallel {\n serial {\n x = pulse(beam_mw, 5e-6, r[0])\n x\n }\n}", "c = 1 < 2", "c = 3 >= 2", "if (1 < 2) {x = 0}", @@ -127,7 +129,7 @@ def test_atomic_type_checker(self, program): "r = ionreg(2) \n beam_mw = beam(2e6, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]) \n \ parallel {\n serial {\n pulse(beam_mw, 5e-6, r[0])\n }\n r[1]\n}", "r = ionreg(2) \n beam_mw = beam(2e6, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]) \n \ - parallel {\n serial {\n x = pulse(beam_mw, 5e-6, r[0])\n }\n}", + parallel {\n serial {\n x = 5\n }\n}", "r = true \n if (r) { \n r = 5} \n r = r + 2", "c = 1 == true", "c = true != 5", diff --git a/tests/test_atomic/test_beam.py b/tests/test_atomic/test_beam.py index 884761b8..5b56ffef 100644 --- a/tests/test_atomic/test_beam.py +++ b/tests/test_atomic/test_beam.py @@ -107,7 +107,6 @@ def test_polarization(self, polarization): wavevector=DEFAULT_WV, ) - @pytest.mark.xfail @pytest.mark.parametrize( "polarization", [ @@ -144,7 +143,6 @@ def test_wavevector(self, wavevector): wavevector=wavevector, ) - @pytest.mark.xfail @pytest.mark.parametrize( "wavevector", [ From 868e338e392ef6899d33f641c83c0d92bfadf9d6 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Tue, 7 Jul 2026 02:06:44 -0400 Subject: [PATCH 09/20] clean: Atomic compiler CFG passes --- .../compiler/atomic/cfg_passes/protocol.py | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/oqd_core/compiler/atomic/cfg_passes/protocol.py diff --git a/src/oqd_core/compiler/atomic/cfg_passes/protocol.py b/src/oqd_core/compiler/atomic/cfg_passes/protocol.py new file mode 100644 index 00000000..eb59adb3 --- /dev/null +++ b/src/oqd_core/compiler/atomic/cfg_passes/protocol.py @@ -0,0 +1,64 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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. + +from __future__ import annotations +from oqd_compiler_infrastructure import Post +from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.compiler.atomic.canonicalize import ResolveNestedProtocol, ResolveRelativeTime +from oqd_core.compiler.atomic.cfg_passes.walk import iter_stmt_blocks +from oqd_core.interface.atomic import ( + AtomicCircuit, + Declaration, + ParallelProtocol, + Pulse, + SerialProtocol, + IfElse, + While, +) + +PROTOCOL_TYPES = (Pulse, ParallelProtocol, SerialProtocol) + + +def apply_protocol_passes(stmt): + stmt = Post(ResolveNestedProtocol())(stmt) + return Post(ResolveRelativeTime())(stmt) + + +def canonicalize_protocol_tree(stmt): + if isinstance(stmt, IfElse): + stmt.then_branch = [canonicalize_protocol_tree(s) for s in stmt.then_branch] + stmt.else_branch = [canonicalize_protocol_tree(s) for s in stmt.else_branch] + return stmt + if isinstance(stmt, While): + stmt.body = [canonicalize_protocol_tree(s) for s in stmt.body] + return stmt + if isinstance(stmt, Declaration) and isinstance(stmt.value, PROTOCOL_TYPES): + stmt.value = apply_protocol_passes(stmt.value) + return stmt + if isinstance(stmt, PROTOCOL_TYPES): + return apply_protocol_passes(stmt) + return stmt + + +def canonicalize_protocol_cfg(cfg: ControlFlowGraph, model: AtomicCircuit) -> ControlFlowGraph: + old_top = list(model.statements) + model.statements = [canonicalize_protocol_tree(s) for s in model.statements] + + for old, new in zip(old_top, model.statements): + if old is not new: + for _, block in iter_stmt_blocks(cfg): + if block.stmt is old: + block.stmt = new + return cfg + From c389420f0e89f7c07853e5ed243522d4ed51e3dc Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Tue, 7 Jul 2026 03:04:15 -0400 Subject: [PATCH 10/20] clean: Add documentation for atomic compiler passes --- docs/analysis/atomic_analysis.md | 4 + docs/grammar/atomic_grammar.md | 4 +- docs/interfaces/atomic_interface.md | 5 +- docs/reference/atomic_compiler.md | 88 +++++++++++++++++++ docs/reference/atomic_interface.md | 4 + examples/atomic/test.ipynb | 8 +- mkdocs.yaml | 2 +- src/oqd_core/compiler/atomic/canonicalize.py | 8 +- src/oqd_core/compiler/atomic/math/rules.py | 42 ++++----- .../compiler/atomic/verify/__init__.py | 5 ++ src/oqd_core/compiler/atomic/verify/passes.py | 5 ++ src/oqd_core/interface/analog/expr.py | 72 +++++++-------- src/oqd_core/interface/atomic/circuit.py | 2 +- src/oqd_core/interface/atomic/expr.py | 48 +++++----- src/oqd_core/interface/atomic/statement.py | 4 +- 15 files changed, 202 insertions(+), 99 deletions(-) create mode 100644 docs/reference/atomic_compiler.md create mode 100644 src/oqd_core/compiler/atomic/verify/__init__.py diff --git a/docs/analysis/atomic_analysis.md b/docs/analysis/atomic_analysis.md index 906456f3..cb272ba6 100644 --- a/docs/analysis/atomic_analysis.md +++ b/docs/analysis/atomic_analysis.md @@ -10,10 +10,14 @@ The atomic Control Flow Graph (CFG) is implemented by the `AtomicCFGBuilder` cla The atomic type checker is implemented by the `AtomicTypeChecker` class in [`type_checker.py`](../../src/oqd_core/analysis/atomic/type_checker.py). The `AtomicTypeLattice` class defines a concrete lattice for atomic types with `leq`, `join`, and `meet` methods. Type inference rules are implemented by the `AtomicSemantics` class in [`semantics.py`](../../src/oqd_core/analysis/atomic/semantics.py). The type checker runs forward dataflow analysis over the CFG. +Protocol blocks (`parallel` / `serial`) accept only pulse statements: `Pulse` nodes, pulse declarations, pulse variable references, and nested protocols. In `serial` blocks, pulse declarations update the local environment for later statements in the same block. + ## Symbol Table The atomic symbol table is implemented in [`symbol_table.py`](../../src/oqd_core/analysis/atomic/symbol_table.py). The `AtomicSymbolTableBuilder` class runs a second forward dataflow pass over the CFG, using the type checker output to track register and target dimensions. The result is an `AtomicSymbolTable` with register environments per block and a statement index. +`SymbolBinding.target_dim` is an `int` giving the total ion-target dimension (register size, extracted ion, or sum of list elements). Unlike the analog symbol table, atomic targets do not use a `(qreg, qmode)` tuple. + ## Usage of the type checker diff --git a/docs/grammar/atomic_grammar.md b/docs/grammar/atomic_grammar.md index 37b8630f..86fdaceb 100644 --- a/docs/grammar/atomic_grammar.md +++ b/docs/grammar/atomic_grammar.md @@ -70,9 +70,9 @@ The grammar supports the core atomic statements through `beam`, `pulse`, `parall - `target`: target expression (`aexpr`) - `measured`: boolean expression (`aexpr`), optional, defaults to `false` - `parallel { ... }` - - `...`: block (`block`) containing pulse statements to run in parallel + - `...`: block (`block`) containing pulse statements, pulse declarations, pulse references, and nested protocols that will be run in parallel. - `serial { ... }` - - `...`: block (`block`) containing pulse statements to run in serial + - `...`: block (`block`) containing pulse statements, pulse declarations, pulse references, and nested protocols that will be run in a serial sequence. ## Generate Parser Files for Frontend diff --git a/docs/interfaces/atomic_interface.md b/docs/interfaces/atomic_interface.md index ac51b572..e98017fa 100644 --- a/docs/interfaces/atomic_interface.md +++ b/docs/interfaces/atomic_interface.md @@ -84,7 +84,7 @@ The [`AtomicCircuit`][oqd_core.interface.atomic.circuit.AtomicCircuit] is the to type: example ```py -from oqd_core.interface.atomic import AtomicCircuit, Beam +from oqd_core.interface.atomic import AtomicCircuit, Beam, Access circuit = AtomicCircuit() @@ -96,7 +96,8 @@ mw = Beam( wavevector=[0.0, 0.0, 1.0], ) -circuit.pulse(duration=10e-6, target=0, beam=mw, measured=False) +ions = Access(name="ions") +circuit.pulse(beam=mw, duration=10e-6, target=ions, measured=False) ``` /// diff --git a/docs/reference/atomic_compiler.md b/docs/reference/atomic_compiler.md new file mode 100644 index 00000000..0c8d87d1 --- /dev/null +++ b/docs/reference/atomic_compiler.md @@ -0,0 +1,88 @@ +# Atomic Compiler + +The atomic compiler is implemented in `src/oqd_core/compiler/atomic`. The entry point is [`compile_atomic_circuit`][oqd_core.compiler.atomic.passes.compile.compile_atomic_circuit]. + +The compile pipeline: +- Canonicalize scalars, beams, and pulse references over the CFG via [`canonicalize_scalars_cfg`][oqd_core.compiler.atomic.cfg_passes.scalar_env.canonicalize_scalars_cfg] +- Verify pulse durations are constant before protocol canonicalization via [`verify_constant_pulse_durations`][oqd_core.compiler.atomic.verify.passes.verify_constant_pulse_durations] +- Canonicalize nested protocols and relative time via [`canonicalize_protocol_cfg`][oqd_core.compiler.atomic.cfg_passes.protocol.canonicalize_protocol_cfg] +- Verify pulse target dimensions via [`verify_pulse_target_dim`][oqd_core.compiler.atomic.verify.passes.verify_pulse_target_dim] + +## Compile Passes + + +::: oqd_core.compiler.atomic.passes.compile + options: + heading_level: 3 + members: [ + "compile_atomic_circuit", + ] + +## CFG Passes + + +::: oqd_core.compiler.atomic.cfg_passes.walk + options: + heading_level: 3 + members: [ + "canonicalize_math_cfg", + "canonicalize_math_block", + "iter_stmt_blocks", + ] + +::: oqd_core.compiler.atomic.cfg_passes.scalar_env + options: + heading_level: 3 + members: [ + "canonicalize_scalars_cfg", + ] + +::: oqd_core.compiler.atomic.cfg_passes.protocol + options: + heading_level: 3 + members: [ + "canonicalize_protocol_cfg", + ] + +## Verification Passes + + +::: oqd_core.compiler.atomic.verify.passes + options: + heading_level: 3 + members: [ + "verify_constant_pulse_durations", + "verify_pulse_target_dim", + ] + +## Atomic Math Passes + + +::: oqd_core.compiler.atomic.math.passes + options: + heading_level: 3 + members: [ + "canonicalize_math_expr", + "evaluate_math_expr", + "simplify_math_expr", + "print_math_expr", + ] + +## Atomic Math Rewrite Rules + + +::: oqd_core.compiler.atomic.math.rules + options: + heading_level: 3 + members: [ + "DistributeMathExpr", + "PartitionMathExpr", + "ProperOrderMathExpr", + "PruneMathExpr", + "EvaluateMathExpr", + "SimplifyMathExpr", + "PrintMathExpr", + ] + +## Usage + diff --git a/docs/reference/atomic_interface.md b/docs/reference/atomic_interface.md index 3fa4d91e..445c33b7 100644 --- a/docs/reference/atomic_interface.md +++ b/docs/reference/atomic_interface.md @@ -19,6 +19,10 @@ "AtomicExpr", "AtomicExprSubtypes", "CastAtomicExpr", + "IonExpr", + "CollectionExpr", + "IndexingExpr", + "RegisterExpr", "Terminal", "Access", "IonRegister", diff --git a/examples/atomic/test.ipynb b/examples/atomic/test.ipynb index 56034ccd..83b885ab 100644 --- a/examples/atomic/test.ipynb +++ b/examples/atomic/test.ipynb @@ -180,13 +180,9 @@ } ], "source": [ - "from oqd_core.compiler.atomic.canonicalize import canonicalize_atomic_circuit_factory\n", - "from oqd_core.compiler.atomic.cfg_passes.scalar_env import canonicalize_scalars_cfg\n", - "from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_math_cfg\n", + "from oqd_core.compiler.atomic.passes.compile import compile_atomic_circuit\n", "\n", - "canonicalize_scalars_cfg(cfg, checker.dataflow_result)\n", - "canonicalize_math_cfg(cfg)\n", - "canonicalize_atomic_circuit_factory()(circuit)" + "compile_atomic_circuit(circuit, cfg, checker.dataflow_result, symbol_table)" ] } ], diff --git a/mkdocs.yaml b/mkdocs.yaml index fb0123da..e7678520 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -25,7 +25,6 @@ nav: - Interfaces: - Analog: interfaces/analog_interface.md - Atomic: interfaces/atomic_interface.md - - Canonicalization: interfaces/canonicalization.md - Grammar: - Analog: grammar/analog_grammar.md @@ -49,6 +48,7 @@ nav: - Compiler: reference/analog_compiler.md - Canonicalization: reference/analog_canonicalization.md - Atomic: + - Compiler: reference/atomic_compiler.md - Canonicalization: reference/atomic_canonicalization.md theme: diff --git a/src/oqd_core/compiler/atomic/canonicalize.py b/src/oqd_core/compiler/atomic/canonicalize.py index 06f62e2a..35dfa032 100644 --- a/src/oqd_core/compiler/atomic/canonicalize.py +++ b/src/oqd_core/compiler/atomic/canonicalize.py @@ -36,10 +36,10 @@ class ResolveNestedProtocol(RewriteRule): Unfolds nested protocols into a standard form with only 2 hierarchy levels, a sequential protocol of parallel protocols. Args: - model (AtomicCircuit): The rule only acts on [`AtomicCircuit`][oqd_core.interface.atomic.AtomicCircuit] objects. + model: A protocol node (`Pulse`, `ParallelProtocol`, or `SerialProtocol`). Returns: - model (AtomicCircuit): + model: The canonicalized protocol node. Assumptions: None @@ -181,10 +181,10 @@ class ResolveRelativeTime(RewriteRule): Handles conversion of relative time to absolute time. Args: - model (AtomicCircuit): The rule only acts on [`AtomicCircuit`][oqd_core.interface.atomic.AtomicCircuit] objects. + model: A protocol node (`Pulse`, `ParallelProtocol`, or `SerialProtocol`). Returns: - model (AtomicCircuit): + model: The canonicalized protocol node. Assumptions: None diff --git a/src/oqd_core/compiler/atomic/math/rules.py b/src/oqd_core/compiler/atomic/math/rules.py index 468d54be..6415d769 100644 --- a/src/oqd_core/compiler/atomic/math/rules.py +++ b/src/oqd_core/compiler/atomic/math/rules.py @@ -67,13 +67,13 @@ def _is_constant_math(model) -> bool: class PrintMathExpr(ConversionRule): """ - This prints [`MathExpr`][oqd_core.interface.math.MathExpr] objects. Verbosity level can be given as an attribute. + This prints [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Verbosity level can be given as an attribute. Args: - model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Returns: - string (str): + string (str) Assumptions: None @@ -194,13 +194,13 @@ def _map_MathBinaryOp(self, model: MathBinaryOp, operands): class DistributeMathExpr(RewriteRule): """ - This distributes [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + This distributes [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Args: - model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Returns: - model (MathExpr): + model (MathExpr) Assumptions: None @@ -237,17 +237,17 @@ def map_MathDiv(self, model: MathDiv): class PartitionMathExpr(RewriteRule): """ - This separates real and complex portions of [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + This separates real and complex portions of [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Args: - model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Returns: - model (MathExpr): + model (MathExpr) Assumptions: - [`DistributeMathExpr`][oqd_core.compiler.math.rules.DistributeMathExpr], - [`ProperOrderMathExpr`][oqd_core.compiler.math.rules.ProperOrderMathExpr] + [`DistributeMathExpr`][oqd_core.compiler.atomic.math.rules.DistributeMathExpr], + [`ProperOrderMathExpr`][oqd_core.compiler.atomic.math.rules.ProperOrderMathExpr] Example: - MathStr(string = '1 + 1j + 2') => MathStr(string = '1 + 2 + 1j') @@ -307,16 +307,16 @@ def map_MathMul(self, model: MathMul): class ProperOrderMathExpr(RewriteRule): """ - This rearranges bracketing of [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + This rearranges bracketing of [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Args: - model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Returns: - model (MathExpr): + model (MathExpr) Assumptions: - [`DistributeMathExpr`][oqd_core.compiler.math.rules.DistributeMathExpr] + [`DistributeMathExpr`][oqd_core.compiler.atomic.math.rules.DistributeMathExpr] Example: - MathStr(string = '2 * (3 * 5)') => MathStr(string = '(2 * 3) * 5') @@ -342,7 +342,7 @@ class PruneMathExpr(RewriteRule): This is constant fold operation where scalar addition, multiplication and power are simplified Args: - model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Returns: model (MathExpr): @@ -386,7 +386,7 @@ class SubstituteMathVar(RewriteRule): This rule substitutes a MathVar with another MathExpr Args: - model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Returns: model (MathExpr): @@ -421,7 +421,7 @@ class EvaluateMathExpr(ConversionRule): This evaluates MathExpr objects and raises a type error if a MathVar exist in the AST. Args: - model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Returns: model (MathExpr): @@ -499,13 +499,13 @@ def map_MathPow(self, model: MathPow, operands): class SimplifyMathExpr(RewriteRule): """ - This simplifies MathExpr objects by evaluating all constants in the AST. + This simplifies MathExpr objects by evaluating constant subexpressions in the AST. Args: - model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.math.MathExpr] objects. + model (MathExpr): The rule only acts on [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] objects. Returns: - model (MathExpr): + model (MathExpr) Assumptions: None diff --git a/src/oqd_core/compiler/atomic/verify/__init__.py b/src/oqd_core/compiler/atomic/verify/__init__.py new file mode 100644 index 00000000..dc73d2b6 --- /dev/null +++ b/src/oqd_core/compiler/atomic/verify/__init__.py @@ -0,0 +1,5 @@ +from .passes import verify_constant_pulse_durations, verify_pulse_target_dim +__all__ = [ + "verify_constant_pulse_durations", + "verify_pulse_target_dim", +] diff --git a/src/oqd_core/compiler/atomic/verify/passes.py b/src/oqd_core/compiler/atomic/verify/passes.py index 1b0b86ad..395558e9 100644 --- a/src/oqd_core/compiler/atomic/verify/passes.py +++ b/src/oqd_core/compiler/atomic/verify/passes.py @@ -21,6 +21,11 @@ from oqd_core.compiler.atomic.error import AtomicCompilerError from oqd_core.interface.atomic import Declaration, ParallelProtocol, Pulse, SerialProtocol +__all__ = [ + "verify_constant_pulse_durations", + "verify_pulse_target_dim", +] + def iter_pulses(stmt): if isinstance(stmt, Pulse): diff --git a/src/oqd_core/interface/analog/expr.py b/src/oqd_core/interface/analog/expr.py index d803b522..162bac6c 100644 --- a/src/oqd_core/interface/analog/expr.py +++ b/src/oqd_core/interface/analog/expr.py @@ -225,7 +225,7 @@ class MathTerminal(MathExpr): ... class MathVar(MathTerminal): """ - Class representing a variable in a [`MathExpr`][oqd_core.interface.math.MathExpr] + Class representing a variable in a [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] Examples: >>> MathVar("t") @@ -237,7 +237,7 @@ class MathVar(MathTerminal): class MathNum(MathTerminal): """ - Class representing a number in a [`MathExpr`][oqd_core.interface.math.MathExpr] + Class representing a number in a [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] """ value: Union[int, float] @@ -245,7 +245,7 @@ class MathNum(MathTerminal): class MathImag(MathTerminal): """ - Class representing the imaginary unit in a [`MathExpr`][oqd_core.interface.math.MathExpr] abstract syntax tree (AST) + Class representing the imaginary unit in a [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] abstract syntax tree (AST) """ pass @@ -423,7 +423,7 @@ def _Terminal_discriminator(value): class MathFunc(AnalogExpr): """ - Class representing a named function applied to a [`MathExpr`][oqd_core.interface.math.MathExpr] abstract syntax tree (AST) + Class representing a named function applied to a [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] abstract syntax tree (AST) Attributes: func (SupportedFuncNames): Named function to apply @@ -484,7 +484,7 @@ def args_validate(cls, data): class MathBinaryOp(MathExpr): """ - Class representing binary operations on [`MathExprs`][oqd_core.interface.math.MathExpr] abstract syntax tree (AST) + Class representing binary operations on [`MathExprs`][oqd_core.interface.analog.expr.MathExpr] abstract syntax tree (AST) """ pass @@ -492,11 +492,11 @@ class MathBinaryOp(MathExpr): class MathAdd(MathBinaryOp): """ - Class representing the addition of [`MathExprs`][oqd_core.interface.analog.operator.Operator] + Class representing the addition of [`MathExprs`][oqd_core.interface.analog.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.analog.operator.Operator] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.analog.operator.Operator] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] """ expr1: CastAnalogExpr @@ -505,11 +505,11 @@ class MathAdd(MathBinaryOp): class MathSub(MathBinaryOp): """ - Class representing the subtraction of [`MathExprs`][oqd_core.interface.math.MathExpr] + Class representing the subtraction of [`MathExprs`][oqd_core.interface.analog.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.math.MathExpr] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.math.MathExpr] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] """ expr1: CastAnalogExpr @@ -518,11 +518,11 @@ class MathSub(MathBinaryOp): class MathMul(MathBinaryOp): """ - Class representing the multiplication of [`MathExprs`][oqd_core.interface.math.MathExpr] + Class representing the multiplication of [`MathExprs`][oqd_core.interface.analog.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.math.MathExpr] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.math.MathExpr] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] """ expr1: CastAnalogExpr @@ -531,11 +531,11 @@ class MathMul(MathBinaryOp): class MathDiv(MathBinaryOp): """ - Class representing the division of [`MathExprs`][oqd_core.interface.math.MathExpr] + Class representing the division of [`MathExprs`][oqd_core.interface.analog.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.math.MathExpr] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.math.MathExpr] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] """ expr1: CastAnalogExpr @@ -544,11 +544,11 @@ class MathDiv(MathBinaryOp): class MathPow(MathBinaryOp): """ - Class representing the exponentiation of [`MathExprs`][oqd_core.interface.math.MathExpr] + Class representing the exponentiation of [`MathExprs`][oqd_core.interface.analog.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.math.MathExpr] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.math.MathExpr] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.analog.expr.MathExpr] """ expr1: CastAnalogExpr @@ -560,7 +560,7 @@ class MathPow(MathBinaryOp): class BoolUnaryOp(BoolExpr): """ - Class representing binary operations on [`BoolExprs`][oqd_core.interface.bool.BoolExpr] abstract syntax tree (AST) + Class representing binary operations on [`BoolExprs`][oqd_core.interface.analog.expr.BoolExpr] abstract syntax tree (AST) """ pass @@ -568,7 +568,7 @@ class BoolUnaryOp(BoolExpr): class BoolBinaryOp(BoolExpr): """ - Class representing binary operations on [`BoolExprs`][oqd_core.interface.bool.BoolExpr] abstract syntax tree (AST) + Class representing binary operations on [`BoolExprs`][oqd_core.interface.analog.expr.BoolExpr] abstract syntax tree (AST) """ pass @@ -576,7 +576,7 @@ class BoolBinaryOp(BoolExpr): class ComparisonOp(BoolExpr): """ - Class representing binary operations on [`BoolExprs`][oqd_core.interface.bool.BoolExpr] abstract syntax tree (AST) + Class representing binary operations on [`BoolExprs`][oqd_core.interface.analog.expr.BoolExpr] abstract syntax tree (AST) """ pass @@ -631,7 +631,7 @@ class BoolGreaterThanEq(ComparisonOp): class OperatorBinaryOp(OperatorExpr): """ - Class representing binary operations on [`Operators`][oqd_core.interface.analog.operator.Operator] + Class representing binary operations on [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] """ pass @@ -639,11 +639,11 @@ class OperatorBinaryOp(OperatorExpr): class OperatorAdd(OperatorBinaryOp): """ - Class representing the addition of [`Operators`][oqd_core.interface.analog.operator.Operator] + Class representing the addition of [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] Attributes: - op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.operator.Operator] - op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.operator.Operator] + op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] + op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] """ op1: CastAnalogExpr @@ -652,11 +652,11 @@ class OperatorAdd(OperatorBinaryOp): class OperatorSub(OperatorBinaryOp): """ - Class representing the subtraction of [`Operators`][oqd_core.interface.analog.operator.Operator] + Class representing the subtraction of [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] Attributes: - op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.operator.Operator] - op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.operator.Operator] + op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] + op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] """ op1: CastAnalogExpr @@ -665,11 +665,11 @@ class OperatorSub(OperatorBinaryOp): class OperatorMul(OperatorBinaryOp): """ - Class representing the multiplication of [`Operators`][oqd_core.interface.analog.operator.Operator] + Class representing the multiplication of [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] Attributes: - op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.operator.Operator] - op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.operator.Operator] + op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] + op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] """ op1: CastAnalogExpr @@ -678,11 +678,11 @@ class OperatorMul(OperatorBinaryOp): class OperatorKron(OperatorBinaryOp): """ - Class representing the tensor product of [`Operators`][oqd_core.interface.analog.operator.Operator] + Class representing the tensor product of [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] Attributes: - op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.operator.Operator] - op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.operator.Operator] + op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] + op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] """ op1: CastAnalogExpr diff --git a/src/oqd_core/interface/atomic/circuit.py b/src/oqd_core/interface/atomic/circuit.py index e3ef15fe..a8cce586 100644 --- a/src/oqd_core/interface/atomic/circuit.py +++ b/src/oqd_core/interface/atomic/circuit.py @@ -30,7 +30,7 @@ class AtomicCircuit(TypeReflectBaseModel): """ - Class representing a trapped-ion experiment in terms of light-matter interactons. + Class representing a trapped-ion experiment in terms of light-matter interactions. Attributes: statements: The trapped-ion system. diff --git a/src/oqd_core/interface/atomic/expr.py b/src/oqd_core/interface/atomic/expr.py index 8568f633..24444f84 100644 --- a/src/oqd_core/interface/atomic/expr.py +++ b/src/oqd_core/interface/atomic/expr.py @@ -168,7 +168,7 @@ class MathTerminal(MathExpr): ... class MathVar(MathTerminal): """ - Class representing a variable in a [`MathExpr`][oqd_core.interface.math.MathExpr] + Class representing a variable in a [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] Examples: >>> MathVar("t") @@ -180,7 +180,7 @@ class MathVar(MathTerminal): class MathNum(MathTerminal): """ - Class representing a number in a [`MathExpr`][oqd_core.interface.math.MathExpr] + Class representing a number in a [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] """ value: Union[int, float] @@ -188,7 +188,7 @@ class MathNum(MathTerminal): class MathImag(MathTerminal): """ - Class representing the imaginary unit in a [`MathExpr`][oqd_core.interface.math.MathExpr] abstract syntax tree (AST) + Class representing the imaginary unit in a [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] abstract syntax tree (AST) """ pass @@ -267,7 +267,7 @@ def _Terminal_discriminator(value): class MathFunc(AtomicExpr): """ - Class representing a named function applied to a [`MathExpr`][oqd_core.interface.math.MathExpr] abstract syntax tree (AST) + Class representing a named function applied to a [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] abstract syntax tree (AST) Attributes: func (SupportedFuncNames): Named function to apply @@ -328,7 +328,7 @@ def args_validate(cls, data): class MathBinaryOp(MathExpr): """ - Class representing binary operations on [`MathExprs`][oqd_core.interface.math.MathExpr] abstract syntax tree (AST) + Class representing binary operations on [`MathExprs`][oqd_core.interface.atomic.expr.MathExpr] abstract syntax tree (AST) """ pass @@ -336,11 +336,11 @@ class MathBinaryOp(MathExpr): class MathAdd(MathBinaryOp): """ - Class representing the addition of [`MathExprs`][oqd_core.interface.Atomic.operator.Operator] + Class representing the addition of [`MathExprs`][oqd_core.interface.atomic.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.Atomic.operator.Operator] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.Atomic.operator.Operator] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] """ expr1: CastAtomicExpr @@ -349,11 +349,11 @@ class MathAdd(MathBinaryOp): class MathSub(MathBinaryOp): """ - Class representing the subtraction of [`MathExprs`][oqd_core.interface.math.MathExpr] + Class representing the subtraction of [`MathExprs`][oqd_core.interface.atomic.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.math.MathExpr] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.math.MathExpr] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] """ expr1: CastAtomicExpr @@ -362,11 +362,11 @@ class MathSub(MathBinaryOp): class MathMul(MathBinaryOp): """ - Class representing the multiplication of [`MathExprs`][oqd_core.interface.math.MathExpr] + Class representing the multiplication of [`MathExprs`][oqd_core.interface.atomic.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.math.MathExpr] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.math.MathExpr] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] """ expr1: CastAtomicExpr @@ -375,11 +375,11 @@ class MathMul(MathBinaryOp): class MathDiv(MathBinaryOp): """ - Class representing the division of [`MathExprs`][oqd_core.interface.math.MathExpr] + Class representing the division of [`MathExprs`][oqd_core.interface.atomic.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.math.MathExpr] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.math.MathExpr] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] """ expr1: CastAtomicExpr @@ -388,11 +388,11 @@ class MathDiv(MathBinaryOp): class MathPow(MathBinaryOp): """ - Class representing the exponentiation of [`MathExprs`][oqd_core.interface.math.MathExpr] + Class representing the exponentiation of [`MathExprs`][oqd_core.interface.atomic.expr.MathExpr] Attributes: - expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.math.MathExpr] - expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.math.MathExpr] + expr1 (MathExpr): Left hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] + expr2 (MathExpr): Right hand side [`MathExpr`][oqd_core.interface.atomic.expr.MathExpr] """ expr1: CastAtomicExpr @@ -404,7 +404,7 @@ class MathPow(MathBinaryOp): class BoolUnaryOp(BoolExpr): """ - Class representing binary operations on [`BoolExprs`][oqd_core.interface.bool.BoolExpr] abstract syntax tree (AST) + Class representing unary operations on [`BoolExprs`][oqd_core.interface.atomic.expr.BoolExpr] abstract syntax tree (AST) """ pass @@ -412,7 +412,7 @@ class BoolUnaryOp(BoolExpr): class BoolBinaryOp(BoolExpr): """ - Class representing binary operations on [`BoolExprs`][oqd_core.interface.bool.BoolExpr] abstract syntax tree (AST) + Class representing binary operations on [`BoolExprs`][oqd_core.interface.atomic.expr.BoolExpr] abstract syntax tree (AST) """ pass @@ -420,7 +420,7 @@ class BoolBinaryOp(BoolExpr): class ComparisonOp(BoolExpr): """ - Class representing binary operations on [`BoolExprs`][oqd_core.interface.bool.BoolExpr] abstract syntax tree (AST) + Class representing binary operations on [`BoolExprs`][oqd_core.interface.atomic.expr.BoolExpr] abstract syntax tree (AST) """ pass @@ -513,9 +513,9 @@ class Pulse(AtomicExpr): target: Target ion of the beam. measured: Boolean that tracks if the pulse has been measured. """ + beam: AtomicExprSubtypes duration: AtomicExprSubtypes target: AtomicExprSubtypes - beam: AtomicExprSubtypes measured: AtomicExprSubtypes diff --git a/src/oqd_core/interface/atomic/statement.py b/src/oqd_core/interface/atomic/statement.py index 2b66c590..60b4b453 100644 --- a/src/oqd_core/interface/atomic/statement.py +++ b/src/oqd_core/interface/atomic/statement.py @@ -49,7 +49,7 @@ class SerialProtocol(TypeReflectBaseModel): class IfElse(TypeReflectBaseModel): """ - Class representing a conditional branch in the analog circuit + Class representing a conditional branch in the atomic circuit """ condition: AtomicExprSubtypes then_branch: List[Statement] = [] @@ -58,7 +58,7 @@ class IfElse(TypeReflectBaseModel): class While(TypeReflectBaseModel): """ - Class representing a while loop in the analog circuit + Class representing a while loop in the atomic circuit """ condition: AtomicExprSubtypes body: List[Statement] = [] From 660b3a84181438583ba787ec1c8193554bf1143d Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Tue, 7 Jul 2026 03:20:29 -0400 Subject: [PATCH 11/20] clean: Update docs for analog and atomic compiler passes --- docs/interfaces/analog_interface.md | 8 +++--- docs/reference/analog_interface.md | 3 +++ docs/reference/atomic_canonicalization.md | 1 - docs/reference/atomic_compiler.md | 25 ++++++++++++++++-- docs/reference/math_interface.md | 0 src/oqd_core/compiler/analog/math/rules.py | 6 ++--- src/oqd_core/compiler/analog/passes/assign.py | 6 ++--- .../compiler/analog/rewrite/canonicalize.py | 4 +-- src/oqd_core/compiler/analog/utils.py | 2 +- .../compiler/analog/verify/canonicalize.py | 18 ++++++------- src/oqd_core/compiler/analog/verify/passes.py | 2 +- src/oqd_core/interface/analog/expr.py | 26 +++++++++---------- 12 files changed, 62 insertions(+), 39 deletions(-) delete mode 100644 docs/reference/atomic_canonicalization.md delete mode 100644 docs/reference/math_interface.md diff --git a/docs/interfaces/analog_interface.md b/docs/interfaces/analog_interface.md index 764b2874..90015e78 100644 --- a/docs/interfaces/analog_interface.md +++ b/docs/interfaces/analog_interface.md @@ -41,13 +41,13 @@ The basis of operators for the bosonic degree of freedom are the ladder operator The basis operators can be combined with the operations: -- Addition
[![](https://img.shields.io/badge/Implementation-7C4DFF)][oqd_core.interface.analog.expr.OperatorAdd]
+- Addition
[![](https://img.shields.io/badge/Implementation-7C4DFF)][oqd_core.interface.analog.expr.OperatorExprAdd]
-- Subtraction
[![](https://img.shields.io/badge/Implementation-7C4DFF)][oqd_core.interface.analog.expr.OperatorSub]
+- Subtraction
[![](https://img.shields.io/badge/Implementation-7C4DFF)][oqd_core.interface.analog.expr.OperatorExprSub]
-- Multiplication
[![](https://img.shields.io/badge/Implementation-7C4DFF)][oqd_core.interface.analog.expr.OperatorMul]
+- Multiplication
[![](https://img.shields.io/badge/Implementation-7C4DFF)][oqd_core.interface.analog.expr.OperatorExprMul]
-- Tensor Product
[![](https://img.shields.io/badge/Implementation-7C4DFF)][oqd_core.interface.analog.expr.OperatorKron]
+- Tensor Product
[![](https://img.shields.io/badge/Implementation-7C4DFF)][oqd_core.interface.analog.expr.OperatorExprKron]
## Math Expressions diff --git a/docs/reference/analog_interface.md b/docs/reference/analog_interface.md index a73818da..e50ea2f1 100644 --- a/docs/reference/analog_interface.md +++ b/docs/reference/analog_interface.md @@ -16,6 +16,9 @@ options: heading_level: 3 members: [ + "OperatorExpr", + "OperatorBinaryOp", + "OperatorTerminal", "AnalogExpr", "AnalogExprSubtypes", "CastAnalogExpr", diff --git a/docs/reference/atomic_canonicalization.md b/docs/reference/atomic_canonicalization.md deleted file mode 100644 index d97484e6..00000000 --- a/docs/reference/atomic_canonicalization.md +++ /dev/null @@ -1 +0,0 @@ -::: oqd_core.compiler.atomic diff --git a/docs/reference/atomic_compiler.md b/docs/reference/atomic_compiler.md index 0c8d87d1..17d59424 100644 --- a/docs/reference/atomic_compiler.md +++ b/docs/reference/atomic_compiler.md @@ -25,8 +25,8 @@ The compile pipeline: options: heading_level: 3 members: [ - "canonicalize_math_cfg", - "canonicalize_math_block", + "canonicalize_expr", + "canonicalize_beam", "iter_stmt_blocks", ] @@ -86,3 +86,24 @@ The compile pipeline: ## Usage + + +/// admonition | Example + type: example +```py +from oqd_core.frontend.atomic import parse_atomic +from oqd_core.analysis.atomic import AtomicCFGBuilder, AtomicTypeChecker, AtomicSymbolTableBuilder +from oqd_core.compiler.atomic.passes.compile import compile_atomic_circuit + +source = """ +ions = ionreg(1) +mw = beam(2.0, 1.0, 0.0, [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]) +pulse(mw, 1e-5, ions[0], true) +""" + +circuit = parse_atomic(source) +cfg = AtomicCFGBuilder().run(circuit) +type_checker = AtomicTypeChecker(cfg) +symbol_table = AtomicSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table +circuit = compile_atomic_circuit(circuit, cfg, symbol_table) +``` diff --git a/docs/reference/math_interface.md b/docs/reference/math_interface.md deleted file mode 100644 index e69de29b..00000000 diff --git a/src/oqd_core/compiler/analog/math/rules.py b/src/oqd_core/compiler/analog/math/rules.py index 8f7449a4..b180e2d4 100644 --- a/src/oqd_core/compiler/analog/math/rules.py +++ b/src/oqd_core/compiler/analog/math/rules.py @@ -250,8 +250,8 @@ class PartitionMathExpr(RewriteRule): model (MathExpr): Assumptions: - [`DistributeMathExpr`][oqd_core.compiler.math.rules.DistributeMathExpr], - [`ProperOrderMathExpr`][oqd_core.compiler.math.rules.ProperOrderMathExpr] + [`DistributeMathExpr`][oqd_core.compiler.analog.math.rules.DistributeMathExpr], + [`ProperOrderMathExpr`][oqd_core.compiler.analog.math.rules.ProperOrderMathExpr] Example: - MathStr(string = '1 + 1j + 2') => MathStr(string = '1 + 2 + 1j') @@ -320,7 +320,7 @@ class ProperOrderMathExpr(RewriteRule): model (MathExpr): Assumptions: - [`DistributeMathExpr`][oqd_core.compiler.math.rules.DistributeMathExpr] + [`DistributeMathExpr`][oqd_core.compiler.analog.math.rules.DistributeMathExpr] Example: - MathStr(string = '2 * (3 * 5)') => MathStr(string = '(2 * 3) * 5') diff --git a/src/oqd_core/compiler/analog/passes/assign.py b/src/oqd_core/compiler/analog/passes/assign.py index 374bcaa0..f7fdafa1 100644 --- a/src/oqd_core/compiler/analog/passes/assign.py +++ b/src/oqd_core/compiler/analog/passes/assign.py @@ -33,13 +33,13 @@ def infer_analog_circuit_dim_cfg(cfg: ControlFlowGraph): This pass assigns n_qreg and n_qmode in the analog circuit and then verifies the assignment Args: - model (AnalogCircuit): n_qreg and n_qmode fields of [`AnalogCircuit`][oqd_core.interface.analog.operations.AnalogCircuit] are not assigned + model (AnalogCircuit): n_qreg and n_qmode fields of [`AnalogCircuit`][oqd_core.interface.analog.circuit.AnalogCircuit] are not assigned Returns: - model (AnalogCircuit): n_qreg and n_qmode fields of [`AnalogCircuit`][oqd_core.interface.analog.operations.AnalogCircuit] are assigned + model (AnalogCircuit): n_qreg and n_qmode fields of [`AnalogCircuit`][oqd_core.interface.analog.circuit.AnalogCircuit] are assigned Assumptions: - All [`Operator`][oqd_core.interface.analog.operator.Operator] inside [`AnalogCircuit`][oqd_core.interface.analog.operations.AnalogCircuit] must be canonicalized + All [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] inside [`AnalogCircuit`][oqd_core.interface.analog.circuit.AnalogCircuit] must be canonicalized """ dim = None for _, block in iter_stmt_blocks(cfg): diff --git a/src/oqd_core/compiler/analog/rewrite/canonicalize.py b/src/oqd_core/compiler/analog/rewrite/canonicalize.py index be225749..2d1b7d08 100644 --- a/src/oqd_core/compiler/analog/rewrite/canonicalize.py +++ b/src/oqd_core/compiler/analog/rewrite/canonicalize.py @@ -108,7 +108,7 @@ def map_OperatorSub(self, model: OperatorSub): class GatherMathExpr(RewriteRule): """ - Gathers the math expressions of [`Operator`][oqd_core.interface.analog.expr.Operator] so that we have math_expr * ( [`Operator`][oqd_core.interface.analog.expr.Operator] without scalar multiplication) + Gathers the math expressions of [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] so that we have math_expr * ( [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] without scalar multiplication) Args: model (VisitableBaseModel): @@ -159,7 +159,7 @@ class GatherPauli(RewriteRule): [`GatherMathExpr`][oqd_core.compiler.analog.rewrite.canonicalize.GatherMathExpr], [`OperatorDistribute`][oqd_core.compiler.analog.rewrite.canonicalize.OperatorDistribute], [`ProperOrder`][oqd_core.compiler.analog.rewrite.canonicalize.ProperOrder] - [`Operator`][oqd_core.interface.analog.expr.Operator] + [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] Example: X@A@Y => X@Y@A diff --git a/src/oqd_core/compiler/analog/utils.py b/src/oqd_core/compiler/analog/utils.py index 37aa5f8e..132ec800 100644 --- a/src/oqd_core/compiler/analog/utils.py +++ b/src/oqd_core/compiler/analog/utils.py @@ -42,7 +42,7 @@ class PrintOperator(ConversionRule): verbosity can be set through the verbose attribute Args: - model (Operator): [`Operator`][oqd_core.interface.analog.operator.Operator] of Analog level + model (Operator): [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] of Analog level Returns: string (str): diff --git a/src/oqd_core/compiler/analog/verify/canonicalize.py b/src/oqd_core/compiler/analog/verify/canonicalize.py index b885a4e2..ab0a98ff 100644 --- a/src/oqd_core/compiler/analog/verify/canonicalize.py +++ b/src/oqd_core/compiler/analog/verify/canonicalize.py @@ -56,7 +56,7 @@ class CanVerPauliAlgebra(RewriteRule): Checks whether there is any incomplete Pauli Algebra computation Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged @@ -89,7 +89,7 @@ class CanVerGatherMathExpr(RewriteRule): there is any scalar multiplication within a term) Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged @@ -126,7 +126,7 @@ class CanVerOperatorDistribute(RewriteRule): Checks for incomplete distribution of Operators Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged @@ -191,7 +191,7 @@ class CanVerProperOrder(RewriteRule): Please see example for clarification Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged @@ -233,7 +233,7 @@ class CanVerPruneIdentity(RewriteRule): Checks if there is any ladder Identity present in ladder multiplication Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged @@ -260,7 +260,7 @@ class CanVerGatherPauli(RewriteRule): Checks whether pauli and ladder have been separated. Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged @@ -292,7 +292,7 @@ class CanVerNormalOrder(RewriteRule): Checks whether the ladder operations are in normal order Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged @@ -329,7 +329,7 @@ class CanVerSortedOrder(RewriteRule): Please see example for further clarification Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged @@ -365,7 +365,7 @@ class CanVerScaleTerm(RewriteRule): Checks whether all terms have a scalar multiplication. Args: - model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.Operator] in Analog level + model (VisitableBaseModel): The rule only verifies [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] in Analog level Returns: model (VisitableBaseMode): unchanged diff --git a/src/oqd_core/compiler/analog/verify/passes.py b/src/oqd_core/compiler/analog/verify/passes.py index 1e748f80..ccd49e1c 100644 --- a/src/oqd_core/compiler/analog/verify/passes.py +++ b/src/oqd_core/compiler/analog/verify/passes.py @@ -38,7 +38,7 @@ def verify_analog_args_dim(model, n_qreg, n_qmode): model (TaskArgsAnalog): Assumptions: - All [`Operator`][oqd_core.interface.analog.operator.Operator] inside TaskArgsAnalog must be canonicalized + All [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] inside TaskArgsAnalog must be canonicalized """ expected = (n_qreg, n_qmode) for metric in model.metrics.values(): diff --git a/src/oqd_core/interface/analog/expr.py b/src/oqd_core/interface/analog/expr.py index 162bac6c..ccc197d2 100644 --- a/src/oqd_core/interface/analog/expr.py +++ b/src/oqd_core/interface/analog/expr.py @@ -631,7 +631,7 @@ class BoolGreaterThanEq(ComparisonOp): class OperatorBinaryOp(OperatorExpr): """ - Class representing binary operations on [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] + Class representing binary operations on [`Operators`][oqd_core.interface.analog.expr.OperatorExprExpr] """ pass @@ -639,11 +639,11 @@ class OperatorBinaryOp(OperatorExpr): class OperatorAdd(OperatorBinaryOp): """ - Class representing the addition of [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] + Class representing the addition of [`Operators`][oqd_core.interface.analog.expr.OperatorExprExpr] Attributes: - op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] - op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] + op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExprExpr] + op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExprExpr] """ op1: CastAnalogExpr @@ -652,11 +652,11 @@ class OperatorAdd(OperatorBinaryOp): class OperatorSub(OperatorBinaryOp): """ - Class representing the subtraction of [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] + Class representing the subtraction of [`Operators`][oqd_core.interface.analog.expr.OperatorExprExpr] Attributes: - op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] - op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] + op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExprExpr] + op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExprExpr] """ op1: CastAnalogExpr @@ -665,11 +665,11 @@ class OperatorSub(OperatorBinaryOp): class OperatorMul(OperatorBinaryOp): """ - Class representing the multiplication of [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] + Class representing the multiplication of [`Operators`][oqd_core.interface.analog.expr.OperatorExprExpr] Attributes: - op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] - op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] + op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExprExpr] + op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExprExpr] """ op1: CastAnalogExpr @@ -678,11 +678,11 @@ class OperatorMul(OperatorBinaryOp): class OperatorKron(OperatorBinaryOp): """ - Class representing the tensor product of [`Operators`][oqd_core.interface.analog.expr.OperatorExpr] + Class representing the tensor product of [`Operators`][oqd_core.interface.analog.expr.OperatorExprExpr] Attributes: - op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] - op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExpr] + op1 (Operator): Left hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExprExpr] + op2 (Operator): Right hand side [`Operator`][oqd_core.interface.analog.expr.OperatorExprExpr] """ op1: CastAnalogExpr From 2cf6e5550803c6ae9a498e34552e701148cf3fb9 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Tue, 7 Jul 2026 16:30:01 -0400 Subject: [PATCH 12/20] fix: Do not resolve access of scalars in atomic compiler --- src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py b/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py index fce276d5..fca07250 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py @@ -245,18 +245,16 @@ def transfer(self, node_id: int, state_in: ScalarEnv) -> ScalarEnv: if isinstance(stmt, Declaration): t: TLatticeValue | None = self.type_out_states[node_id].get(stmt.name) if t is TScalar: - value = canonicalize_scalar_expr( + bound = canonicalize_scalar_expr( resolve_scalar_expr(stmt.value, env) ) - stmt.value = value out = dict(env) - out[stmt.name] = value + out[stmt.name] = bound return out if t is TBool: - value = resolve_scalar_expr(stmt.value, env) - stmt.value = value + bound = resolve_scalar_expr(stmt.value, env) out = dict(env) - out[stmt.name] = value + out[stmt.name] = bound return out if t is TBeam: beam = canonicalize_beam(resolve_beam_expr(stmt.value, env)) From 6fdca24e1199e0042f3f9589bb68d9e85d414e11 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Wed, 8 Jul 2026 00:41:57 -0400 Subject: [PATCH 13/20] clean: Simplify atomic compiler passes. Update docs --- .gitignore | 3 +- docs/reference/atomic_compiler.md | 20 ++- examples/atomic/test.ipynb | 2 +- .../compiler/atomic/cfg_passes/__init__.py | 7 +- .../compiler/atomic/cfg_passes/protocol.py | 7 +- .../cfg_passes/{scalar_env.py => resolve.py} | 148 +----------------- .../compiler/atomic/cfg_passes/walk.py | 32 ++++ .../compiler/atomic/passes/compile.py | 7 +- .../compiler/atomic/verify/__init__.py | 3 +- src/oqd_core/compiler/atomic/verify/passes.py | 15 -- 10 files changed, 62 insertions(+), 182 deletions(-) rename src/oqd_core/compiler/atomic/cfg_passes/{scalar_env.py => resolve.py} (51%) diff --git a/.gitignore b/.gitignore index 103aadc1..030cec62 100644 --- a/.gitignore +++ b/.gitignore @@ -179,4 +179,5 @@ tests/test.bat .pre-commit-config.yaml -*.antlr/ \ No newline at end of file +*.antlr/ +examples/* diff --git a/docs/reference/atomic_compiler.md b/docs/reference/atomic_compiler.md index 17d59424..2e3360ed 100644 --- a/docs/reference/atomic_compiler.md +++ b/docs/reference/atomic_compiler.md @@ -3,8 +3,7 @@ The atomic compiler is implemented in `src/oqd_core/compiler/atomic`. The entry point is [`compile_atomic_circuit`][oqd_core.compiler.atomic.passes.compile.compile_atomic_circuit]. The compile pipeline: -- Canonicalize scalars, beams, and pulse references over the CFG via [`canonicalize_scalars_cfg`][oqd_core.compiler.atomic.cfg_passes.scalar_env.canonicalize_scalars_cfg] -- Verify pulse durations are constant before protocol canonicalization via [`verify_constant_pulse_durations`][oqd_core.compiler.atomic.verify.passes.verify_constant_pulse_durations] +- Canonicalize scalars and beams over the CFG via [`canonicalize_declarations_cfg`][oqd_core.compiler.atomic.cfg_passes.walk.canonicalize_declarations_cfg] - Canonicalize nested protocols and relative time via [`canonicalize_protocol_cfg`][oqd_core.compiler.atomic.cfg_passes.protocol.canonicalize_protocol_cfg] - Verify pulse target dimensions via [`verify_pulse_target_dim`][oqd_core.compiler.atomic.verify.passes.verify_pulse_target_dim] @@ -28,20 +27,26 @@ The compile pipeline: "canonicalize_expr", "canonicalize_beam", "iter_stmt_blocks", + "canonicalize_scalars_cfg", ] -::: oqd_core.compiler.atomic.cfg_passes.scalar_env +::: oqd_core.compiler.atomic.cfg_passes.protocol options: heading_level: 3 members: [ - "canonicalize_scalars_cfg", + "canonicalize_protocol_cfg", ] -::: oqd_core.compiler.atomic.cfg_passes.protocol +::: oqd_core.compiler.atomic.cfg_passes.resolve options: heading_level: 3 members: [ - "canonicalize_protocol_cfg", + "resolve_scalar_expr", + "resolve_beam_expr", + "resolve_beam_ref", + "resolve_pulse_expr", + "resolve_pulse_ref", + "resolve_protocol_pulses", ] ## Verification Passes @@ -51,7 +56,6 @@ The compile pipeline: options: heading_level: 3 members: [ - "verify_constant_pulse_durations", "verify_pulse_target_dim", ] @@ -105,5 +109,5 @@ circuit = parse_atomic(source) cfg = AtomicCFGBuilder().run(circuit) type_checker = AtomicTypeChecker(cfg) symbol_table = AtomicSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table -circuit = compile_atomic_circuit(circuit, cfg, symbol_table) +circuit = compile_atomic_circuit(circuit, cfg, type_checker.dataflow_result, symbol_table) ``` diff --git a/examples/atomic/test.ipynb b/examples/atomic/test.ipynb index 83b885ab..161ee5ff 100644 --- a/examples/atomic/test.ipynb +++ b/examples/atomic/test.ipynb @@ -171,7 +171,7 @@ { "data": { "text/plain": [ - "AtomicCircuit(class_='AtomicCircuit', statements=[Declaration(class_='Declaration', name='ions', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=1)), Declaration(class_='Declaration', name='targets', value=AtomicList(class_='AtomicList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phi', value=MathVar(class_='MathVar', name='#phi')), Declaration(class_='Declaration', name='t_gate', value=MathNum(class_='MathNum', value=1e-05)), Declaration(class_='Declaration', name='flag', value=Bool(class_='Bool', value=True)), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), Declaration(class_='Declaration', name='r', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='beam_mw', value=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Declaration(class_='Declaration', name='beam_det', value=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=1e-05), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=3e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=1e-05), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=3e-06), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])]), IfElse(class_='IfElse', condition=Access(class_='Access', name='flag'), then_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])], else_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=2e-05), target=Access(class_='Access', name='targets'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=12566360.0), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=True))])]), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', duration=MathNum(class_='MathNum', value=1e-06), target=Access(class_='Access', name='targets'), beam=Beam(class_='Beam', frequency=MathNum(class_='MathNum', value=6283180.0), rabi=MathVar(class_='MathVar', name='#omega'), phase=MathVar(class_='MathVar', name='#phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)])), measured=Bool(class_='Bool', value=False))])]), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=2)), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Continue(class_='Continue')], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Break(class_='Break')], else_branch=[])])])" + "AtomicCircuit(class_='AtomicCircuit', statements=[Declaration(class_='Declaration', name='ions', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=1)), Declaration(class_='Declaration', name='targets', value=AtomicList(class_='AtomicList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phi', value=MathVar(class_='MathVar', name='#phi')), Declaration(class_='Declaration', name='t_gate', value=MathNum(class_='MathNum', value=1e-05)), Declaration(class_='Declaration', name='flag', value=Bool(class_='Bool', value=True)), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), Declaration(class_='Declaration', name='r', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='beam_mw', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=2000000.0), expr2=Access(class_='Access', name='pi')), rabi=Access(class_='Access', name='omega'), phase=Access(class_='Access', name='phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Declaration(class_='Declaration', name='beam_det', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=4000000.0), expr2=Access(class_='Access', name='pi')), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=Access(class_='Access', name='t_gate'), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=3e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))]), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=Access(class_='Access', name='t_gate'), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0), measured=Bool(class_='Bool', value=False)), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=3e-06), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), IfElse(class_='IfElse', condition=Access(class_='Access', name='flag'), then_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))])], else_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=2e-05), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=True))])]), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=1e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))])]), Declaration(class_='Declaration', name='n', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=-1), expr2=Access(class_='Access', name='n'))), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Continue(class_='Continue')], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Break(class_='Break')], else_branch=[])])])" ] }, "execution_count": 5, diff --git a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py index 80ad99f1..3fecfe62 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py @@ -1,9 +1,8 @@ -from .walk import iter_stmt_blocks -from .scalar_env import canonicalize_scalar_expr, canonicalize_scalars_cfg, resolve_scalar_expr +from .walk import iter_stmt_blocks, canonicalize_declarations_cfg +from .resolve import resolve_scalar_expr __all__ = [ "iter_stmt_blocks", - "canonicalize_scalar_expr", - "canonicalize_scalars_cfg", + "canonicalize_declarations_cfg", "resolve_scalar_expr", ] diff --git a/src/oqd_core/compiler/atomic/cfg_passes/protocol.py b/src/oqd_core/compiler/atomic/cfg_passes/protocol.py index eb59adb3..01254ebe 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/protocol.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/protocol.py @@ -17,6 +17,8 @@ from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.canonicalize import ResolveNestedProtocol, ResolveRelativeTime from oqd_core.compiler.atomic.cfg_passes.walk import iter_stmt_blocks +from oqd_core.compiler.atomic.math.rules import _is_constant_math +from oqd_core.compiler.atomic.verify.passes import iter_pulses from oqd_core.interface.atomic import ( AtomicCircuit, Declaration, @@ -31,8 +33,11 @@ def apply_protocol_passes(stmt): + if not all(_is_constant_math(pulse.duration) for pulse in iter_pulses(stmt)): + return stmt stmt = Post(ResolveNestedProtocol())(stmt) - return Post(ResolveRelativeTime())(stmt) + stmt = Post(ResolveRelativeTime())(stmt) + return stmt def canonicalize_protocol_tree(stmt): diff --git a/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py b/src/oqd_core/compiler/atomic/cfg_passes/resolve.py similarity index 51% rename from src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py rename to src/oqd_core/compiler/atomic/cfg_passes/resolve.py index fca07250..8d88dc84 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/scalar_env.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/resolve.py @@ -14,16 +14,10 @@ from __future__ import annotations -from typing import Iterable, Union +from oqd_compiler_infrastructure.lattice import LatticeTop -from oqd_compiler_infrastructure.dataflow import DataflowResult, ForwardDataflowAnalysis -from oqd_compiler_infrastructure.lattice import Lattice, LatticeBottom, LatticeTop, maplattice - -from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_beam, canonicalize_expr -from oqd_core.analysis.atomic.types import TBeam, TBool, TScalar, TLatticeValue, TypeEnv, TPulse -from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_beam, canonicalize_expr, canonicalize_scalar_expr from oqd_core.compiler.atomic.error import AtomicCompilerError -from oqd_core.compiler.atomic.math.passes import canonicalize_math_expr from oqd_core.interface.atomic import ( Access, Bool, @@ -36,7 +30,6 @@ BoolNot, BoolNotEq, BoolOr, - Declaration, MathAdd, MathDiv, MathFunc, @@ -59,43 +52,6 @@ BoolAnd, BoolOr, BoolEq, BoolNotEq, BoolLessThan, BoolLessThanEq, BoolGreaterThan, BoolGreaterThanEq) -class ScalarExprLattice(Lattice[Union[object, type[LatticeTop]]]): - def top(self): - return LatticeTop - - def bottom(self): - return LatticeBottom - - def leq(self, t1, t2) -> bool: - if t1 is LatticeBottom or t2 is LatticeTop: - return True - if t1 is LatticeTop or t2 is LatticeBottom: - return t2 is LatticeTop - return t1 == t2 - - def join(self, t1, t2): - if t1 is LatticeTop or t2 is LatticeTop: - return LatticeTop - if t1 is LatticeBottom: - return t2 - if t2 is LatticeBottom: - return t1 - if t1 == t2: - return t1 - return LatticeTop - - def meet(self, t1, t2): - if t1 is LatticeBottom or t2 is LatticeBottom: - return LatticeBottom - if t1 is LatticeTop: - return t2 - if t2 is LatticeTop: - return t1 - if t1 == t2: - return t1 - return LatticeBottom - - def resolve_scalar_expr(expr, env: ScalarEnv): if isinstance(expr, Access): if expr.name not in env: @@ -196,103 +152,3 @@ def resolve_protocol_pulses(pulses, env: ScalarEnv): resolved.append(child) return resolved - -def canonicalize_scalar_expr(expr): - if isinstance(expr, Bool): - return expr - return canonicalize_math_expr(expr) - - -class ScalarEnvBuilder(ForwardDataflowAnalysis[int, ScalarEnv]): - def __init__( - self, - graph: ControlFlowGraph, - type_result: DataflowResult[int, TypeEnv], - ) -> None: - self.type_out_states = type_result.out_states - self.lattice = maplattice(ScalarExprLattice)() - self.blocks = graph.blocks - self.analyze(graph, self.merge_scalar_env) - - def merge_scalar_env(self, states: Iterable[ScalarEnv]) -> ScalarEnv: - states_list = list(states) - if not states_list: - return self.lattice.bottom() - - merged = {} if states_list[0] is LatticeBottom else dict(states_list[0]) - for state in states_list[1:]: - if state is LatticeBottom: - continue - for name in set(merged).union(state): - v1, v2 = merged.get(name), state.get(name) - if v1 is None: - merged[name] = v2 - elif v2 is None: - continue - elif v1 is LatticeTop or v2 is LatticeTop or v1 != v2: - merged[name] = LatticeTop - return merged - - def transfer(self, node_id: int, state_in: ScalarEnv) -> ScalarEnv: - env = {} if state_in is LatticeBottom else dict(state_in) - stmt = self.blocks[node_id].stmt - block = self.blocks[node_id] - - if block.kind == "branch": - block.stmt = resolve_scalar_expr(stmt, env) - return env - - if isinstance(stmt, Declaration): - t: TLatticeValue | None = self.type_out_states[node_id].get(stmt.name) - if t is TScalar: - bound = canonicalize_scalar_expr( - resolve_scalar_expr(stmt.value, env) - ) - out = dict(env) - out[stmt.name] = bound - return out - if t is TBool: - bound = resolve_scalar_expr(stmt.value, env) - out = dict(env) - out[stmt.name] = bound - return out - if t is TBeam: - beam = canonicalize_beam(resolve_beam_expr(stmt.value, env)) - stmt.value = beam - out = dict(env) - out[stmt.name] = beam - return out - if t is TPulse: - pulse = resolve_pulse_expr(stmt.value, env) - stmt.value = pulse - out = dict(env) - out[stmt.name] = pulse - return out - return env - - if isinstance(stmt, Pulse): - resolved = resolve_pulse_expr(stmt, env) - stmt.beam = resolved.beam - stmt.duration = resolved.duration - stmt.target = resolved.target - stmt.measured = resolved.measured - return env - - if isinstance(stmt, Access): - block.stmt = resolve_pulse_ref(stmt, env) - return env - - if isinstance(stmt, (ParallelProtocol, SerialProtocol)): - stmt.pulses = resolve_protocol_pulses(stmt.pulses, env) - return env - - return env - - -def canonicalize_scalars_cfg( - cfg: ControlFlowGraph, - type_result: DataflowResult[int, TypeEnv], -) -> ControlFlowGraph: - ScalarEnvBuilder(cfg, type_result) - return cfg - diff --git a/src/oqd_core/compiler/atomic/cfg_passes/walk.py b/src/oqd_core/compiler/atomic/cfg_passes/walk.py index 10231ea1..75a5bbd7 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/walk.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/walk.py @@ -22,8 +22,12 @@ AtomicList, Beam, Pulse, + Bool, ) from oqd_core.interface.atomic.expr import AtomicExpr +from oqd_core.analysis.atomic.types import TBeam, TScalar, TypeEnv, TPulse +from oqd_core.interface.atomic import Declaration +from oqd_compiler_infrastructure.dataflow import DataflowResult def iter_stmt_blocks(cfg: ControlFlowGraph): for node_id, block in cfg.blocks.items(): @@ -50,3 +54,31 @@ def canonicalize_atomic_list(values: AtomicList) -> AtomicList: values.values = [canonicalize_expr(v) for v in values.values] return values + +def canonicalize_scalar_expr(expr): + if isinstance(expr, Bool): + return expr + return canonicalize_math_expr(expr) + +def canonicalize_declarations_cfg( + cfg: ControlFlowGraph, + type_result: DataflowResult[int, TypeEnv], +) -> ControlFlowGraph: + + for node_id, block in iter_stmt_blocks(cfg): + stmt = block.stmt + if not isinstance(stmt, Declaration): + continue + t = type_result.out_states[node_id].get(stmt.name) + if t is TScalar: + stmt.value = canonicalize_scalar_expr(stmt.value) + elif t is TBeam: + stmt.value = canonicalize_beam(stmt.value) + elif t is TPulse: + pulse = stmt.value + pulse.duration = canonicalize_scalar_expr(pulse.duration) + if isinstance(pulse.beam, Beam): + pulse.beam = canonicalize_beam(pulse.beam) + + return cfg + diff --git a/src/oqd_core/compiler/atomic/passes/compile.py b/src/oqd_core/compiler/atomic/passes/compile.py index 45170d7a..f299fe48 100644 --- a/src/oqd_core/compiler/atomic/passes/compile.py +++ b/src/oqd_core/compiler/atomic/passes/compile.py @@ -16,9 +16,9 @@ from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable from oqd_core.analysis.atomic.types import TypeEnv from oqd_core.analysis.utils.control_flow import ControlFlowGraph -from oqd_core.compiler.atomic.cfg_passes.scalar_env import canonicalize_scalars_cfg +from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_declarations_cfg from oqd_core.compiler.atomic.cfg_passes.protocol import canonicalize_protocol_cfg -from oqd_core.compiler.atomic.verify.passes import verify_pulse_target_dim, verify_constant_pulse_durations +from oqd_core.compiler.atomic.verify.passes import verify_pulse_target_dim from oqd_core.interface.atomic import AtomicCircuit __all__ = ["compile_atomic_circuit"] @@ -30,8 +30,7 @@ def compile_atomic_circuit( type_result: DataflowResult[int, TypeEnv], symbol_table: AtomicSymbolTable, ): - canonicalize_scalars_cfg(cfg, type_result) - verify_constant_pulse_durations(cfg) + canonicalize_declarations_cfg(cfg, type_result) canonicalize_protocol_cfg(cfg, model) verify_pulse_target_dim(cfg, symbol_table) diff --git a/src/oqd_core/compiler/atomic/verify/__init__.py b/src/oqd_core/compiler/atomic/verify/__init__.py index dc73d2b6..1d7dbefa 100644 --- a/src/oqd_core/compiler/atomic/verify/__init__.py +++ b/src/oqd_core/compiler/atomic/verify/__init__.py @@ -1,5 +1,4 @@ -from .passes import verify_constant_pulse_durations, verify_pulse_target_dim +from .passes import verify_pulse_target_dim __all__ = [ - "verify_constant_pulse_durations", "verify_pulse_target_dim", ] diff --git a/src/oqd_core/compiler/atomic/verify/passes.py b/src/oqd_core/compiler/atomic/verify/passes.py index 395558e9..e40de847 100644 --- a/src/oqd_core/compiler/atomic/verify/passes.py +++ b/src/oqd_core/compiler/atomic/verify/passes.py @@ -17,12 +17,9 @@ from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable, target_dim from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.cfg_passes.walk import iter_stmt_blocks -from oqd_core.compiler.atomic.canonicalize import _as_numeric_duration -from oqd_core.compiler.atomic.error import AtomicCompilerError from oqd_core.interface.atomic import Declaration, ParallelProtocol, Pulse, SerialProtocol __all__ = [ - "verify_constant_pulse_durations", "verify_pulse_target_dim", ] @@ -42,18 +39,6 @@ def iter_pulse_targets(stmt) -> Iterator: yield pulse.target -def verify_constant_pulse_durations(cfg: ControlFlowGraph): - for _, block in iter_stmt_blocks(cfg): - for pulse in iter_pulses(block.stmt): - try: - _as_numeric_duration(pulse.duration) - except AtomicCompilerError as exc: - raise AtomicCompilerError( - f"Non-constant pulse duration before protocol canonicalization: {pulse.duration}" - ) from exc - return cfg - - def verify_pulse_target_dim(cfg: ControlFlowGraph, symbol_table: AtomicSymbolTable): """ Check pulse targets are in range at each use. From 0fff144376dae7508928fa788aab331104ef133d Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Thu, 9 Jul 2026 11:51:34 -0400 Subject: [PATCH 14/20] feat: compiler passes modify the control flow graph --- docs/reference/analog_compiler.md | 10 +-- docs/reference/atomic_compiler.md | 14 ++-- examples/analog/test.ipynb | 29 ++++--- examples/atomic/test.ipynb | 4 +- src/oqd_core/analysis/analog/cfg.py | 8 +- src/oqd_core/analysis/analog/type_checker.py | 8 +- src/oqd_core/analysis/atomic/cfg.py | 8 +- src/oqd_core/analysis/utils/control_flow.py | 24 +----- .../compiler/analog/passes/__init__.py | 4 +- .../compiler/analog/passes/compile.py | 7 +- src/oqd_core/compiler/atomic/canonicalize.py | 2 - .../compiler/atomic/cfg_passes/__init__.py | 2 - .../compiler/atomic/cfg_passes/protocol.py | 35 ++------- .../compiler/atomic/cfg_passes/walk.py | 75 +++++++++---------- .../compiler/atomic/passes/compile.py | 12 +-- 15 files changed, 89 insertions(+), 153 deletions(-) diff --git a/docs/reference/analog_compiler.md b/docs/reference/analog_compiler.md index 2204268b..5ba03f0e 100644 --- a/docs/reference/analog_compiler.md +++ b/docs/reference/analog_compiler.md @@ -1,12 +1,12 @@ # Analog Compiler -The analog compiler is implemented in `src/oqd_core/compiler/analog`. The entry point is [`compile_analog_circuit`][oqd_core.compiler.analog.passes.compile.compile_analog_circuit], which takes an [`AnalogCircuit`][oqd_core.interface.analog.circuit.AnalogCircuit], a `ControlFlowGraph`, and an `AnalogSymbolTable`. +The analog compiler is implemented in `src/oqd_core/compiler/analog`. The entry point is [`compile_analog_cfg`][oqd_core.compiler.analog.passes.compile.compile_analog_cfg], which takes a [`ControlFlowGraph`][oqd_core.analysis.utils.control_flow.ControlFlowGraph], and an `AnalogSymbolTable`[oqd_core.analysis.analog.symbol_table.AnalogSymbolTable]. The compile pipeline: - Canonicalize operators over the CFG via [`canonicalize_operators_cfg`][oqd_core.compiler.analog.cfg_passes.walk.canonicalize_operators_cfg] - Canonicalize math expressions over the CFG via [`canonicalize_math_cfg`][oqd_core.compiler.analog.cfg_passes.walk.canonicalize_math_cfg] - Verify register access and Hamiltonian target dimensions -- Infer circuit Hilbert space dimensions from canonicalized `Evolve` statements +- Infer Hilbert space dimensions from canonicalized `Evolve` statements ## Compile Passes @@ -15,7 +15,7 @@ The compile pipeline: options: heading_level: 3 members: [ - "compile_analog_circuit", + "compile_analog_cfg", ] ::: oqd_core.compiler.analog.passes.assign @@ -111,7 +111,7 @@ The compile pipeline: ```py from oqd_core.frontend.analog import parse_analog from oqd_core.analysis.analog import AnalogCFGBuilder, AnalogTypeChecker, AnalogSymbolTableBuilder -from oqd_core.compiler.analog.passes.compile import compile_analog_circuit +from oqd_core.compiler.analog.passes.compile import compile_analog_cfg source = """ q = qreg(2) h = %X %@ %I @@ -122,5 +122,5 @@ circuit = parse_analog(source) cfg = AnalogCFGBuilder().run(circuit) type_checker = AnalogTypeChecker(cfg) symbol_table = AnalogSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table -circuit, (n_qreg, n_qmode) = compile_analog_circuit(circuit, cfg, symbol_table) +cfg = compile_analog_cfg(cfg, symbol_table) ``` diff --git a/docs/reference/atomic_compiler.md b/docs/reference/atomic_compiler.md index 2e3360ed..796ed143 100644 --- a/docs/reference/atomic_compiler.md +++ b/docs/reference/atomic_compiler.md @@ -1,9 +1,9 @@ # Atomic Compiler -The atomic compiler is implemented in `src/oqd_core/compiler/atomic`. The entry point is [`compile_atomic_circuit`][oqd_core.compiler.atomic.passes.compile.compile_atomic_circuit]. +The atomic compiler is implemented in `src/oqd_core/compiler/atomic`. The entry point is [`compile_atomic_circuit`][oqd_core.compiler.atomic.passes.compile.compile_atomic_circuit], which takes a [`ControlFlowGraph`][oqd_core.analysis.utils.control_flow.ControlFlowGraph] and an [`AtomicSymbolTable`][oqd_core.analysis.atomic.symbol_table.AtomicSymbolTable]. The compile pipeline: -- Canonicalize scalars and beams over the CFG via [`canonicalize_declarations_cfg`][oqd_core.compiler.atomic.cfg_passes.walk.canonicalize_declarations_cfg] +- Canonicalize declaration values over the CFG via [`canonicalize_declarations_cfg`][oqd_core.compiler.atomic.cfg_passes.walk.canonicalize_declarations_cfg] - Canonicalize nested protocols and relative time via [`canonicalize_protocol_cfg`][oqd_core.compiler.atomic.cfg_passes.protocol.canonicalize_protocol_cfg] - Verify pulse target dimensions via [`verify_pulse_target_dim`][oqd_core.compiler.atomic.verify.passes.verify_pulse_target_dim] @@ -24,10 +24,12 @@ The compile pipeline: options: heading_level: 3 members: [ - "canonicalize_expr", - "canonicalize_beam", "iter_stmt_blocks", - "canonicalize_scalars_cfg", + "canonicalize_declarations_cfg", + "canonicalize_declarations", + "canonicalize_beam", + "canonicalize_pulse", + "canonicalize_scalar_expr", ] ::: oqd_core.compiler.atomic.cfg_passes.protocol @@ -109,5 +111,5 @@ circuit = parse_atomic(source) cfg = AtomicCFGBuilder().run(circuit) type_checker = AtomicTypeChecker(cfg) symbol_table = AtomicSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table -circuit = compile_atomic_circuit(circuit, cfg, type_checker.dataflow_result, symbol_table) +cfg = compile_atomic_circuit(cfg, symbol_table) ``` diff --git a/examples/analog/test.ipynb b/examples/analog/test.ipynb index e9ebe6f2..93b46e76 100644 --- a/examples/analog/test.ipynb +++ b/examples/analog/test.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 9, "id": "b527eaca", "metadata": {}, "outputs": [ @@ -31,7 +31,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 10, "id": "1c5481c1", "metadata": {}, "outputs": [], @@ -54,7 +54,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 11, "id": "08b33d2c", "metadata": {}, "outputs": [ @@ -75,7 +75,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 12, "id": "f628d79e", "metadata": {}, "outputs": [ @@ -83,7 +83,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4671122368: 1, 4671122048: 2, 4671118288: 3, 4671120608: 4, 4671123248: 5, 4671119008: 6, 4671125568: 7, 4671124928: 8, 4671119728: 9, 4671125728: 10, 4664498672: 11, 4660310368: 12, 4671121888: 13, 4671127168: 14, 4671127088: 15, 4671127328: 16, 4674060368: 17, 4674060448: 18, 4674060608: 19, 4674060768: 20, 4674060928: 21, 4674062048: 22, 4674063248: 23, 4674064528: 24, 4674064688: 25, 4674064928: 26, 4674065248: 27, 4674065568: 28, 4674066048: 29, 4674066368: 30, 4674066608: 31, 4674066848: 32, 4674067168: 33, 4674067488: 34, 4674067808: 35, 4674067968: 36, 4674068128: 37, 4674068368: 38, 4674068528: 39, 4674068768: 40, 4674069008: 41, 4674069168: 42, 4674069328: 43, 4674069728: 44, 4674070048: 45, 4674070368: 46, 4674070848: 47, 4674071008: 48, 4674071248: 49, 4674071408: 50, 4674071568: 51, 4674071808: 52, 4674072048: 53, 4674072368: 54, 4674072608: 55, 4674072848: 56, 4674073168: 57, 4674073088: 58, 4674073328: 59}\"\n" + "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4700091040: 1, 4699968992: 2, 4532353488: 3, 4699943264: 4, 4699571456: 5, 4533652048: 6, 4699937344: 7, 4699940864: 8, 4699925680: 9, 4700120848: 10, 4700126608: 11, 4700124528: 12, 4700126528: 13, 4700114368: 14, 4533662368: 15, 4700126048: 16, 4699983216: 17, 4700111168: 18, 4700113808: 19, 4700114768: 20, 4699724912: 21, 4699892352: 22, 4700126768: 23, 4700123248: 24, 4700115088: 25, 4700125808: 26, 4700117648: 27, 4700087360: 28, 4700114208: 29, 4700124288: 30, 4700121648: 31, 4700111968: 32, 4700194608: 33, 4532207472: 34, 4699587840: 35, 4700199088: 36, 4700193568: 37, 4700196528: 38, 4700199888: 39, 4700207648: 40, 4700195328: 41, 4700207968: 42, 4700207728: 43, 4700205088: 44, 4700206928: 45, 4700208368: 46, 4700193088: 47, 4700204128: 48, 4700207088: 49, 4700203888: 50, 4700195568: 51, 4532478240: 52, 4700197968: 53, 4700209008: 54, 4700194208: 55, 4700200368: 56, 4700205328: 57, 4700193488: 58, 4700193328: 59}\"\n" ] } ], @@ -100,18 +100,17 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 13, "id": "ec743f9f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(AnalogCircuit(class_='AnalogCircuit', statements=[Declaration(class_='Declaration', name='r', value=QuantumRegister(class_='QuantumRegister', size=2)), Declaration(class_='Declaration', name='s', value=ModeRegister(class_='ModeRegister', size=3)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1)), Declaration(class_='Declaration', name='targets', value=AnalogList(class_='AnalogList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='tau', value=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=2), expr2=Access(class_='Access', name='pi'))), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phase', value=MathAdd(class_='MathAdd', expr1=MathVar(class_='MathVar', name='#phi'), expr2=MathMul(class_='MathMul', expr1=MathVar(class_='MathVar', name='#t'), expr2=Access(class_='Access', name='omega')))), Declaration(class_='Declaration', name='neg', value=MathNum(class_='MathNum', value=-1)), Declaration(class_='Declaration', name='cubed', value=MathNum(class_='MathNum', value=8)), Declaration(class_='Declaration', name='sine', value=MathFunc(class_='MathFunc', func='sin', expr=MathNum(class_='MathNum', value=0.5))), Declaration(class_='Declaration', name='cosed', value=MathFunc(class_='MathFunc', func='cos', expr=Access(class_='Access', name='phase'))), Declaration(class_='Declaration', name='cplx', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=1.0), expr2=MathMul(class_='MathMul', expr1=MathImag(class_='MathImag'), expr2=MathNum(class_='MathNum', value=0.5)))), Declaration(class_='Declaration', name='X', value=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=1), op2=PauliX(class_='PauliX'))), Declaration(class_='Declaration', name='Y', value=PauliY(class_='PauliY')), Declaration(class_='Declaration', name='Z', value=PauliZ(class_='PauliZ')), Declaration(class_='Declaration', name='I', value=PauliI(class_='PauliI')), Declaration(class_='Declaration', name='C', value=Creation(class_='Creation')), Declaration(class_='Declaration', name='A', value=Annihilation(class_='Annihilation')), Declaration(class_='Declaration', name='J', value=Identity(class_='Identity')), Declaration(class_='Declaration', name='H_single', value=OperatorAdd(class_='OperatorAdd', op1=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=0.5), op2=PauliX(class_='PauliX')), op2=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=0.5), op2=PauliZ(class_='PauliZ')))), Declaration(class_='Declaration', name='H_pair', value=OperatorAdd(class_='OperatorAdd', op1=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=1), op2=OperatorKron(class_='OperatorKron', op1=PauliI(class_='PauliI'), op2=PauliX(class_='PauliX'))), op2=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=1), op2=OperatorKron(class_='OperatorKron', op1=PauliX(class_='PauliX'), op2=PauliI(class_='PauliI'))))), Declaration(class_='Declaration', name='H_rabi', value=OperatorAdd(class_='OperatorAdd', op1=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=0.5), op2=OperatorKron(class_='OperatorKron', op1=PauliI(class_='PauliI'), op2=PauliY(class_='PauliY'))), op2=OperatorMul(class_='OperatorMul', op1=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=0.5), expr2=MathVar(class_='MathVar', name='#t')), op2=OperatorKron(class_='OperatorKron', op1=PauliX(class_='PauliX'), op2=PauliI(class_='PauliI'))))), Declaration(class_='Declaration', name='x', value=MathNum(class_='MathNum', value=1)), IfElse(class_='IfElse', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Initialize(class_='Initialize', targets=Access(class_='Access', name='r'))], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_single'), duration=MathNum(class_='MathNum', value=1.0), targets=Access(class_='Access', name='q0'))], else_branch=[Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_pair'), duration=MathNum(class_='MathNum', value=0.5), targets=Access(class_='Access', name='r'))]), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_rabi'), duration=MathNum(class_='MathNum', value=0.1), targets=Access(class_='Access', name='targets')), Declaration(class_='Declaration', name='n', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=-1), expr2=Access(class_='Access', name='n')))]), While(class_='While', condition=Bool(class_='Bool', value=True), body=[IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Break(class_='Break')], else_branch=[])]), Declaration(class_='Declaration', name='a', value=MathNum(class_='MathNum', value=5)), Declaration(class_='Declaration', name='b', value=MathNum(class_='MathNum', value=3)), IfElse(class_='IfElse', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='a'), expr2=Access(class_='Access', name='b')), then_branch=[IfElse(class_='IfElse', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='b'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Initialize(class_='Initialize', targets=Access(class_='Access', name='targets'))], else_branch=[Measure(class_='Measure', targets=Access(class_='Access', name='r'))])], else_branch=[]), Initialize(class_='Initialize', targets=Access(class_='Access', name='r')), Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_single'), duration=MathNum(class_='MathNum', value=2.0), targets=Access(class_='Access', name='q1')), Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_pair'), duration=MathNum(class_='MathNum', value=1.0), targets=Access(class_='Access', name='targets')), Evolve(class_='Evolve', hamiltonian=OperatorMul(class_='OperatorMul', op1=PauliX(class_='PauliX'), op2=MathNum(class_='MathNum', value=0.5)), duration=Access(class_='Access', name='pi'), targets=Access(class_='Access', name='q0')), Measure(class_='Measure', targets=Access(class_='Access', name='r')), Declaration(class_='Declaration', name='measurement', value=Measure(class_='Measure', targets=Access(class_='Access', name='q0'))), Declaration(class_='Declaration', name='flag', value=MathNum(class_='MathNum', value=1)), IfElse(class_='IfElse', condition=BoolNotEq(class_='BoolNotEq', expr1=Access(class_='Access', name='flag'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Declaration(class_='Declaration', name='x', value=MathNum(class_='MathNum', value=0))], else_branch=[]), IfElse(class_='IfElse', condition=BoolLessThanEq(class_='BoolLessThanEq', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Declaration(class_='Declaration', name='x', value=MathNum(class_='MathNum', value=1))], else_branch=[]), IfElse(class_='IfElse', condition=BoolGreaterThanEq(class_='BoolGreaterThanEq', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Declaration(class_='Declaration', name='x', value=MathNum(class_='MathNum', value=0))], else_branch=[]), Declaration(class_='Declaration', name='a', value=Bool(class_='Bool', value=True)), IfElse(class_='IfElse', condition=Access(class_='Access', name='a'), then_branch=[Declaration(class_='Declaration', name='b', value=MathNum(class_='MathNum', value=5))], else_branch=[])]),\n", - " (1, 0))" + "" ] }, - "execution_count": 6, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -122,7 +121,7 @@ " AnalogSymbolTableBuilder,\n", " AnalogTypeChecker,\n", ")\n", - "from oqd_core.compiler.analog.passes.compile import compile_analog_circuit\n", + "from oqd_core.compiler.analog.passes.compile import compile_analog_cfg\n", "\n", "with open(\"test.analog\", mode=\"r\", encoding=\"utf8\") as f:\n", " source = f.read()\n", @@ -133,7 +132,7 @@ "dataflow_result = type_checker.dataflow_result\n", "symbol_analysis = AnalogSymbolTableBuilder(cfg, dataflow_result)\n", "symbol_table = symbol_analysis.symbol_table\n", - "compile_analog_circuit(circuit, cfg, symbol_table)\n" + "compile_analog_cfg(cfg, symbol_table)" ] }, { @@ -146,19 +145,19 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 14, "id": "8303ca3d", "metadata": {}, "outputs": [], "source": [ - "# from oqd_core.compiler.analog.passes.compile import compile_analog_circuit\n", - "# out, (n_qreg, n_qmode) = compile_analog_circuit(circuit)\n", + "# from oqd_core.compiler.analog.passes.compile import compile_analog_cfg\n", + "# out = compile_analog_cfg(circuit)\n", "# print(printer(out))" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 15, "id": "b5a6b113", "metadata": {}, "outputs": [], diff --git a/examples/atomic/test.ipynb b/examples/atomic/test.ipynb index 161ee5ff..2a1c0f4d 100644 --- a/examples/atomic/test.ipynb +++ b/examples/atomic/test.ipynb @@ -171,7 +171,7 @@ { "data": { "text/plain": [ - "AtomicCircuit(class_='AtomicCircuit', statements=[Declaration(class_='Declaration', name='ions', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=1)), Declaration(class_='Declaration', name='targets', value=AtomicList(class_='AtomicList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phi', value=MathVar(class_='MathVar', name='#phi')), Declaration(class_='Declaration', name='t_gate', value=MathNum(class_='MathNum', value=1e-05)), Declaration(class_='Declaration', name='flag', value=Bool(class_='Bool', value=True)), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), Declaration(class_='Declaration', name='r', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='beam_mw', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=2000000.0), expr2=Access(class_='Access', name='pi')), rabi=Access(class_='Access', name='omega'), phase=Access(class_='Access', name='phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Declaration(class_='Declaration', name='beam_det', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=4000000.0), expr2=Access(class_='Access', name='pi')), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=Access(class_='Access', name='t_gate'), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=3e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))]), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=Access(class_='Access', name='t_gate'), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0), measured=Bool(class_='Bool', value=False)), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=3e-06), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), IfElse(class_='IfElse', condition=Access(class_='Access', name='flag'), then_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))])], else_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=2e-05), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=True))])]), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=1e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))])]), Declaration(class_='Declaration', name='n', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=-1), expr2=Access(class_='Access', name='n'))), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Continue(class_='Continue')], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Break(class_='Break')], else_branch=[])])])" + "" ] }, "execution_count": 5, @@ -182,7 +182,7 @@ "source": [ "from oqd_core.compiler.atomic.passes.compile import compile_atomic_circuit\n", "\n", - "compile_atomic_circuit(circuit, cfg, checker.dataflow_result, symbol_table)" + "compile_atomic_circuit(cfg, symbol_table)" ] } ], diff --git a/src/oqd_core/analysis/analog/cfg.py b/src/oqd_core/analysis/analog/cfg.py index b78456cb..cc4aabb0 100644 --- a/src/oqd_core/analysis/analog/cfg.py +++ b/src/oqd_core/analysis/analog/cfg.py @@ -34,8 +34,6 @@ def __init__(self): self.cache = {} self.loop_stack = [] self.preds = [] - self.founder = None - self.last_node = None self.edge_labels = None self.fallthrough_labels = {} @@ -83,9 +81,9 @@ def run(self, circuit: AnalogCircuit) -> ControlFlowGraph: self.loop_stack = [] self.edge_labels = None self.fallthrough_labels = {} - self.founder = self.new_node([], "start", kind="start") - exits = self.walk_stmt(circuit, [self.founder]) - self.last_node = self.new_node(exits, "stop", kind="stop") + founder = self.new_node([], "start", kind="start") + exits = self.walk_stmt(circuit, [founder]) + self.new_node(exits, "stop", kind="stop") return ControlFlowGraph(self.cache) def map_AnalogCircuit(self, model: AnalogCircuit): diff --git a/src/oqd_core/analysis/analog/type_checker.py b/src/oqd_core/analysis/analog/type_checker.py index 40e7acbb..b9fe5689 100644 --- a/src/oqd_core/analysis/analog/type_checker.py +++ b/src/oqd_core/analysis/analog/type_checker.py @@ -15,7 +15,7 @@ from __future__ import annotations -from oqd_compiler_infrastructure.dataflow import ForwardDataflowAnalysis +from oqd_compiler_infrastructure.dataflow import DataflowResult, ForwardDataflowAnalysis from oqd_compiler_infrastructure.lattice import LatticeBottom, maplattice from oqd_core.analysis.analog.semantics import AnalogSemantics @@ -25,7 +25,7 @@ TBool, TypeEnv, ) -from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.analysis.utils.control_flow import Block, ControlFlowGraph from oqd_core.interface.analog import Break, Continue, Declaration @@ -35,9 +35,9 @@ def __init__(self, graph: ControlFlowGraph) -> None: self.value_lattice = AnalogTypeLattice() self.semantics = AnalogSemantics(self.value_lattice) self.lattice = maplattice(AnalogTypeLattice)() - self.blocks = graph.blocks + self.blocks: dict[int, Block] = graph.blocks - self.dataflow_result = self.analyze(graph, self.merge_union) + self.dataflow_result: DataflowResult = self.analyze(graph, self.merge_union) def transfer(self, node_id: int, state_in: TypeEnv) -> TypeEnv: env = {} if state_in is LatticeBottom else dict(state_in) diff --git a/src/oqd_core/analysis/atomic/cfg.py b/src/oqd_core/analysis/atomic/cfg.py index 5d71db63..0e28a2b6 100644 --- a/src/oqd_core/analysis/atomic/cfg.py +++ b/src/oqd_core/analysis/atomic/cfg.py @@ -36,8 +36,6 @@ def __init__(self): self.cache = {} self.loop_stack = [] self.preds = [] - self.founder = None - self.last_node = None self.edge_labels = None self.fallthrough_labels = {} @@ -85,9 +83,9 @@ def run(self, circuit: AtomicCircuit) -> ControlFlowGraph: self.loop_stack = [] self.edge_labels = None self.fallthrough_labels = {} - self.founder = self.new_node([], "start", kind="start") - exits = self.walk_stmt(circuit, [self.founder]) - self.last_node = self.new_node(exits, "stop", kind="stop") + founder = self.new_node([], "start", kind="start") + exits = self.walk_stmt(circuit, [founder]) + self.new_node(exits, "stop", kind="stop") return ControlFlowGraph(self.cache) def map_AtomicCircuit(self, model: AtomicCircuit): diff --git a/src/oqd_core/analysis/utils/control_flow.py b/src/oqd_core/analysis/utils/control_flow.py index 1ced14b0..f922b6a8 100644 --- a/src/oqd_core/analysis/utils/control_flow.py +++ b/src/oqd_core/analysis/utils/control_flow.py @@ -52,13 +52,12 @@ def successors(self, node: int) -> Iterable[int]: class Block: """Represents one control flow node with incoming / outgoing edges and metadata.""" def __init__(self, register_id: int, stmt: object, preds: Iterable[Block] | None = None, \ - kind: str = "stmt", scope: int = 0) -> None: + kind: str = "stmt") -> None: self.register_id = register_id self.stmt = stmt self.preds = list(preds) if preds is not None else [] self.succs = [] self.kind = kind - self.scope = scope self.exit_nodes = [] self.edge_labels = {} @@ -76,25 +75,4 @@ def add_pred(self, pred: Block, label: str | None = None) -> None: def add_preds(self, preds: Iterable[Block], label: str | None = None) -> None: for pred in preds: self.add_pred(pred, label=label) - - def to_dict(self) -> dict[str, object]: - if isinstance(self.stmt, str): - stmt_repr = self.stmt - elif hasattr(self.stmt, "class_"): - stmt_repr = self.stmt.class_ - else: - stmt_repr = type(self.stmt).__name__ - return { - "id": self.register_id, - "kind": self.kind, - "scope": self.scope, - "stmt": stmt_repr, - "preds": [p.register_id for p in self.preds], - "succs": [c.register_id for c in self.succs], - "edges": [ - {"to": c.register_id, "label": self.edge_labels.get(c.register_id)} - for c in self.succs - ], - "exit_nodes": [n.register_id for n in self.exit_nodes], - } diff --git a/src/oqd_core/compiler/analog/passes/__init__.py b/src/oqd_core/compiler/analog/passes/__init__.py index 568923d2..eeaa7713 100644 --- a/src/oqd_core/compiler/analog/passes/__init__.py +++ b/src/oqd_core/compiler/analog/passes/__init__.py @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .compile import compile_analog_circuit +from .compile import compile_analog_cfg from .assign import infer_analog_circuit_dim_cfg __all__ = [ - "compile_analog_circuit", + "compile_analog_cfg", "infer_analog_circuit_dim_cfg", ] diff --git a/src/oqd_core/compiler/analog/passes/compile.py b/src/oqd_core/compiler/analog/passes/compile.py index 92c52b6b..a2e9381e 100644 --- a/src/oqd_core/compiler/analog/passes/compile.py +++ b/src/oqd_core/compiler/analog/passes/compile.py @@ -19,11 +19,10 @@ from oqd_core.compiler.analog.verify.passes import verify_analog_args_dim, verify_hamiltonian_target_dim, verify_register_access_dim from oqd_core.analysis.analog.symbol_table import AnalogSymbolTable from oqd_core.analysis.utils.control_flow import ControlFlowGraph -from oqd_core.interface.analog import AnalogCircuit ######################################################################################## -__all__ = [ "compile_analog_circuit" ] +__all__ = [ "compile_analog_cfg" ] ######################################################################################## @@ -34,7 +33,7 @@ def canonicalize_args_metrics(args): metric.operator = canonicalize_operator_expr(metric.operator) -def compile_analog_circuit(model: AnalogCircuit, cfg: ControlFlowGraph, symbol_table: AnalogSymbolTable, args=None): +def compile_analog_cfg(cfg: ControlFlowGraph, symbol_table: AnalogSymbolTable, args=None) -> ControlFlowGraph: canonicalize_operators_cfg(cfg) canonicalize_math_cfg(cfg) @@ -47,5 +46,5 @@ def compile_analog_circuit(model: AnalogCircuit, cfg: ControlFlowGraph, symbol_t canonicalize_args_metrics(args) verify_analog_args_dim(args, n_qreg, n_qmode) - return model, (n_qreg, n_qmode) + return cfg diff --git a/src/oqd_core/compiler/atomic/canonicalize.py b/src/oqd_core/compiler/atomic/canonicalize.py index 35dfa032..228b35cf 100644 --- a/src/oqd_core/compiler/atomic/canonicalize.py +++ b/src/oqd_core/compiler/atomic/canonicalize.py @@ -48,8 +48,6 @@ class ResolveNestedProtocol(RewriteRule): def __init__(self): super().__init__() - self.durations = [] - @classmethod def _get_continuous_duration(cls, model): if isinstance(model, ParallelProtocol): diff --git a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py index 3fecfe62..8de33539 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/__init__.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/__init__.py @@ -1,8 +1,6 @@ from .walk import iter_stmt_blocks, canonicalize_declarations_cfg -from .resolve import resolve_scalar_expr __all__ = [ "iter_stmt_blocks", "canonicalize_declarations_cfg", - "resolve_scalar_expr", ] diff --git a/src/oqd_core/compiler/atomic/cfg_passes/protocol.py b/src/oqd_core/compiler/atomic/cfg_passes/protocol.py index 01254ebe..92f5ed11 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/protocol.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/protocol.py @@ -20,13 +20,10 @@ from oqd_core.compiler.atomic.math.rules import _is_constant_math from oqd_core.compiler.atomic.verify.passes import iter_pulses from oqd_core.interface.atomic import ( - AtomicCircuit, Declaration, ParallelProtocol, Pulse, SerialProtocol, - IfElse, - While, ) PROTOCOL_TYPES = (Pulse, ParallelProtocol, SerialProtocol) @@ -40,30 +37,12 @@ def apply_protocol_passes(stmt): return stmt -def canonicalize_protocol_tree(stmt): - if isinstance(stmt, IfElse): - stmt.then_branch = [canonicalize_protocol_tree(s) for s in stmt.then_branch] - stmt.else_branch = [canonicalize_protocol_tree(s) for s in stmt.else_branch] - return stmt - if isinstance(stmt, While): - stmt.body = [canonicalize_protocol_tree(s) for s in stmt.body] - return stmt - if isinstance(stmt, Declaration) and isinstance(stmt.value, PROTOCOL_TYPES): - stmt.value = apply_protocol_passes(stmt.value) - return stmt - if isinstance(stmt, PROTOCOL_TYPES): - return apply_protocol_passes(stmt) - return stmt - - -def canonicalize_protocol_cfg(cfg: ControlFlowGraph, model: AtomicCircuit) -> ControlFlowGraph: - old_top = list(model.statements) - model.statements = [canonicalize_protocol_tree(s) for s in model.statements] - - for old, new in zip(old_top, model.statements): - if old is not new: - for _, block in iter_stmt_blocks(cfg): - if block.stmt is old: - block.stmt = new +def canonicalize_protocol_cfg(cfg: ControlFlowGraph) -> ControlFlowGraph: + for _, block in iter_stmt_blocks(cfg): + stmt = block.stmt + if isinstance(stmt, Declaration) and isinstance(stmt.value, PROTOCOL_TYPES): + stmt.value = apply_protocol_passes(stmt.value) + elif isinstance(stmt, PROTOCOL_TYPES): + block.stmt = apply_protocol_passes(stmt) return cfg diff --git a/src/oqd_core/compiler/atomic/cfg_passes/walk.py b/src/oqd_core/compiler/atomic/cfg_passes/walk.py index 75a5bbd7..78dcbdf2 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/walk.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/walk.py @@ -19,15 +19,12 @@ from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.math.passes import canonicalize_math_expr from oqd_core.interface.atomic import ( - AtomicList, Beam, Pulse, Bool, + Declaration, ) -from oqd_core.interface.atomic.expr import AtomicExpr -from oqd_core.analysis.atomic.types import TBeam, TScalar, TypeEnv, TPulse -from oqd_core.interface.atomic import Declaration -from oqd_compiler_infrastructure.dataflow import DataflowResult +from oqd_core.interface.atomic.expr import MathExpr def iter_stmt_blocks(cfg: ControlFlowGraph): for node_id, block in cfg.blocks.items(): @@ -35,50 +32,46 @@ def iter_stmt_blocks(cfg: ControlFlowGraph): continue yield node_id, block -def canonicalize_expr(expr): - if isinstance(expr, (Beam, Pulse)): +def canonicalize_scalar_expr(expr): + if isinstance(expr, Bool): return expr - if isinstance(expr, AtomicExpr): - return canonicalize_math_expr(expr) - return expr + return canonicalize_math_expr(expr) def canonicalize_beam(beam: Beam) -> Beam: - beam.frequency = canonicalize_expr(beam.frequency) - beam.rabi = canonicalize_expr(beam.rabi) - beam.phase = canonicalize_expr(beam.phase) - beam.polarization = canonicalize_expr(beam.polarization) - beam.wavevector = canonicalize_expr(beam.wavevector) + beam.frequency = canonicalize_scalar_expr(beam.frequency) + beam.rabi = canonicalize_scalar_expr(beam.rabi) + beam.phase = canonicalize_scalar_expr(beam.phase) + beam.polarization = canonicalize_scalar_expr(beam.polarization) + beam.wavevector = canonicalize_scalar_expr(beam.wavevector) return beam -def canonicalize_atomic_list(values: AtomicList) -> AtomicList: - values.values = [canonicalize_expr(v) for v in values.values] - return values - - -def canonicalize_scalar_expr(expr): - if isinstance(expr, Bool): - return expr - return canonicalize_math_expr(expr) +def canonicalize_pulse(pulse: Pulse) -> Pulse: + pulse.duration = canonicalize_scalar_expr(pulse.duration) + if isinstance(pulse.beam, Beam): + pulse.beam = canonicalize_beam(pulse.beam) + return pulse + +def canonicalize_declarations(expr): + if isinstance(expr, Beam): + return canonicalize_beam(expr) + if isinstance(expr, Pulse): + return canonicalize_pulse(expr) + if isinstance(expr, MathExpr): + return canonicalize_math_expr(expr) + return expr + -def canonicalize_declarations_cfg( - cfg: ControlFlowGraph, - type_result: DataflowResult[int, TypeEnv], -) -> ControlFlowGraph: +def canonicalize_declarations_cfg(cfg: ControlFlowGraph) -> ControlFlowGraph: - for node_id, block in iter_stmt_blocks(cfg): + for _, block in iter_stmt_blocks(cfg): stmt = block.stmt - if not isinstance(stmt, Declaration): - continue - t = type_result.out_states[node_id].get(stmt.name) - if t is TScalar: - stmt.value = canonicalize_scalar_expr(stmt.value) - elif t is TBeam: - stmt.value = canonicalize_beam(stmt.value) - elif t is TPulse: - pulse = stmt.value - pulse.duration = canonicalize_scalar_expr(pulse.duration) - if isinstance(pulse.beam, Beam): - pulse.beam = canonicalize_beam(pulse.beam) + if block.kind == "branch": + if isinstance(stmt, MathExpr): + block.stmt = canonicalize_math_expr(stmt) + return + + if isinstance(stmt, Declaration): + stmt.value = canonicalize_declarations(stmt.value) return cfg diff --git a/src/oqd_core/compiler/atomic/passes/compile.py b/src/oqd_core/compiler/atomic/passes/compile.py index f299fe48..b9cb700e 100644 --- a/src/oqd_core/compiler/atomic/passes/compile.py +++ b/src/oqd_core/compiler/atomic/passes/compile.py @@ -12,27 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -from oqd_compiler_infrastructure.dataflow import DataflowResult from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable -from oqd_core.analysis.atomic.types import TypeEnv from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_declarations_cfg from oqd_core.compiler.atomic.cfg_passes.protocol import canonicalize_protocol_cfg from oqd_core.compiler.atomic.verify.passes import verify_pulse_target_dim -from oqd_core.interface.atomic import AtomicCircuit __all__ = ["compile_atomic_circuit"] def compile_atomic_circuit( - model: AtomicCircuit, cfg: ControlFlowGraph, - type_result: DataflowResult[int, TypeEnv], symbol_table: AtomicSymbolTable, ): - canonicalize_declarations_cfg(cfg, type_result) - canonicalize_protocol_cfg(cfg, model) + canonicalize_declarations_cfg(cfg) + canonicalize_protocol_cfg(cfg) verify_pulse_target_dim(cfg, symbol_table) - - return model + return cfg From 57e19ce3508ade3342bb54fe843a2b40dde6613d Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Thu, 9 Jul 2026 18:14:14 -0400 Subject: [PATCH 15/20] feat: Add visualization for CFG --- examples/analog/test.ipynb | 192 ++++++++++++++++--- examples/atomic/test.ipynb | 121 +++++++++++- pyproject.toml | 1 + src/oqd_core/analysis/utils/__init__.py | 2 + src/oqd_core/analysis/utils/visualization.py | 38 ++++ uv.lock | 11 ++ 6 files changed, 337 insertions(+), 28 deletions(-) create mode 100644 src/oqd_core/analysis/utils/visualization.py diff --git a/examples/analog/test.ipynb b/examples/analog/test.ipynb index 93b46e76..d86254cc 100644 --- a/examples/analog/test.ipynb +++ b/examples/analog/test.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 9, + "execution_count": 1, "id": "b527eaca", "metadata": {}, "outputs": [ @@ -31,7 +31,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 2, "id": "1c5481c1", "metadata": {}, "outputs": [], @@ -54,7 +54,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 3, "id": "08b33d2c", "metadata": {}, "outputs": [ @@ -75,7 +75,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 4, "id": "f628d79e", "metadata": {}, "outputs": [ @@ -83,7 +83,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4700091040: 1, 4699968992: 2, 4532353488: 3, 4699943264: 4, 4699571456: 5, 4533652048: 6, 4699937344: 7, 4699940864: 8, 4699925680: 9, 4700120848: 10, 4700126608: 11, 4700124528: 12, 4700126528: 13, 4700114368: 14, 4533662368: 15, 4700126048: 16, 4699983216: 17, 4700111168: 18, 4700113808: 19, 4700114768: 20, 4699724912: 21, 4699892352: 22, 4700126768: 23, 4700123248: 24, 4700115088: 25, 4700125808: 26, 4700117648: 27, 4700087360: 28, 4700114208: 29, 4700124288: 30, 4700121648: 31, 4700111968: 32, 4700194608: 33, 4532207472: 34, 4699587840: 35, 4700199088: 36, 4700193568: 37, 4700196528: 38, 4700199888: 39, 4700207648: 40, 4700195328: 41, 4700207968: 42, 4700207728: 43, 4700205088: 44, 4700206928: 45, 4700208368: 46, 4700193088: 47, 4700204128: 48, 4700207088: 49, 4700203888: 50, 4700195568: 51, 4532478240: 52, 4700197968: 53, 4700209008: 54, 4700194208: 55, 4700200368: 56, 4700205328: 57, 4700193488: 58, 4700193328: 59}\"\n" + "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4678829792: 1, 4672233200: 2, 4678830512: 3, 4678837312: 4, 4678831792: 5, 4678833552: 6, 4678840752: 7, 4678840832: 8, 4678832912: 9, 4678836832: 10, 4678839392: 11, 4678832352: 12, 4678838432: 13, 4678842192: 14, 4678842352: 15, 4678842512: 16, 4678842672: 17, 4678842832: 18, 4678842992: 19, 4678843152: 20, 4678843312: 21, 4691607632: 22, 4691608752: 23, 4691610032: 24, 4691610192: 25, 4691610432: 26, 4691610752: 27, 4691611152: 28, 4691611632: 29, 4691611952: 30, 4691612192: 31, 4691612432: 32, 4691612752: 33, 4691613072: 34, 4691613392: 35, 4691613712: 36, 4691613632: 37, 4691614032: 38, 4691614192: 39, 4691614432: 40, 4691614672: 41, 4691614832: 42, 4691614992: 43, 4691615392: 44, 4691615712: 45, 4691616032: 46, 4691616512: 47, 4691616672: 48, 4691616912: 49, 4691617072: 50, 4691617312: 51, 4691617552: 52, 4691617792: 53, 4691618112: 54, 4691618352: 55, 4691618672: 56, 4691618992: 57, 4691618912: 58, 4691619152: 59}\"\n" ] } ], @@ -100,21 +100,10 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 5, "id": "ec743f9f", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "from oqd_core.analysis.analog import (\n", " AnalogCFGBuilder,\n", @@ -132,7 +121,7 @@ "dataflow_result = type_checker.dataflow_result\n", "symbol_analysis = AnalogSymbolTableBuilder(cfg, dataflow_result)\n", "symbol_table = symbol_analysis.symbol_table\n", - "compile_analog_cfg(cfg, symbol_table)" + "cfg = compile_analog_cfg(cfg, symbol_table)" ] }, { @@ -140,12 +129,169 @@ "execution_count": null, "id": "34b5e170", "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "digraph {\n", + "\t0 [label=\"0: start\\nstr\"]\n", + "\t0 -> 1\n", + "\t1 [label=\"1: stmt\\nr = ...\"]\n", + "\t1 -> 2\n", + "\t2 [label=\"2: stmt\\ns = ...\"]\n", + "\t2 -> 3\n", + "\t3 [label=\"3: stmt\\nq0 = ...\"]\n", + "\t3 -> 4\n", + "\t4 [label=\"4: stmt\\nq1 = ...\"]\n", + "\t4 -> 5\n", + "\t5 [label=\"5: stmt\\ntargets = ...\"]\n", + "\t5 -> 6\n", + "\t6 [label=\"6: stmt\\npi = ...\"]\n", + "\t6 -> 7\n", + "\t7 [label=\"7: stmt\\ntau = ...\"]\n", + "\t7 -> 8\n", + "\t8 [label=\"8: stmt\\nomega = ...\"]\n", + "\t8 -> 9\n", + "\t9 [label=\"9: stmt\\nphase = ...\"]\n", + "\t9 -> 10\n", + "\t10 [label=\"10: stmt\\nneg = ...\"]\n", + "\t10 -> 11\n", + "\t11 [label=\"11: stmt\\ncubed = ...\"]\n", + "\t11 -> 12\n", + "\t12 [label=\"12: stmt\\nsine = ...\"]\n", + "\t12 -> 13\n", + "\t13 [label=\"13: stmt\\ncosed = ...\"]\n", + "\t13 -> 14\n", + "\t14 [label=\"14: stmt\\ncplx = ...\"]\n", + "\t14 -> 15\n", + "\t15 [label=\"15: stmt\\nX = ...\"]\n", + "\t15 -> 16\n", + "\t16 [label=\"16: stmt\\nY = ...\"]\n", + "\t16 -> 17\n", + "\t17 [label=\"17: stmt\\nZ = ...\"]\n", + "\t17 -> 18\n", + "\t18 [label=\"18: stmt\\nI = ...\"]\n", + "\t18 -> 19\n", + "\t19 [label=\"19: stmt\\nC = ...\"]\n", + "\t19 -> 20\n", + "\t20 [label=\"20: stmt\\nA = ...\"]\n", + "\t20 -> 21\n", + "\t21 [label=\"21: stmt\\nJ = ...\"]\n", + "\t21 -> 22\n", + "\t22 [label=\"22: stmt\\nH_single = ...\"]\n", + "\t22 -> 23\n", + "\t23 [label=\"23: stmt\\nH_pair = ...\"]\n", + "\t23 -> 24\n", + "\t24 [label=\"24: stmt\\nH_rabi = ...\"]\n", + "\t24 -> 25\n", + "\t25 [label=\"25: stmt\\nx = ...\"]\n", + "\t25 -> 26\n", + "\t26 [label=\"26: branch\\nBoolGreaterThan\"]\n", + "\t26 -> 27\n", + "\t26 -> 28\n", + "\t27 [label=\"27: stmt\\nInitialize\"]\n", + "\t27 -> 28\n", + "\t28 [label=\"28: branch\\nBoolEq\"]\n", + "\t28 -> 29\n", + "\t28 -> 30\n", + "\t29 [label=\"29: stmt\\nEvolve\"]\n", + "\t29 -> 31\n", + "\t30 [label=\"30: stmt\\nEvolve\"]\n", + "\t30 -> 31\n", + "\t31 [label=\"31: stmt\\nn = ...\"]\n", + "\t31 -> 32\n", + "\t32 [label=\"32: branch\\nBoolGreaterThan\"]\n", + "\t32 -> 33\n", + "\t32 -> 35\n", + "\t33 [label=\"33: stmt\\nEvolve\"]\n", + "\t33 -> 34\n", + "\t34 [label=\"34: stmt\\nn = ...\"]\n", + "\t34 -> 32\n", + "\t35 [label=\"35: branch\\nBool\"]\n", + "\t35 -> 36\n", + "\t35 -> 38\n", + "\t36 [label=\"36: branch\\nBoolEq\"]\n", + "\t36 -> 37\n", + "\t36 -> 35\n", + "\t37 [label=\"37: stmt\\nBreak\"]\n", + "\t37 -> 38\n", + "\t38 [label=\"38: stmt\\na = ...\"]\n", + "\t38 -> 39\n", + "\t39 [label=\"39: stmt\\nb = ...\"]\n", + "\t39 -> 40\n", + "\t40 [label=\"40: branch\\nBoolGreaterThan\"]\n", + "\t40 -> 41\n", + "\t40 -> 44\n", + "\t41 [label=\"41: branch\\nBoolGreaterThan\"]\n", + "\t41 -> 42\n", + "\t41 -> 43\n", + "\t42 [label=\"42: stmt\\nInitialize\"]\n", + "\t42 -> 44\n", + "\t43 [label=\"43: stmt\\nMeasure\"]\n", + "\t43 -> 44\n", + "\t44 [label=\"44: stmt\\nInitialize\"]\n", + "\t44 -> 45\n", + "\t45 [label=\"45: stmt\\nEvolve\"]\n", + "\t45 -> 46\n", + "\t46 [label=\"46: stmt\\nEvolve\"]\n", + "\t46 -> 47\n", + "\t47 [label=\"47: stmt\\nEvolve\"]\n", + "\t47 -> 48\n", + "\t48 [label=\"48: stmt\\nMeasure\"]\n", + "\t48 -> 49\n", + "\t49 [label=\"49: stmt\\nmeasurement = ...\"]\n", + "\t49 -> 50\n", + "\t50 [label=\"50: stmt\\nflag = ...\"]\n", + "\t50 -> 51\n", + "\t51 [label=\"51: branch\\nBoolNotEq\"]\n", + "\t51 -> 52\n", + "\t51 -> 53\n", + "\t52 [label=\"52: stmt\\nx = ...\"]\n", + "\t52 -> 53\n", + "\t53 [label=\"53: branch\\nBoolLessThanEq\"]\n", + "\t53 -> 54\n", + "\t53 -> 55\n", + "\t54 [label=\"54: stmt\\nx = ...\"]\n", + "\t54 -> 55\n", + "\t55 [label=\"55: branch\\nBoolGreaterThanEq\"]\n", + "\t55 -> 56\n", + "\t55 -> 57\n", + "\t56 [label=\"56: stmt\\nx = ...\"]\n", + "\t56 -> 57\n", + "\t57 [label=\"57: stmt\\na = ...\"]\n", + "\t57 -> 58\n", + "\t58 [label=\"58: branch\\nAccess\"]\n", + "\t58 -> 59\n", + "\t58 -> 60\n", + "\t59 [label=\"59: stmt\\nb = ...\"]\n", + "\t59 -> 60\n", + "\t60 [label=\"60: stop\\nstr\"]\n", + "}\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "'cfg.png'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from oqd_core.analysis.utils import cfg_to_dot\n", + "dot = cfg_to_dot(cfg)\n", + "print(dot.source)\n", + "dot.render(\"cfg\", format=\"png\", cleanup=True)\n" + ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 7, "id": "8303ca3d", "metadata": {}, "outputs": [], @@ -157,7 +303,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 8, "id": "b5a6b113", "metadata": {}, "outputs": [], diff --git a/examples/atomic/test.ipynb b/examples/atomic/test.ipynb index 2a1c0f4d..f32726fa 100644 --- a/examples/atomic/test.ipynb +++ b/examples/atomic/test.ipynb @@ -167,22 +167,133 @@ "execution_count": 5, "id": "9314af17", "metadata": {}, + "outputs": [], + "source": [ + "from oqd_core.compiler.atomic.passes.compile import compile_atomic_circuit\n", + "\n", + "cfg = compile_atomic_circuit(cfg, symbol_table)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "26c77ff2", + "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "digraph {\n", + "\t0 [label=\"0: start\\nstr\"]\n", + "\t0 -> 1\n", + "\t1 [label=\"1: stmt\\nions = ...\"]\n", + "\t1 -> 2\n", + "\t2 [label=\"2: stmt\\nq0 = ...\"]\n", + "\t2 -> 3\n", + "\t3 [label=\"3: stmt\\nq1 = ...\"]\n", + "\t3 -> 4\n", + "\t4 [label=\"4: stmt\\ntargets = ...\"]\n", + "\t4 -> 5\n", + "\t5 [label=\"5: stmt\\npi = ...\"]\n", + "\t5 -> 6\n", + "\t6 [label=\"6: stmt\\nomega = ...\"]\n", + "\t6 -> 7\n", + "\t7 [label=\"7: stmt\\nphi = ...\"]\n", + "\t7 -> 8\n", + "\t8 [label=\"8: stmt\\nt_gate = ...\"]\n", + "\t8 -> 9\n", + "\t9 [label=\"9: stmt\\nflag = ...\"]\n", + "\t9 -> 10\n", + "\t10 [label=\"10: stmt\\nn = ...\"]\n", + "\t10 -> 11\n", + "\t11 [label=\"11: stmt\\nr = ...\"]\n", + "\t11 -> 12\n", + "\t12 [label=\"12: stmt\\nbeam_mw = ...\"]\n", + "\t12 -> 13\n", + "\t13 [label=\"13: stmt\\nbeam_det = ...\"]\n", + "\t13 -> 14\n", + "\t14 [label=\"14: stmt\\nPulse\"]\n", + "\t14 -> 15\n", + "\t15 [label=\"15: stmt\\nSerialProtocol(1)\"]\n", + "\t15 -> 16\n", + "\t16 [label=\"16: stmt\\nSerialProtocol(1)\"]\n", + "\t16 -> 17\n", + "\t17 [label=\"17: stmt\\nPulse\"]\n", + "\t17 -> 18\n", + "\t18 [label=\"18: stmt\\nSerialProtocol(1)\"]\n", + "\t18 -> 19\n", + "\t19 [label=\"19: stmt\\nSerialProtocol(1)\"]\n", + "\t19 -> 20\n", + "\t20 [label=\"20: stmt\\nSerialProtocol(1)\"]\n", + "\t20 -> 21\n", + "\t21 [label=\"21: stmt\\nSerialProtocol(1)\"]\n", + "\t21 -> 22\n", + "\t22 [label=\"22: stmt\\nSerialProtocol(2)\"]\n", + "\t22 -> 23\n", + "\t23 [label=\"23: stmt\\nSerialProtocol(1)\"]\n", + "\t23 -> 24\n", + "\t24 [label=\"24: stmt\\nSerialProtocol(1)\"]\n", + "\t24 -> 25\n", + "\t25 [label=\"25: stmt\\nSerialProtocol(2)\"]\n", + "\t25 -> 26\n", + "\t26 [label=\"26: stmt\\nSerialProtocol(2)\"]\n", + "\t26 -> 27\n", + "\t27 [label=\"27: stmt\\nSerialProtocol(1)\"]\n", + "\t27 -> 28\n", + "\t28 [label=\"28: stmt\\nSerialProtocol(1)\"]\n", + "\t28 -> 29\n", + "\t29 [label=\"29: stmt\\nSerialProtocol(1)\"]\n", + "\t29 -> 30\n", + "\t30 [label=\"30: stmt\\nSerialProtocol(1)\"]\n", + "\t30 -> 31\n", + "\t31 [label=\"31: branch\\nAccess\"]\n", + "\t31 -> 32\n", + "\t31 -> 33\n", + "\t32 [label=\"32: stmt\\nSerialProtocol(1)\"]\n", + "\t32 -> 34\n", + "\t33 [label=\"33: stmt\\nSerialProtocol(1)\"]\n", + "\t33 -> 34\n", + "\t34 [label=\"34: branch\\nBoolGreaterThan\"]\n", + "\t34 -> 35\n", + "\t34 -> 42\n", + "\t35 [label=\"35: stmt\\nSerialProtocol(1)\"]\n", + "\t35 -> 36\n", + "\t36 [label=\"36: stmt\\nSerialProtocol(1)\"]\n", + "\t36 -> 37\n", + "\t37 [label=\"37: stmt\\nn = ...\"]\n", + "\t37 -> 38\n", + "\t38 [label=\"38: branch\\nBoolEq\"]\n", + "\t38 -> 39\n", + "\t38 -> 40\n", + "\t39 [label=\"39: stmt\\nContinue\"]\n", + "\t39 -> 34\n", + "\t40 [label=\"40: branch\\nBoolEq\"]\n", + "\t40 -> 41\n", + "\t40 -> 34\n", + "\t41 [label=\"41: stmt\\nBreak\"]\n", + "\t41 -> 42\n", + "\t42 [label=\"42: stop\\nstr\"]\n", + "}\n", + "\n" + ] + }, { "data": { "text/plain": [ - "" + "'cfg.png'" ] }, - "execution_count": 5, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "from oqd_core.compiler.atomic.passes.compile import compile_atomic_circuit\n", - "\n", - "compile_atomic_circuit(cfg, symbol_table)" + "from oqd_core.analysis.utils import cfg_to_dot\n", + "dot = cfg_to_dot(cfg)\n", + "print(dot.source)\n", + "dot.render(\"cfg\", format=\"png\", cleanup=True)" ] } ], diff --git a/pyproject.toml b/pyproject.toml index 839804e2..2cad3258 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ dependencies = [ "markdown-extensions>=0.0.1", "mdx-truly-sane-lists>=1.3", "mkdocstrings[python]>=0.30.0", + "graphviz>=0.21", ] [project.optional-dependencies] diff --git a/src/oqd_core/analysis/utils/__init__.py b/src/oqd_core/analysis/utils/__init__.py index 3a8a8d0c..2458657a 100644 --- a/src/oqd_core/analysis/utils/__init__.py +++ b/src/oqd_core/analysis/utils/__init__.py @@ -1,8 +1,10 @@ from .control_flow import Block, ControlFlowGraph, alias_types +from .visualization import cfg_to_dot ######################################################################################## __all__ = [ "alias_types", "ControlFlowGraph", "Block", + "cfg_to_dot", ] diff --git a/src/oqd_core/analysis/utils/visualization.py b/src/oqd_core/analysis/utils/visualization.py new file mode 100644 index 00000000..58385fe6 --- /dev/null +++ b/src/oqd_core/analysis/utils/visualization.py @@ -0,0 +1,38 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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 graphviz + +from oqd_core.analysis.utils import ControlFlowGraph + + +def cfg_to_dot(cfg: ControlFlowGraph) -> graphviz.Digraph: + dot = graphviz.Digraph() + + for node_id, block in sorted(cfg.blocks.items()): + stmt_label = getattr(block.stmt, "class__", type(block.stmt).__name__) + if stmt_label == "Declaration": + stmt_label = f"{block.stmt.name} = ..." + if stmt_label in ("ParallelProtocol", "SerialProtocol"): + stmt_label = f"{stmt_label}({len(block.stmt.pulses)})" + label = ( + f"{node_id}: {block.kind}\\n" + f"{stmt_label}" + ) + dot.node(str(node_id), label) + + for succ in block.succs: + dot.edge(str(node_id), str(succ.register_id)) + + return dot diff --git a/uv.lock b/uv.lock index 4cbbe59e..a4a98cc1 100644 --- a/uv.lock +++ b/uv.lock @@ -542,6 +542,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619", size = 11034, upload-time = "2022-05-02T15:47:14.552Z" }, ] +[[package]] +name = "graphviz" +version = "0.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b3/3ac91e9be6b761a4b30d66ff165e54439dcd48b83f4e20d644867215f6ca/graphviz-0.21.tar.gz", hash = "sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78", size = 200434, upload-time = "2025-06-15T09:35:05.824Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl", hash = "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42", size = 47300, upload-time = "2025-06-15T09:35:04.433Z" }, +] + [[package]] name = "griffe" version = "1.13.0" @@ -1570,6 +1579,7 @@ source = { editable = "." } dependencies = [ { name = "antlr4-python3-runtime" }, { name = "antlr4-tools" }, + { name = "graphviz" }, { name = "markdown" }, { name = "markdown-extensions" }, { name = "mdx-truly-sane-lists" }, @@ -1610,6 +1620,7 @@ dev = [ requires-dist = [ { name = "antlr4-python3-runtime", specifier = ">=4.13.2" }, { name = "antlr4-tools", specifier = ">=0.2.2" }, + { name = "graphviz", specifier = ">=0.21" }, { name = "markdown", specifier = ">=3.8.2" }, { name = "markdown-extensions", specifier = ">=0.0.1" }, { name = "mdx-truly-sane-lists", specifier = ">=1.3" }, From 05af9d4fa360552dc6a39e3af0ddd09d3d309eb8 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Fri, 10 Jul 2026 14:23:42 -0400 Subject: [PATCH 16/20] clean: Use pydantic for control flow graph and blocks --- src/oqd_core/analysis/analog/cfg.py | 13 ++-- src/oqd_core/analysis/analog/symbol_table.py | 4 +- src/oqd_core/analysis/analog/type_checker.py | 9 ++- src/oqd_core/analysis/atomic/cfg.py | 13 ++-- src/oqd_core/analysis/atomic/symbol_table.py | 4 +- src/oqd_core/analysis/atomic/type_checker.py | 6 +- src/oqd_core/analysis/atomic/types.py | 6 +- src/oqd_core/analysis/utils/control_flow.py | 67 +++++++++++++------ .../compiler/analog/cfg_passes/walk.py | 4 +- .../compiler/atomic/cfg_passes/walk.py | 4 +- 10 files changed, 83 insertions(+), 47 deletions(-) diff --git a/src/oqd_core/analysis/analog/cfg.py b/src/oqd_core/analysis/analog/cfg.py index cc4aabb0..66c13397 100644 --- a/src/oqd_core/analysis/analog/cfg.py +++ b/src/oqd_core/analysis/analog/cfg.py @@ -17,7 +17,12 @@ from oqd_compiler_infrastructure import RewriteRule -from oqd_core.analysis.utils.control_flow import Block, ControlFlowGraph +from oqd_core.analysis.utils.control_flow import ( + Block, + CFGStart, + CFGStop, + ControlFlowGraph, +) from oqd_core.interface.analog import ( AnalogCircuit, Break, @@ -81,10 +86,10 @@ def run(self, circuit: AnalogCircuit) -> ControlFlowGraph: self.loop_stack = [] self.edge_labels = None self.fallthrough_labels = {} - founder = self.new_node([], "start", kind="start") + founder = self.new_node([], CFGStart(), kind="start") exits = self.walk_stmt(circuit, [founder]) - self.new_node(exits, "stop", kind="stop") - return ControlFlowGraph(self.cache) + self.new_node(exits, CFGStop(), kind="stop") + return ControlFlowGraph(blocks=self.cache) def map_AnalogCircuit(self, model: AnalogCircuit): return self.walk_block(model.statements, self.preds) diff --git a/src/oqd_core/analysis/analog/symbol_table.py b/src/oqd_core/analysis/analog/symbol_table.py index 3947f29f..e8d2ef3c 100644 --- a/src/oqd_core/analysis/analog/symbol_table.py +++ b/src/oqd_core/analysis/analog/symbol_table.py @@ -38,7 +38,7 @@ TTargetRef, TypeEnv, ) -from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.analysis.utils.control_flow import CFGStart, CFGStop, ControlFlowGraph from oqd_core.interface.analog import ( Access, AnalogList, @@ -218,7 +218,7 @@ def __init__(self, graph: ControlFlowGraph, type_result: DataflowResult[int, Typ stmt_index={ id(block.stmt): node_id for node_id, block in graph.blocks.items() - if not isinstance(block.stmt, str) + if not isinstance(block.stmt, (CFGStart, CFGStop)) }, ) diff --git a/src/oqd_core/analysis/analog/type_checker.py b/src/oqd_core/analysis/analog/type_checker.py index b9fe5689..375707a1 100644 --- a/src/oqd_core/analysis/analog/type_checker.py +++ b/src/oqd_core/analysis/analog/type_checker.py @@ -25,7 +25,12 @@ TBool, TypeEnv, ) -from oqd_core.analysis.utils.control_flow import Block, ControlFlowGraph +from oqd_core.analysis.utils.control_flow import ( + Block, + CFGStart, + CFGStop, + ControlFlowGraph, +) from oqd_core.interface.analog import Break, Continue, Declaration @@ -48,7 +53,7 @@ def transfer(self, node_id: int, state_in: TypeEnv) -> TypeEnv: state_out[stmt.name] = self.semantics.infer_type(stmt.value, env) return state_out - if isinstance(stmt, (str, Break, Continue)): + if isinstance(stmt, (CFGStart, CFGStop, Break, Continue)): return env t = self.semantics.infer_type(stmt, env) diff --git a/src/oqd_core/analysis/atomic/cfg.py b/src/oqd_core/analysis/atomic/cfg.py index 0e28a2b6..1d87c680 100644 --- a/src/oqd_core/analysis/atomic/cfg.py +++ b/src/oqd_core/analysis/atomic/cfg.py @@ -17,7 +17,12 @@ from oqd_compiler_infrastructure import RewriteRule -from oqd_core.analysis.utils.control_flow import Block, ControlFlowGraph +from oqd_core.analysis.utils.control_flow import ( + Block, + CFGStart, + CFGStop, + ControlFlowGraph, +) from oqd_core.interface.atomic import ( AtomicCircuit, Break, @@ -83,10 +88,10 @@ def run(self, circuit: AtomicCircuit) -> ControlFlowGraph: self.loop_stack = [] self.edge_labels = None self.fallthrough_labels = {} - founder = self.new_node([], "start", kind="start") + founder = self.new_node([], CFGStart(), kind="start") exits = self.walk_stmt(circuit, [founder]) - self.new_node(exits, "stop", kind="stop") - return ControlFlowGraph(self.cache) + self.new_node(exits, CFGStop(), kind="stop") + return ControlFlowGraph(blocks=self.cache) def map_AtomicCircuit(self, model: AtomicCircuit): return self.walk_block(model.statements, self.preds) diff --git a/src/oqd_core/analysis/atomic/symbol_table.py b/src/oqd_core/analysis/atomic/symbol_table.py index 72af0a92..73ffa49e 100644 --- a/src/oqd_core/analysis/atomic/symbol_table.py +++ b/src/oqd_core/analysis/atomic/symbol_table.py @@ -36,7 +36,7 @@ TTargetRef, TypeEnv, ) -from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.analysis.utils.control_flow import CFGStart, CFGStop, ControlFlowGraph from oqd_core.interface.atomic import ( Access, AtomicList, @@ -201,7 +201,7 @@ def __init__(self, graph: ControlFlowGraph, type_result: DataflowResult[int, Typ stmt_index={ id(block.stmt): node_id for node_id, block in graph.blocks.items() - if not isinstance(block.stmt, str) + if not isinstance(block.stmt, (CFGStart, CFGStop)) }, ) diff --git a/src/oqd_core/analysis/atomic/type_checker.py b/src/oqd_core/analysis/atomic/type_checker.py index be53147c..1594074a 100644 --- a/src/oqd_core/analysis/atomic/type_checker.py +++ b/src/oqd_core/analysis/atomic/type_checker.py @@ -27,7 +27,7 @@ TypeEnv, type_name, ) -from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.analysis.utils.control_flow import CFGStart, CFGStop, ControlFlowGraph from oqd_core.interface.atomic import ( Break, Continue, @@ -39,8 +39,6 @@ ######################################################################################## - - class AtomicTypeChecker(ForwardDataflowAnalysis[int, TypeEnv]): """Forward dataflow type checker over the Control Flow Graph.""" def __init__(self, graph: ControlFlowGraph) -> None: @@ -95,7 +93,7 @@ def transfer(self, node_id: int, state_in: TypeEnv) -> TypeEnv: state_out[stmt.name] = self.semantics.infer_type(stmt.value, env) return state_out - if isinstance(stmt, (str, Break, Continue)): + if isinstance(stmt, (CFGStart, CFGStop, Break, Continue)): return env if isinstance(stmt, (ParallelProtocol, SerialProtocol)): diff --git a/src/oqd_core/analysis/atomic/types.py b/src/oqd_core/analysis/atomic/types.py index 4421c9c9..5ef169e4 100644 --- a/src/oqd_core/analysis/atomic/types.py +++ b/src/oqd_core/analysis/atomic/types.py @@ -15,7 +15,6 @@ from __future__ import annotations -from dataclasses import dataclass from typing import Union from oqd_compiler_infrastructure.lattice import ( @@ -23,6 +22,7 @@ LatticeBottom, LatticeTop, ) +from pydantic import BaseModel, ConfigDict from oqd_core.interface.atomic import ( BoolAnd, @@ -45,9 +45,9 @@ class AtomicTypeError(TypeError): """Type Error class for Atomic.""" pass -@dataclass -class TList(LatticeTop): +class TList(LatticeTop, BaseModel): """Lattice value representing a list.""" + model_config = ConfigDict(frozen=True) elem: TLatticeValue TLatticeValue = Union[TList, type[LatticeTop]] diff --git a/src/oqd_core/analysis/utils/control_flow.py b/src/oqd_core/analysis/utils/control_flow.py index f922b6a8..86dd408c 100644 --- a/src/oqd_core/analysis/utils/control_flow.py +++ b/src/oqd_core/analysis/utils/control_flow.py @@ -15,9 +15,10 @@ from __future__ import annotations from types import UnionType -from typing import Annotated, Iterable, Union, get_args, get_origin +from typing import Annotated, Iterable, Literal, Union, get_args, get_origin -from oqd_compiler_infrastructure.dataflow import GraphProtocol +from oqd_compiler_infrastructure import VisitableBaseModel +from pydantic import BaseModel, Field def alias_types(alias: object) -> tuple[type, ...]: @@ -37,29 +38,23 @@ def alias_types(alias: object) -> tuple[type, ...]: return () -class ControlFlowGraph(GraphProtocol[int]): - """Defines a Control Flow Graph (CFG) with the GraphProtocol required by DataflowAnalysis.""" - def __init__(self, blocks: dict[int, Block]): - self.blocks = blocks - def nodes(self) -> Iterable[int]: - return self.blocks.keys() - def predecessors(self, node: int) -> Iterable[int]: - return (pred.register_id for pred in self.blocks[node].preds) - def successors(self, node: int) -> Iterable[int]: - return (succ.register_id for succ in self.blocks[node].succs) +class CFGStart(VisitableBaseModel): + pass + +class CFGStop(VisitableBaseModel): + pass -class Block: +class Block(BaseModel): """Represents one control flow node with incoming / outgoing edges and metadata.""" - def __init__(self, register_id: int, stmt: object, preds: Iterable[Block] | None = None, \ - kind: str = "stmt") -> None: - self.register_id = register_id - self.stmt = stmt - self.preds = list(preds) if preds is not None else [] - self.succs = [] - self.kind = kind - self.exit_nodes = [] - self.edge_labels = {} + + register_id: int + stmt: VisitableBaseModel + preds: list[Block] = Field(default_factory=list) + succs: list[Block] = Field(default_factory=list) + kind: Literal["start", "stop", "branch", "stmt"] = "stmt" + exit_nodes: list[Block] = Field(default_factory=list) + edge_labels: dict[int, str] = Field(default_factory=dict) def add_succ(self, succ: Block, label: str | None = None) -> None: if succ not in self.succs: @@ -76,3 +71,31 @@ def add_preds(self, preds: Iterable[Block], label: str | None = None) -> None: for pred in preds: self.add_pred(pred, label=label) + +class ControlFlowGraph(BaseModel): + """Defines a Control Flow Graph (CFG) with the GraphProtocol required by DataflowAnalysis.""" + blocks: dict[int, Block] + + def nodes(self) -> Iterable[int]: + return self.blocks.keys() + + def predecessors(self, node: int) -> Iterable[int]: + return (pred.register_id for pred in self.blocks[node].preds) + + def successors(self, node: int) -> Iterable[int]: + return (succ.register_id for succ in self.blocks[node].succs) + + def to_dict(self) -> dict: + return { + node_id: { + "register_id": block.register_id, + "kind": block.kind, + "stmt": block.stmt.model_dump(), + "preds": [p.register_id for p in block.preds], + "succs": [s.register_id for s in block.succs], + "exit_nodes": [e.register_id for e in block.exit_nodes], + "edge_labels": block.edge_labels, + } + for node_id, block in self.blocks.items() + } + diff --git a/src/oqd_core/compiler/analog/cfg_passes/walk.py b/src/oqd_core/compiler/analog/cfg_passes/walk.py index 3fe7b1cc..cbb99987 100644 --- a/src/oqd_core/compiler/analog/cfg_passes/walk.py +++ b/src/oqd_core/compiler/analog/cfg_passes/walk.py @@ -14,7 +14,7 @@ from __future__ import annotations -from oqd_core.analysis.utils.control_flow import ControlFlowGraph, Block +from oqd_core.analysis.utils.control_flow import ControlFlowGraph, Block, CFGStart, CFGStop from oqd_core.compiler.analog.math.passes import canonicalize_math_expr from oqd_core.interface.analog import Declaration, Evolve from oqd_core.interface.analog.expr import MathExpr, OperatorExpr @@ -23,7 +23,7 @@ def iter_stmt_blocks(cfg: ControlFlowGraph): for node_id, block in cfg.blocks.items(): - if isinstance(block.stmt, str): + if isinstance(block.stmt, (CFGStart, CFGStop)): continue yield node_id, block diff --git a/src/oqd_core/compiler/atomic/cfg_passes/walk.py b/src/oqd_core/compiler/atomic/cfg_passes/walk.py index 78dcbdf2..a4c03d98 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/walk.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/walk.py @@ -16,7 +16,7 @@ from __future__ import annotations -from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.analysis.utils.control_flow import ControlFlowGraph, CFGStart, CFGStop from oqd_core.compiler.atomic.math.passes import canonicalize_math_expr from oqd_core.interface.atomic import ( Beam, @@ -28,7 +28,7 @@ def iter_stmt_blocks(cfg: ControlFlowGraph): for node_id, block in cfg.blocks.items(): - if isinstance(block.stmt, str): + if isinstance(block.stmt, (CFGStart, CFGStop)): continue yield node_id, block From 22e28ca6f45536481125e85b6f9f7601ccda3a0c Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Mon, 13 Jul 2026 20:58:18 -0400 Subject: [PATCH 17/20] feat: Compiler passes return updated control flow graph and circuit --- examples/analog/test.ipynb | 43 +++++-- examples/atomic/test.ipynb | 111 ++++++++++++------ .../compiler/analog/passes/__init__.py | 4 +- .../compiler/analog/passes/compile.py | 7 +- .../compiler/atomic/cfg_passes/protocol.py | 36 ++++-- .../compiler/atomic/cfg_passes/walk.py | 42 +++---- .../compiler/atomic/passes/compile.py | 26 +++- 7 files changed, 179 insertions(+), 90 deletions(-) diff --git a/examples/analog/test.ipynb b/examples/analog/test.ipynb index d86254cc..8f0a923f 100644 --- a/examples/analog/test.ipynb +++ b/examples/analog/test.ipynb @@ -83,7 +83,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4678829792: 1, 4672233200: 2, 4678830512: 3, 4678837312: 4, 4678831792: 5, 4678833552: 6, 4678840752: 7, 4678840832: 8, 4678832912: 9, 4678836832: 10, 4678839392: 11, 4678832352: 12, 4678838432: 13, 4678842192: 14, 4678842352: 15, 4678842512: 16, 4678842672: 17, 4678842832: 18, 4678842992: 19, 4678843152: 20, 4678843312: 21, 4691607632: 22, 4691608752: 23, 4691610032: 24, 4691610192: 25, 4691610432: 26, 4691610752: 27, 4691611152: 28, 4691611632: 29, 4691611952: 30, 4691612192: 31, 4691612432: 32, 4691612752: 33, 4691613072: 34, 4691613392: 35, 4691613712: 36, 4691613632: 37, 4691614032: 38, 4691614192: 39, 4691614432: 40, 4691614672: 41, 4691614832: 42, 4691614992: 43, 4691615392: 44, 4691615712: 45, 4691616032: 46, 4691616512: 47, 4691616672: 48, 4691616912: 49, 4691617072: 50, 4691617312: 51, 4691617552: 52, 4691617792: 53, 4691618112: 54, 4691618352: 55, 4691618672: 56, 4691618992: 57, 4691618912: 58, 4691619152: 59}\"\n" + "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4575237440: 1, 4575234000: 2, 4575237280: 3, 4575238640: 4, 4568348736: 5, 4575242480: 6, 4575240160: 7, 4575238400: 8, 4575236960: 9, 4575237040: 10, 4575240080: 11, 4575239280: 12, 4575239440: 13, 4575244080: 14, 4575244240: 15, 4575244400: 16, 4575244560: 17, 4575244720: 18, 4575244880: 19, 4575245040: 20, 4575245200: 21, 4575246160: 22, 4575247440: 23, 4578427360: 24, 4578427520: 25, 4578427760: 26, 4578428080: 27, 4578428400: 28, 4578428640: 29, 4578429120: 30, 4578429360: 31, 4578429600: 32, 4578429920: 33, 4578430240: 34, 4578430560: 35, 4578430880: 36, 4578430800: 37, 4578431200: 38, 4578431360: 39, 4578431600: 40, 4578431840: 41, 4578432000: 42, 4578432160: 43, 4578432560: 44, 4578432880: 45, 4578433200: 46, 4578433680: 47, 4578433840: 48, 4578434080: 49, 4578434240: 50, 4578434480: 51, 4578434720: 52, 4578434960: 53, 4578435200: 54, 4578435600: 55, 4578435520: 56, 4578435920: 57, 4578436080: 58, 4578436160: 59}\"\n" ] } ], @@ -110,7 +110,7 @@ " AnalogSymbolTableBuilder,\n", " AnalogTypeChecker,\n", ")\n", - "from oqd_core.compiler.analog.passes.compile import compile_analog_cfg\n", + "from oqd_core.compiler.analog.passes.compile import compile_analog_circuit\n", "\n", "with open(\"test.analog\", mode=\"r\", encoding=\"utf8\") as f:\n", " source = f.read()\n", @@ -121,12 +121,33 @@ "dataflow_result = type_checker.dataflow_result\n", "symbol_analysis = AnalogSymbolTableBuilder(cfg, dataflow_result)\n", "symbol_table = symbol_analysis.symbol_table\n", - "cfg = compile_analog_cfg(cfg, symbol_table)" + "circuit, cfg = compile_analog_circuit(circuit, cfg, symbol_table)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, + "id": "69e5dfa5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AnalogCircuit(class_='AnalogCircuit', statements=[Declaration(class_='Declaration', name='r', value=QuantumRegister(class_='QuantumRegister', size=2)), Declaration(class_='Declaration', name='s', value=ModeRegister(class_='ModeRegister', size=3)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1)), Declaration(class_='Declaration', name='targets', value=AnalogList(class_='AnalogList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='tau', value=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=2), expr2=Access(class_='Access', name='pi'))), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phase', value=MathAdd(class_='MathAdd', expr1=MathVar(class_='MathVar', name='#phi'), expr2=MathMul(class_='MathMul', expr1=MathVar(class_='MathVar', name='#t'), expr2=Access(class_='Access', name='omega')))), Declaration(class_='Declaration', name='neg', value=MathNum(class_='MathNum', value=-1)), Declaration(class_='Declaration', name='cubed', value=MathNum(class_='MathNum', value=8)), Declaration(class_='Declaration', name='sine', value=MathFunc(class_='MathFunc', func='sin', expr=MathNum(class_='MathNum', value=0.5))), Declaration(class_='Declaration', name='cosed', value=MathFunc(class_='MathFunc', func='cos', expr=Access(class_='Access', name='phase'))), Declaration(class_='Declaration', name='cplx', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=1.0), expr2=MathMul(class_='MathMul', expr1=MathImag(class_='MathImag'), expr2=MathNum(class_='MathNum', value=0.5)))), Declaration(class_='Declaration', name='X', value=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=1), op2=PauliX(class_='PauliX'))), Declaration(class_='Declaration', name='Y', value=PauliY(class_='PauliY')), Declaration(class_='Declaration', name='Z', value=PauliZ(class_='PauliZ')), Declaration(class_='Declaration', name='I', value=PauliI(class_='PauliI')), Declaration(class_='Declaration', name='C', value=Creation(class_='Creation')), Declaration(class_='Declaration', name='A', value=Annihilation(class_='Annihilation')), Declaration(class_='Declaration', name='J', value=Identity(class_='Identity')), Declaration(class_='Declaration', name='H_single', value=OperatorAdd(class_='OperatorAdd', op1=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=0.5), op2=PauliX(class_='PauliX')), op2=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=0.5), op2=PauliZ(class_='PauliZ')))), Declaration(class_='Declaration', name='H_pair', value=OperatorAdd(class_='OperatorAdd', op1=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=1), op2=OperatorKron(class_='OperatorKron', op1=PauliI(class_='PauliI'), op2=PauliX(class_='PauliX'))), op2=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=1), op2=OperatorKron(class_='OperatorKron', op1=PauliX(class_='PauliX'), op2=PauliI(class_='PauliI'))))), Declaration(class_='Declaration', name='H_rabi', value=OperatorAdd(class_='OperatorAdd', op1=OperatorMul(class_='OperatorMul', op1=MathNum(class_='MathNum', value=0.5), op2=OperatorKron(class_='OperatorKron', op1=PauliI(class_='PauliI'), op2=PauliY(class_='PauliY'))), op2=OperatorMul(class_='OperatorMul', op1=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=0.5), expr2=MathVar(class_='MathVar', name='#t')), op2=OperatorKron(class_='OperatorKron', op1=PauliX(class_='PauliX'), op2=PauliI(class_='PauliI'))))), Declaration(class_='Declaration', name='x', value=MathNum(class_='MathNum', value=1)), IfElse(class_='IfElse', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Initialize(class_='Initialize', targets=Access(class_='Access', name='r'))], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_single'), duration=MathNum(class_='MathNum', value=1.0), targets=Access(class_='Access', name='q0'))], else_branch=[Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_pair'), duration=MathNum(class_='MathNum', value=0.5), targets=Access(class_='Access', name='r'))]), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_rabi'), duration=MathNum(class_='MathNum', value=0.1), targets=Access(class_='Access', name='targets')), Declaration(class_='Declaration', name='n', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=-1), expr2=Access(class_='Access', name='n')))]), While(class_='While', condition=Bool(class_='Bool', value=True), body=[IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Break(class_='Break')], else_branch=[])]), Declaration(class_='Declaration', name='a', value=MathNum(class_='MathNum', value=5)), Declaration(class_='Declaration', name='b', value=MathNum(class_='MathNum', value=3)), IfElse(class_='IfElse', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='a'), expr2=Access(class_='Access', name='b')), then_branch=[IfElse(class_='IfElse', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='b'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Initialize(class_='Initialize', targets=Access(class_='Access', name='targets'))], else_branch=[Measure(class_='Measure', targets=Access(class_='Access', name='r'))])], else_branch=[]), Initialize(class_='Initialize', targets=Access(class_='Access', name='r')), Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_single'), duration=MathNum(class_='MathNum', value=2.0), targets=Access(class_='Access', name='q1')), Evolve(class_='Evolve', hamiltonian=Access(class_='Access', name='H_pair'), duration=MathNum(class_='MathNum', value=1.0), targets=Access(class_='Access', name='targets')), Evolve(class_='Evolve', hamiltonian=OperatorMul(class_='OperatorMul', op1=PauliX(class_='PauliX'), op2=MathNum(class_='MathNum', value=0.5)), duration=Access(class_='Access', name='pi'), targets=Access(class_='Access', name='q0')), Measure(class_='Measure', targets=Access(class_='Access', name='r')), Declaration(class_='Declaration', name='measurement', value=Measure(class_='Measure', targets=Access(class_='Access', name='q0'))), Declaration(class_='Declaration', name='flag', value=MathNum(class_='MathNum', value=1)), IfElse(class_='IfElse', condition=BoolNotEq(class_='BoolNotEq', expr1=Access(class_='Access', name='flag'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Declaration(class_='Declaration', name='x', value=MathNum(class_='MathNum', value=0))], else_branch=[]), IfElse(class_='IfElse', condition=BoolLessThanEq(class_='BoolLessThanEq', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Declaration(class_='Declaration', name='x', value=MathNum(class_='MathNum', value=1))], else_branch=[]), IfElse(class_='IfElse', condition=BoolGreaterThanEq(class_='BoolGreaterThanEq', expr1=Access(class_='Access', name='x'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Declaration(class_='Declaration', name='x', value=MathNum(class_='MathNum', value=0))], else_branch=[]), Declaration(class_='Declaration', name='a', value=Bool(class_='Bool', value=True)), IfElse(class_='IfElse', condition=Access(class_='Access', name='a'), then_branch=[Declaration(class_='Declaration', name='b', value=MathNum(class_='MathNum', value=5))], else_branch=[])])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 7, "id": "34b5e170", "metadata": {}, "outputs": [ @@ -135,7 +156,7 @@ "output_type": "stream", "text": [ "digraph {\n", - "\t0 [label=\"0: start\\nstr\"]\n", + "\t0 [label=\"0: start\\nCFGStart\"]\n", "\t0 -> 1\n", "\t1 [label=\"1: stmt\\nr = ...\"]\n", "\t1 -> 2\n", @@ -266,7 +287,7 @@ "\t58 -> 60\n", "\t59 [label=\"59: stmt\\nb = ...\"]\n", "\t59 -> 60\n", - "\t60 [label=\"60: stop\\nstr\"]\n", + "\t60 [label=\"60: stop\\nCFGStop\"]\n", "}\n", "\n" ] @@ -277,7 +298,7 @@ "'cfg.png'" ] }, - "execution_count": 6, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -291,19 +312,19 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "8303ca3d", "metadata": {}, "outputs": [], "source": [ - "# from oqd_core.compiler.analog.passes.compile import compile_analog_cfg\n", - "# out = compile_analog_cfg(circuit)\n", + "# from oqd_core.compiler.analog.passes.compile import compile_analog_circuit\n", + "# out = compile_analog_circuit(circuit)\n", "# print(printer(out))" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "id": "b5a6b113", "metadata": {}, "outputs": [], diff --git a/examples/atomic/test.ipynb b/examples/atomic/test.ipynb index f32726fa..39948a82 100644 --- a/examples/atomic/test.ipynb +++ b/examples/atomic/test.ipynb @@ -171,12 +171,33 @@ "source": [ "from oqd_core.compiler.atomic.passes.compile import compile_atomic_circuit\n", "\n", - "cfg = compile_atomic_circuit(cfg, symbol_table)" + "circuit, cfg = compile_atomic_circuit(circuit, cfg, symbol_table, checker.dataflow_result)" ] }, { "cell_type": "code", "execution_count": 6, + "id": "7196b9c1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "AtomicCircuit(class_='AtomicCircuit', statements=[Declaration(class_='Declaration', name='ions', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='q0', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=0)), Declaration(class_='Declaration', name='q1', value=Extract(class_='Extract', access=Access(class_='Access', name='ions'), index=1)), Declaration(class_='Declaration', name='targets', value=AtomicList(class_='AtomicList', values=[Access(class_='Access', name='q0'), Access(class_='Access', name='q1')])), Declaration(class_='Declaration', name='pi', value=MathNum(class_='MathNum', value=3.14159)), Declaration(class_='Declaration', name='omega', value=MathVar(class_='MathVar', name='#omega')), Declaration(class_='Declaration', name='phi', value=MathVar(class_='MathVar', name='#phi')), Declaration(class_='Declaration', name='t_gate', value=MathNum(class_='MathNum', value=1e-05)), Declaration(class_='Declaration', name='flag', value=Bool(class_='Bool', value=True)), Declaration(class_='Declaration', name='n', value=MathNum(class_='MathNum', value=3)), Declaration(class_='Declaration', name='r', value=IonRegister(class_='IonRegister', size=2)), Declaration(class_='Declaration', name='beam_mw', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=2000000.0), expr2=Access(class_='Access', name='pi')), rabi=Access(class_='Access', name='omega'), phase=Access(class_='Access', name='phi'), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Declaration(class_='Declaration', name='beam_det', value=Beam(class_='Beam', frequency=MathMul(class_='MathMul', expr1=MathNum(class_='MathNum', value=4000000.0), expr2=Access(class_='Access', name='pi')), rabi=MathNum(class_='MathNum', value=0.25), phase=MathNum(class_='MathNum', value=0.0), polarization=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0), MathNum(class_='MathNum', value=0.0)]), wavevector=AtomicList(class_='AtomicList', values=[MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=0.0), MathNum(class_='MathNum', value=1.0)]))), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=Access(class_='Access', name='t_gate'), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=3e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))]), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=Access(class_='Access', name='t_gate'), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=0), measured=Bool(class_='Bool', value=False)), SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=3e-06), target=Extract(class_='Extract', access=Access(class_='Access', name='r'), index=1), measured=Bool(class_='Bool', value=True))]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q0'), measured=Bool(class_='Bool', value=False)), Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))]), ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=5e-06), target=Access(class_='Access', name='q1'), measured=Bool(class_='Bool', value=False))])]), IfElse(class_='IfElse', condition=Access(class_='Access', name='flag'), then_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=2e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))])], else_branch=[SerialProtocol(class_='SerialProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_det'), duration=MathNum(class_='MathNum', value=2e-05), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=True))])]), While(class_='While', condition=BoolGreaterThan(class_='BoolGreaterThan', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), body=[SerialProtocol(class_='SerialProtocol', pulses=[ParallelProtocol(class_='ParallelProtocol', pulses=[Pulse(class_='Pulse', beam=Access(class_='Access', name='beam_mw'), duration=MathNum(class_='MathNum', value=1e-06), target=Access(class_='Access', name='targets'), measured=Bool(class_='Bool', value=False))])]), Declaration(class_='Declaration', name='n', value=MathAdd(class_='MathAdd', expr1=MathNum(class_='MathNum', value=-1), expr2=Access(class_='Access', name='n'))), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=1)), then_branch=[Continue(class_='Continue')], else_branch=[]), IfElse(class_='IfElse', condition=BoolEq(class_='BoolEq', expr1=Access(class_='Access', name='n'), expr2=MathNum(class_='MathNum', value=0)), then_branch=[Break(class_='Break')], else_branch=[])])])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 7, "id": "26c77ff2", "metadata": {}, "outputs": [ @@ -185,7 +206,7 @@ "output_type": "stream", "text": [ "digraph {\n", - "\t0 [label=\"0: start\\nstr\"]\n", + "\t0 [label=\"0: start\\nCFGStart\"]\n", "\t0 -> 1\n", "\t1 [label=\"1: stmt\\nions = ...\"]\n", "\t1 -> 2\n", @@ -217,63 +238,83 @@ "\t14 -> 15\n", "\t15 [label=\"15: stmt\\nSerialProtocol(1)\"]\n", "\t15 -> 16\n", - "\t16 [label=\"16: stmt\\nSerialProtocol(1)\"]\n", + "\t16 [label=\"16: stmt\\nPulse\"]\n", "\t16 -> 17\n", - "\t17 [label=\"17: stmt\\nPulse\"]\n", + "\t17 [label=\"17: stmt\\nSerialProtocol(1)\"]\n", "\t17 -> 18\n", - "\t18 [label=\"18: stmt\\nSerialProtocol(1)\"]\n", + "\t18 [label=\"18: stmt\\nPulse\"]\n", "\t18 -> 19\n", - "\t19 [label=\"19: stmt\\nSerialProtocol(1)\"]\n", + "\t19 [label=\"19: stmt\\nPulse\"]\n", "\t19 -> 20\n", "\t20 [label=\"20: stmt\\nSerialProtocol(1)\"]\n", "\t20 -> 21\n", - "\t21 [label=\"21: stmt\\nSerialProtocol(1)\"]\n", + "\t21 [label=\"21: stmt\\nPulse\"]\n", "\t21 -> 22\n", - "\t22 [label=\"22: stmt\\nSerialProtocol(2)\"]\n", + "\t22 [label=\"22: stmt\\nSerialProtocol(1)\"]\n", "\t22 -> 23\n", - "\t23 [label=\"23: stmt\\nSerialProtocol(1)\"]\n", + "\t23 [label=\"23: stmt\\nParallelProtocol(2)\"]\n", "\t23 -> 24\n", - "\t24 [label=\"24: stmt\\nSerialProtocol(1)\"]\n", + "\t24 [label=\"24: stmt\\nPulse\"]\n", "\t24 -> 25\n", - "\t25 [label=\"25: stmt\\nSerialProtocol(2)\"]\n", + "\t25 [label=\"25: stmt\\nPulse\"]\n", "\t25 -> 26\n", "\t26 [label=\"26: stmt\\nSerialProtocol(2)\"]\n", "\t26 -> 27\n", - "\t27 [label=\"27: stmt\\nSerialProtocol(1)\"]\n", + "\t27 [label=\"27: stmt\\nParallelProtocol(1)\"]\n", "\t27 -> 28\n", - "\t28 [label=\"28: stmt\\nSerialProtocol(1)\"]\n", + "\t28 [label=\"28: stmt\\nPulse\"]\n", "\t28 -> 29\n", - "\t29 [label=\"29: stmt\\nSerialProtocol(1)\"]\n", + "\t29 [label=\"29: stmt\\nParallelProtocol(1)\"]\n", "\t29 -> 30\n", - "\t30 [label=\"30: stmt\\nSerialProtocol(1)\"]\n", + "\t30 [label=\"30: stmt\\nPulse\"]\n", "\t30 -> 31\n", - "\t31 [label=\"31: branch\\nAccess\"]\n", + "\t31 [label=\"31: stmt\\nSerialProtocol(2)\"]\n", "\t31 -> 32\n", - "\t31 -> 33\n", - "\t32 [label=\"32: stmt\\nSerialProtocol(1)\"]\n", - "\t32 -> 34\n", - "\t33 [label=\"33: stmt\\nSerialProtocol(1)\"]\n", + "\t32 [label=\"32: stmt\\nParallelProtocol(3)\"]\n", + "\t32 -> 33\n", + "\t33 [label=\"33: stmt\\nPulse\"]\n", "\t33 -> 34\n", - "\t34 [label=\"34: branch\\nBoolGreaterThan\"]\n", + "\t34 [label=\"34: stmt\\nPulse\"]\n", "\t34 -> 35\n", - "\t34 -> 42\n", - "\t35 [label=\"35: stmt\\nSerialProtocol(1)\"]\n", + "\t35 [label=\"35: stmt\\nPulse\"]\n", "\t35 -> 36\n", - "\t36 [label=\"36: stmt\\nSerialProtocol(1)\"]\n", + "\t36 [label=\"36: stmt\\nParallelProtocol(1)\"]\n", "\t36 -> 37\n", - "\t37 [label=\"37: stmt\\nn = ...\"]\n", + "\t37 [label=\"37: stmt\\nPulse\"]\n", "\t37 -> 38\n", - "\t38 [label=\"38: branch\\nBoolEq\"]\n", + "\t38 [label=\"38: branch\\nAccess\"]\n", "\t38 -> 39\n", - "\t38 -> 40\n", - "\t39 [label=\"39: stmt\\nContinue\"]\n", - "\t39 -> 34\n", - "\t40 [label=\"40: branch\\nBoolEq\"]\n", - "\t40 -> 41\n", - "\t40 -> 34\n", - "\t41 [label=\"41: stmt\\nBreak\"]\n", + "\t38 -> 41\n", + "\t39 [label=\"39: stmt\\nSerialProtocol(1)\"]\n", + "\t39 -> 40\n", + "\t40 [label=\"40: stmt\\nPulse\"]\n", + "\t40 -> 43\n", + "\t41 [label=\"41: stmt\\nSerialProtocol(1)\"]\n", "\t41 -> 42\n", - "\t42 [label=\"42: stop\\nstr\"]\n", + "\t42 [label=\"42: stmt\\nPulse\"]\n", + "\t42 -> 43\n", + "\t43 [label=\"43: branch\\nBoolGreaterThan\"]\n", + "\t43 -> 44\n", + "\t43 -> 52\n", + "\t44 [label=\"44: stmt\\nSerialProtocol(1)\"]\n", + "\t44 -> 45\n", + "\t45 [label=\"45: stmt\\nParallelProtocol(1)\"]\n", + "\t45 -> 46\n", + "\t46 [label=\"46: stmt\\nPulse\"]\n", + "\t46 -> 47\n", + "\t47 [label=\"47: stmt\\nn = ...\"]\n", + "\t47 -> 48\n", + "\t48 [label=\"48: branch\\nBoolEq\"]\n", + "\t48 -> 49\n", + "\t48 -> 50\n", + "\t49 [label=\"49: stmt\\nContinue\"]\n", + "\t49 -> 43\n", + "\t50 [label=\"50: branch\\nBoolEq\"]\n", + "\t50 -> 51\n", + "\t50 -> 43\n", + "\t51 [label=\"51: stmt\\nBreak\"]\n", + "\t51 -> 52\n", + "\t52 [label=\"52: stop\\nCFGStop\"]\n", "}\n", "\n" ] @@ -284,7 +325,7 @@ "'cfg.png'" ] }, - "execution_count": 6, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } diff --git a/src/oqd_core/compiler/analog/passes/__init__.py b/src/oqd_core/compiler/analog/passes/__init__.py index eeaa7713..568923d2 100644 --- a/src/oqd_core/compiler/analog/passes/__init__.py +++ b/src/oqd_core/compiler/analog/passes/__init__.py @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .compile import compile_analog_cfg +from .compile import compile_analog_circuit from .assign import infer_analog_circuit_dim_cfg __all__ = [ - "compile_analog_cfg", + "compile_analog_circuit", "infer_analog_circuit_dim_cfg", ] diff --git a/src/oqd_core/compiler/analog/passes/compile.py b/src/oqd_core/compiler/analog/passes/compile.py index a2e9381e..933797ba 100644 --- a/src/oqd_core/compiler/analog/passes/compile.py +++ b/src/oqd_core/compiler/analog/passes/compile.py @@ -19,10 +19,11 @@ from oqd_core.compiler.analog.verify.passes import verify_analog_args_dim, verify_hamiltonian_target_dim, verify_register_access_dim from oqd_core.analysis.analog.symbol_table import AnalogSymbolTable from oqd_core.analysis.utils.control_flow import ControlFlowGraph +from oqd_core.interface.analog import AnalogCircuit ######################################################################################## -__all__ = [ "compile_analog_cfg" ] +__all__ = [ "compile_analog_circuit" ] ######################################################################################## @@ -33,7 +34,7 @@ def canonicalize_args_metrics(args): metric.operator = canonicalize_operator_expr(metric.operator) -def compile_analog_cfg(cfg: ControlFlowGraph, symbol_table: AnalogSymbolTable, args=None) -> ControlFlowGraph: +def compile_analog_circuit(circuit: AnalogCircuit, cfg: ControlFlowGraph, symbol_table: AnalogSymbolTable, args=None) -> tuple[AnalogCircuit, ControlFlowGraph]: canonicalize_operators_cfg(cfg) canonicalize_math_cfg(cfg) @@ -46,5 +47,5 @@ def compile_analog_cfg(cfg: ControlFlowGraph, symbol_table: AnalogSymbolTable, a canonicalize_args_metrics(args) verify_analog_args_dim(args, n_qreg, n_qmode) - return cfg + return circuit, cfg diff --git a/src/oqd_core/compiler/atomic/cfg_passes/protocol.py b/src/oqd_core/compiler/atomic/cfg_passes/protocol.py index 92f5ed11..d7f40fe5 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/protocol.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/protocol.py @@ -14,9 +14,7 @@ from __future__ import annotations from oqd_compiler_infrastructure import Post -from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.canonicalize import ResolveNestedProtocol, ResolveRelativeTime -from oqd_core.compiler.atomic.cfg_passes.walk import iter_stmt_blocks from oqd_core.compiler.atomic.math.rules import _is_constant_math from oqd_core.compiler.atomic.verify.passes import iter_pulses from oqd_core.interface.atomic import ( @@ -24,6 +22,9 @@ ParallelProtocol, Pulse, SerialProtocol, + IfElse, + While, + AtomicCircuit, ) PROTOCOL_TYPES = (Pulse, ParallelProtocol, SerialProtocol) @@ -37,12 +38,27 @@ def apply_protocol_passes(stmt): return stmt -def canonicalize_protocol_cfg(cfg: ControlFlowGraph) -> ControlFlowGraph: - for _, block in iter_stmt_blocks(cfg): - stmt = block.stmt - if isinstance(stmt, Declaration) and isinstance(stmt.value, PROTOCOL_TYPES): - stmt.value = apply_protocol_passes(stmt.value) - elif isinstance(stmt, PROTOCOL_TYPES): - block.stmt = apply_protocol_passes(stmt) - return cfg +def canonicalize_protocol_tree(stmt): + if isinstance(stmt, IfElse): + stmt.then_branch = [canonicalize_protocol_tree(s) for s in stmt.then_branch] + stmt.else_branch = [canonicalize_protocol_tree(s) for s in stmt.else_branch] + return stmt + + if isinstance(stmt, While): + stmt.body = [canonicalize_protocol_tree(s) for s in stmt.body] + return stmt + + if isinstance(stmt, Declaration) and isinstance(stmt.value, PROTOCOL_TYPES): + stmt.value = apply_protocol_passes(stmt.value) + return stmt + + if isinstance(stmt, PROTOCOL_TYPES): + return apply_protocol_passes(stmt) + + return stmt + + +def canonicalize_protocol_circuit(circuit: AtomicCircuit) -> AtomicCircuit: + circuit.statements = [canonicalize_protocol_tree(s) for s in circuit.statements] + return circuit diff --git a/src/oqd_core/compiler/atomic/cfg_passes/walk.py b/src/oqd_core/compiler/atomic/cfg_passes/walk.py index a4c03d98..5a2e7013 100644 --- a/src/oqd_core/compiler/atomic/cfg_passes/walk.py +++ b/src/oqd_core/compiler/atomic/cfg_passes/walk.py @@ -15,12 +15,12 @@ from __future__ import annotations - +from oqd_compiler_infrastructure.dataflow import DataflowResult +from oqd_core.analysis.atomic.types import TBeam, TPulse, TScalar, TypeEnv from oqd_core.analysis.utils.control_flow import ControlFlowGraph, CFGStart, CFGStop from oqd_core.compiler.atomic.math.passes import canonicalize_math_expr from oqd_core.interface.atomic import ( Beam, - Pulse, Bool, Declaration, ) @@ -45,33 +45,29 @@ def canonicalize_beam(beam: Beam) -> Beam: beam.wavevector = canonicalize_scalar_expr(beam.wavevector) return beam -def canonicalize_pulse(pulse: Pulse) -> Pulse: - pulse.duration = canonicalize_scalar_expr(pulse.duration) - if isinstance(pulse.beam, Beam): - pulse.beam = canonicalize_beam(pulse.beam) - return pulse - -def canonicalize_declarations(expr): - if isinstance(expr, Beam): - return canonicalize_beam(expr) - if isinstance(expr, Pulse): - return canonicalize_pulse(expr) - if isinstance(expr, MathExpr): - return canonicalize_math_expr(expr) - return expr - +def canonicalize_declarations_cfg(cfg: ControlFlowGraph, type_result: DataflowResult[int, TypeEnv],) -> ControlFlowGraph: -def canonicalize_declarations_cfg(cfg: ControlFlowGraph) -> ControlFlowGraph: - - for _, block in iter_stmt_blocks(cfg): + for node_id, block in iter_stmt_blocks(cfg): stmt = block.stmt + if block.kind == "branch": if isinstance(stmt, MathExpr): block.stmt = canonicalize_math_expr(stmt) - return + continue + + if not isinstance(stmt, Declaration): + continue - if isinstance(stmt, Declaration): - stmt.value = canonicalize_declarations(stmt.value) + t = type_result.out_states[node_id].get(stmt.name) + if t is TScalar: + stmt.value = canonicalize_scalar_expr(stmt.value) + elif t is TBeam: + stmt.value = canonicalize_beam(stmt.value) + elif t is TPulse: + pulse = stmt.value + pulse.duration = canonicalize_scalar_expr(pulse.duration) + if isinstance(pulse.beam, Beam): + pulse.beam = canonicalize_beam(pulse.beam) return cfg diff --git a/src/oqd_core/compiler/atomic/passes/compile.py b/src/oqd_core/compiler/atomic/passes/compile.py index b9cb700e..2618b3a8 100644 --- a/src/oqd_core/compiler/atomic/passes/compile.py +++ b/src/oqd_core/compiler/atomic/passes/compile.py @@ -12,21 +12,35 @@ # See the License for the specific language governing permissions and # limitations under the License. -from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable +from oqd_compiler_infrastructure.dataflow import DataflowResult +from oqd_core.analysis.atomic.cfg import AtomicCFGBuilder +from oqd_core.analysis.atomic.symbol_table import AtomicSymbolTable, AtomicSymbolTableBuilder +from oqd_core.analysis.atomic.type_checker import AtomicTypeChecker +from oqd_core.analysis.atomic.types import TypeEnv from oqd_core.analysis.utils.control_flow import ControlFlowGraph from oqd_core.compiler.atomic.cfg_passes.walk import canonicalize_declarations_cfg -from oqd_core.compiler.atomic.cfg_passes.protocol import canonicalize_protocol_cfg +from oqd_core.compiler.atomic.cfg_passes.protocol import canonicalize_protocol_circuit from oqd_core.compiler.atomic.verify.passes import verify_pulse_target_dim +from oqd_core.interface.atomic import AtomicCircuit __all__ = ["compile_atomic_circuit"] def compile_atomic_circuit( + circuit: AtomicCircuit, cfg: ControlFlowGraph, symbol_table: AtomicSymbolTable, -): - canonicalize_declarations_cfg(cfg) - canonicalize_protocol_cfg(cfg) + type_result: DataflowResult[int, TypeEnv], +) -> tuple[AtomicCircuit, ControlFlowGraph]: + canonicalize_declarations_cfg(cfg, type_result) + canonicalize_protocol_circuit(circuit) + + cfg = AtomicCFGBuilder().run(circuit) + type_checker = AtomicTypeChecker(cfg) + symbol_table = AtomicSymbolTableBuilder( + cfg, type_checker.dataflow_result + ).symbol_table + verify_pulse_target_dim(cfg, symbol_table) - return cfg + return circuit, cfg From 9bc47a66531e8f62c785918fab33640945863798 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Mon, 13 Jul 2026 21:17:48 -0400 Subject: [PATCH 18/20] clean: Update docs --- docs/reference/analog_compiler.md | 8 ++++---- docs/reference/atomic_compiler.md | 12 +++++++----- src/oqd_core/analysis/analog/symbol_table.py | 6 +++++- src/oqd_core/analysis/atomic/symbol_table.py | 6 +++++- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/reference/analog_compiler.md b/docs/reference/analog_compiler.md index 5ba03f0e..2d308402 100644 --- a/docs/reference/analog_compiler.md +++ b/docs/reference/analog_compiler.md @@ -1,6 +1,6 @@ # Analog Compiler -The analog compiler is implemented in `src/oqd_core/compiler/analog`. The entry point is [`compile_analog_cfg`][oqd_core.compiler.analog.passes.compile.compile_analog_cfg], which takes a [`ControlFlowGraph`][oqd_core.analysis.utils.control_flow.ControlFlowGraph], and an `AnalogSymbolTable`[oqd_core.analysis.analog.symbol_table.AnalogSymbolTable]. +The analog compiler is implemented in `src/oqd_core/compiler/analog`. The entry point is [`compile_analog_circuit`][oqd_core.compiler.analog.passes.compile.compile_analog_circuit], which takes an [`AnalogCircuit`][oqd_core.interface.analog.circuit.AnalogCircuit], a [`ControlFlowGraph`][oqd_core.analysis.utils.control_flow.ControlFlowGraph], and an `AnalogSymbolTable`[oqd_core.analysis.analog.symbol_table.AnalogSymbolTable]. The compile pipeline: - Canonicalize operators over the CFG via [`canonicalize_operators_cfg`][oqd_core.compiler.analog.cfg_passes.walk.canonicalize_operators_cfg] @@ -15,7 +15,7 @@ The compile pipeline: options: heading_level: 3 members: [ - "compile_analog_cfg", + "compile_analog_circuit", ] ::: oqd_core.compiler.analog.passes.assign @@ -111,7 +111,7 @@ The compile pipeline: ```py from oqd_core.frontend.analog import parse_analog from oqd_core.analysis.analog import AnalogCFGBuilder, AnalogTypeChecker, AnalogSymbolTableBuilder -from oqd_core.compiler.analog.passes.compile import compile_analog_cfg +from oqd_core.compiler.analog.passes.compile import compile_analog_circuit source = """ q = qreg(2) h = %X %@ %I @@ -122,5 +122,5 @@ circuit = parse_analog(source) cfg = AnalogCFGBuilder().run(circuit) type_checker = AnalogTypeChecker(cfg) symbol_table = AnalogSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table -cfg = compile_analog_cfg(cfg, symbol_table) +cfg = compile_analog_circuit(circuit, cfg, symbol_table) ``` diff --git a/docs/reference/atomic_compiler.md b/docs/reference/atomic_compiler.md index 796ed143..c0cc573a 100644 --- a/docs/reference/atomic_compiler.md +++ b/docs/reference/atomic_compiler.md @@ -1,10 +1,12 @@ # Atomic Compiler -The atomic compiler is implemented in `src/oqd_core/compiler/atomic`. The entry point is [`compile_atomic_circuit`][oqd_core.compiler.atomic.passes.compile.compile_atomic_circuit], which takes a [`ControlFlowGraph`][oqd_core.analysis.utils.control_flow.ControlFlowGraph] and an [`AtomicSymbolTable`][oqd_core.analysis.atomic.symbol_table.AtomicSymbolTable]. +The atomic compiler is implemented in `src/oqd_core/compiler/atomic`. The entry point is [`compile_atomic_circuit`][oqd_core.compiler.atomic.passes.compile.compile_atomic_circuit], which takes an [`AtomicCircuit`][oqd_core.interface.atomic.circuit.AtomicCircuit], a [`ControlFlowGraph`][oqd_core.analysis.utils.control_flow.ControlFlowGraph] and an [`AtomicSymbolTable`][oqd_core.analysis.atomic.symbol_table.AtomicSymbolTable]. The compile pipeline: - Canonicalize declaration values over the CFG via [`canonicalize_declarations_cfg`][oqd_core.compiler.atomic.cfg_passes.walk.canonicalize_declarations_cfg] - Canonicalize nested protocols and relative time via [`canonicalize_protocol_cfg`][oqd_core.compiler.atomic.cfg_passes.protocol.canonicalize_protocol_cfg] +- Rebuild the CFG from the updated circuit via [`AtomicCFGBuilder`][oqd_core.analysis.atomic.cfg.AtomicCFGBuilder] +- Re-run the type checker and symbol table on the rebuilt CFG - Verify pulse target dimensions via [`verify_pulse_target_dim`][oqd_core.compiler.atomic.verify.passes.verify_pulse_target_dim] ## Compile Passes @@ -26,9 +28,7 @@ The compile pipeline: members: [ "iter_stmt_blocks", "canonicalize_declarations_cfg", - "canonicalize_declarations", "canonicalize_beam", - "canonicalize_pulse", "canonicalize_scalar_expr", ] @@ -36,7 +36,9 @@ The compile pipeline: options: heading_level: 3 members: [ - "canonicalize_protocol_cfg", + "apply_protocol_passes", + "canonicalize_protocol_tree", + "canonicalize_protocol_circuit", ] ::: oqd_core.compiler.atomic.cfg_passes.resolve @@ -111,5 +113,5 @@ circuit = parse_atomic(source) cfg = AtomicCFGBuilder().run(circuit) type_checker = AtomicTypeChecker(cfg) symbol_table = AtomicSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table -cfg = compile_atomic_circuit(cfg, symbol_table) +cfg = compile_atomic_circuit(circuit, cfg, symbol_table, type_checker.dataflow_result) ``` diff --git a/src/oqd_core/analysis/analog/symbol_table.py b/src/oqd_core/analysis/analog/symbol_table.py index e8d2ef3c..5976a191 100644 --- a/src/oqd_core/analysis/analog/symbol_table.py +++ b/src/oqd_core/analysis/analog/symbol_table.py @@ -28,6 +28,7 @@ ) from pydantic import BaseModel, ConfigDict +from oqd_core.analysis.analog.type_checker import AnalogTypeChecker from oqd_core.analysis.analog.types import ( TLatticeValue, TList, @@ -203,8 +204,11 @@ def target_dim(expr, env: RegisterEnv): class AnalogSymbolTableBuilder(ForwardDataflowAnalysis[int, RegisterEnv]): """Forward dataflow symbol table for register / target dimension checking.""" - def __init__(self, graph: ControlFlowGraph, type_result: DataflowResult[int, TypeEnv]) -> None: + def __init__(self, graph: ControlFlowGraph, type_result: DataflowResult[int, TypeEnv] | None = None,) -> None: + if type_result is None: + type_result = AnalogTypeChecker(graph).dataflow_result self.type_out_states = type_result.out_states + self.lattice = maplattice(SymbolBindingLattice)() self.blocks = graph.blocks diff --git a/src/oqd_core/analysis/atomic/symbol_table.py b/src/oqd_core/analysis/atomic/symbol_table.py index 73ffa49e..18883bdf 100644 --- a/src/oqd_core/analysis/atomic/symbol_table.py +++ b/src/oqd_core/analysis/atomic/symbol_table.py @@ -28,6 +28,7 @@ ) from pydantic import BaseModel, ConfigDict +from oqd_core.analysis.atomic.type_checker import AtomicTypeChecker from oqd_core.analysis.atomic.types import ( TIonRef, TIonReg, @@ -186,8 +187,11 @@ def target_dim(expr, env: RegisterEnv): class AtomicSymbolTableBuilder(ForwardDataflowAnalysis[int, RegisterEnv]): """Forward dataflow symbol table for register / target dimension checking.""" - def __init__(self, graph: ControlFlowGraph, type_result: DataflowResult[int, TypeEnv]) -> None: + def __init__(self, graph: ControlFlowGraph, type_result: DataflowResult[int, TypeEnv] | None = None,) -> None: + if type_result is None: + type_result = AtomicTypeChecker(graph).dataflow_result self.type_out_states = type_result.out_states + self.lattice = maplattice(SymbolBindingLattice)() self.blocks = graph.blocks From 27e5c49fbbd2c47e56c49fccbb5acd5ffea6e883 Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Tue, 14 Jul 2026 13:16:54 -0400 Subject: [PATCH 19/20] clean: Update docs and add tests for compiler passes --- docs/analysis/analog_analysis.md | 2 +- docs/analysis/atomic_analysis.md | 2 +- tests/test_analog/test_analog_cfg_passes.py | 124 ++++++++++++++++++++ tests/test_atomic/test_atomic_cfg_passes.py | 120 +++++++++++++++++++ 4 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 tests/test_analog/test_analog_cfg_passes.py create mode 100644 tests/test_atomic/test_atomic_cfg_passes.py diff --git a/docs/analysis/analog_analysis.md b/docs/analysis/analog_analysis.md index 17cf4c63..e4e0952d 100644 --- a/docs/analysis/analog_analysis.md +++ b/docs/analysis/analog_analysis.md @@ -40,4 +40,4 @@ symbol_table = AnalogSymbolTableBuilder(cfg, type_checker.dataflow_result).symbo /// -The type checker dataflow result is available at `type_checker.dataflow_result`. +The type checker dataflow result is available at `type_checker.dataflow_result`. This result is used to build the Symbol Table. Note that the Symbol Table will run the Type Checker to get the dataflow result if the result is not provided. diff --git a/docs/analysis/atomic_analysis.md b/docs/analysis/atomic_analysis.md index cb272ba6..c556c0d7 100644 --- a/docs/analysis/atomic_analysis.md +++ b/docs/analysis/atomic_analysis.md @@ -42,4 +42,4 @@ symbol_table = AtomicSymbolTableBuilder(cfg, type_checker.dataflow_result).symbo /// -The type checker dataflow result is available at `type_checker.dataflow_result`. +The type checker dataflow result is available at `type_checker.dataflow_result`. This result is used to build the Symbol Table. Note that the Symbol Table will run the Type Checker to get the dataflow result if the result is not provided. diff --git a/tests/test_analog/test_analog_cfg_passes.py b/tests/test_analog/test_analog_cfg_passes.py new file mode 100644 index 00000000..3ccaf9f2 --- /dev/null +++ b/tests/test_analog/test_analog_cfg_passes.py @@ -0,0 +1,124 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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 pytest +from oqd_core.analysis.analog.cfg import AnalogCFGBuilder +from oqd_core.analysis.analog.symbol_table import AnalogSymbolTableBuilder +from oqd_core.analysis.analog.type_checker import AnalogTypeChecker +from oqd_core.compiler.analog.cfg_passes.walk import ( + canonicalize_math_cfg, + canonicalize_operators_cfg, + iter_stmt_blocks, +) +from oqd_core.compiler.analog.error import AnalogCompilerError +from oqd_core.compiler.analog.math.passes import evaluate_math_expr +from oqd_core.compiler.analog.passes.assign import infer_analog_circuit_dim_cfg +from oqd_core.compiler.analog.passes.compile import compile_analog_circuit +from oqd_core.frontend.analog.AnalogCircuitAST import parse_analog +from oqd_core.interface.analog import Declaration, Evolve, MathNum +from oqd_core.interface.analog.expr import OperatorAdd, OperatorMul + + +def build_inputs(program: str): + circuit = parse_analog(program) + cfg = AnalogCFGBuilder().run(circuit) + type_checker = AnalogTypeChecker(cfg) + symbol_table = AnalogSymbolTableBuilder( + cfg, type_checker.dataflow_result + ).symbol_table + return circuit, cfg, symbol_table + + +def declaration_value(cfg, name): + for _, block in iter_stmt_blocks(cfg): + stmt = block.stmt + if isinstance(stmt, Declaration) and stmt.name == name: + return stmt.value + raise KeyError(name) + + +## Compile ## + +class TestAnalogCompile: + @pytest.mark.parametrize( + "program", + [ + "r = qreg(2)\n evolve(%X %@ %I, 1.0, r)", + "r = qreg(2)\n h = %X %@ %I %+ %Y %@ %I\n evolve(h, 1.0, r)", + ], + ) + def test_compile(self, program): + circuit, cfg, symbol_table = build_inputs(program) + compile_analog_circuit(circuit, cfg, symbol_table) + + def test_hamiltonian_target_dim_error(self): + circuit, cfg, symbol_table = build_inputs( + "r = qreg(2)\n s = qmode(2)\n evolve(%X %@ %I, 1.0, s)" + ) + with pytest.raises(AnalogCompilerError): + compile_analog_circuit(circuit, cfg, symbol_table) + + +## CFG Passes ## + +class TestAnalogCanonicalizeMathCfg: + + def test_evolve_duration(self): + _, cfg, _ = build_inputs("r = qreg(2)\n evolve(%X, 1.0 + 1.0, r)") + canonicalize_math_cfg(cfg) + for _, block in iter_stmt_blocks(cfg): + if isinstance(block.stmt, Evolve): + assert evaluate_math_expr(block.stmt.duration) == 2 + + def test_skips_operator_declarations(self): + _, cfg, _ = build_inputs("h = %X %+ %Y") + canonicalize_math_cfg(cfg) + assert isinstance(declaration_value(cfg, "h"), OperatorAdd) + + +class TestAnalogCanonicalizeOperatorsCfg: + def test_canonicalizes_operator_declarations(self): + _, cfg, _ = build_inputs("h = %X %+ %Y") + canonicalize_operators_cfg(cfg) + h = declaration_value(cfg, "h") + assert isinstance(h, OperatorAdd) + assert isinstance(h.op1, OperatorMul) + assert isinstance(h.op2, OperatorMul) + assert h.op1.op1 == MathNum(value=1) + assert h.op2.op1 == MathNum(value=1) + + def test_skips_math_declarations(self): + _, cfg, _ = build_inputs("s = 2 * 3") + canonicalize_operators_cfg(cfg) + assert not isinstance(declaration_value(cfg, "s"), MathNum) + + +class TestAnalogInferDim: + def test_qreg_dim(self): + _, cfg, _ = build_inputs("r = qreg(2)\n evolve(%X %@ %I, 1.0, r)") + assert infer_analog_circuit_dim_cfg(cfg) == (2, 0) + + def test_qmode_dim(self): + _, cfg, _ = build_inputs("s = qmode(2)\n evolve(%C %@ %A, 1.0, s)") + assert infer_analog_circuit_dim_cfg(cfg) == (0, 2) + + def test_inconsistent_evolve_dims(self): + _, cfg, _ = build_inputs( + "r = qreg(2)\n s = qmode(2)\n" + "evolve(%X, 1.0, r)\n" + "evolve(%C %@ %A, 1.0, s)" + ) + with pytest.raises(AnalogCompilerError): + infer_analog_circuit_dim_cfg(cfg) + diff --git a/tests/test_atomic/test_atomic_cfg_passes.py b/tests/test_atomic/test_atomic_cfg_passes.py new file mode 100644 index 00000000..7952888d --- /dev/null +++ b/tests/test_atomic/test_atomic_cfg_passes.py @@ -0,0 +1,120 @@ +# Copyright 2024-2025 Open Quantum Design + +# 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 pytest +from oqd_core.analysis.atomic.cfg import AtomicCFGBuilder +from oqd_core.analysis.atomic.symbol_table import ( + AtomicSymbolError, + AtomicSymbolTableBuilder, +) +from oqd_core.analysis.atomic.type_checker import AtomicTypeChecker +from oqd_core.compiler.atomic.cfg_passes.protocol import canonicalize_protocol_circuit +from oqd_core.compiler.atomic.cfg_passes.walk import ( + canonicalize_declarations_cfg, + iter_stmt_blocks, +) +from oqd_core.compiler.atomic.passes.compile import compile_atomic_circuit +from oqd_core.frontend.atomic.AtomicCircuitAST import parse_atomic +from oqd_core.interface.atomic import ( + Declaration, + Pulse, + MathNum, + ParallelProtocol, + SerialProtocol, +) + +REGISTER = "r = ionreg(2)\n" +BEAM = "b = beam(2e6, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0])\n" + +def build_inputs(program: str): + circuit = parse_atomic(program) + cfg = AtomicCFGBuilder().run(circuit) + type_checker = AtomicTypeChecker(cfg) + symbol_table = AtomicSymbolTableBuilder( + cfg, type_checker.dataflow_result + ).symbol_table + return circuit, cfg, symbol_table, type_checker.dataflow_result + + +def declaration_value(cfg, name): + for _, block in iter_stmt_blocks(cfg): + stmt = block.stmt + if isinstance(stmt, Declaration) and stmt.name == name: + return stmt.value + raise KeyError(name) + + +## Compile ## + +class TestAtomicCompile: + @pytest.mark.parametrize( + "program", + [ + REGISTER + BEAM + "pulse(b, 1e-5, r, true)", + REGISTER + BEAM + "parallel {\n pulse(b, 5e-6, r[0])\n pulse(b, 5e-6, r[1])\n}", + REGISTER + BEAM + "serial {\n pulse(b, 5e-6, r[0])\n pulse(b, 5e-6, r[1])\n}", + REGISTER + BEAM + "parallel {\n serial {\n pulse(b, 5e-6, r[0])\n pulse(b, 5e-6, r[1])\n}\n}", + ], + ) + def test_compile(self, program): + circuit, cfg, symbol_table, type_result = build_inputs(program) + compile_atomic_circuit(circuit, cfg, symbol_table, type_result) + + def test_rebuilds_cfg_after_protocol(self): + program = ( + REGISTER + BEAM + + "parallel {\n serial {\n pulse(b, 5e-6, r[0])\n pulse(b, 5e-6, r[1])\n}\n}" + ) + circuit, cfg, symbol_table, type_result = build_inputs(program) + _, new_cfg = compile_atomic_circuit(circuit, cfg, symbol_table, type_result) + assert new_cfg is not cfg + + +## CFG Passes ## + +class TestAtomicCanonicalizeDeclarationsCfg: + def test_beam_fields_canonicalized(self): + _, cfg, _, type_result = build_inputs( + "b = beam(1e6 + 1e6, 0.25, 0.0, [0.0, 1.0, 0.0], [0.0, 0.0, 1.0])" + ) + canonicalize_declarations_cfg(cfg, type_result) + assert declaration_value(cfg, "b").frequency == MathNum(value=2e6) + + def test_pulse_duration_canonicalized(self): + _, cfg, _, type_result = build_inputs( + REGISTER + BEAM + "p = pulse(b, 1e-5 + 1e-5, r[0])" + ) + canonicalize_declarations_cfg(cfg, type_result) + assert declaration_value(cfg, "p").duration == MathNum(value=2e-5) + + +class TestAtomicCanonicalizeProtocol: + def test_nested_serial_in_parallel(self): + program = ( + REGISTER + BEAM + + "parallel {\n serial {\n pulse(b, 5e-6, r[0])\n pulse(b, 5e-6, r[1])\n}\n}" + ) + circuit, _, _, _ = build_inputs(program) + canonicalize_protocol_circuit(circuit) + stmt = circuit.statements[-1] + assert isinstance(stmt, SerialProtocol) + assert all(isinstance(p, ParallelProtocol) for p in stmt.pulses) + + def test_serial_protocol_pulses_remain_pulses(self): + program = REGISTER + BEAM + "serial {\n pulse(b, 5e-6, r[0])\n pulse(b, 5e-6, r[1])\n}" + circuit, _, _, _ = build_inputs(program) + canonicalize_protocol_circuit(circuit) + stmt = circuit.statements[-1] + assert all(isinstance(p, ParallelProtocol) for p in stmt.pulses) + assert all(isinstance(p.pulses[0], Pulse) for p in stmt.pulses) From b9bb328881fc54e94490d43808be63b29480df6e Mon Sep 17 00:00:00 2001 From: vishnu-m77 Date: Wed, 15 Jul 2026 16:39:38 -0400 Subject: [PATCH 20/20] fix: output of analog compiler, update docs --- docs/reference/analog_compiler.md | 2 +- docs/reference/atomic_compiler.md | 2 +- examples/analog/test.ipynb | 4 ++-- src/oqd_core/compiler/analog/passes/compile.py | 5 +++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/reference/analog_compiler.md b/docs/reference/analog_compiler.md index 2d308402..7a64a3b9 100644 --- a/docs/reference/analog_compiler.md +++ b/docs/reference/analog_compiler.md @@ -122,5 +122,5 @@ circuit = parse_analog(source) cfg = AnalogCFGBuilder().run(circuit) type_checker = AnalogTypeChecker(cfg) symbol_table = AnalogSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table -cfg = compile_analog_circuit(circuit, cfg, symbol_table) +circuit, cfg, n_qreg, n_qmode = compile_analog_circuit(circuit, cfg, symbol_table) ``` diff --git a/docs/reference/atomic_compiler.md b/docs/reference/atomic_compiler.md index c0cc573a..9b6d97ab 100644 --- a/docs/reference/atomic_compiler.md +++ b/docs/reference/atomic_compiler.md @@ -113,5 +113,5 @@ circuit = parse_atomic(source) cfg = AtomicCFGBuilder().run(circuit) type_checker = AtomicTypeChecker(cfg) symbol_table = AtomicSymbolTableBuilder(cfg, type_checker.dataflow_result).symbol_table -cfg = compile_atomic_circuit(circuit, cfg, symbol_table, type_checker.dataflow_result) +circuit, cfg = compile_atomic_circuit(circuit, cfg, symbol_table, type_checker.dataflow_result) ``` diff --git a/examples/analog/test.ipynb b/examples/analog/test.ipynb index 8f0a923f..ffde8eab 100644 --- a/examples/analog/test.ipynb +++ b/examples/analog/test.ipynb @@ -83,7 +83,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4575237440: 1, 4575234000: 2, 4575237280: 3, 4575238640: 4, 4568348736: 5, 4575242480: 6, 4575240160: 7, 4575238400: 8, 4575236960: 9, 4575237040: 10, 4575240080: 11, 4575239280: 12, 4575239440: 13, 4575244080: 14, 4575244240: 15, 4575244400: 16, 4575244560: 17, 4575244720: 18, 4575244880: 19, 4575245040: 20, 4575245200: 21, 4575246160: 22, 4575247440: 23, 4578427360: 24, 4578427520: 25, 4578427760: 26, 4578428080: 27, 4578428400: 28, 4578428640: 29, 4578429120: 30, 4578429360: 31, 4578429600: 32, 4578429920: 33, 4578430240: 34, 4578430560: 35, 4578430880: 36, 4578430800: 37, 4578431200: 38, 4578431360: 39, 4578431600: 40, 4578431840: 41, 4578432000: 42, 4578432160: 43, 4578432560: 44, 4578432880: 45, 4578433200: 46, 4578433680: 47, 4578433840: 48, 4578434080: 49, 4578434240: 50, 4578434480: 51, 4578434720: 52, 4578434960: 53, 4578435200: 54, 4578435600: 55, 4578435520: 56, 4578435920: 57, 4578436080: 58, 4578436160: 59}\"\n" + "\"in_env={0: {}, 1: {}, 2: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None)}, 3: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None)}, 4: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 5: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None)}, 6: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 7: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 8: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 9: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 10: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 11: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 12: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 13: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 14: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 15: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 16: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 17: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 18: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 19: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 20: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 21: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 22: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 23: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 24: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 25: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 26: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 27: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 28: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 29: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 30: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 31: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 32: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 33: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 34: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 35: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 36: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 37: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 38: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 39: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 40: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 41: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 42: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 43: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 44: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 45: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 46: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 47: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 48: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 49: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 50: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 51: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 52: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 53: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 54: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 55: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 56: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 57: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 58: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 59: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}, 60: {'r': SymbolBinding(lattice_type=, target_dim=(2, 0), list_elem=None), 's': SymbolBinding(lattice_type=, target_dim=(0, 3), list_elem=None), 'q0': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'q1': SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None), 'targets': SymbolBinding(lattice_type=TList(elem=), target_dim=(2, 0), list_elem=SymbolBinding(lattice_type=, target_dim=(1, 0), list_elem=None))}} stmt_index={4531015744: 1, 4531012384: 2, 4531018704: 3, 4531016144: 4, 4531015504: 5, 4531017744: 6, 4531021824: 7, 4531021984: 8, 4531017504: 9, 4531019184: 10, 4531017264: 11, 4531018144: 12, 4531019344: 13, 4531023264: 14, 4531023424: 15, 4531023584: 16, 4531023744: 17, 4531023904: 18, 4531024064: 19, 4531024224: 20, 4531024384: 21, 4531025424: 22, 4531026624: 23, 4534206544: 24, 4534206704: 25, 4534206944: 26, 4534207264: 27, 4534207664: 28, 4534208144: 29, 4534208464: 30, 4534208704: 31, 4534208944: 32, 4534209264: 33, 4534209584: 34, 4534209904: 35, 4534210224: 36, 4534210144: 37, 4534210544: 38, 4534210704: 39, 4534210944: 40, 4534211184: 41, 4534211344: 42, 4534211504: 43, 4534211904: 44, 4534212224: 45, 4534212544: 46, 4534213024: 47, 4534213184: 48, 4534213424: 49, 4534213584: 50, 4534213824: 51, 4534214064: 52, 4534214304: 53, 4534214624: 54, 4534214864: 55, 4534215104: 56, 4534215424: 57, 4534215344: 58, 4534215584: 59}\"\n" ] } ], @@ -121,7 +121,7 @@ "dataflow_result = type_checker.dataflow_result\n", "symbol_analysis = AnalogSymbolTableBuilder(cfg, dataflow_result)\n", "symbol_table = symbol_analysis.symbol_table\n", - "circuit, cfg = compile_analog_circuit(circuit, cfg, symbol_table)" + "circuit, cfg, n_qreg, n_qmode = compile_analog_circuit(circuit, cfg, symbol_table)" ] }, { diff --git a/src/oqd_core/compiler/analog/passes/compile.py b/src/oqd_core/compiler/analog/passes/compile.py index 933797ba..622308e1 100644 --- a/src/oqd_core/compiler/analog/passes/compile.py +++ b/src/oqd_core/compiler/analog/passes/compile.py @@ -34,7 +34,8 @@ def canonicalize_args_metrics(args): metric.operator = canonicalize_operator_expr(metric.operator) -def compile_analog_circuit(circuit: AnalogCircuit, cfg: ControlFlowGraph, symbol_table: AnalogSymbolTable, args=None) -> tuple[AnalogCircuit, ControlFlowGraph]: +def compile_analog_circuit(circuit: AnalogCircuit, cfg: ControlFlowGraph, symbol_table: AnalogSymbolTable, args=None) \ + -> tuple[AnalogCircuit, ControlFlowGraph, int, int]: canonicalize_operators_cfg(cfg) canonicalize_math_cfg(cfg) @@ -47,5 +48,5 @@ def compile_analog_circuit(circuit: AnalogCircuit, cfg: ControlFlowGraph, symbol canonicalize_args_metrics(args) verify_analog_args_dim(args, n_qreg, n_qmode) - return circuit, cfg + return circuit, cfg, n_qreg, n_qmode