code: def dfa_co_reachable(dfa: dict) -> dict:
      
  
      co_reachable_states = dfa['accepting_states'].copy()
      boundary = co_reachable_states.copy()
  
      # inverse transition function
      inverse_transitions = dict()
      for key, value in dfa['transitions'].items():
          inverse_transitions.setdefault(value, set()).add(key)
  
      while boundary:
          s = boundary.pop()
          if s in inverse_transitions:
              for (state, action) in inverse_transitions[s]:
                  if state not in co_reachable_states:
                      boundary.add(state)
                      co_reachable_states.add(state)
  
      dfa['states'] = co_reachable_states
  
      # If not s_0 ∈ S_F the resulting dfa is empty
      if dfa['initial_state'] not in dfa['states']:
          dfa = {
              'alphabet': set(),
              'states': set(),
              'initial_state': None,
              'accepting_states': set(),
              'transitions': dict()
          }
          return dfa
  
      transitions = dfa['transitions'].copy()
      for t in transitions:
          if t[0] not in dfa['states']:
              dfa['transitions'].pop(t)
          elif dfa['transitions'][t] not in dfa['states']:
              dfa['transitions'].pop(t)
  
      return dfa
docs: Side effects on input! Removes from the DFA all states that
      do not reach a final state and returns the pruned DFA.
  
      It is possible to remove from a DFA A all states that do not
      reach a final state without altering the language.
      The co-reachable dfa :math:`A_F` corresponding to A is
      defined as:
  
      :math:`A_F = (Σ, S_F , s_0 , ρ|S_F , F )`
  
      where
  
      • :math:`S_F` is the set of states that reach a final state
      • :math:`ρ|S_F` is the restriction on :math:`S_F × Σ` of ρ.
  
      :param dict dfa: input DFA.
      :return: *(dict)* representing the pruned DFA.