private void doubleCheckRedundancies() {
    this.secondPassStartTime = System.currentTimeMillis();

    sorter.setConstraints(this.safeProcess.getAllConstraints());
    // Let us take ALL constraints of the safe process
    ArrayList<Constraint> constraintsSortedForDoubleCheck =
        new ArrayList<Constraint>(sorter.sort(this.rankingPolicies));
    // Let us visit them in the reverse order with which they were added -- so as to be consistent
    // with the given ranking policy
    ListIterator<Constraint> iterator =
        constraintsSortedForDoubleCheck.listIterator(
            constraintsSortedForDoubleCheck.size()
                // The last one is the constraint that we checked last. In theory, it should not
                // constitute a problem
                - 2);
    Constraint candidateCon = null;
    Automaton secondPassGridCheckAutomaton = null;

    while (iterator.hasPrevious()) {
      candidateCon = iterator.previous();
      logger.trace("Second-pass grid check of constraint: " + candidateCon);

      secondPassGridCheckAutomaton =
          AutomatonFactory.buildAutomaton(
              this.safeProcess.bag,
              this.safeProcess.getTaskCharArchive().getIdentifiersAlphabet(),
              candidateCon);

      // If the safe automaton accepts
      if (secondPassGridCheckAutomaton.subsetOf(
          // ... all the constraints BUT the current one...
          //					this.safeAutomaton.minus(
          // ... accepts a subset of the languages that the current one accepts...
          //							new RegExp(candidateCon.getRegularExpression()).toAutomaton()))) {
          this.safeAutomaton)) {
        // ... then the current constraint is basically useless. Explanation is: some other
        // constraint had been added later that made an already saved constraint redundant.
        this.safeProcess.bag.remove(candidateCon);
        this.redundantConstraintsAtSecondPass.add(candidateCon);
        this.redundantConstraints.add(candidateCon);
        logger.warn(candidateCon + " is redundant (second-pass grid check)");
      }
      redundancyChecksPerformed++;
    }
  }
 private boolean checkRedundancy(
     Automaton safeAutomaton,
     ConstraintsBag safeBag,
     Automaton candidateAutomaton,
     Constraint candidateCon) {
   redundancyChecksPerformed++;
   logger.trace("Checking redundancy of " + candidateCon);
   // If candidateCon is not redundant, i.e., if the language of safeAutomaton is not a subset of
   // the language of automaton, then candidateCon can be included
   if (!safeAutomaton.subsetOf(candidateAutomaton)) {
     return true;
   } else {
     logger.warn(
         candidateCon
             + " is redundant. It is already implied"
             + (safeBag.howManyConstraints()
                     < ConflictAndRedundancyResolver
                         .MAXIMUM_VISIBLE_CONSTRAINTS_FOR_REDUNDANCY_CHECK
                 ? " by " + LinearConstraintsIndexFactory.getAllConstraints(safeBag)
                 : " by the current set of constraints."));
     this.redundantConstraints.add(candidateCon);
     return false;
   }
 }