void Party::TransformPartitionIntoOrderedListStrategies(DifferentSizePartitions *different_size_partitions) {
    for (DifferentSizePartitions::iterator my_iterator = different_size_partitions->begin();
         my_iterator != different_size_partitions->end(); my_iterator++) {
        SameSizePartitions same_size_partitions = *my_iterator;
        SameSizeStrategies same_size_strategies;
        Strategy *strategy;
        for (SameSizePartitions::iterator same_size_iterator = same_size_partitions.begin();
             same_size_iterator != same_size_partitions.end(); same_size_iterator++) {
            Partition partition = *same_size_iterator;

            strategy = new Strategy(this);
            CandidateListInfo *to_be_find_group;
            for (Partition::iterator group_iterator = partition.begin();
                 group_iterator != partition.end(); group_iterator++) {
                GroupInPartition group_in_partition = *group_iterator;
                to_be_find_group = new CandidateListInfo();
                for (GroupInPartition::iterator my_iterator = group_in_partition.begin();
                     my_iterator != group_in_partition.end(); my_iterator++) {
                    CandidateId candidate_id = *my_iterator;
                    to_be_find_group->candidates_->push_back(candidate_id);
                }
                strategy->candidate_list_info_list_.push_back(GetExactGroupPointer(to_be_find_group));
                delete to_be_find_group;
            }

            same_size_strategies.push_back(*strategy);
            delete strategy;
        }
        strategies_with_different_size_.push_back(same_size_strategies);
    }
}
void SequentialEquivalenceAction::exec() {
  TrivialEq teq;
  vector<EqualFn *> eqs;
  eqs.push_back(&teq);

  int rseed = model().options()["rand"].as<int>();
  if(rseed != -1)
    srand(rseed);

  ExprAttachment * const eat = (ExprAttachment *) model().constAttachment(Key::EXPR);

  Expr::Manager::View * ev = model().newView();

  FMap fmap;
  vector<ID> vars = eat->stateVars();
  for (vector<ID>::const_iterator it = vars.begin(); it != vars.end(); ++it)
    fmap.insert(FMap::value_type(*it, eat->nextStateFnOf(*it)));
 
  //uninitialized latches or those that get dropped out of ECs
  FMap singletonLatches = fmap; 

  // currently only works for AIGER 1.9 initial conditions
  Partition parts;
  set<ID> fpart, tpart;
  fpart.insert(ev->bfalse());
  tpart.insert(ev->btrue());
  vector<ID> init = eat->initialConditions();
  for (vector<ID>::const_iterator it = init.begin(); it != init.end(); ++it) {
    if (ev->op(*it) == Expr::Var) {
      tpart.insert(*it);
      singletonLatches.erase(*it);
    }
    else {
      fpart.insert(ev->apply(Expr::Not, *it));
      singletonLatches.erase(ev->apply(Expr::Not,*it));
    }
  }

  if (fpart.size() == 1 && tpart.size() == 1) {
    delete ev;
    return;
  }
  parts.push_back(fpart);
  parts.push_back(tpart);

  // Construct map of latches to fan-in latches.
  IDIDSetMap nsfSupport;
  for (vector<ID>::const_iterator it = vars.begin(); it != vars.end(); ++it) {
    set<ID> support;
    eat->supportStateVars(*ev, eat->nextStateFnOf(*it), support);
    nsfSupport.insert(IDIDSetMap::value_type(*it, support));
  }

  if (model().verbosity() > Options::Terse)
    cout << "SequentialEquivalenceAction starting" << endl;
  if (model().verbosity() > Options::Silent)
    cout << "SequentialEquivalence: Initial # latches = " << vars.size() << endl;

  //Refine classes
  if (model().verbosity() > Options::Informative)
    cout << "SequentialEquivalence: Simulation refinement" << endl;
  SimRefine simRefine(model(), ev, parts, fmap);
  sequentialSimulateRandom64(model(), 100, simRefine);

  CacheMap cache;
  ev->begin_local();
  for (vector<EqualFn *>::iterator eq = eqs.begin(); eq != eqs.end(); ++eq) {
    for (;;) {
      if (model().verbosity() > Options::Informative) {
        cout << " " << parts.size();
#if 0
        for (Partition::iterator it = parts.begin(); it != parts.end(); ++it)
          cout << " " << it->size();
#endif
        cout << endl;
      }
      FMap curr(fmap);
      iterate(ev, eat, parts, curr, nsfSupport, cache);
      if (!refine(ev, parts, curr, fmap, **eq)) {
        if (eq+1 == eqs.end()) {
          // globalize roots
          vector<ID> roots;
          for (FMap::const_iterator it = curr.begin(); it != curr.end(); ++it)
            roots.push_back(it->second);
          ev->global(roots);
          // make curr point to global roots
          unsigned int i = 0;
          for (FMap::iterator it = curr.begin(); it != curr.end(); ++it, ++i)
            it->second = roots[i];
          // save as fmap
          fmap = curr;
        }
        break;
      }
    }
  }
  ev->end_local();
  model().constRelease(eat);

  //Add latches that were dropped from ECs
  for (vector<ID>::const_iterator it = vars.begin(); it != vars.end(); ++it) {
    if (fmap.find(*it) == fmap.end())
      singletonLatches.insert(FMap::value_type(*it, eat->nextStateFnOf(*it)));
  }


  bool changed = false;
  for (Partition::const_iterator it = parts.begin(); it != parts.end(); ++it)
    if (it->size() > 1) {
      changed = true;
      break;
    }
  if (changed) {
    SeqAttachment * seqat = (SeqAttachment *) model().attachment(Key::SEQ);
    ExprAttachment * eat = (ExprAttachment *) model().attachment(Key::EXPR);

    FMap lmap;
    if(seqat->stateVars.empty()) {
      seqat->stateVars = eat->stateVars();
      seqat->nextStateFns = eat->nextStateFns();
    }
    eat->clearNextStateFns();
    map<ID, ID> latchToNsf;
    for (Partition::const_iterator it = parts.begin(); it != parts.end(); ++it) {
      // set next state function
      set<ID>::const_iterator rep = it->begin();
      if (*rep != ev->bfalse() && *rep != ev->btrue()) {
        FMap::const_iterator rit = fmap.find(*rep);
        latchToNsf.insert(map<ID, ID>::value_type(*rep, rit->second));
      }
      // build map of latch to representative latch
      set<ID>::const_iterator pit = rep;
      for (++pit; pit != it->end(); ++pit) {
        lmap.insert(FMap::value_type(*pit, *rep));
        seqat->optimized.insert(unordered_map<ID, ID>::value_type(*pit, *rep));
      }
    }
    for(FMap::const_iterator it = singletonLatches.begin();
        it != singletonLatches.end(); ++it) {
      ID nsf = Expr::varSub(*ev, lmap, it->second);
      latchToNsf.insert(map<ID, ID>::value_type(it->first, nsf));
    }
    for (map<ID, ID>::const_iterator it = latchToNsf.begin();
        it != latchToNsf.end(); ++it) {
      eat->setNextStateFn(it->first, it->second);
    }
    ev->keep(eat->nextStateFnOf(eat->stateVars()));

    if (model().verbosity() > Options::Silent)
      cout << "SequentialEquivalence: Final # latches = " << eat->stateVars().size() << endl;

    vector<ID> init(eat->initialConditions());
    if(seqat->initialConditions.empty())
      seqat->initialConditions = init;
    eat->clearInitialConditions();
    for (vector<ID>::iterator it = init.begin(); it != init.end(); ++it)
      if (Expr::varSub(*ev, lmap, *it) == *it)
        eat->addInitialCondition(*it);

    vector<ID> constraints(eat->constraints());
    vector<ID> constraintFns(eat->constraintFns());
    eat->clearConstraints();
    for (vector<ID>::size_type i = 0; i != constraintFns.size(); ++i) {
      //Changed by Zyad 11/08/2011
      //if (Expr::varSub(*ev, lmap, *it) == *it)
        //eat->addConstraint(*it);
      ID f = Expr::varSub(*ev, lmap, constraintFns[i]);
      eat->addConstraint(constraints[i], f);
    }
    ev->keep(eat->constraintFns());

    vector<ID> outputs(eat->outputs());
    vector<ID> outputFns(eat->outputFnOf(outputs));
    eat->clearOutputFns();
    Expr::varSub(*ev, lmap, outputFns);
    eat->setOutputFns(outputs, outputFns);
    ev->keep(outputFns);

    vector<ID> bad(eat->bad());
    vector<ID> badFns(eat->badFnOf(bad));
    eat->clearBadFns();
    Expr::varSub(*ev, lmap, badFns);
    eat->setBadFns(bad, badFns);
    ev->keep(badFns);

    vector<ID> fairness(eat->fairness());
    vector<ID> fairnessFns(eat->fairnessFnOf(fairness));
    eat->clearFairnessFns();
    Expr::varSub(*ev, lmap, fairnessFns);
    eat->setFairnessFns(fairness, fairnessFns);
    ev->keep(fairnessFns);

    vector<ID> justice(eat->justice());
    vector< vector<ID> > justiceS(eat->justiceSets());
    eat->clearJusticeSets();
    for (size_t i = 0; i < justiceS.size(); ++i) {
      Expr::varSub(*ev, lmap, justiceS[i]);
      eat->setJusticeSet(justice[i], justiceS[i]);
      ev->keep(justiceS[i]);
    }

    vector<ID> ctlProps(eat->ctlProperties());
    eat->clearCtlProperties();
    Expr::varSub(*ev, lmap, ctlProps);
    eat->addCtlProperties(ctlProps);

    model().release(eat);
    model().release(seqat);
  }
  else {
    if (model().verbosity() > Options::Silent)
      cout << "SequentialEquivalence: Final # latches = " << vars.size() << endl;
  }

  delete ev;
}