Exemple #1
0
void Timer :: AddTimerWithType(const uint64_t llAbsTime, const int iType, uint32_t & iTimerID)
{
    iTimerID = m_iNowTimerID++;

    TimerObj tObj(iTimerID, llAbsTime, iType);
    m_vecTimerHeap.push_back(tObj);
    push_heap(begin(m_vecTimerHeap), end(m_vecTimerHeap));
}
Exemple #2
0
  double Solver::solve( double timeout )
  {
    chrono::duration<double,milli> elapsedTime;
    chrono::duration<double,milli> elapsedTimeTour;
    chrono::duration<double,milli> postprocessGap(0);
    chrono::time_point<chrono::system_clock> start;
    chrono::time_point<chrono::system_clock> startTour;
    start = chrono::system_clock::now();

    // to time simulateCost and cost functions
    chrono::duration<double,milli> timeSimCost(0);
    chrono::time_point<chrono::system_clock> startSimCost; 

#ifndef NDEBUG
    chrono::duration<double,milli> toverlap(0), tbuildable(0), tnoholes(0), tstt(0);
    chrono::time_point<chrono::system_clock> soverlap, sbuildable, snoholes, sstt; 
#endif

    int sizeGrid = grid.getNberRows() * grid.getNberCols() + 1; // + 1 for the "position -1" outside the grid
    vector< vector< double > >  vecConstraintsCosts( vecConstraints.size() );
    vector< double >		vecGlobalCosts( sizeGrid );
    vector< vector< double > >  vecVarSimCosts( sizeGrid );
    objective->initHelper( sizeGrid );

    bestCost = numeric_limits<int>::max();
    double beforePostProc = bestCost;
    double bestGlobalCost = numeric_limits<int>::max();
    double globalCost;
    double currentCost;
    double estimatedCost;
    double bestEstimatedCost;
    int    bestPosition;

    vector<int> worstBuildings;
    double worstVariableCost;
    int worstBuildingId;
    int sizeWall;

    shared_ptr<Building> oldBuilding;
    vector<int> possiblePositions;
    vector<double> varSimCost( vecBuildings.size() );
    vector<double> bestSimCost( vecBuildings.size() );

    int tour = 0;
    int iterations = 0;

    do // optimization loop
    {
      startTour = chrono::system_clock::now();
      ++tour;
      globalCost = numeric_limits<int>::max();
      bestEstimatedCost = numeric_limits<int>::max();
      sizeWall  = numeric_limits<int>::max();
      std::fill( varSimCost.begin(), varSimCost.end(), 0. );
      std::fill( bestSimCost.begin(), bestSimCost.end(), 0. );
      std::fill( vecConstraintsCosts.begin(), vecConstraintsCosts.end(), vector<double>( vecBuildings.size(), 0. ) );
      std::fill( vecVarSimCosts.begin(), vecVarSimCosts.end(), vector<double>( vecBuildings.size(), 0. ) );
      std::fill( variableCost.begin(), variableCost.end(), 0. );
      std::fill( tabuList.begin(), tabuList.end(), 0 );

      do // solving loop 
      {
	++iterations;

	if( globalCost == numeric_limits<int>::max() )
	{
	  currentCost = 0.;

	  for( auto c : vecConstraints )
	    currentCost += c->cost( variableCost );

	  if( currentCost < globalCost )
	    globalCost = currentCost;
	  else
	  {
	    reset();
	    continue;
	  }
	}

	// make sure there is at least one untabu variable
	bool freeVariables = false;

	// Update tabu list
	for( int i = 0; i < tabuList.size(); ++i )
	{
	  if( tabuList[i] <= 1 )
	  {
	    tabuList[i] = 0;
	    if( !freeVariables )
	      freeVariables = true;      
	  }
	  else
	    --tabuList[i];
	}

	// Here, we look at neighbor configurations with the lowest cost.
	worstBuildings.clear();
	worstVariableCost = 0;
	for( int i = 0; i < variableCost.size(); ++i )
	{
	  if( !freeVariables || tabuList[i] == 0 )
	  {
	    if( worstVariableCost < variableCost[i] )
	    {
	      worstVariableCost = variableCost[i];
	      worstBuildings.clear();
	      worstBuildings.push_back( i );
	    }
	    else 
	      if( worstVariableCost == variableCost[i] )
		worstBuildings.push_back( i );	  
	  }
	}
      
	// can apply some heuristics here, according to the objective function
	worstBuildingId = objective->heuristicVariable( worstBuildings, vecBuildings, grid );
	oldBuilding = vecBuildings[ worstBuildingId ];
      
	// get possible positions for oldBuilding.
	possiblePositions = grid.possiblePos( *oldBuilding );

	// time simulateCost
	startSimCost = chrono::system_clock::now();

	// variable simulated costs
	fill( bestSimCost.begin(), bestSimCost.end(), 0. );

#ifndef NDEBUG
	soverlap = chrono::system_clock::now();
	vecConstraintsCosts[0] = vecConstraints[0]->simulateCost( *oldBuilding, possiblePositions, sizeGrid, vecVarSimCosts, objective );
	toverlap += chrono::system_clock::now() - soverlap;

	sbuildable = chrono::system_clock::now();
	vecConstraintsCosts[1] = vecConstraints[1]->simulateCost( *oldBuilding, possiblePositions, sizeGrid, vecVarSimCosts );
	tbuildable += chrono::system_clock::now() - sbuildable;

	snoholes = chrono::system_clock::now();
	vecConstraintsCosts[2] = vecConstraints[2]->simulateCost( *oldBuilding, possiblePositions, sizeGrid, vecVarSimCosts );
	tnoholes += chrono::system_clock::now() - snoholes;

	sstt = chrono::system_clock::now();
	vecConstraintsCosts[3] = vecConstraints[3]->simulateCost( *oldBuilding, possiblePositions, sizeGrid, vecVarSimCosts );
	tstt += chrono::system_clock::now() - sstt;
#else
	vecConstraintsCosts[0] = vecConstraints[0]->simulateCost( *oldBuilding, possiblePositions, sizeGrid, vecVarSimCosts, objective );
	for( int i = 1; i < vecConstraints.size(); ++i )
	  vecConstraintsCosts[i] = vecConstraints[i]->simulateCost( *oldBuilding, possiblePositions, sizeGrid, vecVarSimCosts );
#endif

	fill( vecGlobalCosts.begin(), vecGlobalCosts.end(), 0. );

	// sum all numbers in the vector vecConstraintsCosts[i] and put it into vecGlobalCosts[i] 
	for( auto v : vecConstraintsCosts )
	  transform( vecGlobalCosts.begin(), 
		     vecGlobalCosts.end(), 
		     v.begin(), 
		     vecGlobalCosts.begin(), 
		     plus<double>() );

	// replace all negative numbers by the max value for double
	replace_if( vecGlobalCosts.begin(), 
		    vecGlobalCosts.end(), 
		    bind( less<double>(), placeholders::_1, 0. ), 
		    numeric_limits<int>::max() );

	// look for the first smallest cost, according to objective heuristic
	int b = objective->heuristicValue( vecGlobalCosts, bestEstimatedCost, bestPosition, grid);
	bestSimCost = vecVarSimCosts[ b ];

	timeSimCost += chrono::system_clock::now() - startSimCost;

	currentCost = bestEstimatedCost;

	if( bestEstimatedCost < globalCost )
	{
	  globalCost = bestEstimatedCost;

	  if( globalCost < bestGlobalCost )
	    bestGlobalCost = globalCost;

	  variableCost = bestSimCost;
	  move( oldBuilding, bestPosition );
	}
	else // local minima
	  tabuList[ worstBuildingId ] = TABU;

	elapsedTimeTour = chrono::system_clock::now() - startTour;
      } while( globalCost != 0. && elapsedTimeTour.count() < timeout );

      // remove useless buildings
      if( globalCost == 0 )
      {
	bool change;
	double cost;
	NoHoles nh( vecBuildings, grid );

	// remove all unreachable buildings from the starting building out of the grid
	set< shared_ptr<Building> > visited = getNecessaryBuildings();
	for( auto b : vecBuildings )
	  if( visited.find( b ) == visited.end() )
	  {
	    grid.clear( *b );
	    b->setPos( -1 );
	  }

	// clean wall from unnecessary buildings.
	do
	{
	  for( auto b : vecBuildings )
	    if( ! grid.isStartingOrTargetTile( b->getId() ) )
	    {
	      change = false;
	      if( b->isOnGrid() )
	      {
		cost = 0.;
		fill( varSimCost.begin(), varSimCost.end(), 0. );
	      
		cost = nh.simulateCost( *b, -1, varSimCost );
	      
		if( cost == 0. )
		{
		  grid.clear( *b );
		  b->setPos( -1 );
		  nh.update( grid );
		  change = true;
		}	  
	      }
	    }
	} while( change );

	double objectiveCost = objective->cost( vecBuildings, grid );
	int currentSizeWall = countBuildings( vecBuildings );

	if( objectiveCost < bestCost || ( objectiveCost == bestCost && currentSizeWall < sizeWall ) )
	{
	  sizeWall = currentSizeWall;
	  bestCost = objectiveCost;
	  for( int i = 0; i < vecBuildings.size(); ++i )
	    bestSolution[i] = vecBuildings[i]->getPosition();
	}
      }
      reset();
      elapsedTime = chrono::system_clock::now() - start;
    }
    while( ( objective->getName().compare("none") != 0 || loops == 0 )  && ( elapsedTime.count() < OPT_TIME )//|| ( elapsedTime.count() >= OPT_TIME && bestGlobalCost != 0 && elapsedTime.count() < 10 * OPT_TIME ) ) 
	   || ( objective->getName().compare("none") == 0 && elapsedTime.count() < timeout * loops ) );

    clearAllInGrid( vecBuildings, grid );

    for( int i = 0; i < vecBuildings.size(); ++i )
      vecBuildings[i]->setPos( bestSolution[i] );
    
    addAllInGrid( vecBuildings, grid );

    // For gap objective, try now to decrease the number of gaps.
    if( ( objective->getName().compare("gap") == 0 || objective->getName().compare("techtree") == 0 ) && bestGlobalCost == 0 )
    {
      //objective.reset( new GapObj("gap") );
      std::fill( tabuList.begin(), tabuList.end(), 0 );
        
      for( auto v : vecBuildings )
	buildingSameSize.insert( make_pair( v->getSurface(), v ) );

      vector<int> goodVar;
      shared_ptr<Building> toSwap;
      bool mustSwap;

      chrono::time_point<chrono::system_clock> startPostprocess = chrono::system_clock::now(); 
    
      bestCost = objective->cost( vecBuildings, grid );
      double currentCost = bestCost;
      beforePostProc = bestCost;

      while( (postprocessGap = chrono::system_clock::now() - startPostprocess).count() < static_cast<int>( ceil(OPT_TIME / 100) ) && bestCost > 0 )
      {
	goodVar.clear();

	for( int i = 0; i < tabuList.size(); ++i )
	{
	  if( tabuList[i] <= 1 )
	    tabuList[i] = 0;
	  else
	    --tabuList[i];
	}

	for( int i = 0; i < vecBuildings.size(); ++i )
	{
	  if( tabuList[i] == 0 )
	    goodVar.push_back( i );
	}

	if( goodVar.empty() )
	  for( int i = 0; i < vecBuildings.size(); ++i )
	    goodVar.push_back( i );	

	int index = objective->heuristicVariable( goodVar, vecBuildings, grid );
	oldBuilding = vecBuildings[ index ];
	auto surface = buildingSameSize.equal_range( oldBuilding->getSurface() );
	
	for( auto it = surface.first; it != surface.second; ++it )
	{
	  mustSwap = false;
	  if( it->second->getId() != oldBuilding->getId() )
	  {
	    grid.swap( *it->second, *oldBuilding );
	    
	    currentCost = objective->cost( vecBuildings, grid );
	    if( currentCost < bestCost )
	    {
	      bestCost = currentCost;
	      toSwap = it->second;
	      mustSwap = true;
	    }

	    grid.swap( *it->second, *oldBuilding );
	  }
	  
	  if( mustSwap )
	    grid.swap( *toSwap, *oldBuilding );
	}

	tabuList[ index ] = 2;//std::max(2, static_cast<int>( ceil(TABU / 2) ) );
      }
    }
 
    cout << "Grids:" << grid << endl;

    if( objective->getName().compare("none") == 0 )
      cout << "SATISFACTION run: try to find a sound wall only!" << endl;
    else
      cout << "OPTIMIZATION run with objective " << objective->getName() << endl;
      
    cout << "Elapsed time: " << elapsedTime.count() << endl
	 << "Global cost: " << bestGlobalCost << endl
	 << "Number of tours: " << tour << endl
	 << "Number of iterations: " << iterations << endl;

    if( objective->getName().compare("none") == 0 )
    {
      if( bestGlobalCost == 0 )
      {
	BuildingObj bObj("building");
	GapObj gObj("gap");
	TechTreeObj tObj("techtree");
	
	cout << "Opt Cost if the objective was building: " << bObj.cost( vecBuildings, grid ) << endl
	     << "Opt Cost if the objective was gap: \t" << gObj.cost( vecBuildings, grid ) << endl
	     << "Opt Cost if the objective was techtree: " << tObj.cost( vecBuildings, grid ) << endl;
      }
    }
    else
    {
      cout << "Optimization cost: " << bestCost << endl
	   << "Opt Cost BEFORE post-processing: " << beforePostProc << endl;
    }

    if( objective->getName().compare("gap") == 0 || objective->getName().compare("techtree") == 0 )
      cout << "Post-processing time: " << postprocessGap.count() << endl; 

#ifndef NDEBUG
    cout << endl << "Elapsed time to simulate cost: " << timeSimCost.count() << endl
	 << "Overlap: " << toverlap.count() << endl
	 << "Buildable: " << tbuildable.count() << endl
	 << "NoHoles: " << tnoholes.count() << endl
	 << "STT: " << tstt.count() << endl;

    updateConstraints( vecConstraints, grid );

    // print cost for each constraint
    for( auto c : vecConstraints )
    {
      fill( varSimCost.begin(), varSimCost.end(), 0. );
      cout << "Cost of " << typeid(*c).name() << ": " << c->cost( varSimCost ) << " [";

      for( auto v : varSimCost )
	cout << " " << v;

      cout << " ]" << endl;
    }      
    
    cout << endl;
#endif

    if( objective->getName().compare("none") == 0 )
      return bestGlobalCost;
    else
      return bestCost;
  }