Source code for mqt.ionshuttler.multi_shuttler.inside.compilation

# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
# All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Licensed under the MIT License

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

from ..circuit_parsing import is_qasm_file, parse_qasm_circuit

if TYPE_CHECKING:
    from ..circuit_types import ParsedCircuit


[docs] def parse_qasm(filename: Path) -> list[tuple[int, ...]]: """Parse a QASM file and return qubits used for each gate preserving their order.""" return parse_qasm_circuit(filename, normalize_registers=False).qubit_sequence
[docs] def create_initial_circuit(filename: Path) -> ParsedCircuit: """Return a canonicalized parsed circuit with stable gate ids.""" return parse_qasm_circuit(filename)
[docs] def compile(filename: Path | str) -> list[tuple[int, ...]]: # ruff:ignore[builtin-variable-shadowing] """Compile a QASM file and return the compiled sequence of qubits.""" filename = Path(filename) # Check if the file is a valid QASM file if not is_qasm_file(filename): msg = "Invalid QASM file format" raise ValueError(msg) # Parse the QASM file to extract the qubits used for each gate return parse_qasm(filename)
# print(gates_and_qubits) # # Compile the sequence of qubits # sequence = [] # for qubits in gates_and_qubits: # for qubit in qubits: # sequence.append(qubit) # def get_front_layer(dag): # """Get the front layer of the DAG.""" # front_layer = [] # for node in dag.get_nodes(): # # If a node has no predecessors, it's in the front layer # if not dag.direct_predecessors(node.node_id): # front_layer.append(node) # return front_layer # def remove_node(dag, node): # """Execute a node and update the DAG (remove the node and its edges).""" # # if dag.direct_successors(node.node_id): # # for successor in dag.direct_successors(node.node_id): # # dag._multi_graph.remove_edge(node.node_id, successor) # dag._multi_graph.remove_node(node.node_id) # def find_best_gate(front_layer, dist_map): # """Find the best gate to execute based on distance.""" # min_gate_cost = math.inf # for _i, gate_node in enumerate(front_layer): # qubit_indices = gate_node.qindices # gate_cost = max([dist_map[qs] for qs in qubit_indices]) # # if both ions of 2-qubit gate are in pz execute 2-qubit gate # if len(qubit_indices) == 2 and gate_cost == 0: # return gate_node # if gate_cost < min_gate_cost: # min_gate_cost = gate_cost # best_gate = gate_node # return best_gate # def manual_copy_dag(dag): # new_dag = DAGDependency() # # Recreate quantum registers in the new DAG # for qreg in dag.qregs.values(): # new_dag.add_qreg(qreg) # # Iterate over all operation nodes in the original DAG and copy them # for node in dag.get_nodes(): # new_dag.add_op_node(node.op, node.qargs, node.cargs) # return new_dag # def update_sequence(dag, dist_map): # """Get the sequence of gates from the DAG. # Creates a new DAG and removes all gates from it while creating the sequence.""" # working_dag = manual_copy_dag(dag) # sequence = [] # i = 0 # while True: # first_gates = get_front_layer(working_dag) # if not first_gates: # break # first_gate_to_execute = find_best_gate(first_gates, dist_map) # if i == 0: # first_node = first_gate_to_execute # i = 1 # remove_node(working_dag, first_gate_to_execute) # sequence.append(first_gate_to_execute.qindices) # return sequence, first_node