-
Notifications
You must be signed in to change notification settings - Fork 28
Compiler for Code Switching #524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
98 commits
Select commit
Hold shift + click to select a range
fe606c4
update git_ignore
inctechs ad9e877
Merge remote-tracking branch 'origin/main' into code-switching-compiler
inctechs 892cba3
add networkx to mypy ignore
inctechs 9d5fdb8
implement first version of min-cut solution
inctechs e5e16fc
add one way transveral CNOTs to be allowed
inctechs bdb5b9b
add edge_type keyword to edges
inctechs 0e9b3cf
change default order of magnitude for temporal edges
inctechs bb33537
add code bias functionality
inctechs 91df0eb
clear/ reorder code
inctechs eee407a
read in QC as dag to support depth and prepare idle switching
inctechs c1d3f52
change qubit activity collection to list instead of set
inctechs adc87f5
make Global default temporal edge weight
inctechs 3bf1bff
add idle bonus calculation and idle switching funcitonality
inctechs 1c7684e
update docstrings and comments
inctechs 73ffd1c
fix counting of switches
inctechs 5b08d68
Revert "fix counting of switches"
inctechs ad6ff67
fix counting of switching operations
inctechs c63e2aa
add placeholder switch operations to qiskit circuit
inctechs 9b5bb38
add extraction of switching position
inctechs 4317cd4
add feature that idle bonus only considered for certain length
inctechs 2c58f77
change return of min-cut function
inctechs 38d1304
add scripts for generating ciruits
inctechs 1914d5b
add function to generate universal random qiskit circuit
inctechs 4b40503
add edge ration
inctechs 796e032
change default folder name of circuit output
inctechs 926fb01
update default number of seeds
inctechs e330bca
add lookahead function
inctechs 4689579
add scripts for performance analysis
inctechs f07cc68
change default number of generated cicuits
inctechs ef3dfd4
remove raw data return form min_cut
inctechs 0ec634d
make lookahead deterministic
inctechs 63c982d
add lookahead to init file
inctechs a5c02dd
change simulations to be gate distribution sensitive
inctechs f99ee41
add feature to avoid generating circuits twice
inctechs 6d9e3ac
add script to generate array with steps of 64
inctechs 1436eb8
add all qubits numbers to performance bash
inctechs 80fbb09
add intermediate results
inctechs a82e97d
add new results
inctechs c0c39ca
update simulations
inctechs d37f0ab
move utils functions to utils file
inctechs a785748
set up code switching compilation test
inctechs 595ecba
Merge remote-tracking branch 'origin/main' into code-switching-compiler
inctechs 4d7b7a1
repair test for idle bonus
inctechs a333e5d
redefine api by making functions private
inctechs 1d90c17
add full function docstring extract switch locations
inctechs 1af4cd8
add one way transversal test
inctechs 82fdcf1
add CompilerConfig for different settings and keep it tidy
inctechs e73f6fc
add CompilerConfig to init
inctechs 5c8f2ec
connect biased code to CompilerConfig
inctechs ffc1375
add code bias test
inctechs 42ae8cf
add test for compilation utils
inctechs 2e4e588
remove dag layer visualization used for debugging previously
inctechs 9f75e39
Merge remote-tracking branch 'origin/main' into code-switching-compiler
inctechs 76a2649
work in CodeRabbitAI code review
inctechs 3c23ca5
fix more CodeRabbitAIs comments
inctechs 0ffd8f1
rename variables in scripts
inctechs 6cb8917
rename class to MinimalCodeSwitchingCompiler
inctechs 2defa2d
generalise Graph construction
inctechs 648fe47
remove unused methods to connect to terminals and connecting CNOTs
inctechs 7e2dd98
fix typo with parameter names
inctechs c8e66ca
add idle bonus calcualtion from the paper
inctechs 2dfb57d
move random circuit generation from utils to scripts
inctechs fe44822
rename naive code switching method and adjust collaterals
inctechs 364550b
remove unnecessary comments
inctechs 85b2d35
move node parser back to graph class
inctechs d9fe652
remove redundancy
inctechs 4afedfb
rename tests for naive switching
inctechs 45a3a97
remove stress test, adapt parsing node test, fix num_switches typo
inctechs 24793dd
improve placeholder test
inctechs ec589b7
remove personal playground folder
inctechs 7415903
add networkx to pyproject.toml
inctechs e5b3beb
automatic reordering by uv
inctechs 30509e0
fix logical error where same back to back gates are allowed
inctechs 85fc4b6
rabbit edits
inctechs e458dae
rename package to code_switching
inctechs 5b529a0
add safe guard for non negative bonus
inctechs a8d3ca2
save uv.lock
inctechs b92b2f7
Merge remote-tracking branch 'origin/main' into code-switching-compiler
inctechs 27060ce
add CodeSwitching docs
inctechs 518d63e
rename unary edges to bias edges
inctechs 364b621
generalise one-way transversal gate definition.
inctechs bd00389
sketch doc structure
inctechs 13d38b8
fix bug in docs
inctechs b71d9b4
fix bug in code cells
inctechs f63fec2
fix typos in the docs
inctechs 3b38882
Merge remote-tracking branch 'origin/main' into code-switching-compiler
inctechs 909c3c6
Update docs/CodeSwitching.md
inctechs dff65bc
Apply suggestions from code review for docs
inctechs e81fe16
Apply suggestions from code review: fix naming of class in docstrings
inctechs 5674e4f
edit Changelog.md
inctechs 9adb064
Merge branch 'code-switching-compiler' of https://github.com/munich-q…
inctechs ed674dc
fix latest coderabbit feedback
inctechs e901ac5
add missing references to changelog
inctechs 2908247
Merge remote-tracking branch 'origin' into code-switching-compiler
inctechs 94f31ea
🎨 pre-commit fixes
pre-commit-ci[bot] 1eb3f39
fix last coderabbit changes
inctechs 7f5b1e5
Merge branch 'code-switching-compiler' of https://github.com/munich-q…
inctechs a43628c
remove note from README and add key feature description
inctechs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Copyright (c) 2023 - 2025 Chair for Design Automation, TUM | ||
| # All rights reserved. | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
| # | ||
| # Licensed under the MIT License | ||
|
|
||
| """Methods and utilities for code switching compilation.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from .code_switching_compiler import CodeSwitchGraph | ||
|
|
||
| __all__ = ["CodeSwitchGraph"] |
198 changes: 198 additions & 0 deletions
198
src/mqt/qecc/circuit_compilation/code_switching_compiler.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| # Copyright (c) 2023 - 2025 Chair for Design Automation, TUM | ||
| # All rights reserved. | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
| # | ||
| # Licensed under the MIT License | ||
|
|
||
| """Code Switching Compiler to find the minimum number of switches.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from typing import TYPE_CHECKING | ||
|
|
||
| import networkx as nx | ||
|
|
||
| if TYPE_CHECKING: | ||
| from qiskit import QuantumCircuit | ||
|
|
||
|
|
||
| class CodeSwitchGraph: | ||
inctechs marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| """A directed graph representation of a quantum circuit for code-switching analysis using min-cut / max-flow optimization. | ||
|
|
||
| The graph is constructed such that: | ||
| - Each quantum operation (T, H, CNOT) corresponds to one or more nodes. | ||
| - Source (SRC) and sink (SNK) nodes represent two different codes: | ||
| * Source-connected nodes (T, CNOT) → operations that can be done transversally in code A. | ||
| * Sink-connected nodes (H, CNOT) → operations that can be done transversally in code B. | ||
| - Infinite-capacity edges enforce code consistency between operations (e.g., CNOT links). | ||
| - Finite-capacity edges (default 1.0) represent potential code transitions along qubit timelines. | ||
|
|
||
| Attributes: | ||
| ---------- | ||
| G : nx.DiGraph | ||
| Directed graph storing the nodes and edges. | ||
| source : str | ||
| Identifier for the source node ("SRC"). | ||
| sink : str | ||
| Identifier for the sink node ("SNK"). | ||
| """ | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def __init__(self) -> None: | ||
| """Initialize the CodeSwitchGraph with source and sink nodes.""" | ||
| self.G: nx.DiGraph = nx.DiGraph() | ||
| self.source: str = "SRC" | ||
| self.sink: str = "SNK" | ||
| self.G.add_node(self.source) | ||
| self.G.add_node(self.sink) | ||
|
|
||
| def add_gate_node(self, gate_type: str, qubit: int, depth: int) -> str: | ||
| """Add a node representing a quantum gate operation. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| gate_type : str | ||
| The gate type (e.g., "H", "T", "CNOTc", "CNOTt"). | ||
| qubit : int | ||
| Index of the qubit the gate acts on. | ||
| depth : int | ||
| Depth (or layer index) of the operation in the circuit. | ||
|
|
||
| Returns: | ||
| ------- | ||
| str | ||
| The unique node identifier created for this operation. | ||
| """ | ||
| node_id = f"{gate_type}_q{qubit}_d{depth}" | ||
| self.G.add_node(node_id, gate=gate_type, qubit=qubit, depth=depth) | ||
| return node_id | ||
|
|
||
| def add_edge_with_capacity(self, u: str, v: str, capacity: float, bidirectional: bool = True) -> None: | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| """Add a directed edge with specified capacity between two nodes. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| u : str | ||
| Source node identifier. | ||
| v : str | ||
| Target node identifier. | ||
| capacity : float | ||
| Edge capacity. | ||
| """ | ||
| self.G.add_edge(u, v, capacity=capacity) | ||
| if bidirectional: | ||
| self.G.add_edge(v, u, capacity=capacity) | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def add_infinite_edge(self, u: str, v: str, bidirectional: bool = True) -> None: | ||
| """Add an edge of infinite capacity between two nodes. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| u : str | ||
| Source node identifier. | ||
| v : str | ||
| Target node identifier. | ||
| """ | ||
| self.add_edge_with_capacity(u, v, capacity=float("inf"), bidirectional=bidirectional) | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def add_regular_edge(self, u: str, v: str, capacity: float = 1.0, bidirectional: bool = True) -> None: | ||
| """Add a regular (finite-capacity) directed edge. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| u : str | ||
| Source node identifier. | ||
| v : str | ||
| Target node identifier. | ||
| capacity : float, optional | ||
| Edge capacity (default is 1.0). | ||
| """ | ||
| self.add_edge_with_capacity(u, v, capacity=capacity, bidirectional=bidirectional) | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def connect_to_code(self, node_id: str, gate_type: str) -> None: | ||
| """Connect a gate node to the source and/or sink according to which code can perform the operation transversally. | ||
|
|
||
| Note: Here we fix the convention that the 2D Color Code corresponds to the source (can perform H and CNOT) | ||
| and the 3D Surface Code corresponds to the sink (can perform T and CNOT). This convention is arbitrary and can be swapped. | ||
| However, swapping the convention requires to change the one-way transversal CNOT setting: | ||
| 2D Source + 3D Sink <-> (infinite edge) Control -> Target | ||
| 3D Source + 2D Sink <-> (infinite edge) Control <- Target | ||
|
|
||
| Parameters | ||
| ---------- | ||
| node_id : str | ||
| Node identifier of the gate operation. | ||
| gate_type : str | ||
| Type of the gate (e.g., "H", "T", "CNOT"). | ||
| """ | ||
| # Source code can perform T and CNOT gates | ||
| if gate_type == "T": | ||
| self.add_infinite_edge(self.sink, node_id) | ||
| # Sink code can perform H and CNOT gates | ||
| if gate_type == "H": | ||
| self.add_infinite_edge(node_id, self.source) | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def add_cnot_links(self, control_node: str, target_node: str, one_way_transversal_cnot: bool = False) -> None: | ||
| """Add bidirectional infinite-capacity edges between two CNOT-related nodes to enforce that both qubits remain in the same code. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| control_node : str | ||
| Node representing the control qubit's CNOT operation. | ||
| target_node : str | ||
| Node representing the target qubit's CNOT operation. | ||
| """ | ||
| self.add_infinite_edge(control_node, target_node, bidirectional=not (one_way_transversal_cnot)) | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def build_from_qiskit(self, circuit: QuantumCircuit, one_way_transversal_cnot: bool = False) -> None: | ||
| """Construct the code-switch graph from a Qiskit QuantumCircuit. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| circuit : QuantumCircuit | ||
| The input quantum circuit containing H, T, and CX (CNOT) gates. | ||
|
|
||
| Notes: | ||
| ----- | ||
| - For each gate, a node is created per qubit. | ||
| - Temporal ordering along qubit lines is maintained via regular edges. | ||
| - CNOT gates create two linked nodes (control, target) with infinite capacity. | ||
| """ | ||
| qubit_last_node: list[str | None] = [None] * circuit.num_qubits | ||
| depth = 0 | ||
|
|
||
| for depth, instr in enumerate(circuit.data): | ||
| gate = instr.operation.name.upper() | ||
| qubits = [circuit.find_bit(q).index for q in instr.qubits] | ||
|
|
||
| if gate in {"H", "T"}: | ||
| q = qubits[0] | ||
| node = self.add_gate_node(gate, q, depth) | ||
| self.connect_to_code(node, gate) | ||
| if qubit_last_node[q]: | ||
| self.add_regular_edge(qubit_last_node[q], node) | ||
| qubit_last_node[q] = node | ||
|
|
||
| elif gate == "CX": | ||
| ctrl, tgt = qubits | ||
| node_ctrl = self.add_gate_node("CNOTc", ctrl, depth) | ||
| node_tgt = self.add_gate_node("CNOTt", tgt, depth) | ||
| self.add_cnot_links(node_ctrl, node_tgt, one_way_transversal_cnot=one_way_transversal_cnot) | ||
| for q, node in [(ctrl, node_ctrl), (tgt, node_tgt)]: | ||
| if qubit_last_node[q]: | ||
| self.add_regular_edge(qubit_last_node[q], node) | ||
| qubit_last_node[q] = node | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| def compute_min_cut(self) -> tuple[float, set[str], set[str]]: | ||
| """Compute the minimum s-t cut between the source and sink. | ||
|
|
||
| Returns: | ||
| ------- | ||
| Tuple[float, Set[str], Set[str]] | ||
| A tuple (cut_value, S, T) where: | ||
| - cut_value is the total capacity of the minimum cut, | ||
| - S is the set of nodes reachable from the source, | ||
| - T is the complementary set of nodes. | ||
| """ | ||
| cut_value, (S, T) = nx.minimum_cut(self.G, self.source, self.sink, capacity="capacity") # noqa: N806 | ||
| return cut_value, S, T | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.