/***************************************************************************** * Modul : phase2.c * * Zweck : Phase II des Simplexalgorithmus * * Autor : Stefan Förster * * * * Datum | Version | Bemerkung * * -----------|---------|--------------------------------------------------- * * 06.02.1989 | 0.0 | * * 07.02.1989 | 0.1 | Anpassung an PHASE_I * * 25.02.1989 | 0.2 | CHUZR(), WRETA(), 1. Testlauf erfolgreich * * 26.02.1989 | 0.3 | PRICE() verbessert * * 26.02.1989 | 0.4 | VERBOSE-Option, Reinvertierung von AB1 * * 02.03.1989 | 0.5 | Bug in CHUZR(): dqi<-EPS_NULL statt dqi0 ? lower[qs] : upper[qs]+lower[qs]; } for(i=0; iEPS_NULL) meth = (*c0-c0_old)/fabs(c0_old) <= PERCENT ? STEEPEST_ASCENT : SMALLEST_INDEX; } } } /***************************************************************************** * VOID BTRAN() * * Backward Transformation * *****************************************************************************/ VOID BTRAN(m,c,pi,dummy) SHORT m; DOUBLE *c, *pi, *dummy; /* dummy : (m)-Hilfsvektor */ { DOUBLE *ptr=dummy; SHORT i; for(i=0; i OPTIMAL/NOT_OPTIMAL * * meth & STEEPEST_ASCENT => Steilster-Anstieg-Regel * * meth & SMALLEST_INDEX => (zyklische) Kleinster-Index-Regel * *****************************************************************************/ USHORT PRICE(m,n,c,cq,pi,s,flags,lastpos) SHORT m, n; DOUBLE *c, *cq, *pi; SHORT *s; USHORT flags; /* PHASE_I/PHASE_II, SMALLEST_INDEX/STEEPEST_ASCENT */ SHORT *lastpos; { REGISTER DOUBLE *ptr1, *ptr2, sum; REGISTER SHORT j, i; SHORT qs, nm = n-m, pos; USHORT flag = OPTIMAL; USHORT phase = flags & (PHASE_I | PHASE_II); USHORT meth = flags & (SMALLEST_INDEX | STEEPEST_ASCENT); SHORT columns = phase==PHASE_I ? nm : n; DOUBLE dummy; if(meth == STEEPEST_ASCENT) { for(i=0; i=nm) sum -= pi[qs-nm]; else { ptr2 = A+qs; for(j=0; j EPS_NULL && cq[i]*Nq[i] > 0.0) { if(flag==OPTIMAL) { flag = NOT_OPTIMAL; *s = i+1; /* Index s : 1,...,n-m */ sum = dummy; } else { if(dummy>sum) { *s = i+1; sum = dummy; } } } } } else { /* meth == SMALLEST_INDEX */ pos = ((*lastpos)+1) % nm; /* lastpos+1 modulo nm */ for(i=0; i=nm) sum -= pi[qs-nm]; else { ptr2 = A+qs; for(j=0; jEPS_NULL && sum*Nq[pos]>0.0) { cq[pos] = sum; *s = pos+1; /* s: Index 1,...,nm */ *lastpos = pos; return(NOT_OPTIMAL); } ++pos; pos %= nm; } } return(flag); } /***************************************************************************** * VOID FTRAN() * * Forward Transformation * *****************************************************************************/ VOID FTRAN(m,n,qs,dq,phase) SHORT m, n, qs; DOUBLE *dq; USHORT phase; { REGISTER DOUBLE *ptr1, *ptr2=AB1, sum; REGISTER SHORT j, i; SHORT nm = n-m, columns = phase==PHASE_I ? nm : n; qs = ABS(qs)-1; if(phase == PHASE_I && qs>=nm) { ptr1 = AB1 + (qs-nm); for(i=0; i UNBOUNDED/NOT_UNBOUNDED * * Ergebnis: Zeile r, rowflag (Art des Pivotschritts) * *****************************************************************************/ USHORT CHUZR(m,dq,qs,s,r,rowflag) SHORT m; DOUBLE *dq; SHORT qs, s, *r; /* qs: 0,...,n-1 s: 1,...,n-m r: 1,...,m */ USHORT *rowflag; /* LAMBDA_0, LAMBDA_1 oder LAMBDA_2 */ { REGISTER DOUBLE lambda0 = INFINITE, lambda1 = INFINITE; REGISTER SHORT i; DOUBLE lambda2 = upper[ABS(qs)-1]; REGISTER DOUBLE dqi, dummy, min = lambda2; SHORT sigma = SGN(qs), min_i; *rowflag = LAMBDA_2; for(i=0; i EPS_NULL) { dummy = b2q[i]/dqi; if(lambda0 == INFINITE || dummyfabs(dq[min_i-1])) { lambda0 = min = dummy; min_i = i+1; *rowflag = LAMBDA_0; } } else if(dqi < -EPS_NULL && (dummy = upper[B[i]-1])!=INFINITE) { dummy = (b2q[i]-dummy)/dqi; if(lambda1 == INFINITE || dummyfabs(dq[min_i-1])) { lambda1 = min = dummy; min_i = i+1; *rowflag = LAMBDA_1; } } } *r = min_i; if(lambda0==INFINITE && lambda1==INFINITE && lambda2==INFINITE) return(UNBOUNDED); return(NOT_UNBOUNDED); } /***************************************************************************** * USHORT WRETA() -> INVERTABLE/NOT_INVERTABLE * * je nachdem, ob AB invertierbar ist (sollte es zumindest) oder nicht * *****************************************************************************/ USHORT WRETA(m,n,c,cq,c0,c0start,dq,r,s,eta,help,Nminus,flags,iter) SHORT m, n; DOUBLE *c, *cq, *c0, c0start, *dq; SHORT r, s; DOUBLE *eta, *help; /* eta : (n)-Vektor (=x), als (m)-Vektor verw. */ SHORT *Nminus; /* Nminus (n-m)-Vektor, negativer Anteil von Nq */ USHORT flags; /* PHASE_I/PHASE_II, rowflag, verbose */ ULONG iter; /* Zahl der bewältigten Iterationen */ { REGISTER DOUBLE *ptr1, *ptr2, eta_r = 1.0/dq[r-1], eta_dummy; REGISTER SHORT j, i; LONG offset = (LONG)(r-1)*(LONG)m; SHORT anzneg = 0; /* Anzahl negativer Elemente in Nq */ SHORT nm = n-m, swap; USHORT phase = flags & (PHASE_I | PHASE_II); USHORT rowflag = flags & (LAMBDA_0 | LAMBDA_1 | LAMBDA_2); SHORT columns = phase==PHASE_I ? nm : n; if(invert_freq) iter %= (ULONG)invert_freq; if(rowflag != LAMBDA_2) { /* Falls Nq[s-1]<0 ist, ändert sich c0 zusätzlich !!!! */ /* Falls AB1 reinvertiert wird, wird c0 jedoch völlig neu berechnet */ if(Nq[s-1]<0) *c0 -= cq[s-1]*upper[ABS(Nq[s-1])-1]; swap = B[r-1]; B[r-1] = ABS(Nq[s-1]); Nq[s-1] = rowflag == LAMBDA_0 ? swap : -swap; for(j=0; j0) { /* wenn also das alte qs_quer positiv war */ for(i=0; i