diff --git a/src/iqm/iqm_client/transpile.py b/src/iqm/iqm_client/transpile.py index a1b194c39..f31f9d150 100644 --- a/src/iqm/iqm_client/transpile.py +++ b/src/iqm/iqm_client/transpile.py @@ -38,7 +38,7 @@ from collections.abc import Iterable from enum import Enum -from typing import Any, Optional +from typing import Optional import warnings from iqm.iqm_client import ( @@ -163,39 +163,30 @@ def create_move_instructions( self, qubit: str, resonator: str, - *, - apply_move: Optional[bool] = True, - reverse_qubit_mapping: Optional[dict[str, str]] = None, ) -> Iterable[Instruction]: """MOVE instruction(s) to move the state of the given resonator into the - resonator if needed and then move resonator state to the given qubit. + qubit that owns it if needed, and then move the state of the given qubit to the resonator. Args: qubit: The qubit resonator: The resonator - apply_move: Whether the moves should be applied to the resonator tracking state. - reverse_qubit_mapping: Mapping of physical qubit names to logical qubit names. Yields: The one or two MOVE instructions needed. """ res_state_owner = self.res_state_owner[resonator] if res_state_owner not in [qubit, resonator]: - other = res_state_owner - if apply_move: - self.apply_move(other, resonator) - qbs = tuple(reverse_qubit_mapping[q] if reverse_qubit_mapping else q for q in [other, resonator]) - yield Instruction(name=self.move_gate, qubits=qbs, args={}) - if apply_move: - self.apply_move(qubit, resonator) - qbs = tuple(reverse_qubit_mapping[q] if reverse_qubit_mapping else q for q in [qubit, resonator]) - yield Instruction(name=self.move_gate, qubits=qbs, args={}) + locus = (res_state_owner, resonator) + self.apply_move(*locus) + yield Instruction(name=self.move_gate, qubits=locus, args={}) + + locus = (qubit, resonator) + self.apply_move(*locus) + yield Instruction(name=self.move_gate, qubits=locus, args={}) def reset_as_move_instructions( self, resonators: Optional[Iterable[str]] = None, - *, - reverse_qubit_mapping: Optional[dict[str, str]] = None, ) -> list[Instruction]: """MOVE instructions that move all the states held in the given resonators back to their qubits. @@ -204,7 +195,6 @@ def reset_as_move_instructions( Args: resonators: Resonators that hold qubit states that should be moved back to the qubits. If ``None``, the states in any resonators will be returned to the qubits. - reverse_qubit_mapping: Mapping of physical qubit names to logical qubit names. Returns: Instructions needed to move all qubit states out of the resonators. @@ -215,9 +205,9 @@ def reset_as_move_instructions( instructions: list[Instruction] = [] for r, q in self.res_state_owner.items(): if r != q and r in resonators: - locus = tuple(reverse_qubit_mapping[q] if reverse_qubit_mapping else q for q in [q, r]) + locus = (q, r) instructions.append(Instruction(name=self.move_gate, qubits=locus, args={})) - self.apply_move(q, r) + self.apply_move(*locus) return instructions def available_resonators_to_move(self, qubits: Iterable[str]) -> dict[str, list[str]]: @@ -242,7 +232,9 @@ def resonators_holding_qubits(self, qubits: Iterable[str]) -> list[str]: """ return [r for r, q in self.res_state_owner.items() if q in qubits and q not in self.resonators] - def choose_move_pair(self, qubits: list[str], remaining_instructions: Iterable[Instruction]) -> list[tuple[str, str]]: + def choose_move_pair( + self, qubits: list[str], remaining_instructions: Iterable[Instruction] + ) -> list[tuple[str, str]]: """Choose which of the given qubits to move into which resonator. The choice is made using a heuristic based on the given lookahead sequence diff --git a/tests/test_transpiler.py b/tests/test_transpiler.py index eb65e20d7..6d4c87ecb 100644 --- a/tests/test_transpiler.py +++ b/tests/test_transpiler.py @@ -434,7 +434,6 @@ def test_unavailable_cz(self): class TestResonatorStateTracker: - reverse_qubit_mapping = {'COMP_R': 'A', 'QB1': 'B', 'QB3': 'C'} def test_apply_move(self, sample_dynamic_architecture, sample_move_architecture): # Check handling of an architecture without a resonator @@ -462,30 +461,21 @@ def test_create_move_instructions(self, sample_move_architecture): sample_move_architecture.gates['move'].implementations[default_move_impl].loci += (('QB1', 'COMP_R'),) status = ResonatorStateTracker.from_dynamic_architecture(sample_move_architecture) instr = Instruction(name='move', qubits=('QB3', 'COMP_R'), args={}) - # Check insertion without and with apply_move - gen_instr = tuple(status.create_move_instructions('QB3', 'COMP_R', apply_move=False)) + # Check insertion + gen_instr = tuple(status.create_move_instructions('QB3', 'COMP_R')) assert len(gen_instr) == 1 assert gen_instr[0] == instr - assert status.res_state_owner['COMP_R'] == 'COMP_R' - gen_instr = tuple(status.create_move_instructions('QB3', 'COMP_R', apply_move=True)) + assert status.res_state_owner['COMP_R'] == 'QB3' + gen_instr = tuple(status.create_move_instructions('QB3', 'COMP_R')) assert len(gen_instr) == 1 assert gen_instr[0] == instr - assert status.res_state_owner['COMP_R'] == 'QB3' + assert status.res_state_owner['COMP_R'] == 'COMP_R' status.res_state_owner['COMP_R'] = 'QB1' - # Check removal without and with apply_move - gen_instr = tuple(status.create_move_instructions('QB3', 'COMP_R', apply_move=False)) + # Check removal + gen_instr = tuple(status.create_move_instructions('QB3', 'COMP_R')) assert len(gen_instr) == 2 assert gen_instr[0] == Instruction(name='move', qubits=('QB1', 'COMP_R'), args={}) assert gen_instr[1] == instr - # Check with a qubit mapping - gen_instr = tuple( - status.create_move_instructions( - 'QB3', 'COMP_R', apply_move=True, reverse_qubit_mapping=self.reverse_qubit_mapping - ) - ) - assert len(gen_instr) == 2 - assert gen_instr[0] == Instruction(name='move', qubits=('B', 'A'), args={}) - assert gen_instr[1] == Instruction(name='move', qubits=('C', 'A'), args={}) assert status.res_state_owner['COMP_R'] == 'QB3' def test_reset_as_move_instructions(self, sample_move_architecture): @@ -499,12 +489,6 @@ def test_reset_as_move_instructions(self, sample_move_architecture): assert len(gen_instr) == 1 assert gen_instr[0] == Instruction(name='move', qubits=('QB3', 'COMP_R'), args={}) assert status.res_state_owner['COMP_R'] == 'COMP_R' - # Reset without argument, with qubit mapping - status.apply_move('QB3', 'COMP_R') - gen_instr = tuple(status.reset_as_move_instructions(reverse_qubit_mapping=self.reverse_qubit_mapping)) - assert len(gen_instr) == 1 - assert gen_instr[0] == Instruction(name='move', qubits=('C', 'A'), args={}) - assert status.res_state_owner['COMP_R'] == 'COMP_R' # Reset without arguments status.apply_move('QB3', 'COMP_R') gen_instr = tuple(status.reset_as_move_instructions())