Skip to content

Commit e3a42f2

Browse files
committed
Updated get_subgraphs_of_size to use a Redelmeier/ESU hybrid
1 parent f6ba5ff commit e3a42f2

File tree

1 file changed

+57
-40
lines changed

1 file changed

+57
-40
lines changed

bqskit/qis/graph.py

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,11 @@ def get_subgraph(
429429
subgraph.append((renumbering[q_i], renumbering[q_i_neighbor]))
430430
return CouplingGraph(subgraph, len(location))
431431

432-
def get_subgraphs_of_size(self, size: int) -> list[CircuitLocation]:
432+
def get_subgraphs_of_size(
433+
self,
434+
size: int,
435+
include_smaller: bool = False,
436+
) -> list[CircuitLocation]:
433437
"""
434438
Find all sets of indices that form connected subgraphs on their own.
435439
@@ -441,6 +445,9 @@ def get_subgraphs_of_size(self, size: int) -> list[CircuitLocation]:
441445
Args:
442446
size (int): The size of each location in the final list.
443447
448+
include_smaller (bool): Includes subgraphs with size less
449+
than `size`. (Default: False)
450+
444451
Returns:
445452
list[CircuitLocation]: The locations compliant with the machine.
446453
@@ -466,67 +473,77 @@ def get_subgraphs_of_size(self, size: int) -> list[CircuitLocation]:
466473
if size <= 0:
467474
raise ValueError(f'Nonpositive size; got {size}.')
468475

469-
locations: set[frozenset[int]] = set()
476+
subgraphs: list[tuple[int, ...]] = list()
470477

471478
for qudit in range(self.num_qudits):
472-
# Get every valid set containing `qudit` with size <= size
473-
self._location_search(locations, set(), qudit, size)
479+
subgraph = [qudit]
480+
extension = {q for q in self._adj[qudit] if q > qudit}
481+
exclusion = {qudit}
482+
self._extend_subgraph(
483+
size, subgraph, extension,
484+
exclusion, qudit, subgraphs, include_smaller,
485+
)
474486

475-
# filter groups with size < size and convert remaining
476-
# groups to CircuitLocation
477487
locations: list[CircuitLocation] = [
478-
CircuitLocation(
479-
list(group),
480-
) for group in locations if len(group) == size
488+
CircuitLocation(list(group)) for group in subgraphs
481489
]
482490

483491
return locations
484492

485-
def _location_search(
493+
def _extend_subgraph(
486494
self,
487-
locations: set[frozenset[int]],
488-
path: set[int],
495+
size: int,
496+
subgraph: list[int],
497+
extension: set[int],
498+
exclusion: set[int],
489499
vertex: int,
490-
limit: int,
500+
subgraphs: list[tuple[int, ...]],
501+
include_smaller: bool,
491502
) -> None:
492503
"""
493-
Add paths with length equal to limit to the `locations` set.
504+
Add subgraphs with size equal to `size` to the `subgraphs` list.
494505
495506
Args:
496-
locations (set[frozenset[int]]): A list that contains all paths
497-
found so far of length equal to `limit`.
507+
size (int): The desired size of subgraphs in the
508+
`subgraphs` set.
498509
499-
path (set[int]): The qudit vertices currently included in
500-
the path.
510+
subgraph (list[int]): The qudit vertices currently included
511+
in the subgraph.
501512
502-
vertex (int): The vertex in the graph currently being examined.
513+
extension (set[int]): The qudit vertices currently being
514+
considered for addition to the subgraph.
503515
504-
limit (int): The desired length of paths in the `locations`
505-
list.
506-
"""
507-
if vertex in path:
508-
return
516+
exclusion (set[int]): The qudit vertices which have already
517+
been searched.
509518
510-
curr_path = path.copy()
511-
curr_path.add(vertex)
519+
vertex (int): The vertex in the graph currently being examined.
512520
513-
if frozenset(curr_path) in locations:
514-
return
521+
subgraphs (list[tuple[int,...]]): A list that contains all subgraphs
522+
found so far of length equal to `size`.
515523
516-
if len(curr_path) <= limit:
517-
locations.add(frozenset(curr_path))
518-
if len(curr_path) == limit:
524+
include_smaller (bool): Includes subgraphs with size less
525+
than `size`.
526+
"""
527+
if len(subgraph) == size or (include_smaller and len(subgraph) < size):
528+
subgraphs.append(tuple(subgraph))
529+
if len(subgraph) == size:
519530
return
520531

521-
frontier: set[int] = {
522-
qudit
523-
for node in curr_path
524-
for qudit in self._adj[node]
525-
if qudit not in curr_path
526-
}
527-
528-
for neighbor in frontier:
529-
self._location_search(locations, curr_path, neighbor, limit)
532+
while len(extension) > 0:
533+
w = extension.pop()
534+
exclusion.add(w)
535+
new_extension = set(extension)
536+
for neighbor in self._adj[w]:
537+
if neighbor > vertex and neighbor not in exclusion:
538+
new_extension.add(neighbor)
539+
540+
subgraph.append(w)
541+
self._extend_subgraph(
542+
size, subgraph, new_extension, set(
543+
exclusion,
544+
), vertex, subgraphs, include_smaller,
545+
)
546+
subgraph.pop()
530547

531548
@staticmethod
532549
def is_valid_coupling_graph(

0 commit comments

Comments
 (0)