#include "DA.h" // #include #ifndef EPSILON #define EPSILON 0.001 #endif // #include #include #include #include static double s_infini = INFINI ; using namespace std; DualAscent::DualAscent(vector dem, powerplants2_t nb_centrales) { b = dem ; b_EMAX = dem; // Ajout Affectation sur b et b_EMAX b_EMAX.resize( dem.size() + nb_centrales , (kWh)1 ); b.resize( dem.size() + nb_centrales , (kWh)1 ); euros coutTherm = (euros) 0; euros b_PMAX_coutTherm = (euros) 0; for (week_t w=(week_t) 0;wm_cout_reduit<<" pour la centrale "<< cplan->m_i << endl; ajoutcolonne(&cplan->m_colonne, cplan->m_cout, cplan->m_arcs, cplan->m_reste); } /// retrait d'un plan de production nucléaire void DualAscent::retraitColonne(const CPlan* plan) { size_t indice = std::find(m_plans.begin(), m_plans.end(), plan) - m_plans.begin() + 1 ; m_plans.erase(m_plans.begin()+indice-1); A.erase(A.begin()+indice); cost.erase(cost.begin()+indice); recharge.erase(recharge.begin()+indice); reste.erase(reste.begin()+indice); } vector DualAscent::calculeDuals() const { // lambda = vector(lambda.size(),0); int nbCol = cost.size(); int nbLig = b.size(); vector q = calculePoids(); vector L(nbCol, (euros) 0); coeff_t pas = (coeff_t) 1; euros meilleurZd = (euros) - s_infini; vector meilleursU(m_u); vector meilleursLambda(m_lambda); #ifdef VERBOSE_COUT_COLONNES cout << "Cout des colonnes : "; for (int c = 0; c < cost.size(); c++) cout << cost[c] << "\t" ; cout << endl; #endif // Recherche d'un borne sup #ifndef BORNE_SUP_VERSION_2 if (UB < 1) { UB = (double) testUB(); } if (UB>0) { if (UB > 1) { UB = min(UB,recherche_UB()); } else { UB = recherche_UB(); } } #else if (m_UB > (euros) 0) m_UB = min(m_UB,recherche_UB2(q)); else m_UB = recherche_UB2(q); #endif int nbItMax = 3000; int nbItMaxSansAmelioration = 100; int derniereItAmeliorant = 0; int nbIt_ = 0; for ( int nbIt=0 ; (nbIt < nbItMax) && (derniereItAmeliorant > nbIt-nbItMaxSansAmelioration) ; nbIt++ ) { nbIt_=nbIt; m_u = DAcalc(m_lambda, L, q); vector x(nbCol, (coeff_t)0); vector s = sousgrad(x, m_u, m_lambda, L, q); //Calcul de Zd euros zd = (euros)0; kWh_carre normeS = (kWh_carre)0; for ( int i=0 ; i < nbLig ; i++ ) { #ifdef _DEBUG_LAMBDA if (nbIt ==0) { cout <<"lambda["<(euros)0) cout << "Borne Sup utilisée = "<< m_UB < DualAscent::calculePoids() const { vector q(cost.size(), (kWh)0); for ( size_t j=0 ; j < cost.size() ; j++ ) { for ( size_t i=0 ; i < b.size() ; i++ ) { q[j] += a(j, i); } } return q; } vector DualAscent::DAcalc(const vector &lambda, vector &L,const vector &q ) const { vector u(b.size(), (euros_par_kWh)0); //Calcul des L[j] for ( size_t j=0 ; j < L.size() ; j++ ) { L[j] = (euros) 0; for ( size_t i=0 ; i < b.size() ; i++ ) { L[j] += lambda[i] * a(j, i) ; } } //Calcul des Ui for ( size_t i=0 ; i < b.size() ; i++ ) { euros_par_kWh wmin = (euros_par_kWh) s_infini; for ( size_t j=0 ; j < L.size() ; j++ ) { if ( a(j, i) > (kWh) 0 ) { euros_par_kWh w = (cost[j]-L[j])/q[j]; wmin = (wmin < w) ? wmin : w; } } u[i] = wmin + lambda[i]; } return u; } vector DualAscent::sousgrad(vector &x, const vector &u, const vector &lambda, const vector &L, const vector &q) const { //Calcul de l'indexMin vector indexMin(b.size(), -1); for ( size_t i=0 ; i < b.size() ; i++ ) { euros_par_kWh mini = (euros_par_kWh) s_infini; for ( size_t j=0 ; j < cost.size() ; j++ ) { if ( a(j, i) > (kWh)0 ) { euros_par_kWh w = (cost[j]-L[j])/q[j]; if ( w < mini ) { mini = w; indexMin[i] = j; } } } } //Calcul de x //initialisation vector somme_b(x.size(), (kWh) 0); /* Créé NULL juste avant sousgrad for ( size_t j=0 ; j < cost.size() ; j++ ) { x[j] = (coeff_t) 0; } //*/ //Remplissage for ( size_t i=0 ; i < indexMin.size() ; i++) { somme_b[indexMin[i]] += b[i]; } //Division for ( size_t j=0 ; j < cost.size() ; j++ ) { x[j] = somme_b[j] / q[j]; } //Calcul de s vector s(b.size(), (kWh) 0); for ( size_t i=0 ; i < s.size() ; i++ ) { for ( size_t j=0 ; j < cost.size() ; j++ ) { s[i] += a(j, i) * x[j]; } s[i] -= b[i]; } return s; } void DualAscent::vireColonneThermique() { therm_A = A.front() ; therm_recharge = recharge.front(); therm_cost = cost.front(); therm_reste = reste.front(); A.erase(A.begin()); recharge.erase(recharge.begin()); cost.erase(cost.begin()); reste.erase(reste.begin()); } void DualAscent::remetColonneThermique() { A.insert ( A.begin(), therm_A ); recharge.insert ( recharge.begin(), therm_recharge ); cost.insert ( cost.begin(), therm_cost ); reste.insert ( reste.begin(), therm_reste); } // Test Borne Sup bool DualAscent::testUB () const { bool out = false; bool STOP = false; size_t compteur = 0; kWh SumProd; while (!STOP) { SumProd = (kWh) 0; for (size_t l =1 ; l < cost.size() ; l++) { SumProd+=a(l,compteur); } #ifdef PMAX_POUR_DEM out = (SumProd>=b_EMAX[compteur]); #else out = (SumProd>=b[compteur]); #endif STOP = (!out); compteur++; if (compteur==b.size()) { STOP = true; } } #ifdef VERBOSE_SUMPROD if (!(out)) { #ifdef PMAX_POUR_DEM cout << "Sumprod : "<< SumProd<< " et b_EMAX["<<(compteur-1)<<"] = "< &q) const { euros UB = (euros) 0; size_t n = cost.size(); size_t m = b.size(); if ( n > (unsigned) (3*I()) ) { // vector choix (n,false); // choix[0] = true ; // la première colonne est la colonne thermique vector SumProd (m, (kWh) 0); vector index_min(I(), -1); // Ne pas sélectionner les premières colonnes (sans production) vector ratio_min (I(), (euros_par_kWh) s_infini) ; for (size_t k = H(); k