/***************************************************************************** * 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 * * 06.05.1989 | 1.3a | BUG in TryPivot(): Pivot auch, wenn Nq[i]<0 !! * * | | Änd. in Calc1(): b2q neuberechnen * * 20.05.1989 | 1.4 | Änd. in PhaseI(): bsum globale Variable * * 06.08.1989 | 1.5 | Überflüssige Parameter gestrichen * *****************************************************************************/ #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; GLOBAL DOUBLE *lower, *upper; /* T */ GLOBAL DOUBLE bsum; /* bsum = 1 b */ GLOBAL DOUBLE *A, *AB1, *b, *b2q; GLOBAL SHORT *B, *Nq; /***************************************************************************** * 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,c,c2,c0,c0start,flags,x,cq,pi,dq,Nminus,help,iter) SHORT *m; /* Zeiger auf m */ SHORT *n; /* Zeiger auf n */ /* *B (m)-Vektor */ /* *Nq (n)-Vektor: (n-m)+m */ /* *b (m)-Vektor */ /* *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 */ /* *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 */ { 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,&bsum,c2,c0); /* Das Hilfsprogramm hat eine optimale Lösung (theoretisches Ergebnis) */ result = PhaseII(mm,mm+nn,c2,c0,0.0,PHASE_I | flags,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,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(b,help,mm,_FALSE); for(i=0; i mm */ Calc1(mm,nn,c,c0,c0start,Nminus,help); return(OPTIMAL); } } else { /* künstl. Variablen in der Basis */ if(Calc2(m,nn,help) == NOT_INVERTABLE) return(NOT_INVERTABLE); mm = *m; if(nn == mm) { /* trivialer Fall */ Mult(b,help,mm,_FALSE); 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,eta,dq) SHORT pos, mm, nn; DOUBLE *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 EPS_NULL) { /* Pivotelement != 0.0 => Pivotschritt */ dq[pos] = sum; /* dq[] jetzt ganz berechnen */ ptr1 = AB1; for(k=0; k 0.0) */ } /* if(möglicher Kandidat) */ } /* for(i= ... */ return(NO_PIVOT); } /***************************************************************************** * VOID Calc1() * * Entfernt die künstlichen Variablen aus Nq und berechnet b2q und c0 neu * *****************************************************************************/ VOID Calc1(mm,nn,c,c0,c0start,Nminus,help) SHORT mm, nn; DOUBLE *c, *c0, c0start; SHORT *Nminus; DOUBLE *help; { REGISTER DOUBLE dummy, *ptr1, *ptr3; 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,help) SHORT *m, nn; DOUBLE *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