docs: def hopcroft(self):
          """
          Performs the Hopcroft minimization algorithm
          Args:
              None
          Returns:
              DFA: The minimized input DFA
          """
  
          def _getset(testset, partition):
              """
              Checks if a set is in a partition
              Args:
                  testset (set): The examined set
                  partition (list): A list of sets
              Returns:
                  bool: A value indicating if it is a member or not
              """
              for part in partition:
                  if set(testset) == set(part):
                      return True
              return None
  
          def _create_transitions_representation(graph):
              """
              In order to speedup the transition iteration using
              the alphabet, the function creates an index
              Args:
                  graph (DFA): The input dfa
                  state (DFA state): The examined state
              Returns:
                  dict: The generated transition map
              """
              return {x.stateid:{self.isyms.find(arc.ilabel): arc.nextstate \
                                 for arc in x} for x in graph.states}
  
          def _create_reverse_transitions_representation(graph):
              """
              In order to speedup the transition iteration using
              the alphabet, the function creates an index
              Args:
                  graph (DFA): The input dfa
                  state (DFA state): The examined state
              Returns:
                  dict: The generated transition map
              """
              return {x.stateid: {self.isyms.find(arc.ilabel): arc.nextstate \
                                  for arc in x} for x in graph.states}
  
          def _reverse_to_source(target, group1):
              """
              Args:
                  target (dict): A table containing the reverse transitions for each state
                  group1 (list): A group of states
              Return:
                  Set: A set of states for which there is a transition with the states of the group
              """
              new_group = []
              for dst in group1:
                  new_group += target[dst]
              return set(new_group)
  
          def _get_group_from_state(groups, sid):
              """
              Args:
                  sid (int): The state identifier
              Return:
                  int: The group identifier that the state belongs
              """
              for index, selectgroup in enumerate(groups):
                  if sid in selectgroup:
                      return index
  
          def _delta(graph, cur_state, char):
              """
              Function describing the transitions
              Args:
                  graph (DFA): The DFA states
                  cur_state (DFA state): The DFA current state
                  char (str):: The char that will be used for the transition
              Return:
                  DFA Node: The next state
              """
              for arc in cur_state.arcs:
                  if graph.isyms.find(arc.ilabel) == char:
                      return graph[arc.nextstate]
  
          def _partition_group(bookeeping, group):
              """
              Args:
                  group (list):  A group of states
              Return:
                  tuple: A set of two groups
              """
              for (group1, group2) in bookeeping:
                  if group & group1 != set() and not group.issubset(group1):
                      new_g1 = group & group1
                      new_g2 = group - group1
                      return (new_g1, new_g2)
                  if group & group2 != set() and not group.issubset(group2):
                      new_g1 = group & group2
                      new_g2 = group - group2
                      return (new_g1, new_g2)
              assert False, "Unmatched group partition"
  
          def _object_set_to_state_list(objectset):
              """
              Args:
                  objectset (list): A list of all the DFA states (as objects)
              Return:
                  list: A list of all the DFA states (as identifiers)
              """
              return [state.stateid for state in objectset]
  
          def _get_accepted(graph):
              """
              Find the accepted states
              Args:
                  graph (DFA): The DFA states
              Return:
                  list: Returns the list of the accepted states
              """
              return [state for state in graph \
                      if  state.final != TropicalWeight(float('inf'))]
  
          graph = self
  
          # Find Q
          set_q = set(_object_set_to_state_list(graph.states))
          # We will work with states addresses here instead of states stateid for
          # more convenience
          set_f = set(_object_set_to_state_list(_get_accepted(graph)))
          # Perform P := {F, Q-F}
          set_nf = set_q.copy() - set_f.copy()
          groups = [set_f.copy(), set_nf.copy()]
          bookeeping = [(set_f, set_nf)]
  
          done = False
          while not done:
              done = True
              new_groups = []
              for selectgroup in groups:
                  # _check for each letter if it splits the current group
                  for character in self.alphabet:
                      # print 'Testing symbol: ', c
                      target = defaultdict(list)
                      target_states = defaultdict(int)
                      new_g = [set(selectgroup)]
                      for sid in selectgroup:
                          # _check if all transitions using c are going in a state
                          # in the same group. If they are going on a different
                          # group then split
                          deststate = _delta(graph, graph[sid], character)
                          destgroup = _get_group_from_state(groups,
                              deststate.stateid)
                          target[destgroup].append(sid)
                          target_states[destgroup] = deststate.stateid
                      if len(target) > 1:
  
                          inv_target_states = {
                              v: k for k, v in target_states.iteritems()}
                          new_g = [set(selectedstate) for selectedstate in target.values()]
                          done = False
                          # Get all the partitions of destgroups
                          queue = [set([x for x in target_states.values()])]
                          while queue:
                              top = queue.pop(0)
                              (group1, group2) = _partition_group(bookeeping, top)
                              ng1 = _reverse_to_source(
                                  target, [inv_target_states[x] for x in group1])
                              ng2 = _reverse_to_source(
                                  target, [inv_target_states[x] for x in group2])
  
                              bookeeping.append((ng1, ng2))
  
                              if len(group1) > 1:
                                  queue.append(group1)
                              if len(group2) > 1:
                                  queue.append(group2)
                          break
                  new_groups += new_g
  
              # End of iteration for the k-equivalence
              # Assign new groups and check if any change occured
              groups = new_groups
  
          # Make a copy of the old states, and prepare the
          # automaton to host the minimum states
  
          oldstates = copy.deepcopy(self.states)
          self.states = []
          self.define()
  
          def findpart(stateid, partitions):
              """Searches for the groupt that the state identifier
              belongs to.
              Args:
                  stateid (int): The state identifier
                  partitions (list): The list of the groups
              Returns:
                  set: The group that the stateid belongs to.
              """
              for group in partitions:
                  if stateid in group:
                      return frozenset(group)
              return frozenset(set(            ))
  
          def add_state_if_not_exists(group, statesmap, final):
              """
              Adds a new state in the final dfa. It initialy checks if
              the group of states is already registered to the automaton.
              If it is registered, the state identifier is returned, or
              else, a new state is added.
              Args:
                  group (frozenset):  The group that the state identifier belongs
                  statesmap (dict):   A dictionary that maintains the state
                                      identifiers for each forzenset
                  final (bool):       A value indicating if the current state is
                                      final
              Returns:
                  int: The new state identifier
              """
              if group not in statesmap:
                  sid = self.add_state()
                  self[sid].final = final
                  statesmap[group] = sid
              return statesmap[group]
  
          statesmap = {}
          self.states = []
          group = findpart(0, groups)
          sid = add_state_if_not_exists(frozenset(list(group)), statesmap,
                                        oldstates[0].final)
          self[sid].initial = True
          for group in groups:
              if len(group) == 0:
                  continue
              sid = add_state_if_not_exists(frozenset(group), statesmap,
                                            oldstates[list(group)[0]].final)
              state = next(iter(group))
              for arc in oldstates[state]:
                  dst_group = findpart(arc.nextstate, groups)
                  dst_sid = add_state_if_not_exists(
                      dst_group, statesmap, oldstates[arc.nextstate].final)
                  self.add_arc(sid, dst_sid, graph.isyms.find(arc.ilabel))