/***************************************************************************** * Modul : main.c * * Zweck : Simplexalgorithmus * * Autor : Stefan Förster * * * * Datum | Version | Bemerkung * * -----------|---------|--------------------------------------------------- * * 14.03.1989 | 1.0 | * * 15.03.1989 | | Zeitmessung mittels CurrentTime() * * 17.03.1989 | 1.1 | SetTaskPri() jetzt korrekt * * | | min cTx zugelassen * * 18.03.1989 | 1.2 | Optional Ausgabe an ein File möglich (-f) * * 06.05.1989 | 1.3 | BUG in Phase I behoben (TryPivot()) * * 09.05.1989 | | BUG in Phase II behoben (PhaseII()) * * | | Neue Funktion PrintTime() + Zeitmessung geändert * * 20.05.1989 | 1.4 | Bessere Ausgabe bei VERBOSE ON * * | | Neues Kommando "INVERT" * * | | Kommando "VERBOSE" erweitert: VERBOSE [N] * * | | Neues Kommando "PRICE" * * | | Neues Kommando "MINIMIZE" * * | | 'bsum' als globale Variable für PhaseI() definiert * * 21.07.1989 | | mpsx.c: Nach NAME jetzt max. 33 Zeichen möglich. * * 06.08.1989 | 1.5 | Überflüssige Parameter gestrichen * * 07.08.1989 | | Ein-/Ausgabe in eigenem (NEW)CON:-window * * | | DEFAULT-Option * *****************************************************************************/ IMPORT USHORT PhaseI(), PhaseII(); IMPORT BOOL MPSX(), SearchExpr(); IMPORT VOID GetInput(); IMPORT SHORT GetExpr(); IMPORT VOID GiveMemBack(), GetRidOfLists(), PrintError(), Cap(); IMPORT VOID CurrentTime(), *OpenLibrary(), SetTaskPri(), fclose(); IMPORT struct Task *FindTask(); IMPORT FILE *freopen(); struct IntuitionBase *IntuitionBase = NULL; struct GfxBase *GfxBase = NULL; DOUBLE INFINITE = 1.0/0.0; /* IEEE: NAN (Not A Number) */ #ifdef PAL TEXT version[] = "NEWCON:0/11/640/245/ASimplex Version 1.5"; #else TEXT version[] = "NEWCON:0/11/640/189/ASimplex Version 1.5"; #endif TEXT comment[] = "THE Amiga Simplex Program\n(c) 06.02.-07.08.1989\n\ Stefan Förster"; TEXT reverse[] = "\033[0;0H\033[41;32m\033[J"; FILE *file[2] = { NULL }, *con = NULL; TEXT symbols[NUM_SYMBOLS][MAX_STRLEN+1]; BOOL minimize = _FALSE; /* _TRUE, falls Zielfunktion minimiert wird */ BOOL global_minimize = _FALSE; LONG invert_freq = INVERT_FREQUENCY, verbose_freq = 1L; USHORT method = MIXED; DOUBLE bsum; /* für PhaseI() */ ITEMPTR list[NUM_LISTS]; TEXT args[BUFFER], line[BUFFER]; SHORT m, n, *B = NULL, *Nq = NULL, *Nminus = NULL; DOUBLE c0, c0start; DOUBLE *A = NULL, *AB1 = NULL, *b = NULL, *b2q = NULL; DOUBLE *c = NULL, *c2 = NULL, *upper = NULL, *lower = NULL; DOUBLE *x = NULL, *cq = NULL, *pi = NULL, *dq = NULL, *help = NULL; STRPTR errors[] = { (STRPTR)"Invalid arguments for \"load\"", (STRPTR)"Identifier too long", (STRPTR)"Identifier declared twice", (STRPTR)"Unknown Identifier", (STRPTR)"Sections have to start in column 1", (STRPTR)"Section defined twice", (STRPTR)"Unknown section", (STRPTR)"Illegal order of sections", (STRPTR)"Missing NAME-section (1st section) or NAME-section empty", (STRPTR)"Missing ROWS-section (2nd section) or ROWS-section empty", (STRPTR)"Missing goal or goal not found", (STRPTR)"Missing COLUMNS-section (3rd section) or COLUMNS-section empty", (STRPTR)"Missing RHS-section (4th section)", (STRPTR)"Missing ENDATA-section (last section)", (STRPTR)"Constraint must be of type N, E, L or G", (STRPTR)"Bound must be of type UP or LO", (STRPTR)"Lower bound > upper bound", (STRPTR)"Expression in RANGES belongs to a \"E\"-constraint", (STRPTR)"Can\'t find necessary expression in this line", (STRPTR)"File-name too long", (STRPTR)"Can\'t open file for read access", (STRPTR)"Can\'t open file for write access", (STRPTR)"End-of-file reached", (STRPTR)"Not enough memory", (STRPTR)"FATAL ERROR (This error should not occur, reboot system!)" }; main() { SHORT start, stop, length, i; BOOL end = _FALSE; USHORT verbose = 0, result; TEXT ch; STRPTR sptr; ULONG iter1, iter2, sec1, sec2, micro1, micro2; LONG pri = 0L; SHORT atoi(); VOID PrintSolution(), PrintTime(), Leave(), OpenAll(); OpenAll(); FOREVER { printf(">> "); GetInput(args); Cap(args,0,BUFFER); if(SearchExpr(args,&start,&stop)) { length = GetExpr(line,args,start,stop); if(strcmp(line,"HELP") == 0) { puts(" HELP"); puts(" LOAD [-cGOAL] [-bRHS] [-rRANGE] [-uBOUND] [-m] \ [-fFILE]"); puts(" VERBOSE [N]"); puts(" INVERT [N]"); puts(" PRICE [MIXED|CYCL|STEEP]"); puts(" MINIMIZE"); puts(" PRIORITY [N]"); puts(" DEFAULT"); puts(" QUIT"); } else if(strcmp(line,"QUIT") == 0) { do { printf("?? Really [Y,N] ? "); GetInput(args); Cap(args,0,BUFFER); if(!SearchExpr(args,&start,&stop)) start = 0; } while((ch = *(args+start))!='N' && ch!='Y'); if(ch == 'Y') Leave(""); } else if(strcmp(line,"VERBOSE") == 0) { sptr = args+stop+1; if(SearchExpr(sptr,&start,&stop)) { verbose = VERBOSE; length = GetExpr(line,sptr,start,stop); verbose_freq = (LONG)atoi(line); if(verbose_freq < 1L) verbose_freq = 1L; } else verbose = verbose ? 0 : VERBOSE; printf(" VERBOSE %ld O%s\n",verbose_freq, verbose ? "N" : "FF"); } else if(strcmp(line,"INVERT") == 0) { sptr = args+stop+1; if(SearchExpr(sptr,&start,&stop)) { length = GetExpr(line,sptr,start,stop); invert_freq = (LONG)atoi(line); if(invert_freq <= 0L) invert_freq = 0L; printf(" Changed invert frequency to %ld.\n",invert_freq); } else printf(" Current invert frequency is %ld.\n",invert_freq); } else if(strcmp(line,"PRICE") == 0) { sptr = args+stop+1; if(SearchExpr(sptr,&start,&stop)) { length = GetExpr(line,sptr,start,stop); if(strcmp(line,"MIXED") == 0) method = MIXED; else if(strcmp(line,"CYCL") == 0) method = CYCL; else if(strcmp(line,"STEEP") == 0) method = STEEP; printf(" Changed price method to "); } else printf(" Current price method is "); switch(method) { case MIXED: puts("MIXED."); break; case CYCL : puts("CYCL."); break; case STEEP: puts("STEEP."); break; } } else if(strcmp(line,"MINIMIZE") == 0) { global_minimize = !global_minimize; printf(" GLOBAL MINIMIZE O%s.\n", global_minimize ? "N" : "FF"); } else if(strcmp(line,"PRIORITY") == 0) { sptr = args+stop+1; if(SearchExpr(sptr,&start,&stop)) { length = GetExpr(line,sptr,start,stop); pri = (LONG)atoi(line); if(pri<0L) pri = 0L; if(pri>20L) pri = 20L; SetTaskPri(FindTask((STRPTR)0),pri); printf(" Changed task priority to %ld.\n",pri); } else printf(" Current task priority is %ld.\n",pri); } else if(strcmp(line,"DEFAULT") == 0) { SetTaskPri(FindTask((STRPTR)0),0L); global_minimize = _FALSE; method = MIXED; invert_freq = INVERT_FREQUENCY; verbose = 0; verbose_freq = 1; puts(" Changed task priority to 0."); puts(" Changed price method to MIXED."); printf(" Changed invert frequency to %ld.\n",INVERT_FREQUENCY); puts(" GLOBAL MINIMIZE OFF."); puts(" VERBOSE 1 OFF."); } else if(strcmp(line,"LOAD") == 0) { if(MPSX(args+stop+1)) { CurrentTime(&sec1,µ1); if(!verbose) puts("@@ Please wait - calculation."); iter1 = iter2 = 0L; result = PhaseI(&m,&n,c,c2,&c0,c0start,verbose,x,cq,pi,dq, Nminus,help,&iter1); if(result == NOT_INVERTABLE) { puts(" Matrix AB is not invertable."); if(file[1]) fputs(" Matrix AB is not invertable.\n",file[1]); } else if(result == UNBOUNDED) { puts(" PHASE I IS UNBOUNDED. THIS SHOULD NOT OCCUR!!"); if(file[1]) fputs(" PHASE I IS UNBOUNDED. THIS SHOULD NOT OCCUR!!\n",file[1]); } else if(result == EMPTY) { puts(" This problem is not solveable."); if(file[1]) fputs(" This problem is not solveable.\n",file[1]); } else if(result == CLEAR_CUT) PrintSolution(); else { result = PhaseII(m,n,c,&c0,c0start,verbose|PHASE_II,x,cq,pi, dq,Nminus,help,&iter2); if(result == NOT_INVERTABLE) { puts(" Matrix AB is not invertable."); if(file[1]) fputs(" Matrix AB is not invertable.\n",file[1]); } else if(result == UNBOUNDED) { puts(" This problem is unbounded."); if(file[1]) fputs(" This problem is unbounded.\n",file[1]); } else PrintSolution(); } printf("-> %ld iterations needed.\n",iter1+iter2); if(file[1]) fprintf(file[1],"-> %ld iterations needed.\n",iter1+iter2); GiveMemBack(); GetRidOfLists(); minimize = _FALSE; CurrentTime(&sec2,µ2); PrintTime("-> Solution time = ",sec1,micro1,sec2,micro2,file[1]); } if(file[0]) { fclose(file[0]); file[0] = NULL; } if(file[1]) { fprintf(file[1],"\f"); fclose(file[1]); file[1] = NULL; } } else printf(" Unknown command \"%s\".\n",line); } } /* FOREVER */ } /***************************************************************************** * VOID PrintTime(str,s1,m1,s2,m2,fptr) * * berechnet die Zeitdifferenz zwischen s2/m2 und s1/m1 (von CurrentTime() * * ermittelt, und gibt den String str und die Zeitdauer aus; falls fptr!=NULL* * auch in das file fptr. * *****************************************************************************/ VOID PrintTime(str,s1,m1,s2,m2,fptr) STRPTR str; ULONG s1, m1, s2, m2; FILE *fptr; { LONG h, min, sec, sec100; sec100 = m2-m1; sec = s2-s1; if(sec100 < 0L) { sec100 += 1000000L; --sec; } sec100 /= 10000L; h = sec/3600L; min = (sec-3600L*h)/60; sec -= 3600L*h+60*min; printf("%s %3ld : %02ld : %02ld,%02ld\n",str,h,min,sec,sec100); if(file[1]) fprintf(file[1],"%s %3ld : %02ld : %02ld,%02ld\n",str,h,min,sec,sec100); } /***************************************************************************** * VOID PrintSolution() * * Ausgabe der Lösung * *****************************************************************************/ VOID PrintSolution() { VOID PrintX(); puts("@@ Solution:\n"); printf(" %-9s = %14.10lg\n",symbols[GOAL],minimize ? -c0 : c0); PrintX(list[VAR_LIST],stdout); puts(""); if(file[1]) { fputs("@@ Solution:\n\n",file[1]); fprintf(file[1]," %-9s = %14.10lg\n",symbols[GOAL],minimize ? -c0 : c0); PrintX(list[VAR_LIST],file[1]); fputs("\n",file[1]); } } /***************************************************************************** * VOID PrintX() * * Gibt das Ergebnis der Berechnungen aus. * *****************************************************************************/ VOID PrintX(ptr,fptr) ITEMPTR ptr; FILE *fptr; { if(ptr) { PrintX(ptr->next,fptr); fprintf(fptr," %-9s = %14.10lg\n",ptr->string,x[ptr->nr-1]); } } /***************************************************************************** * VOID OpenAll() * * Öffnen der Bibliotheken und des (NEW)CON: - windows. * *****************************************************************************/ VOID OpenAll() { VOID Leave(); if(!(IntuitionBase = OpenLibrary("intuition.library",0L))) Leave("Can't find \"intuition.library\"!"); if(!(GfxBase = OpenLibrary("graphics.library",0L))) Leave("Can't find \"graphics.library\"!"); if(!(con = freopen(version,"w+",stdout)) && !(con = freopen(version+3,"w+",stdout)) ) Leave("Can't open (NEW)CON: - window!"); printf("%s\033[1m%s\n%s\033[0m\033[41;32m\n\n",reverse,version+20,comment); } /***************************************************************************** * VOID Leave() * * Verlassen des Programms * *****************************************************************************/ VOID Leave(str) STRPTR str; { if(con) fclose(con); if(GfxBase) CloseLibrary(GfxBase); if(IntuitionBase) CloseLibrary(IntuitionBase); fprintf(stderr,"\n%s\n\n",str); exit(0); }