@@ -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