diff --git a/CHANGELOG.md b/CHANGELOG.md index cc4ee5b0..dd155fd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ parameter - `CircuitBuilder` accepts multiple (qu)bit registers through `add_register` method - Docstrings added to (user facing) public methods - Add `interaction_graph` as a property of the `Circuit`. +- Add `mapping` as an attribute of the `Circuit`, which contains an identity mapping, prior to any +arbitrarily applied mapper pass. ## [ 0.9.0 ] - [ 2025-12-19 ] diff --git a/opensquirrel/circuit.py b/opensquirrel/circuit.py index 78e168c7..d90d4f88 100644 --- a/opensquirrel/circuit.py +++ b/opensquirrel/circuit.py @@ -8,6 +8,7 @@ from opensquirrel.ir import Instruction from opensquirrel.ir.non_unitary import Measure from opensquirrel.ir.statement import AsmDeclaration +from opensquirrel.passes.mapper import IdentityMapper if TYPE_CHECKING: from opensquirrel.ir.ir import IR @@ -62,6 +63,7 @@ def __init__(self, register_manager: RegisterManager, ir: IR) -> None: """Create a circuit object from a register manager and an IR.""" self.register_manager = register_manager self.ir = ir + self.mapping = IdentityMapper().map(self, self.qubit_register_size) @classmethod def from_string(cls, cqasm_string: str) -> Circuit: @@ -176,9 +178,9 @@ def map(self, mapper: Mapper) -> None: """ from opensquirrel.passes.mapper.qubit_remapper import remap_ir - mapping = mapper.map(self, self.qubit_register_size) + self.mapping = mapper.map(self, self.qubit_register_size) - remap_ir(self, mapping) + remap_ir(self, self.mapping) def merge(self, merger: Merger) -> None: """Merges the circuit using the specified merger. diff --git a/tests/passes/mapper/test_general_mapper.py b/tests/passes/mapper/test_general_mapper.py index 12a00645..531a99cf 100644 --- a/tests/passes/mapper/test_general_mapper.py +++ b/tests/passes/mapper/test_general_mapper.py @@ -43,7 +43,9 @@ def remapped_circuit(self) -> Circuit: builder.CNOT(1, 0) builder.CNOT(0, 2) builder.measure(1, 0) - return builder.to_circuit() + circuit = builder.to_circuit() + circuit.mapping = Mapping([1, 0, 2]) + return circuit def test_circuit_map(self, circuit: Circuit, remapped_circuit: Circuit) -> None: mapper = HardcodedMapper(mapping=Mapping([1, 0, 2])) diff --git a/tests/test_circuit.py b/tests/test_circuit.py index 00a89654..8265cc06 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -3,6 +3,8 @@ from opensquirrel import Circuit, CircuitBuilder from opensquirrel.circuit import MeasurementToBitMap from opensquirrel.ir import AsmDeclaration +from opensquirrel.passes.mapper import HardcodedMapper, IdentityMapper +from opensquirrel.passes.mapper.mapping import Mapping def test_asm_filter() -> None: @@ -129,3 +131,59 @@ def test_interaction_graph_multi_qubit_gate_pairs() -> None: (0, 2): 1, (1, 2): 1, } + + +def test_mapping_attribute_initial_identity() -> None: + """Test that circuit.mapping is initially an identity mapping.""" + builder = CircuitBuilder(5) + builder.H(0) + builder.CNOT(0, 1) + circuit = builder.to_circuit() + + assert hasattr(circuit, "mapping") + assert isinstance(circuit.mapping, Mapping) + assert circuit.mapping == Mapping([0, 1, 2, 3, 4]) + + +def test_mapping_attribute_after_mapping() -> None: + """Test that circuit.mapping contains the mapping produced by circuit.map().""" + builder = CircuitBuilder(5) + builder.H(0) + builder.CNOT(0, 1) + circuit = builder.to_circuit() + + mapper = HardcodedMapper(Mapping([4, 3, 2, 1, 0])) + circuit.map(mapper=mapper) + + assert circuit.mapping == Mapping([4, 3, 2, 1, 0]) + + +def test_mapping_attribute_identity_mapping() -> None: + """Test that circuit.mapping doesn't change when identity mapper is applied.""" + builder = CircuitBuilder(3) + builder.H(0) + circuit = builder.to_circuit() + + initial_mapping = circuit.mapping + + mapper = IdentityMapper() + circuit.map(mapper=mapper) + + assert circuit.mapping == initial_mapping + assert circuit.mapping == Mapping([0, 1, 2]) + + +def test_mapping_attribute_from_string() -> None: + """Test that circuit.mapping is set correctly when creating a circuit from string.""" + circuit = Circuit.from_string( + """ + version 3.0 + qubit[4] q + H q[0] + CNOT q[0], q[1] + """ + ) + + assert hasattr(circuit, "mapping") + assert isinstance(circuit.mapping, Mapping) + assert circuit.mapping == Mapping([0, 1, 2, 3])