/***************************************************************************** * Modul : phase1.c * * Zweck : Phase I des Simplexalgorithmus * * Autor : Stefan Förster * * * * Datum | Version | Bemerkung * * -----------|---------|--------------------------------------------------- * * 01.03.1989 | 0.0 | * * 02.03.1989 | 0.1 | TryPivot(), Calc1(), Calc2() * * 03.03.1989 | 0.2 | Bug in TryPivot(): sum = eta[k] statt sum = eta[i] * * | | Abfrage auf Invertierbarkeit von AB * * 04.03.1989 | 1.0 | Bug in Calc2(): zusätzl.: b[i] = b[j] * * 06.03.1989 | 1.1 | Bug in TryPivot(): else ptr1+=mm; bei AB1-Update * * 07.03.1989 | | Ein Aufruf von Mult() gespart * * 10.03.1989 | 1.2 | Änd. in Calc1(): *c0 = dummy + c0start; * * 14.03.1989 | 1.3 | BUG in PhaseI(): c0 neuberechnen, falls CLEAR_CUT * *****************************************************************************/ #define PIVOT (USHORT)1 #define NO_PIVOT (USHORT)0 IMPORT VOID Mult(); IMPORT USHORT Invers(); IMPORT DOUBLE M(); IMPORT VOID SetM(); IMPORT USHORT PhaseII(); IMPORT VOID CopyMemQuick(); GLOBAL DOUBLE INFINITE; GLOBAL BOOL minimize; /***************************************************************************** * USHORT PhaseI() * * - EMPTY, falls das Polyeder leer ist * * - CLEAR_CUT, falls das Polyeder einelementig ist * * - OPTIMAL, falls eine zulässige Basis gefunden wurde * * - UNBOUNDED, falls (unzulässigerweise !) das Hilfsprogramm unbeschr. ist * * - NOT_INVERTABLE, falls AB (unzulässigerweise!) nicht invertierbar ist * * * * Input: m, n, A, b, c, c0start, upper (b>=0) * * * * Output: EMPTY : - * * CLEAR_CUT : x * * OPTIMAL : m, A, b, B, Nq, AB1, b2q * * UNBOUNDED : - * * NOT_INVERTABLE : - * *****************************************************************************/ USHORT PhaseI(m,n,B,Nq,A,AB1,b,b2q,c,c2,c0,c0start,flags,upper,x,cq,pi,dq, Nminus,help,iter) SHORT *m; /* Zeiger auf m */ SHORT *n; /* Zeiger auf n */ SHORT *B; /* (m)-Vektor */ SHORT *Nq; /* (n)-Vektor: (n-m)+m */ DOUBLE *A; /* (m,n)-Matrix */ DOUBLE *AB1; /* (m,m)-Matrix */ DOUBLE *b; /* (m)-Vektor */ DOUBLE *b2q; /* (m)-Vektor */ DOUBLE *c; /* (n)-Vektor */ DOUBLE *c2; /* (n+m)-Vektor */ DOUBLE *c0; /* Zeiger auf c0 */ DOUBLE c0start; /* Korr.wert f. Zielfktsw.*/ USHORT flags; /* VERBOSE */ DOUBLE *upper; /* (n+m)-Vektor */ DOUBLE *x; /* (n+m)-Vektor */ DOUBLE *cq; /* (n)-Vektor: (n-m)+m */ DOUBLE *pi; /* (m)-Vektor */ DOUBLE *dq; /* (m)-Vektor */ SHORT *Nminus; /* (n)-Vektor: (n-m)+m */ DOUBLE *help; /* (m)-Vektor */ ULONG *iter; /* Anzahl Iterationen */ { /* T */ DOUBLE bsum; /* bsum = 1 b */ DOUBLE sum, *ptr1; SHORT mm = *m, nn = *n, i, j, pivots, no_of_bad; USHORT result; VOID PrepareData(), Calc1(); USHORT TryPivot(), Calc2(); PrepareData(mm,nn,B,Nq,A,AB1,b,b2q,&bsum,c2,c0,upper); /* Das Hilfsprogramm hat eine optimale Lösung (theoretisches Ergebnis) */ result = PhaseII(mm,mm+nn,B,Nq,A,AB1,b,b2q,c2,c0,0.0,PHASE_I | flags,upper, NULL,x,cq,pi,dq,Nminus,help,iter); if(result == UNBOUNDED) { puts("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); puts("!! Hilfsprogramm von Phase I unbeschränkt !!"); puts("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"); return(UNBOUNDED); } /* T T */ /* P(A,b) == EMPTY, wenn 1 Ax < 1 b ist */ if(bsum-(*c0) > EPS_NULL) return(EMPTY); /* Versuch, künstliche Variablen aus der Basis zu werfen */ do { pivots = no_of_bad = 0; for(i=1; i<=mm; ++i) { if(B[i-1]>nn) { /* help als eta-Vektor */ if(TryPivot(i,mm,nn,B,Nq,A,AB1,help,dq) == PIVOT) ++pivots; else ++no_of_bad; } } } while(pivots>0); if(no_of_bad == 0) { /* keine künstlichen Variablen in der Basis (Yeah!) */ if(nn == mm) { /* trivialer Fall */ Mult(AB1,b,help,mm,mm,1); for(i=0; i mm */ Calc1(mm,nn,B,Nq,b2q,c,c0,c0start,upper,Nminus); return(OPTIMAL); } } else { /* künstl. Variablen in der Basis */ if(Calc2(m,nn,B,A,AB1,b,b2q,help) == NOT_INVERTABLE) return(NOT_INVERTABLE); mm = *m; if(nn == mm) { /* trivialer Fall */ Mult(AB1,b,help,mm,mm,1); for(i=0; i c2 */ ptr1 = c2; for(i=0; i PIVOT/NO_PIVOT * * Versuch, die künstliche Variable B[pos-1] aus der Basis zu entfernen * *****************************************************************************/ USHORT TryPivot(pos,mm,nn,B,Nq,A,AB1,eta,dq) SHORT pos, mm, nn, *B, *Nq; DOUBLE *A, *AB1, *eta, *dq; { REGISTER SHORT j, k, i; REGISTER DOUBLE *ptr1, *ptr2, sum; SHORT nandm = nn+mm, column; LONG offset = (LONG)(--pos)*(LONG)mm; /* pos: 0,...,m-1 */ for(i=0; i= 0 && column < nn) { /* mögl. Kandidat gefunden */ ptr1 = AB1+offset; /* dq[pos] Pivotelement berechnen */ ptr2 = A+column; /* column : 0,...,n-1 */ for(sum=0.0,j=0; j EPS_NULL) { /* Pivotelement != 0.0 => Pivotschritt */ dq[pos] = sum; /* dq[] jetzt ganz berechnen */ ptr1 = AB1; for(k=0; k 0 */ Nq[i] = k; return(PIVOT); } /* if(Pivotelement > 0.0) */ } /* if(möglicher Kandidat) */ } /* for(i= ... */ return(NO_PIVOT); } /***************************************************************************** * VOID Calc1() * * berechnet c0 für die gefundene Basislösung und entfernt die künstlichen * * Variablen aus Nq * *****************************************************************************/ VOID Calc1(mm,nn,B,Nq,b2q,c,c0,c0start,upper,Nminus) SHORT mm, nn, *B, *Nq; DOUBLE *b2q, *c, *c0, c0start, *upper; SHORT *Nminus; { REGISTER DOUBLE dummy, *ptr1; REGISTER SHORT j, i, *ptr2; SHORT nm = nn-mm, anzneg = 0; /* künstliche Variable aus Nq entfernen und gleichzeitig Nminus erstellen */ for(ptr2=Nq,i=0; iINVERTABLE/NOT_INVERTABLE * * je nachdem, ob AB invertierbar ist (sollte es) oder nicht * * Streichen der überflüssigen Zeilen von A, Entfernen der künstlichen * * Variablen aus B, Update von *m und Neuberechnung von AB1 * *****************************************************************************/ USHORT Calc2(m,nn,B,A,AB1,b,b2q,help) SHORT *m, nn, *B; DOUBLE *A, *AB1, *b, *b2q, *help; { REGISTER SHORT j, i, mm = *m, *ptr; DOUBLE *dest, *src; SHORT column; LONG length = (LONG)nn*(LONG)sizeof(DOUBLE); for(ptr=B,i=0; i