private String getName(AbstractState pState) {
   if (pState instanceof AutomatonState) {
     return ((AutomatonState) pState).getOwningAutomatonName();
   }
   if (pState instanceof PredicateAbstractState) {
     return PredicateAbstractState.class.getName();
   }
   return pState.getClass().getName();
 }
  private Pair<Map<String, Integer>, List<AbstractState>>
      identifyCompositeStateTypesAndTheirInitialInstances(Collection<ARGState> rootNodes)
          throws InterruptedException, CPAException {
    logger.log(Level.FINE, "Derive composite state structure of combined ARG");

    List<AbstractState> initialState = new ArrayList<>();
    Map<String, Integer> stateToPos = new HashMap<>();
    List<String> automataStateNames = new ArrayList<>();

    String name;
    int nextId = 0;
    Iterable<AbstractState> wrapped;

    logger.log(Level.FINE, "Add non-automaton states");
    for (ARGState root : rootNodes) {
      shutdown.shutdownIfNecessary();

      wrapped = getWrappedStates(root);

      for (AbstractState innerWrapped : wrapped) {
        shutdown.shutdownIfNecessary();

        if (innerWrapped instanceof AssumptionStorageState) {
          continue;
        }

        name = getName(innerWrapped);

        if (stateToPos.containsKey(name)) {
          if (!initialState.get(stateToPos.get(name)).equals(innerWrapped)) {
            logger.log(
                Level.WARNING,
                "Abstract state ",
                innerWrapped.getClass(),
                " is used by multiple configurations, but cannot check that always start in the same initial state as it is assumed");
          }
        } else {
          assert (initialState.size() == nextId);

          if (innerWrapped instanceof AutomatonState) {
            automataStateNames.add(name);
          } else {
            stateToPos.put(name, nextId);
            initialState.add(innerWrapped);
            nextId++;
          }
        }
      }
    }

    logger.log(Level.FINE, "Add automaton states related to specification");
    Collections.sort(automataStateNames);

    int numRootStates = rootNodes.size();
    Set<String> commonAutomataStates = new TreeSet<>();
    for (int i = 1, j = 0; i < automataStateNames.size(); i++) {
      assert (j < i && j >= 0);
      if (automataStateNames.get(j).equals(automataStateNames.get(i))) {
        if (j + numRootStates - 1 == i) {
          // automaton states commonly used
          commonAutomataStates.add(automataStateNames.get(j));
        }
      } else {
        j = i;
      }
    }

    // assume root is the root node of the first ARG constructed
    ARGState root = rootNodes.iterator().next();

    if (root.getWrappedState() instanceof AbstractWrapperState) {
      wrapped = ((AbstractWrapperState) root.getWrappedState()).getWrappedStates();
    } else {
      wrapped = Collections.singleton(root.getWrappedState());
    }

    for (AbstractState innerWrapped : wrapped) {
      shutdown.shutdownIfNecessary();

      name = getName(innerWrapped);
      if (commonAutomataStates.contains(name)) {
        assert (initialState.size() == nextId);

        stateToPos.put(name, nextId);
        if (!automatonARGBuilderSupport.registerAutomaton((AutomatonState) innerWrapped)) {
          logger.log(
              Level.SEVERE,
              "Property specification, given by automata specification, is ambigous.");
          throw new CPAException(
              "Ambigious property specification,  automata specification contains automata with same name or same state names");
        }
        initialState.add(
            automatonARGBuilderSupport.replaceStateByStateInAutomatonOfSameInstance(
                (AutomatonState) innerWrapped));
        nextId++;
      }
    }

    return Pair.of(stateToPos, initialState);
  }
 @Override
 public boolean isLessOrEqual(AbstractState state1, AbstractState state2)
     throws CPAException, InterruptedException {
   return state1.equals(state2);
 }