#include "selecteur.h" #include #include #include #include #include using namespace std; #ifdef DEBUG_CPLEX #define DEBUG_CPLEX_PRINT(a) std::cout< & coefs, double rhs ) { map, double>::iterator it = m_cliques.find ( coefs ); if ( it == m_cliques.end() ) { //Si la contraint n'existe pas déjà, on l'ajoute m_cliques[coefs] = rhs; } else { //Sinon, on la met à jour m_cliques[coefs] = min ( m_cliques[coefs], rhs ); } } void Selecteur::ajoute_contraintes ( constraint_t type1, constraint_t type2 ) { for ( constraint_t type = type1; type <= type2; ++type ) { if ( true or (type != C14 and type != C15 and type != C18) ) { // contraintes 14 à 21, sauf la 18 // pour chaque contrainte du type courant for ( size_t m = 0 ; m < CInstance::M ( type ) ; m++ ) { const vector & centralesDuSubset = CInstance::constraint ( type, m )->C(); size_t nbCentralesDuSubset = centralesDuSubset.size(); // une clique possible par semaine for ( week_t h = ( week_t ) 0; h < CInstance::constraint ( type, m )->h_max(); ++h ) { typedef map facteur_t ; facteur_t colonnes_concernees ; // pour chaque colonne de la contrainte for ( size_t idx_i = 0 ; idx_i < nbCentralesDuSubset ; idx_i++ ) { powerplants2_t i = centralesDuSubset[idx_i]; for ( size_t idx_c = 0 ; idx_c < CPlan::plans_centrale(i).size() ; idx_c++ ) { size_t c = CPlan::plans_centrale(i)[idx_c]; // ajout de la colonne dans la clique, si elle est concernée double val = CInstance::constraint ( type, m )->concerne_other ( h, CPlan::getPlan(c) ); if ( val != 0 ) { colonnes_concernees[c] = val ; } } } double somme = 0 ; for ( facteur_t::iterator it = colonnes_concernees.begin(); it != colonnes_concernees.end(); it++ ) somme += it->second ; double borne = CInstance::constraint ( type, m )->borne ( h ) ; if ( somme <= borne ) continue ; vector contrainte ( CPlan::getNbPlans(), 0 ); for ( facteur_t::iterator it = colonnes_concernees.begin(); it != colonnes_concernees.end(); it++ ) contrainte[it->first] = it->second ; ajoutContrainte ( contrainte, borne ); } } } else { // contraintes 14, 15 ou 18 for ( size_t m = 0 ; m < CInstance::M ( type ) ; m++ ) { const vector & centralesDuSubset = CInstance::constraint ( type, m )->C(); size_t nbCentralesDuSubset = centralesDuSubset.size(); // une clique possible par colonne concernée et par semaine de début d'outage // pour chaque colonne de la contrainte // parcours des colonnes c1 de la contrainte for ( size_t idx_i1 = 0 ; idx_i1 < nbCentralesDuSubset ; idx_i1++ ) { powerplants2_t i1 = centralesDuSubset[idx_i1]; for ( size_t idx_c1 = 0 ; idx_c1 < CPlan::plans_centrale(i1).size() ; idx_c1++ ) { size_t c1 = CPlan::plans_centrale(i1)[idx_c1]; // pour chaque début d'outage ha1 possible dans la colonne c1 for ( campaign_t k1 = ( campaign_t ) 0; ( unsigned ) k1 < CPlan::getPlan(c1)->m_ha.size(); ++k1 ) { week_t ha1 = CPlan::getPlan(c1)->ha ( k1 ); if ( not CInstance::constraint ( type, m )->concerne_self( ha1, CPlan::getPlan(c1) ) ) continue ; typedef map facteur_t ; facteur_t colonnes_concernees ; // table des colonnes qui empêchent un outage en ha1 pour i1 // parcours des colonnes c2 de la contrainte for ( size_t idx_i2 = 0 ; idx_i2 < nbCentralesDuSubset ; idx_i2++ ) { // on omet les colonnes c2 de la même centrale, déjà empêchées par la contrainte d'unicité if ( idx_i2 == idx_i1 ) continue ; powerplants2_t i2 = centralesDuSubset[idx_i2]; for ( size_t idx_c2 = 0; idx_c2 < CPlan::plans_centrale(i2).size(); idx_c2++ ) { // ajout de la colonne c2 dans la table, si elle empêche ha1 pour c1 int c2 = CPlan::plans_centrale(i2)[idx_c2]; double val = CInstance::constraint ( type, m )->concerne_other ( ha1, CPlan::getPlan(c2) ); if ( val != 0 ) { colonnes_concernees[c2] = val ; } } } // ajout d'une contrainte "somme(contrainte[c_i]) <= taille(colonnes c2 concernées)" // avec : contrainte[c1]=taille(colonnes c2 concernées) // contrainte[c2]=1 pour chaque colonne c2 concernée // Ainsi, toutes les colonnes c2 peuvent apparaître si c1 n'apparaît pas // mais aucune colonne c2 ne peut apparaître si c1 apparaît dans la solution double nb_colonnes_c2_concernees ; if ( ( nb_colonnes_c2_concernees = colonnes_concernees.size() ) == 0 ) continue ; vector contrainte ( CPlan::getNbPlans(), 0 ); for ( facteur_t::iterator it = colonnes_concernees.begin(); it != colonnes_concernees.end(); it++ ) contrainte[it->first] = 1 ; contrainte[c1] = nb_colonnes_c2_concernees ; ajoutContrainte ( contrainte, nb_colonnes_c2_concernees ); } } } } } #ifdef DEBUG_CLIQUES cout << "Nombre de cliques " << type << " : " << m_cliques.size() << std::endl ; #endif } } vector Selecteur::resolution() { // résolution de problème setproblemdata(); #ifdef VERBOSE_SOLUTION_STATUS double result_value = #endif m_cplex.resolution(); //Récupération des colonnes sélectionnées vector result = m_cplex.getResult("colonnes nucléaires"); std::vector selection ; for( size_t c =0 ; c1-EPSILON ) selection.push_back(c); } #ifdef VERBOSE_SOLUTION_STATUS cout << "cplex objective value : " << result_value << endl; #endif // retourne la liste des colonnes sélectionnées par cplex return selection; } struct OrdreCoutSolution { bool operator()(const pair< double, vector > & i, const pair< double, vector > & j) { return i.first < j.first ; } }; vector< vector > Selecteur::populate() { // résolution de problème setproblemdata(); double result_value = m_cplex.resolution(); //Récupération des colonnes sélectionnées vector result = m_cplex.getResult("colonnes nucléaires"); std::vector selection ; for( size_t c =0 ; c1-EPSILON ) selection.push_back(c); } #ifdef VERBOSE_SOLUTION_STATUS cout << "cplex objective value : " << result_value << endl; #endif // peuplement avec la solution optimale vector< pair< double, vector > > cout_population ; pair< double, vector > solution ; solution.first = result_value ; solution.second = selection ; cout_population.push_back( solution ); // calcul et peuplement avec d'autres solutions vector result_values = m_cplex.populate() ; for (size_t i=0; i1-EPSILON ) selection.push_back(c); } solution.first = result_values[i] ; solution.second = selection ; cout_population.push_back( solution ); } // tri de la population de solutions par coût croissant std::sort(cout_population.begin(), cout_population.end(), OrdreCoutSolution() ); // recopie des colonnes des solutions dans le vecteur de retour vector< vector > population ; for (size_t i=0; i >::iterator found = std::find( population.begin()+i+1, population.end(), population[i] ) ; if ( found != population.end() ) population.erase( found ); else i++ ; } // retourne la liste des colonnes sélectionnées par cplex return population; } Selecteur::~Selecteur() { }