#include "DA.h" #include #ifndef EPSILON #define EPSILON 0.001 #endif #include static double s_infini = INFINI ; using namespace std; void DualAscent::ajoutcolonne( vector * colonne, double cou, std::vector& arcs, double resteCol ) { A.push_back(colonne); cost.push_back(cou); vector quantiteRefuelee; for ( size_t i=0 ; i < arcs.size() ; i++ ) { if ( arcs[i].m_type == TYPE_OUTAGE ) { quantiteRefuelee.push_back(arcs[i].m_recharge); } } recharge.push_back(quantiteRefuelee); reste.push_back(resteCol); } void DualAscent::ajoutcolonne(CPlan* cplan) { Clique::ajoutcolonne(cplan, A.size()); ajoutcolonne(&cplan->m_colonne, cplan->m_cout, cplan->m_arcs, cplan->m_reste); m_plans.push_back(cplan); } DualAscent::~DualAscent() { std::for_each(m_plans.begin() , m_plans.end() , Delete()); // les colonnes font partie des objets CPlan. Pas besoin de détruire les vecteurs // de A. } void DualAscent::boucle(vector& u, vector & lambda, double& UB, const char*x) const { // lambda = vector(lambda.size(),0); int nbCol = cost.size(); int nbLig = b.size(); vector q = calculePoids(); vector L(nbCol, 0); double pas = 1; double meilleurZd = - s_infini; vector meilleursU(u); vector meilleursLambda(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 (UB > 0) UB = min(UB,recherche_UB2(q)); else UB = recherche_UB2(q); #endif int nbItMax = 3000; int nbItMaxSansAmelioration = 100; int derniereItAmeliorant = 0; for ( int nbIt=0 ; (nbIt < nbItMax) && (derniereItAmeliorant > nbIt-nbItMaxSansAmelioration) ; nbIt++ ) { u = DAcalc(lambda, L, q); vector x(nbCol, 0); vector s = sousgrad(x, u, lambda, L, q); //Calcul de Zd double zd = 0; double normeS = 0; for ( int i=0 ; i < nbLig ; i++ ) { #ifdef _DEBUG_LAMBDA if (nbIt ==0) { cout <<"lambda["<0) cout << "Borne Sup utilisée = "<< UB < DualAscent::calculePoids() const { vector q(cost.size(), 0); for ( int j=0 ; j < cost.size() ; j++ ) { for ( int 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(), 0); //Calcul des L[j] for ( int j=0 ; j < L.size() ; j++ ) { L[j] = 0; for ( int i=0 ; i < b.size() ; i++ ) { L[j] += a(j, i) * lambda[i]; } } //Calcul des Ui for ( int i=0 ; i < b.size() ; i++ ) { double wmin = s_infini; for ( int j=0 ; j < L.size() ; j++ ) { if ( a(j, i) > 0 ) { double 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 ( int i=0 ; i < b.size() ; i++ ) { double mini = s_infini; for ( int j=0 ; j < cost.size() ; j++ ) { if ( a(j, i) > 0 ) { double w = (cost[j]-L[j])/q[j]; if ( mini > w ) { mini = w; indexMin[i] = j; } } } } //Calcul de x //initialisation for ( int j=0 ; j < cost.size() ; j++ ) { x[j] = 0; } //Remplissage for ( int i=0 ; i < indexMin.size() ; i++) { x[indexMin[i]] += b[i]; } //Division for ( int j=0 ; j < cost.size() ; j++ ) { x[j] /= q[j]; } //Calcul de s vector s(b.size(), 0); for ( int i=0 ; i < s.size() ; i++ ) { for ( int j=0 ; j < cost.size() ; j++ ) { s[i] += x[j]*a(j, i); } 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; int compteur = 0; double SumProd; while (!STOP) { SumProd = 0; for (int l =1 ; l < cost.size() ; l++) { SumProd+=a(l,compteur); } #ifdef PMAX_POUR_DEM out = (SumProd>=b_PMAX[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_PMAX["<<(compteur-1)<<"] = "< &q) const { double UB = 0; int n = cost.size(); int m = b.size(); if ( n > 3*I() ) { // vector choix (n,false); // choix[0] = true ; // la première colonne est la colonne thermique vector SumProd (m,0); vector index_min= vector (I(), -1); // Ne pas sélectionner les premières colonnes (sans production) vector ratio_min = vector (I(),s_infini) ; for (int k = m-1;k>=H();k--) { /// Choix des colonnes for ( int i = I()+1 ; i < n ; i++) { // cout << "i = " << i << endl; if (a(i,k) > 0) // ==1 car partie affectation { int id_cent = (i-1) % I(); // Colonne à production positive double ratio = cost[i]/q[i]; if (ratio < ratio_min[id_cent]) { index_min[id_cent]=i; ratio_min[id_cent]=ratio ; //cost[i]; } } } } /// Somme des productions nucléaires for (int i=0;i