void CliquePartitionProblem::writeSolution(
    FractionnarySolution const& bestSolution, double lb) const {
  std::ofstream file(
      GetStr("optimal/", problemName(), "_", lb, ".txt").c_str());
  for (auto const & c : bestSolution) {
    for (auto const & edge : getCosts()) {
      int const r(edge._i);
      int const b(edge._j);
      if (c.first->contains(r) && c.first->contains(b)) {
        file << std::setw(6) << 1 + r;
        file << std::setw(6) << 1 + b;
        file << std::endl;
      }

    }
//		for (int r(0); r < nR(); ++r) {
//			for (int b(0); b < nB(); ++b) {
//				if (c.first->contains(r) && c.first->contains(nR() + b)) {
//					file << std::setw(6) << 1 + r;
//					file << std::setw(6) << 1 + b + nR();
//					file << std::endl;
//				}
//
//			}
//		}
  }
  file.close();
}
/** fill the initial stack with all parents of conjunctions and all initial constraints */
void OptimalNodeBasedEstimatorPhase::findStartingState(CgNodePtr mainMethod) {

    CgNodePtrSet startingParents = {mainMethod};	// main() is implicitly instrumented
    NodeBasedConstraintContainer startingConstraints;

    for (auto node : (*graph)) {
        if (CgHelper::isConjunction(node)) {

            CgNodePtrSet parentNodes = node->getParentNodes();

            startingParents.insert(parentNodes.begin(), parentNodes.end());
            startingConstraints.push_back(NodeBasedConstraint(parentNodes, node));
        }
    }

    auto startingState = NodeBasedState(startingParents, startingConstraints);

    optimalInstrumentation = startingParents;
    optimalCosts = startingState.getCosts();

    stateStack.push(startingState);
}
void handleSolution(std::size_t round, GMMDesc const& gmmdesc, double time, bool hasChanged)
{
	
	if (ioutil::StatisticFileIsOpen())
	{
		// compute costs (only if the solution has changed)
		if(!costs.empty() && !hasChanged)
		    costs.push_back(costs.back());
		else
		    costs.push_back(getCosts(input, gmmdesc));		
		
		// output
		ioutil::storeStatisticEntry(round, time, costs.back());

		// minimum?
		if(costs.size()==1 || (mincost > costs.back()))
		{
			mincost = costs.back();
			mincost_runtime = time;
			mincost_round = round;
		}
	}
}
double runAlgoSequence(AlgoDescriptor const* descriptor, GMMDesc initialSolution, double initialTime,
	std::string const& outputDir, std::string const& outputFile)
{
	// Initialize output
	std::stringstream pathStream;
	pathStream << outputDir << "/csv";
	boost::filesystem::path outPath(pathStream.str());
	boost::filesystem::create_directories(outPath);
	std::stringstream filenameStream;
	filenameStream << pathStream.str() << "/" << outputFile;
	ioutil::openStatisticFile(filenameStream.str());


	// compute maximum spread
	Vector spreads = (input.points.rowwise().maxCoeff()
					 -input.points.rowwise().minCoeff());
					 
	if (commonSettings().verbose)
		std::cout << "maximum spread is " << spreads.maxCoeff() << std::endl;

	// Initialisation
	double totaltime = initialTime;
	GMMDesc last = initialSolution;

	// handle initial solution
	handleSolution(0, last, totaltime, true);

	// start computation of new algorithm sequence
	std::cout << "starting new algorithm sequence:" << std::endl;
			  
	AlgoDescriptor const* nextAlgo = descriptor;
	std:size_t roundOffset = 0;
	std::vector<std::size_t> finalRounds;
	std::vector<double> finalTimes;
	while (nextAlgo!=NULL)
	{
		std::cout << "creating algorithm from descriptor: "
				  << nextAlgo->tag() << std::endl;
				  
		GMMAlgorithm* algorithm = nextAlgo->create(input);
		algorithm->init(last);
		
		// run current algorithm
		for (std::size_t i=0; i<nextAlgo->steps(); ++i)
		{
			algorithm->run();
			handleSolution(roundOffset+i+1, algorithm->getGMMDesc(),
				algorithm->getRuntime()+totaltime, algorithm->hasChanged());
		}
		
		// Save results and delete algorithm
		last = algorithm->getGMMDesc();
		roundOffset += nextAlgo->steps();
		totaltime += algorithm->getRuntime();
		finalRounds.push_back(roundOffset);
		finalTimes.push_back(totaltime);
		std::cout << "   computation took " << algorithm->getRuntime() << " seconds." << std::endl;

		delete algorithm;

		nextAlgo = nextAlgo->getNext();
	}
	std::cout << std::endl;

	if (ioutil::StatisticFileIsOpen())
	{
		// Store statistics markers
		ioutil::storeStatisticMarkerVector(finalRounds, finalTimes, mincost_round, mincost_runtime);

		// Print overall results
		if (!truth.empty())
			std::cout << "         cost of truth = " << getCosts(input, truth) << std::endl;
		std::cout << "cost of final solution = " << costs.back() << std::endl;
		std::cout << "     cheapest solution = " << mincost << " after " << mincost_runtime << " seconds" << std::endl;
	}

	std::cout << std::endl;
	
	// Finalize output
	ioutil::closeAllFiles();
	
	return totaltime-initialTime;
}
void CliquePartitionProblem::branchingWeights(
    FractionnarySolution const & solution, BranchingWeights & weights) const {
// on cherche des arrêtes présentes et semi-présentes dans deux colonnes
  BranchingWeights2 temp;
  std::map<Edge, std::pair<IntSet, IntSet> > toto;
  for (auto const & kvp : solution) {
    //		std::cout << std::setw(6) << kvp.first->id();
    //		std::cout << std::setw(15) << kvp.second;
    //		std::cout << std::endl;
    for (Edge const & e : getCosts()) {
      bool const iFirst(kvp.first->contains(e._i));
      bool const iSecond(kvp.first->contains(e._j));
      if (iFirst && iSecond) {
        toto[e].first.insert(kvp.first->id());
      } else if (iFirst || iSecond) {
        toto[e].second.insert(kvp.first->id());
      }
    }
  }
//	std::cout << "synthese" << std::endl;
  weights.clear();
  for (auto const & t : toto) {
    //		std::cout << std::setw(6) << t.second.first.size();
    //		std::cout << std::setw(6) << t.second.second.size();
    //		std::cout << std::endl;
    if (!t.second.first.empty() && !t.second.second.empty()) {
      //			std::cout << std::setw(6) << t.first._i;
      //			std::cout << std::setw(6) << t.first._j;
      //			std::cout << std::endl;
      weights.insert(
          std::make_pair(
              0.5 * ((int) ((t.second.first.size() + t.second.second.size()))),
              std::make_pair(t.first._i, t.first._j)));
    }
  }
  if (weights.empty()) {
    std::cout << "Weights.empty(), generating full weights" << std::endl;
    for (auto const & kvp : solution) {
      for (Edge const & e : getCosts()) {
        bool const iR(kvp.first->contains(e._i));
        bool const iB(kvp.first->contains(e._j));
        if (iR && iB) {
          toto[Edge(e._i, e._j, 1)].first.insert(kvp.first->id());
        } else if (iR || iB) {
          toto[Edge(e._i, e._j, 1)].second.insert(kvp.first->id());
        }

      }
    }

    for (auto const & t : toto) {
      //		std::cout << std::setw(6) << t.second.first.size();
      //		std::cout << std::setw(6) << t.second.second.size();
      //		std::cout << std::endl;
      if (!t.second.first.empty() && !t.second.second.empty()) {
        //			std::cout << std::setw(6) << t.first._i;
        //			std::cout << std::setw(6) << t.first._j;
        //			std::cout << std::endl;
        weights.insert(
            std::make_pair(
                0.5
                    * ((int) ((t.second.first.size() + t.second.second.size()))),
                std::make_pair(t.first._i, t.first._j)));
      }
    }
    if (weights.empty())
      std::cout << "weights.empty()" << std::endl;
  }
}