@@ -257,6 +257,18 @@ def update(self, swap: tuple):
257
257
), self ._circuit_logical .index (swap [1 ])
258
258
self ._circuit_logical [idx_0 ], self ._circuit_logical [idx_1 ] = swap [1 ], swap [0 ]
259
259
260
+ def undo (self ):
261
+ """Undo the last swap. Method works in-place."""
262
+ last_swap_block = self ._routed_blocks .return_last_block ()
263
+ swap = tuple (self .physical_to_logical (q ) for q in last_swap_block .qubits )
264
+ self ._routed_blocks .remove_block (last_swap_block )
265
+ self ._swaps -= 1
266
+
267
+ idx_0 , idx_1 = self ._circuit_logical .index (
268
+ swap [0 ]
269
+ ), self ._circuit_logical .index (swap [1 ])
270
+ self ._circuit_logical [idx_0 ], self ._circuit_logical [idx_1 ] = swap [1 ], swap [0 ]
271
+
260
272
def get_logical_qubits (self , block : Block ):
261
273
"""Returns the current logical qubits where a block is acting on.
262
274
@@ -659,8 +671,7 @@ def __init__(
659
671
self .circuit = None
660
672
self ._memory_map = None
661
673
self ._final_measurements = None
662
- self ._temporary_added_swaps = 0
663
- self ._saved_circuit = None
674
+ self ._temp_added_swaps = []
664
675
random .seed (seed )
665
676
666
677
def __call__ (self , circuit : Circuit , initial_layout : dict ):
@@ -674,7 +685,6 @@ def __call__(self, circuit: Circuit, initial_layout: dict):
674
685
(:class:`qibo.models.circuit.Circuit`, dict): routed circuit and final layout.
675
686
"""
676
687
self ._preprocessing (circuit = circuit , initial_layout = initial_layout )
677
- self ._saved_circuit = deepcopy (self .circuit )
678
688
longest_path = np .max (self ._dist_matrix )
679
689
680
690
while self ._dag .number_of_nodes () != 0 :
@@ -687,9 +697,12 @@ def __call__(self, circuit: Circuit, initial_layout: dict):
687
697
# If the number of added swaps is too high, the algorithm is stuck.
688
698
# Reset the circuit to the last saved state and make the nearest gate executable by manually adding SWAPs.
689
699
if (
690
- self ._temporary_added_swaps > self .swap_threshold * longest_path
700
+ len ( self ._temp_added_swaps ) > self .swap_threshold * longest_path
691
701
): # threshold is arbitrary
692
- self .circuit = deepcopy (self ._saved_circuit )
702
+ while self ._temp_added_swaps :
703
+ swap = self ._temp_added_swaps .pop ()
704
+ self .circuit .undo ()
705
+ self ._temp_added_swaps = []
693
706
self ._shortest_path_routing ()
694
707
695
708
circuit_kwargs = circuit .init_kwargs
@@ -800,7 +813,7 @@ def _find_new_mapping(self):
800
813
for qubit in self .circuit .logical_to_physical (best_candidate , index = True ):
801
814
self ._delta_register [qubit ] += self .delta
802
815
self .circuit .update (best_candidate )
803
- self ._temporary_added_swaps += 1
816
+ self ._temp_added_swaps . append ( best_candidate )
804
817
805
818
def _compute_cost (self , candidate : int ):
806
819
"""Compute the cost associated to a possible SWAP candidate."""
@@ -897,8 +910,7 @@ def _execute_blocks(self, blocklist: list):
897
910
self ._update_front_layer ()
898
911
self ._memory_map = []
899
912
self ._delta_register = [1.0 for _ in self ._delta_register ]
900
- self ._temporary_added_swaps = 0
901
- self ._saved_circuit = deepcopy (self .circuit )
913
+ self ._temp_added_swaps = []
902
914
903
915
def _shortest_path_routing (self ):
904
916
"""Route a gate in the front layer using the shortest path. This method is executed when the standard SABRE fails to find an optimized solution.
0 commit comments