code: def find_rings(self, including=None):
          
  
          # Copies self.graph such that all edges (u, v) matched by edges (v, u)
          undirected = self.graph.to_undirected()
          directed = undirected.to_directed()
  
          cycles_nodes = []
          cycles_edges = []
  
          # Remove all two-edge cycles
          all_cycles = [c for c in nx.simple_cycles(directed) if len(c) > 2]
  
          # Using to_directed() will mean that each cycle always appears twice
          # So, we must also remove duplicates
          unique_sorted = []
          unique_cycles = []
          for cycle in all_cycles:
              if sorted(cycle) not in unique_sorted:
                  unique_sorted.append(sorted(cycle))
                  unique_cycles.append(cycle)
  
          if including is None:
              cycles_nodes = unique_cycles
          else:
              for i in including:
                  for cycle in unique_cycles:
                      if i in cycle and cycle not in cycles_nodes:
                          cycles_nodes.append(cycle)
  
          for cycle in cycles_nodes:
              edges = []
              for i, e in enumerate(cycle):
                  edges.append((cycle[i-1], e))
              cycles_edges.append(edges)
  
          return cycles_edges
docs: Find ring structures in the MoleculeGraph.
  
          :param including: list of site indices. If
          including is not None, then find_rings will
          only return those rings including the specified
          sites. By default, this parameter is None, and
          all rings will be returned.
          :return: dict {index:cycle}. Each
          entry will be a ring (cycle, in graph theory terms) including the index
          found in the Molecule. If there is no cycle including an index, the
          value will be an empty list.