def greedy_router(problem_instance: dimod.BinaryQuadraticModel, qpu: Type[QPU]): #find edge coloring for problem graph #color_sets = edge_coloring.find_edge_coloring(problem_instance.to_networkx_graph()) #color_sets = sorted(color_sets, key=lambda color_set: len(color_set), reverse=True) # find initial mapping and execute interaction gates #initial_mapping, int_layer = int_pair_mapper(qpu, problem_instance, color_sets[0]) initial_mapping, int_layers = twoColorMapper(problem_instance, qpu) route = Routing(problem_instance, qpu, initial_mapping=initial_mapping) int_count = 0 for int_layer in int_layers: for int_gate in int_layer: int_count += 1 route.apply_int(int_gate) print(int_count) # find valid edge coloring #route = Routing(problem_instance, qpu) color_sets = edge_coloring.find_edge_coloring(route.remaining_interactions) color_sets = sorted(color_sets, key=lambda color_set: len(color_set), reverse=True) #finish remaining layers of color sets for color_set in color_sets: greedy_pair_mapper(route, color_set) return route
def setUp(self) -> None: gr = nx.grid_2d_graph(2, 2) gr.add_edge((0, 0), (1, 1)) self.qpu = Grid2dQPU(2, 2) self.problem_instance = dimod.generators.random.uniform(gr, dimod.SPIN) init_map = {cirq.GridQubit(*loc): loc for loc in self.problem_instance.variables} self.initial_mapping = Mapping(self.qpu, self.problem_instance, initial_mapping=init_map) self.routing = Routing(self.problem_instance, self.qpu, cp.deepcopy(self.initial_mapping))
def fallback_routine(routing: Routing, int_pairs: Set[frozenset]) -> None: @lru_cache(maxsize=None) def deterministic_pair(int_pairs): int_pairs_copy = copy(set(int_pairs)) return int_pairs_copy.pop() det_pair = deterministic_pair(frozenset(int_pairs)) hard_qb0 = routing.mapping.log2hard[list(det_pair)[0]] hard_qb1 = routing.mapping.log2hard[list(det_pair)[1]] shortest_path = nx.shortest_path(routing.qpu.graph, hard_qb0, hard_qb1) routing.apply_swap(frozenset(shortest_path[:2]))
def test_execute_all_possible_int_gates(self): qpu = Grid2dQPU(2, 2) linear = {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0} quadratic = {(0, 1): 1, (1, 2): 1, (2, 3): 1, (3, 0): 1} bqm = dimod.BinaryQuadraticModel(linear, quadratic, 0.0, dimod.SPIN) initial_mapping_dict = { cirq.GridQubit(0, 0): 0, cirq.GridQubit(1, 0): 1, cirq.GridQubit(0, 1): 2, cirq.GridQubit(1, 1): 3 } mapping = Mapping(qpu, bqm, partial_initial_mapping=initial_mapping_dict) int_pairs = {frozenset((0, 1)), frozenset((0, 2)), frozenset((2, 3))} route = Routing(bqm, qpu, initial_mapping=mapping) gate_executed = execute_all_possible_int_gates(route, int_pairs) self.assertTrue( gate_executed, msg= 'did not execute a single int gate even though log qubits are adjacent on the qpu' ) test = route.layers[-1].gates[cirq.GridQubit(0, 0)][cirq.GridQubit( 1, 0)]['int'] and route.layers[-1].gates[cirq.GridQubit( 0, 1)][cirq.GridQubit(1, 1)]['int'] self.assertTrue( test, msg='did not execute maximal possible set of int gates')
def test_int_pair_distance_change(self): qpu = Grid2dQPU(2, 2) bqm = dimod.generators.randint(qpu.graph, dimod.SPIN) route = Routing(bqm, qpu) log_qb0 = route.mapping.hard2log[cirq.GridQubit(0, 0)] log_qb1 = route.mapping.hard2log[cirq.GridQubit(0, 1)] int_pairs = {frozenset((log_qb0, log_qb1))} swap = frozenset((cirq.GridQubit(0, 0), cirq.GridQubit(0, 1))) self.assertEqual( 0, int_pair_distance_change(route, int_pairs, swap), msg='swap distance did change after swap on interaction pair') log_qb0 = route.mapping.hard2log[cirq.GridQubit(0, 0)] log_qb1 = route.mapping.hard2log[cirq.GridQubit(1, 1)] int_pairs = {frozenset((log_qb0, log_qb1))} swap = frozenset((cirq.GridQubit(0, 0), cirq.GridQubit(1, 0))) self.assertEqual(1, int_pair_distance_change(route, int_pairs, swap), msg='swap distance change is incorrect') log_qb0 = route.mapping.hard2log[cirq.GridQubit(0, 1)] log_qb1 = route.mapping.hard2log[cirq.GridQubit(1, 0)] int_pairs.add(frozenset((log_qb0, log_qb1))) self.assertEqual(2, int_pair_distance_change(route, int_pairs, swap), msg='swap distance change is incorrect')
def test_randomized_greedy_pair_mapper(self): for bqm in self.bqm_arr: color_sets = find_edge_coloring(bqm.to_networkx_graph()) route = Routing(bqm, self.qpu) greedy_pair_mapper(route, color_sets[0]) for color_pair in color_sets[0]: self.assertFalse( route.remaining_interactions.has_edge(*color_pair), msg='did not execute interaction given in int pairs')
def execute_all_possible_int_gates(routing: Routing, int_pairs: Set[frozenset]) -> bool: int_graph = nx.Graph() gate_executed = False for int_pair in int_pairs: hard_qb0 = routing.mapping.log2hard[list(int_pair)[0]] hard_qb1 = routing.mapping.log2hard[list(int_pair)[1]] if routing.qpu.graph.has_edge(hard_qb0, hard_qb1): if routing.layers[-1].int_gate_applicable(frozenset((hard_qb0, hard_qb1))): int_graph.add_edge(hard_qb1, hard_qb0) gate_executed = True matching = nx.maximal_matching(int_graph) for match in matching: gate = frozenset(match) log_qb0 = routing.mapping.hard2log[list(match)[0]] log_qb1 = routing.mapping.hard2log[list(match)[1]] int_pair = frozenset((log_qb0, log_qb1)) routing.apply_int(gate) int_pairs.remove(int_pair) return gate_executed
def test_int_pair_distance(self): for bqm in self.bqm_arr: color_sets = find_edge_coloring(bqm.to_networkx_graph()) for color_set in color_sets: mapping, int_layer = int_pair_mapper(self.qpu, bqm, color_set) route = Routing(bqm, self.qpu, mapping) self.assertEqual( 0, int_pair_distance(route, color_set), msg= 'does not correctly calculate the total int_pair distance')
def decrease_int_pair_distance(routing: Routing, int_pairs: Set[frozenset]) -> bool: gate_executed = False for _ in range(routing.qpu.graph.size()): no_swap_gate_executed = True swap1_gate = None for hard_qb0, hard_qb1 in routing.qpu.graph.edges(): swap_gate = frozenset((hard_qb0, hard_qb1)) if routing.layers[-1].swap_gate_applicable(swap_gate): diff = int_pair_distance_change(routing, int_pairs, swap_gate) if diff == 2: routing.apply_swap(swap_gate) gate_executed = True no_swap_gate_executed = False elif diff == 1: swap1_gate = swap_gate if no_swap_gate_executed: if swap1_gate is not None: routing.apply_swap(swap1_gate) gate_executed = True continue else: break return gate_executed
def test_greedy_pair_mapper(self): qpu = Grid2dQPU(2, 2) linear = {0: 0.0, 1: 0.0, 2: 0.0, 3: 0.0} quadratic = { (0, 1): 1, (1, 2): 1, (2, 3): 1, (3, 0): 1, (0, 2): 1, (1, 3): 1 } bqm = dimod.BinaryQuadraticModel(linear, quadratic, 0.0, dimod.SPIN) int_pairs = {frozenset((0, 2)), frozenset((1, 3))} route = Routing(bqm, qpu) greedy_pair_mapper(route, int_pairs) for pair in int_pairs: self.assertFalse( route.remaining_interactions.has_edge(*pair), msg='did not execute interaction given in int pairs')
def test_decrease_int_pair_distance(self): for bqm in self.bqm_arr: color_sets = find_edge_coloring(bqm.to_networkx_graph()) route = Routing(bqm, self.qpu) dist_before = int_pair_distance(route, color_sets[0]) gate_executed = decrease_int_pair_distance(route, color_sets[0]) dist_after = int_pair_distance(route, color_sets[0]) if gate_executed: self.assertTrue( dist_before > dist_after, msg= 'even though swap gate was applied the int_pair_distance did not decrease' ) else: self.assertEqual( dist_before, dist_after, msg= 'int_pair_distance did change even though no swap was applied' )
class TestRouting(TestCase): def setUp(self) -> None: gr = nx.grid_2d_graph(2, 2) gr.add_edge((0, 0), (1, 1)) self.qpu = Grid2dQPU(2, 2) self.problem_instance = dimod.generators.random.uniform(gr, dimod.SPIN) init_map = {cirq.GridQubit(*loc): loc for loc in self.problem_instance.variables} self.initial_mapping = Mapping(self.qpu, self.problem_instance, initial_mapping=init_map) self.routing = Routing(self.problem_instance, self.qpu, cp.deepcopy(self.initial_mapping)) def test_apply_swap(self) -> None: self.routing.apply_swap(frozenset((cirq.GridQubit(0, 0), cirq.GridQubit(1, 0)))) self.assertEqual(self.initial_mapping.hard2log[cirq.GridQubit(0, 0)], self.routing.mapping.hard2log[cirq.GridQubit(1, 0)], msg="application of swap gate did not update mapping") self.assertEqual(self.initial_mapping.hard2log[cirq.GridQubit(1, 0)], self.routing.mapping.hard2log[cirq.GridQubit(0, 0)], msg="application of swap gate did not update mapping") self.assertTrue(self.routing.layers[0].gates[cirq.GridQubit(0, 0)][cirq.GridQubit(1, 0)]['swap'], msg="did not add swap gate to layer") self.routing.apply_swap(frozenset((cirq.GridQubit(0, 1), cirq.GridQubit(1, 1)))) self.assertEqual(self.initial_mapping.hard2log[cirq.GridQubit(0, 1)], self.routing.mapping.hard2log[cirq.GridQubit(1, 1)], msg="application of swap gate did not update mapping") self.assertEqual(self.initial_mapping.hard2log[cirq.GridQubit(1, 1)], self.routing.mapping.hard2log[cirq.GridQubit(0, 1)], msg="application of swap gate did not update mapping") self.assertTrue(self.routing.layers[0].gates[cirq.GridQubit(0, 1)][cirq.GridQubit(1, 1)]['swap'], msg="did not add swap gate to layer") self.routing.apply_swap(frozenset((cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)))) self.assertTrue(self.routing.layers[1].gates[cirq.GridQubit(0, 0)][cirq.GridQubit(0, 1)]['swap'], msg="did not add layer containing new swap gate") self.routing.draw() def test_apply_int(self) -> None: self.routing.apply_int(frozenset((cirq.GridQubit(0, 0), cirq.GridQubit(1, 0)))) self.assertTrue(self.routing.layers[0].gates[cirq.GridQubit(0, 0)][cirq.GridQubit(1, 0)]['int'], msg="did not add int gate to layer") self.assertFalse(self.routing.remaining_interactions.has_edge(cirq.GridQubit(0, 0), cirq.GridQubit(1, 0)), msg='interaction has not been deleted from routing.remaining_interactions') self.routing.apply_int(frozenset((cirq.GridQubit(0, 1), cirq.GridQubit(1, 1)))) self.assertTrue(self.routing.layers[0].gates[cirq.GridQubit(0, 1)][cirq.GridQubit(1, 1)]['int'], msg="did not add int gate to layer") self.assertFalse(self.routing.remaining_interactions.has_edge(cirq.GridQubit(0, 1), cirq.GridQubit(1, 1)), msg='interaction has not been deleted from routing.remaining_interactions') self.routing.apply_int(frozenset((cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)))) self.assertTrue(self.routing.layers[1].gates[cirq.GridQubit(0, 0)][cirq.GridQubit(0, 1)]['int'], msg="did not add layer containing new int gate") self.assertFalse(self.routing.remaining_interactions.has_edge(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)), msg='interaction has not been deleted from routing.remaining_interactions')
def int_pair_distance_change(routing: Routing, int_pairs: Set[frozenset], swap: frozenset) -> int: dist_before = int_pair_distance(routing, int_pairs) routing.apply_swap(swap) dist_after = int_pair_distance(routing, int_pairs) routing.apply_swap(swap) return dist_before - dist_after