Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion dev_tools/qualtran_dev_tools/make_reference_docs/_make.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@
]
MINIMAL = True

DEFINED_IN_CONTAINER_EXCEPTIONS = ['qualtran.dtype', 'qualtran.exception', 'qualtran.cirq_interop']
DEFINED_IN_CONTAINER_EXCEPTIONS = [
'qualtran.dtype',
'qualtran.exception',
'qualtran.cirq_interop',
'qualtran.l1.nodes',
]


def _get_all_aliases(obj: Union[griffe.Object, griffe.Alias]) -> Set[str]:
Expand Down
28 changes: 28 additions & 0 deletions qualtran/_infra/composite_bloq.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@

from qualtran.bloqs.bookkeeping.auto_partition import Unused
from qualtran.cirq_interop._cirq_to_bloq import CirqQuregInT, CirqQuregT
from qualtran.drawing import WireSymbol
from qualtran.resource_counting import BloqCountDictT, SympySymbolAllocator
from qualtran.simulation.classical_sim import ClassicalValT
from qualtran.symbolics import SymbolicInt
Expand Down Expand Up @@ -141,12 +142,20 @@ class CompositeBloq(Bloq):
should correspond to the dangling `Soquets` in the `cxns`.
bloq_instances: Optionally specify the unique bloq instances. Otherwise, deduce them from
the connections.
decomposed_from: Optionally include a reference to the bloq from whence this
`CompositeBloq` was decomposed. This can be used for debugging and error
reporting, but is never used for deriving any properties.
bloq_key: An optional string key for this bloq. This can be used for debugging and
error reporting, but is never used for deriving any properties.
"""

connections: Tuple[Connection, ...] = attrs.field(converter=_to_tuple)
signature: Signature
bloq_instances: FrozenSet[BloqInstance] = attrs.field(converter=_to_set)

decomposed_from: Optional[Bloq] = attrs.field(default=None, kw_only=True)
bloq_key: Optional[str] = attrs.field(default=None, kw_only=True)

@bloq_instances.default
def _default_bloq_instances(self):
return {
Expand Down Expand Up @@ -524,7 +533,23 @@ def debug_text(self) -> str:
delimited_gens = ('\n' + '-' * 20 + '\n').join(gen_texts)
return delimited_gens

def wire_symbol(
self, reg: Optional['Register'], idx: Tuple[int, ...] = tuple()
) -> 'WireSymbol':
from qualtran.drawing import Text

if reg is None:
if self.decomposed_from is not None:
return self.decomposed_from.wire_symbol(None)
if self.bloq_key is not None:
return Text(self.bloq_key)
return Text('cbloq')

return super().wire_symbol(reg, idx)

def __str__(self):
if self.bloq_key is not None:
return self.bloq_key
return f'CompositeBloq([{len(self.bloq_instances)} subbloqs...])'


Expand Down Expand Up @@ -554,6 +579,9 @@ def _binst_to_cxns(
binst: Union[BloqInstance, DanglingT], binst_graph: nx.DiGraph
) -> Tuple[List[Connection], List[Connection]]:
"""Helper method to extract all predecessor and successor Connections for a binst."""
if binst not in binst_graph.nodes:
return [], []

pred_cxns: List[Connection] = []
for pred in binst_graph.pred[binst]:
pred_cxns.extend(binst_graph.edges[pred, binst]['cxns'])
Expand Down
178 changes: 178 additions & 0 deletions qualtran/l1/L1-Text-IR.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "83e446f6-4f99-4a93-a854-0423e4421b35",
"metadata": {},
"source": [
"# Qualtran-L1 Intermediate Representation\n",
"\n",
"The L1 intermediate representation (IR) for Qualtran is a host-language-agnostic interchange format for hierarchical composite quantum programs. The Python `qualtran` library (Qualtran-L2) can compile to Qualtran-L1.\n",
"\n",
" - L1 quantum functions are represented as text vs. L2 bloqs represented as in-memory Python objects.\n",
" - a L1 `*.qlt` file contains a full hierarchical record of the quantum funciton vs. \"lazy\" evaluation of decompositions in L2.\n",
" - Compile-time classical parameters are filled in and static in L1 vs. templated families of quantum subroutines via bloq classes in L2."
]
},
{
"cell_type": "markdown",
"id": "7d56515d-2d3f-4cc2-97c6-5efe02eb3b84",
"metadata": {},
"source": [
"## Example usage"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ab390b71-0792-4a48-af09-27463f7d3390",
"metadata": {},
"outputs": [],
"source": [
"import qualtran as qlt\n",
"import qualtran.dtype as qdt"
]
},
{
"cell_type": "markdown",
"id": "667a66b5-8e1c-4d20-b3a4-17a499a8b512",
"metadata": {},
"source": [
"### `dump_l1`\n",
"\n",
"This function will take a bloq and recursively \"compile\" it to the static L1 textual representation. \n",
"\n",
" - The hierarchical structure of the program definition is maintained.\n",
" - Each bloq object is included as a `qdef` quantum function declaration with a static quantum signature (enclosed in square brackets).\n",
" - Bloq objects with a defined decomposition include a `qdef` quantum function definition with a static function body (enclosed in curly braces) encoding the composition.\n",
" - Bloq objects without a defined decomposition are included as `extern qdef` declarations *only*. These must include the `from` clause, which provides the L1-objectstrng used to *link* the extern qdefs with an in-memory Python bloq object."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4f412be1-1377-4524-a124-fd51383ac335",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.bloqs.arithmetic import BitwiseNot\n",
"from qualtran.l1 import dump_l1\n",
"\n",
"l1_code = dump_l1(BitwiseNot(qdt.QUInt(4)))\n",
"print(l1_code)"
]
},
{
"cell_type": "markdown",
"id": "b8cf9e9d-e528-4925-872b-ed598ba6928c",
"metadata": {},
"source": [
"### `dump_root_l1`\n",
"\n",
"This convenience function is provided to only dump one level of decomposition and declare each of the immediate callees as extern qdefs."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d6f7696e-b255-434b-a8d7-ff767a0e050c",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.bloqs.arithmetic import Negate\n",
"from qualtran.l1 import dump_root_l1\n",
"\n",
"negate = Negate(qdt.QUInt(8))\n",
"root_l1_code = dump_root_l1(negate)\n",
"print(root_l1_code)"
]
},
{
"cell_type": "markdown",
"id": "9ac23592-9f55-4ef0-9675-2c2c97f82a6c",
"metadata": {},
"source": [
"### `load_module`"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "76769eeb-a777-4bf3-9466-05efda846cf5",
"metadata": {},
"outputs": [],
"source": [
"from qualtran.l1 import load_module\n",
"module = load_module(\"\"\"\n",
"# Qualtran-L1\n",
"# 1.0.0\n",
"\n",
"qdef Negate[x: QUInt(8)] {\n",
" x2 = BitwiseNot(8)[x=x] \n",
" x3 = AddK(k=1)[x=x2] \n",
" return [x=x3] \n",
"}\n",
"\n",
"extern qdef BitwiseNot(8)\n",
"from qualtran.bloqs.arithmetic.BitwiseNot(QUInt(8))\n",
"[x: QUInt(8)]\n",
"\n",
"extern qdef AddK(k=1)\n",
"from qualtran.bloqs.arithmetic.AddK(QUInt(8), 1)\n",
"[x: QUInt(8)]\"\"\")\n",
"module.keys()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0d98758f-8efd-42bb-a918-6842074be601",
"metadata": {},
"outputs": [],
"source": [
"module['Negate'].bloq_instances"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "72e18029-f45f-4a31-8cf9-1f5ce72698ef",
"metadata": {},
"outputs": [],
"source": [
"type(module['Negate']), type(negate)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8b7a75c5-7002-4294-8171-7edaecdccd55",
"metadata": {},
"outputs": [],
"source": [
"module['Negate'].call_classically(x=1)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
10 changes: 7 additions & 3 deletions qualtran/l1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from ._eval import eval_cvalue_node
from ._parse import parse_objectstring
from ._parse_eval import load_objectstring
from ._ast_to_code import L1ASTPrinter
from ._ast_visitor_base import L1VisitorBase
from ._eval import eval_cvalue_node, eval_module
from ._parse import dump_ast, parse_module, parse_objectstring
from ._parse_eval import load_bloq, load_module, load_objectstring
from ._to_cobject_node import dump_objectstring, to_cobject_node
from ._to_l1 import dump_l1, dump_root_l1, L1ModuleBuilder
from ._vm import StandardQualtranArchitectureAgnosticVirtualMachine
Loading
Loading