docs: def find_matches(self, topology):
          """Return sets of atoms that match this SMARTS pattern in a topology.
  
          Notes:
          ------
          When this function gets used in atomtyper.py, we actively modify the
          white- and blacklists of the atoms in `topology` after finding a match.
          This means that between every successive call of
          `subgraph_isomorphisms_iter()`, the topology against which we are
          matching may have actually changed. Currently, we take advantage of this
          behavior in some edges cases (e.g. see `test_hexa_coordinated` in
          `test_smarts.py`).
  
          """
          # Note: Needs to be updated in sync with the grammar in `smarts.py`.
          ring_tokens = ['ring_size', 'ring_count']
          has_ring_rules = any(self.ast.select(token)
                               for token in ring_tokens)
          _prepare_atoms(topology, compute_cycles=has_ring_rules)
  
          top_graph = nx.Graph()
          top_graph.add_nodes_from(((a.index, {'atom': a})
                                    for a in topology.atoms()))
          top_graph.add_edges_from(((b[0].index, b[1].index)
                                    for b in topology.bonds()))
  
          if self._graph_matcher is None:
              atom = nx.get_node_attributes(self, name='atom')[0]
              if len(atom.select('atom_symbol')) == 1 and not atom.select('not_expression'):
                  try:
                      element = atom.select('atom_symbol').strees[0].tail[0]
                  except IndexError:
                      try:
                          atomic_num = atom.select('atomic_num').strees[0].tail[0]
                          element = pt.Element[int(atomic_num)]
                      except IndexError:
                          element = None
              else:
                  element = None
              self._graph_matcher = SMARTSMatcher(top_graph, self,
                                                  node_match=self._node_match,
                                                  element=element)
  
          matched_atoms = set()
          for mapping in self._graph_matcher.subgraph_isomorphisms_iter():
              mapping = {node_id: atom_id for atom_id, node_id in mapping.items()}
              # The first node in the smarts graph always corresponds to the atom
              # that we are trying to match.
              atom_index = mapping[0]
              # Don't yield duplicate matches found via matching the pattern in a
              # different order.
              if atom_index not in matched_atoms:
                  matched_atoms.add(atom_index)
                  yield atom_index