_simplex.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:13k
开发平台:

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _simplex.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. /****************************************************************************
  12. *                                                                           *
  13. *    simplex.c                                                              *
  14. *    *********                                                              *
  15. *    ist ein Programm zur Loesung linearer Programme !                      *
  16. *    *************************************************                      *
  17. *                                                                           *
  18. *    Die Implementierung basiert auf dem Zweiphasen-Simplex-Verfahren       *
  19. *    aus Dinkelbach, Operations Research, Kapitel 1.                        *
  20. *                                                                           *
  21. *    Kommentare und die Wahl der Bezeichnernamen beziehen sich in der       *
  22. *    Regel auf die entsprechenden Stellen im Buch.                          *
  23. *                                                                           *
  24. *    29.06.1992                                                             *
  25. *                                                                           *
  26. *    Sascha Portz und Johannes Helders                                      *
  27. *                                                                           *
  28. ****************************************************************************/
  29. #include <LEDA/simplex.h>
  30. static void Init_Tableau (matrix A, matrix& M, vector c, vector b,int kl,int gr,
  31.    int gl, int *&B, int *&NB, int zeilen, int spalten, int n)
  32. {
  33.    int nb = n;                      // Zaehler zur Initialisierung der Menge NB
  34.    int s;
  35.    int z;
  36.    for ( s=0 ; s<n; s++ )
  37.       M(0,s+1) = -c[s];
  38.    for ( z=0; z<kl; z++ )
  39.    {
  40.       for ( s=0; s < n; s++ )
  41.  M(z+1,s+1) = A(z,s);
  42.       M(z+1,n+z+1) = 1;              // Schlupfvariablen setzen
  43.       B[z] = n+z+1;                  // der z.te Basisvektor
  44.    }
  45.    for ( z=0; z<gr; z++ )
  46.    {
  47.       for ( int s=0; s < n; s++ )
  48.  M(kl+z+1,s+1) = A(kl+z,s);
  49.       M(z+kl+1,n+z+kl+1) = -1;        // bei >= Nebenbedingungen neg. Schlupf
  50.       M(z+kl+1,n+kl+gr+z+1) = 1;      // kuenstliche Variable
  51.       B[kl+z] = n+kl+gr+z+1;          // der kl+gr+z.te Basisvektor
  52.       NB[nb] = n+kl+z+1; nb++;        // n+kl+gr+z ist Nichtbasisvaiable
  53.       M(zeilen-1,n+kl+gr+z+1) = 1;    // Initialisieren der Hilfszielfunktion
  54.    }
  55.    for ( z=0; z<gl; z++ )
  56.    {
  57.       for ( int s=0; s<n; s++ )
  58.  M(z+kl+gr+1,s+1) = A(z+kl+gr,s);
  59.       M(z+kl+gr+1,n+kl+2*gr+z+1) = 1;  // kuenstliche Variable
  60.       B[kl+gr+z] = kl+2*gr+n+z+1;      // der z.te Basisvektor
  61.       M(zeilen-1,n+kl+2*gr+z+1) = 1;   //Initialisieren der Hilfszielfunktion
  62.    }
  63.    for ( z=0; z<b.dim(); z++)
  64.       M(z+1,0) = b[z];
  65.    for( s=0; s < n ; s++)               // 1,...,n sind Nichtbasisvariablen
  66.       NB[s] = s+1;
  67.    for ( z=kl+1; z<=kl+gr+gl; z++)      // Subtrahieren der Zeilen mit kuenstl.
  68.       for ( s=0; s<spalten; s++)    // Variablen von der letzten Zeile
  69.  M(zeilen-1,s) = M(zeilen-1,s) - M(z,s);
  70. }
  71. static void InitIntArray (int *&A, int *B, int l)
  72. // Initialisiert das int-Array A der Laenge l mit dem int-Array B
  73. {
  74.    for (int i=0; i<l; i++)
  75.       A[i] = B[i];
  76. }
  77. static void InitMatrix (matrix &A, matrix B, int dim1, int dim2)
  78. // Initialisierung der Matrix A mit der Matrix B
  79. {
  80.    for (int l=0; l<dim1; l++)
  81.       for (int m=0; m<dim2; m++)
  82.  A(l,m) = B(l,m);
  83. }
  84. static int PivotSpalte (matrix M, int *&NB, int z, int l, int m)
  85. // in der Zeile z (z=0 oder z = m+1) wird die Pivotspalte gesucht
  86. // l ist die Groesse der Menge der Nichtbasisvariablen
  87. // accept = 1 impliziert die Gueltigkeit der gefundenen Pivotspalte, d.h.
  88. // es gibt in dieser Zeile ein Element, das > 0 ist,
  89. // ist dies nicht der Fall so wird nach einer neuen Pivotspalte gesucht
  90. // iter zaehlt die Anzahl der Iterationen
  91. {
  92.    double eps = 0.00001; // das Intervall [-eps..eps] entspricht NULL
  93.    double min=-eps;
  94.    double minmin=-10000;
  95.    int mins = 0;
  96.    int p, accept = 0;
  97.    int iter = 1;
  98.    while ( (accept == 0) && (iter <= l) )
  99.    { int q;
  100.       for ( q=0; q<l; q++)
  101.  if ( ( M(z,NB[q]) <= min ) && ( M(z,NB[q]) > minmin ) )
  102.  {
  103.     min = M(z,NB[q]);
  104.     mins = NB[q];
  105.  }
  106.       p = 1;                                // Test ob die gefundene Spalte
  107.       while ( (p <= m) && (accept == 0) )   // als Pivotspalte akzeptiert
  108.       {                                     // wird
  109.  if ( M(p,mins) > eps )
  110.     accept = 1;
  111.  p++;
  112.       }
  113.       if (accept == 0)                      // falls nicht
  114.       {                                     // -> Suche nach der naechst-
  115.  minmin = min;              // besten Pivotspalte
  116.  min = -eps;
  117.  q = 0;
  118.  mins = 0;
  119.       }
  120.       iter++;
  121.    }
  122.    return mins;
  123. }
  124. static int D_PivotSpalte (matrix M, int *&NB, int z,int n,int kl,int gr)
  125. // Liefert die Pivotspalte fuer einen Dualsimplexschritt in der Zeile z
  126. {
  127.    double eps = 0.00001; // das Intervall [-eps..eps] entspricht NULL
  128.    double min = 1000;
  129.    int mins = 0;
  130.    for(int q=0; q<n+gr; q++)
  131.       if ( ( M(z,NB[q]) < -eps ) && ( NB[q] <= n+kl+gr ) )
  132.  if ( min >= -M(0,NB[q]) / M(z,NB[q]) )
  133.  {
  134.     min = -M(0,NB[q]) / M(z,NB[q]);
  135.     mins = NB[q];
  136.  }
  137.    return mins;
  138. }
  139. static int PivotZeile (matrix M, int s, int m)
  140. // Liefert die Pivotzeile fuer einen Primalsimplexschritt in der Spalte s
  141. {
  142.    double eps = 0.00001; // das Intervall [-eps..eps] entspricht NULL
  143.    int minz = 0;
  144.    double min = 1000;
  145.    for (int p=1; p<=m; p++)
  146.       if ( M(p,s) > eps )
  147.   if (min > M(p,0)/M(p,s) )
  148.   {
  149.      min = M(p,0)/M(p,s);
  150.      minz = p;
  151.   }
  152.    return minz;
  153. }
  154. static void Basiswechsel (matrix &M, int p, int q, int n,int kl, int gr, int gl)
  155. // Basiswechsel : siehe Dinkelbach
  156. {
  157.    double pivot = M(p,q);
  158.    double pivot2;
  159.    int spalten = n+kl+2*gr+gl;
  160.    int zeilen = kl+gr+gl;
  161.    for (int s=0; s<=spalten; s++)
  162.       M(p,s)= M(p,s)/pivot;
  163.    int z;
  164.    for (z=0; z<p; z++)
  165.    {
  166.       pivot2 = M(z,q);
  167.       for (int s=0; s<=spalten; s++)
  168.  M(z,s) = M(z,s)-M(p,s)*pivot2;
  169.    }
  170.    for (z=p+1; z<=zeilen+1; z++)
  171.    {
  172.       pivot2 = M(z,q);
  173.       for (int s=0; s<=spalten; s++)
  174.  M(z,s) = M(z,s)-M(p,s)*pivot2;
  175.    }
  176. }
  177. static void NB_NNB_Update (int *&B, int *&NB, int p, int q, int l)
  178. // Nach jedem Simplex-Schritt werden die Mengen der Basis- ( B ) und
  179. // Nichtbasisvariablen ( NB ) neu berechnet
  180. // p und q bezeichnen die Pivotzeile bzw die Pivotspalte
  181. // l ist die Groesse der Menge der Nichtbasisvariablen (diese aendert
  182. // sich im Laufe des Verfahrens)
  183. {
  184.    int h1, h2;
  185.    for (int x=0; x<l; x++)
  186.       if (NB[x] == q)
  187.  h1 = x;
  188.    h2 = B[p-1];
  189.    B [p-1] = q;
  190.    NB [h1] = h2;
  191. }
  192. static void NNB_Update (int *&NB, int n, int kl, int gr, int gl)
  193. // Veringerung der Menge der Nichtbasisvariablen um die k抧stlichen Variablen
  194. {
  195.    int *nnb = new int[n-gl];
  196.    int m = 0;
  197.    for (int l=0; l<n+gr; l++)
  198.       if ( NB[l] <= n+kl+gr )
  199.       {
  200.  nnb[m] = NB[l];
  201.  m++;
  202.       }
  203.    delete NB;
  204.    NB = nnb;
  205. }
  206. static int nicht_optimal (matrix &M, int n, int kl, int gr)
  207. // returniert 1, wenn das Simplextableau nicht optimal ist, sonst 0
  208. {
  209.    double eps = 0.00001; // das Intervall [-eps..eps] entspricht NULL
  210.    int not_opt = 0;
  211.    for (int i=1; i<=n+gr+kl; i++)
  212.       if ( M(0,i) < -eps )
  213.  not_opt = 1;
  214.    return not_opt;
  215. }
  216. static void Eliminiere_kuenstl_Var (matrix M, int *&B, int *&NB, int &error,
  217.      int m, int n, int kl, int gr, int gl)
  218. // die kuenstlichen Variablen, die noch Basisvariablen sind, werden zu
  219. // Nichtbasisvariablen "pivotiert"
  220. {
  221.    int q;
  222.    int l=0;
  223.    while ( (l<m) && nicht_optimal(M,n,kl,gr) )
  224.    {
  225.       if (B[l] > n+kl+gr)
  226.       {
  227.  q = D_PivotSpalte (M,NB,l+1,n,kl,gr);
  228.          if ( (q != 0) && ( error == 0 ) )
  229.  {
  230.     Basiswechsel (M,l+1,q,n,kl,gr,gl);
  231.     NB_NNB_Update (B,NB,l+1,q,n+gr);
  232.  }
  233.  else
  234.     error = 1;
  235.       }
  236.       l++;
  237.    }
  238.    if ( (error==0) && nicht_optimal(M,n,kl,gr) )
  239.       NNB_Update (NB,n,kl,gr,gl);
  240. }
  241. static vector Basisloesung (matrix M, int *B, int m, int n)
  242. // returniert eine optimale Basisloesung
  243. {
  244.    vector X(n);
  245.    for (int l=0; l<m; l++)
  246.       if ( B[l] <= n )
  247.  X[B[l]-1] = M(l+1,0);
  248.    return X;
  249. }
  250. static vector Extremalstrahl (matrix M, int *&B, int *&MF, int l, int m, int n)
  251. // returniert die Steigung des Extremalstrahls
  252. {
  253.    vector s(n);
  254.    for (int j=0; j<m; j++)
  255.       if ( B[j] <= n )
  256. s[B[j]-1] = -M(j+1,MF[l]);
  257.    if ( MF[l] <= n )
  258.       s[MF[l]-1]=1;
  259.    return s;
  260. }
  261. static int ZERO (vector v,int n)
  262. // returniert 1, falls v gleich dem Nullvektor ist, sonst 0
  263. {
  264.    double eps = 0.00001; // das Intervall [-eps..eps] entspricht NULL
  265.    int zero = 1;
  266.    for (int i=0; i<n; i++)
  267.       if ( (v[i] < -eps) || (v[i] > eps) )
  268.          zero = 0;
  269.    return zero;
  270. }
  271. static void Init_Matrix (matrix &A, vector x, int n)
  272. // initialisiert die (1xn)-Matrix mit dem Vektor x
  273. {
  274.    for (int i=0; i<n; i++)
  275.       A(0,i) = x[i];
  276. }
  277. static void Enlarge_Matrix (matrix &A, vector v, int n)
  278. // vergroessert die Matrix A um den Zeilenvektor v
  279. {
  280.    int dim1 = A.dim1();
  281.    matrix B(dim1+1,A.dim2());
  282.    InitMatrix (B,A,dim1,A.dim2());
  283.    for (int i=0; i<n; i++)
  284.       B(dim1,i) = v[i];
  285.    A = B;
  286. }
  287. static void Test_auf_Extremalstrahl (matrix &M,int *&B,int *&NB,list<matrix>& L,
  288.       int *&MF, int *&PZ, int i, vector x, int m, 
  289.                               int n, int kl, int gr)
  290. // Berechnung und Ausgabe eines optimalen Extremalstrahls
  291. // Aufbau der Liste L der optimalen Loesungen
  292. {
  293.    vector s(n);
  294.    matrix A (1,n);
  295.    int l;
  296.    Init_Matrix (A,x,n);
  297.    for ( l=0; l<i; l++)
  298.       if ( NB[l] <= n+gr+kl )             // Test ob im optimalen Tableau ein
  299.  if ( M(0,NB[l]) == 0 )        // Zielfunktionskoeffient einer Nicht-
  300.     MF[l] = NB[l];                // basisvariable = 0 ist
  301.  else
  302.     MF[l] = 0;
  303.       else
  304.          MF[l] = 0;
  305.    for ( l=0; l<i; l++)
  306.    {
  307.       if ( MF[l] > 0 )
  308.       {
  309.  PZ[l] = PivotZeile (M,MF[l],m);
  310.  if ( PZ[l] == 0 )
  311.  {
  312.     s = Extremalstrahl (M,B,MF,l,m,n);
  313.     if ( !ZERO(s,n) )
  314.        Enlarge_Matrix (A,s,n);
  315.  }
  316.       }
  317.    }
  318.    L.append (A);
  319. }
  320. static
  321. void Test_auf_Mehrfachloesungen(matrix &M,int *&B,int *&NB,list<matrix> &L,
  322. int x, vector v,int zeilen, int spalten,
  323. int m, int n, int kl, int gr, int gl)
  324. // Berechnung von eventuell existierenden weiteren optimalen Basisloesungen
  325. // x ist die Groesse der Menge der Nichtbasisvariablen
  326. {
  327.     // Hilfsmatrix zur Berechnung weiterer
  328.    matrix A (m+2,n+kl+2*gr+gl+1);   // optimaler Simplextableaus
  329.    int *MF = new int[x];              // fuer die Indizes der Spalten in
  330.       // denen die 0.te Zeile =0 ist
  331.    int *PZ = new int[x];              // die zugehoerigen Pivotzeilen
  332.    int *H1 = new int[x];              // Hilfsarrays
  333.    int *H2 = new int[x];
  334.    int *b = new int [m];              // Hilfsarrays fuer B
  335.    int *nb = new int [x];             // und NB
  336.    Test_auf_Extremalstrahl (M,B,NB,L,MF,PZ,x,v,m,n,kl,gr);
  337.    for (int l=0; l<x; l++)
  338.    {
  339.       if ( MF[l] > 0 )
  340.  if ( PZ[l] > 0 )
  341.  {
  342.     InitMatrix (A,M,zeilen,spalten);
  343.     InitIntArray (b,B,m);
  344.     InitIntArray (nb,NB,x);
  345.     Basiswechsel (A,PZ[l],MF[l],n,kl,gr,gl);
  346.     NB_NNB_Update (b,nb,PZ[l],MF[l],x);
  347.     v = Basisloesung (A,b,m,n);
  348.     Test_auf_Extremalstrahl (A,b,nb,L,H1,H2,x,v,m,n,kl,gr);
  349.  // H1, H2 sind Hilfsarrays
  350.  }
  351.    }
  352.    delete MF; delete PZ; delete H1;
  353.    delete H2; delete b; delete nb;
  354. }
  355. static
  356. void Run (matrix &M, int *&B, int *&NB, list<matrix> &L, int zeilen, 
  357.           int spalten, int m, int n, int kl, int gr, int gl)
  358. // Hauptprozedur
  359. {
  360.    double eps = 0.00001; // das Intervall [-eps..eps] entspricht NULL
  361.    int p, q;
  362.    int error=0;
  363.    vector x;
  364.    q = PivotSpalte (M,NB,m+1,n+gr,m);
  365.    while (q != 0)
  366.    {
  367.       p = PivotZeile (M,q,m);
  368.       if (p != 0)
  369.       {
  370.  Basiswechsel (M,p,q,n,kl,gr,gl);
  371.  NB_NNB_Update (B,NB,p,q,n+gr);
  372.       }
  373.       q = PivotSpalte (M,NB,m+1,n+gr,m);
  374.    }
  375.    if ( ( M(m+1,0) > -eps ) && ( M(m+1,0) < eps ) )
  376.    {
  377.       Eliminiere_kuenstl_Var (M,B,NB,error,m,n,kl,gr,gl);
  378.       if ( nicht_optimal (M,n,kl,gr) )
  379.       {
  380. // falls error = 1 so konnte ein notwendiger Dualsimplexschritt nicht
  381. // durchgefuehrt werden
  382.  if ( error == 0 )
  383.  {
  384.     q = PivotSpalte (M,NB,0,n-gl,m);
  385.     while (q != 0)
  386.     {
  387.        p = PivotZeile (M,q,m);
  388.        if (p != 0)
  389.        {
  390.   Basiswechsel (M,p,q,n,kl,gr,gl);
  391.   NB_NNB_Update (B,NB,p,q,n-gl);
  392.        }
  393.        q = PivotSpalte (M,NB,0,n-gl,m);
  394.     }
  395.     x = Basisloesung(M,B,m,n);
  396.     Test_auf_Mehrfachloesungen(M,B,NB,L,n-gl,x,zeilen,
  397.        spalten,m,n,kl,gr,gl);
  398.  }
  399.       }
  400.       else                              // das Tableau war schon optimal
  401.       {
  402.   x = Basisloesung(M,B,m,n);
  403.   Test_auf_Mehrfachloesungen (M,B,NB,L,n+gr,x,zeilen,
  404.       spalten,m,n,kl,gr,gl);
  405.       }
  406.    }
  407. }
  408. list<matrix> SIMPLEX(matrix A, int i, int j, int k, vector b, vector c)
  409. {
  410.    int *B; int *NB;
  411.  
  412.    list<matrix> L;
  413.    int kl =i,  gr=j, gl=k;
  414.    int n = A.dim2(),m = A.dim1(); // setzen der globalen Variablen
  415.    int zeilen = m+2, spalten = n+m+gr+1;
  416.    matrix M(zeilen,spalten);
  417.    B  = new int[m];
  418.    NB = new int[n+gr];
  419.    Init_Tableau(A,M,c,b,i,j,k,B,NB,zeilen,spalten,n);
  420.    Run (M,B,NB,L,zeilen,spalten,m,n,kl,gr,gl);
  421.    delete B; delete NB;
  422.    return L;
  423. }