/* $Id */ /* * Source code for an implementation of the Omega test, a integer programming algorithm for dependence analysis, by * William Pugh, appeared in Supercomputing '91 and CACM Aug 92 * * C Source written by: William Pugh Dept. of Computer Science Univ. of Maryland, College Park pugh@cs.umd.edu * * Options SPEED - don't bother checking debugging flags eliminateRedundantConstraints - use expensive methods to * eliminate all redundant constraints singleResult - only produce a single simplified result verifySimplication - * simplifyProblem checks for problem with no soloutions reduceWithSubstitutions - if not defined, convert * substitutions back to EQs APROX - approximate inexact reductions */ #define maxWildCards 18 #ifndef APROX #define APROX 0 #endif #ifdef _WIN32 extern "C" void addToCollection(const int line, const char *file, void *pointer, int type); extern "C" void removeFromCollection(void *pointer); #endif #include "include/portable.h" #include "include/flags.h" #include #include #include #include "include/ip.h" #define EQ_type 1 #define GEQ_type 2 #define keyMult 31 #define indexMult 17 #define abs(x) ((x) >= 0 ? (x) : -(x)) #define max(x,y) ((x) > (y) ? (x) : (y)) #define min(x,y) ((x) < (y) ? (x) : (y)) #define setMax(m,x) { if ((m) < (x)) m = (x); } #define setMin(m,x) { if ((m) > (x)) m = (x); } #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #define nVars (problemPtr->getVarsN()) #define nEQ (problemPtr->getNumEqs()) #define nGEQ (problemPtr->getNumGEqs()) #define nSUB (problemPtr->getNumSUBs()) #define SUBs (problemPtr->_SUBs) #define GEQs (problemPtr->_GEQs) #define EQs (problemPtr->_EQs) #define safeVars (problemPtr->_safeVars) #define printEQ(e) printEqn(problemPtr,e,0,0) #define printGEQ(e) printEqn(problemPtr,e,1,0) #define printGEQextra(e) printEqn(problemPtr,e,1,1) #define variable(i) orgVariable(problemPtr->_var[i]) #define orgVariable(i) (i == 0 ? "1" : (i < 0?wildName[-i]: (*problemPtr->_getVarName)(i,problemPtr->_getVarNameArgs))) #define doTrace (trace && TRACE) #define doDelete(e,nV) {if (DEBUG) {fprintf(outputFile,"Deleting %d (last:%d): ",e,nGEQ-1); printGEQ(&GEQs[e]);fprintf(outputFile,"\n");}; \ if (e < nGEQ-1) eqnncpy (&GEQs[e], &GEQs[nGEQ - 1],(nV)); \ (problemPtr->addNumGEqs(-1));} #define doDeleteExtra(e,nV) {if (DEBUG) {fprintf(outputFile,"Deleting %d: ",e); printGEQextra(&GEQs[e]);fprintf(outputFile,"\n");}; \ if (e < nGEQ-1) eqnncpy (&GEQs[e], &GEQs[nGEQ - 1],(nV)); \ (problemPtr->addNumGEqs(-1));} #define isRed(e) (desiredResult == SIMPLIFY && (e)->color) static int mayBeRed = 0; #define hashTableSize 550 #define maxKeys 500 #ifdef SPEED #define TRACE 0 #define DBUG 0 #define DEBUG 0 #else #define TRACE (debugLevel) #define DBUG (debugLevel > 1) #define DEBUG (debugLevel > 2) #endif extern void addingEqualityConstraint(Problem * problemPtr, int e); #define mallocProblem ((Problem *) malloc(sizeof(Problem))) static struct _eqn hashMaster[hashTableSize]; int nonConvex = 0; int firstCheckForRedundantEquations = 0; static int doItAgain; static int conservative = 0; static FILE *outputFile; /* printProblem writes its output to this file */ static int nextKey; static char wildName[200][20]; static int nextWildCard = 0; static int trace = 1; static int depth = 0; static int foundReduction; static int packing[maxVars]; static int inApproximateMode = 0; #if reduceWithSubstitutions int reduceWithSubs = 1; #else int reduceWithSubs = 0; #endif static int pleaseNoEqualitiesInSimplifiedProblems = 0; int hashVersion = 0; #define noProblem ((Problem *) 0) Problem *originalProblem = noProblem; void noProcedure(Problem *problemPtr) { } void(*whenReduced) (Problem *problemPtr) = noProcedure; static int gcd(int b, int a) { if (b == 1) return (1); while (b != 0) { int t = b; b = a % b; a = t; }; return (a); } int checkIfSingleVar(Eqn e, int i) { for (; i > 0; i--) if (e->coef[i]) { i--; break; }; for (; i > 0; i--) if (e->coef[i]) break; return (i == 0); } void initializeVariables(Problem *p) { int i; for (i = p->getVarsN(); i > 0; i--) p->forwardingAddress[i] = p->_var[i] = i; p->variablesInitialized = 1; } void initializeProblem(Problem *p) { p->hashVersion = hashVersion; p->variablesInitialized = 0; p->variablesFreed = 0; p->_safeVars = 0; p->_init(0, 0, 0, 0); } void problemcpy(Problem *p1, Problem *p2) { int e, i; p1->hashVersion = p2->hashVersion; p1->variablesInitialized = p2->variablesInitialized; p1->variablesFreed = p2->variablesFreed; p1->_safeVars = p2->_safeVars; p1->_init(p2->getNumEqs(), p2->getNumGEqs(), p2->getNumSUBs(), p2->getVarsN()); for (e = p2->getNumEqs() - 1; e >= 0; e--) eqnncpy(&(p1->_EQs[e]), &(p2->_EQs[e]), p2->getVarsN()); for (e = p2->getNumGEqs() - 1; e >= 0; e--) eqnncpy(&(p1->_GEQs[e]), &(p2->_GEQs[e]), p2->getVarsN()); for (e = p2->getNumSUBs() - 1; e >= 0; e--) eqnncpy(&(p1->_SUBs[e]), &(p2->_SUBs[e]), p2->getVarsN()); p1->_var.resize(p2->getVarsN() + 1); for (i = 0; i <= p2->getVarsN(); i++) p1->_var[i] = p2->_var[i]; p1->forwardingAddress.resize(maxVars + 2); for (i = 0; i <= maxVars; i++) p1->forwardingAddress[i] = p2->forwardingAddress[i]; p1->_getVarName = p2->_getVarName; p1->_getVarNameArgs = p2->_getVarNameArgs; } static void printTerm(Problem *problemPtr, Eqn e, int c) { int i; int first; int n = nVars; int wentFirst = -1; first = 1; for (i = 1; i <= n; i++) if (c * e->coef[i] > 0) { first = 0; wentFirst = i; if (c * e->coef[i] == 1) fprintf(outputFile, "%s", variable(i)); else fprintf(outputFile, "%d%s", c * e->coef[i], variable(i)); break; }; for (i = 1; i <= n; i++) if (i != wentFirst && c * e->coef[i] != 0) { if (!first && c * e->coef[i] > 0) fprintf(outputFile, "+"); first = 0; if (c * e->coef[i] == 1) fprintf(outputFile, "%s", variable(i)); else if (c * e->coef[i] == -1) fprintf(outputFile, "-%s", variable(i)); else fprintf(outputFile, "%d%s", c * e->coef[i], variable(i)); }; if (!first && c * e->coef[0] > 0) fprintf(outputFile, "+"); if (first || c * e->coef[0] != 0) fprintf(outputFile, "%d", c * e->coef[0]); } void printEqn(Problem *problemPtr, Eqn e, int test, int extra) { char buf[maxVars * 12 + 80]; sprintEqn(buf, problemPtr, e, test, extra); fprintf(outputFile, "%s", buf); } void sprintEqn(char *str, Problem *problemPtr, Eqn e, int test, int extra) { int i; int first; int n = nVars + extra; if (test) { if (DEBUG && e->touched) { sprintf(str, "!"); while (*str) str++; } else if (DBUG && !e->touched && e->key != 0) { sprintf(str, "%d: ", e->key); while (*str) str++; } } if (e->color) { sprintf(str, "["); while (*str) str++; } first = 1; for (i = 0; i <= n; i++) if (e->coef[i] < 0) { if (!first) { sprintf(str, "+"); while (*str) str++; } else first = 0; if (i == 0) { sprintf(str, "%d", -e->coef[i]); while (*str) str++; } else if (e->coef[i] == -1) { sprintf(str, "%s", variable(i)); while (*str) str++; } else { sprintf(str, "%d%s", -e->coef[i], variable(i)); while (*str) str++; } }; if (first) { sprintf(str, "0"); while (*str) str++; } if (test == 0) { sprintf(str, " = "); while (*str) str++; } else { sprintf(str, " <= "); while (*str) str++; } first = 1; for (i = 0; i <= n; i++) if (e->coef[i] > 0) { if (!first) { sprintf(str, "+"); while (*str) str++; } else first = 0; if (i == 0) { sprintf(str, "%d", e->coef[i]); while (*str) str++; } else if (e->coef[i] == 1) { sprintf(str, "%s", variable(i)); while (*str) str++; } else { sprintf(str, "%d%s", e->coef[i], variable(i)); while (*str) str++; } } if (first) { sprintf(str, "0"); while (*str) str++; } if (e->color) { sprintf(str, "]"); while (*str) str++; } } void printVars(Problem *problemPtr) { int i; fprintf(outputFile, "variables = "); if (problemPtr->_safeVars > 0) fprintf(outputFile, "("); for (i = 1; i <= nVars; i++) { fprintf(outputFile, "%s", variable(i)); if (i == problemPtr->_safeVars) fprintf(outputFile, ")"); if (i < nVars) fprintf(outputFile, ", "); }; fprintf(outputFile, "\n"); } void printProblem(Problem *problemPtr) { int e; if (!problemPtr->variablesInitialized) initializeVariables(problemPtr); printVars(problemPtr); for (e = 0; e < nEQ; e++) { printEQ(&EQs[e]); fprintf(outputFile, "\n"); }; for (e = 0; e < nGEQ; e++) { printGEQ(&GEQs[e]); fprintf(outputFile, "\n"); }; for (e = 0; e < nSUB; e++) { Eqn eq = &SUBs[e]; if (DBUG && eq->color) fprintf(outputFile, "["); if (eq->key > 0) fprintf(outputFile, "%s := ", orgVariable(eq->key)); else fprintf(outputFile, "#%d := ", eq->key); printTerm(problemPtr, eq, 1); if (DBUG && eq->color) fprintf(outputFile, "]"); fprintf(outputFile, "\n"); }; fflush(outputFile); } void printRedEquations(Problem *problemPtr) { int e; if (!problemPtr->variablesInitialized) initializeVariables(problemPtr); printVars(problemPtr); for (e = 0; e < nEQ; e++) { if (EQs[e].color == red) { printEQ(&EQs[e]); fprintf(outputFile, "\n"); } }; for (e = 0; e < nGEQ; e++) { if (GEQs[e].color == red) { printGEQ(&GEQs[e]); fprintf(outputFile, "\n"); } }; for (e = 0; e < nSUB; e++) { if (SUBs[e].color == red) { Eqn eq = &SUBs[e]; if (DBUG && eq->color) fprintf(outputFile, "["); if (eq->key > 0) fprintf(outputFile, "%s := ", orgVariable(eq->key)); else fprintf(outputFile, "#%d := ", eq->key); printTerm(problemPtr, eq, 1); if (DBUG && eq->color) fprintf(outputFile, "]"); fprintf(outputFile, "\n"); } }; fflush(outputFile); } void prettyPrintProblem(Problem *problemPtr) { int e; int v; int live[maxGEQs]; int v1, v2, v3; int t, change; int stuffPrinted = 0; typedef enum { none, le, lt } partialOrderType; partialOrderType po[maxVars][maxVars]; int poE[maxVars][maxVars]; int lastLinks[maxVars]; int firstLinks[maxVars]; int chainLength[maxVars]; int chain[maxVars]; int i, m, multiprint; if (!problemPtr->variablesInitialized) initializeVariables(problemPtr); if (nVars > 0) { eliminateRedundant(problemPtr, 0); for (e = 0; e < nEQ; e++) { if (stuffPrinted) fprintf(outputFile, "; "); stuffPrinted = 1; printEQ(&EQs[e]); }; for (e = 0; e < nGEQ; e++) live[e] = TRUE; while (1) { for (v = 1; v <= nVars; v++) { lastLinks[v] = firstLinks[v] = 0; chainLength[v] = 0; for (v2 = 1; v2 <= nVars; v2++) po[v][v2] = none; }; for (e = 0; e < nGEQ; e++) if (live[e]) { for (v = 1; v <= nVars; v++) { if (GEQs[e].coef[v] == 1) firstLinks[v]++; else if (GEQs[e].coef[v] == -1) lastLinks[v]++; }; v1 = nVars; while (v1 > 0 && GEQs[e].coef[v1] == 0) v1--; v2 = v1 - 1; while (v2 > 0 && GEQs[e].coef[v2] == 0) v2--; v3 = v2 - 1; while (v3 > 0 && GEQs[e].coef[v3] == 0) v3--; if (GEQs[e].coef[0] > 0 || GEQs[e].coef[0] < -1 || v2 <= 0 || v3 > 0 || GEQs[e].coef[v1] * GEQs[e].coef[v2] != -1) { /* Not a partial order relation */ } else { if (GEQs[e].coef[v1] == 1) { v3 = v2; v2 = v1; v1 = v3; }; /* relation is v1 <= v2 or v1 < v2 */ po[v1][v2] = ((GEQs[e].coef[0] == 0) ? le : lt); poE[v1][v2] = e; }; } for (v = 1; v <= nVars; v++) chainLength[v] = lastLinks[v]; /* Just in case nVars <= 0 */ change = FALSE; for (t = 0; t < nVars; t++) { change = FALSE; for (v1 = 1; v1 <= nVars; v1++) for (v2 = 1; v2 <= nVars; v2++) if (po[v1][v2] != none && chainLength[v1] <= chainLength[v2]) { chainLength[v1] = chainLength[v2] + 1; change = TRUE; } }; if (change) { /* caught in cycle */ assert(0); }; v = 1; for (v1 = 2; v1 <= nVars; v1++) if (chainLength[v1] + firstLinks[v1] > chainLength[v] + firstLinks[v]) v = v1; if (chainLength[v] == 0) break; if (stuffPrinted) fprintf(outputFile, "; "); stuffPrinted = 1; /* chain starts at v */ /* print firstLinks */ { int tmp, first; first = 1; for (e = 0; e < nGEQ; e++) if (live[e] && GEQs[e].coef[v] == 1) { if (!first) fprintf(outputFile, ", "); tmp = GEQs[e].coef[v]; GEQs[e].coef[v] = 0; printTerm(problemPtr, &GEQs[e], -1); GEQs[e].coef[v] = tmp; live[e] = FALSE; first = 0; }; if (!first) fprintf(outputFile, " <= "); }; /* find chain */ chain[0] = v; m = 1; while (1) { /* print chain */ for (v2 = 1; v2 <= nVars; v2++) if (po[v][v2] && chainLength[v] == 1 + chainLength[v2]) break; if (v2 > nVars) break; chain[m++] = v2; v = v2; } fprintf(outputFile, "%s", variable(chain[0])); multiprint = 0; for (i = 1; i < m; i++) { v = chain[i - 1]; v2 = chain[i]; if (po[v][v2] == le) fprintf(outputFile, " <= "); else fprintf(outputFile, " < "); fprintf(outputFile, "%s", variable(v2)); live[poE[v][v2]] = FALSE; if (!multiprint && i < m - 1) for (v3 = 1; v3 <= nVars; v3++) { if (v == v3 || v2 == v3) continue; if (po[v][v2] != po[v][v3]) continue; if (po[v2][chain[i + 1]] != po[v3][chain[i + 1]]) continue; fprintf(outputFile, ",%s", variable(v3)); live[poE[v][v3]] = FALSE; live[poE[v3][chain[i + 1]]] = FALSE; multiprint = 1; } else multiprint = 0; }; v = chain[m - 1]; /* print lastLinks */ { int tmp, first; first = 1; for (e = 0; e < nGEQ; e++) if (live[e] && GEQs[e].coef[v] == -1) { if (!first) fprintf(outputFile, ", "); else fprintf(outputFile, " <= "); tmp = GEQs[e].coef[v]; GEQs[e].coef[v] = 0; printTerm(problemPtr, &GEQs[e], 1); GEQs[e].coef[v] = tmp; live[e] = FALSE; first = 0; }; }; }; for (e = 0; e < nGEQ; e++) if (live[e]) { if (stuffPrinted) fprintf(outputFile, "; "); stuffPrinted = 1; printGEQ(&GEQs[e]); }; for (e = 0; e < nSUB; e++) { Eqn eq = &SUBs[e]; if (stuffPrinted) fprintf(outputFile, "; "); stuffPrinted = 1; if (eq->key > 0) fprintf(outputFile, "%s := ", orgVariable(eq->key)); else fprintf(outputFile, "#%d := ", eq->key); printTerm(problemPtr, eq, 1); }; }; fflush(outputFile); } static void nameWildcard(Problem *problemPtr, int i) { --nextWildCard; if (nextWildCard < -maxWildCards) nextWildCard = -1; problemPtr->_var[i] = nextWildCard; } static int addNewWildcard(Problem *problemPtr) { int e; int i = ++safeVars; problemPtr->addToVarsN(1); //nVars++; if (nVars != i) { for (e = nGEQ - 1; e >= 0; e--) { if (GEQs[e].coef[i] != 0) GEQs[e].touched = TRUE; GEQs[e].coef[nVars] = GEQs[e].coef[i]; }; for (e = nEQ - 1; e >= 0; e--) { EQs[e].coef[nVars] = EQs[e].coef[i]; }; for (e = nSUB - 1; e >= 0; e--) { SUBs[e].coef[nVars] = SUBs[e].coef[i]; }; problemPtr->_var[nVars] = problemPtr->_var[i]; }; for (e = nGEQ - 1; e >= 0; e--) GEQs[e].coef[i] = 0; for (e = nEQ - 1; e >= 0; e--) EQs[e].coef[i] = 0; for (e = nSUB - 1; e >= 0; e--) SUBs[e].coef[i] = 0; nameWildcard(problemPtr, i); return (i); } extern void substitute(Problem * problemPtr, Eqn sub, int i, int c); extern void deleteVariable(Problem *problemPt, int j); static void doMod(Problem *problemPtr, int factor, int e, int j) /* Solve e = factor alpha for x_j and substitute */ { int k, i; struct _eqn eq; int nFactor; int killJ = FALSE; eqncpy(&eq, &EQs[e]); for (k = nVars; k >= 0; k--) { eq.coef[k] = intMod(eq.coef[k], factor); if (2 * eq.coef[k] >= factor) eq.coef[k] -= factor; }; nFactor = eq.coef[j]; if (j <= safeVars && problemPtr->_var[j] > 0) { i = addNewWildcard(problemPtr); eq.coef[nVars] = eq.coef[i]; eq.coef[j] = 0; eq.coef[i] = -factor; killJ = TRUE; } else { eq.coef[j] = -factor; if (problemPtr->_var[j] > 0) nameWildcard(problemPtr, j); }; substitute(problemPtr, &eq, j, nFactor); for (k = nVars; k >= 0; k--) EQs[e].coef[k] = EQs[e].coef[k] / factor; if (killJ) deleteVariable(problemPtr, j); if (DEBUG) { fprintf(outputFile, "Mod-ing and normalizing produces:\n"); printProblem(problemPtr); }; } void negateGEQ(Problem * problemPtr, int e) { int i; for (i = nVars; i >= 0; i--) GEQs[e].coef[i] = -GEQs[e].coef[i]; GEQs[e].coef[0]--; GEQs[e].touched = TRUE; } static int verifyProblem(Problem *problemPtr) { int result, e, anyColor; Problem tmpProblem; /*tmpProblem = mallocProblem; if (tmpProblem == NULL) { printf("ERROR!!\n"); } tmpProblem->_init();*/ problemcpy(&tmpProblem, problemPtr); tmpProblem._safeVars = 0; tmpProblem.setNumSUBs(0); anyColor = 0; for (e = nGEQ - 1; e >= 0; e--) anyColor |= GEQs[e].color; anyColor |= pleaseNoEqualitiesInSimplifiedProblems; if (anyColor) { originalProblem = noProblem; } else originalProblem = problemPtr; if (DBUG) { fprintf(outputFile, "verifying problem"); if (anyColor) fprintf(outputFile, " (color mode)"); fprintf(outputFile, " :\n"); printProblem(problemPtr); }; result = solve(&tmpProblem, UNKNOWN); originalProblem = noProblem; //free(tmpProblem); if (DBUG) { if (result) fprintf(outputFile, "verified problem\n"); else fprintf(outputFile, "disproved problem\n"); printProblem(problemPtr); }; return result; } #define implies(A,B) (A==(A&B)) void resurrectSubs(Problem * problemPtr); int eliminateRedundant(Problem *problemPtr, bool expensive) { int e, e1, e2, e3, p, q, i, k, alpha, alpha1, alpha2, alpha3; int c; int isDead[maxGEQs]; unsigned int P[maxGEQs], Z[maxGEQs], N[maxGEQs]; unsigned int PP, PZ, PN; /* possible Positives, possible zeros & possible negatives */ for (e = nGEQ - 1; e >= 0; e--) { int tmp = 1; isDead[e] = 0; P[e] = Z[e] = N[e] = 0; for (i = nVars; i >= 1; i--) { if (GEQs[e].coef[i] > 0) P[e] |= tmp; else if (GEQs[e].coef[i] < 0) N[e] |= tmp; else Z[e] |= tmp; tmp <<= 1; } } for (e1 = nGEQ - 1; e1 >= 0; e1--) if (!isDead[e1]) for (e2 = e1 - 1; e2 >= 0; e2--) if (!isDead[e2]) { for (p = nVars; p > 1; p--) { for (q = p - 1; q > 0; q--) { alpha = (GEQs[e1].coef[p] * GEQs[e2].coef[q] - GEQs[e2].coef[p] * GEQs[e1].coef[q]); if (alpha != 0) goto foundPQ; }; }; continue; foundPQ: PZ = (Z[e1] & Z[e2]) | (P[e1] & N[e2]) | (N[e1] & P[e2]); PP = P[e1] | P[e2]; PN = N[e1] | N[e2]; for (e3 = nGEQ - 1; e3 >= 0; e3--) if (e3 != e1 && e3 != e2) { if (!implies(Z[e3], PZ)) goto nextE3; alpha1 = GEQs[e2].coef[q] * GEQs[e3].coef[p] - GEQs[e2].coef[p] * GEQs[e3].coef[q]; alpha2 = -(GEQs[e1].coef[q] * GEQs[e3].coef[p] - GEQs[e1].coef[p] * GEQs[e3].coef[q]); alpha3 = alpha; if (alpha1 * alpha2 <= 0) goto nextE3; if (alpha1 < 0) { alpha1 = -alpha1; alpha2 = -alpha2; alpha3 = -alpha3; } if (alpha3 > 0) { /* Trying to prove e3 is redundant */ if (!implies(P[e3], PP) | !implies(N[e3], PN)) goto nextE3; if (!GEQs[e3].color && (GEQs[e1].color || GEQs[e2].color)) goto nextE3; /* verify alpha1*v1+alpha2*v2 = alpha3*v3 */ for (k = nVars; k >= 1; k--) if (alpha3 * GEQs[e3].coef[k] != alpha1 * GEQs[e1].coef[k] + alpha2 * GEQs[e2].coef[k]) goto nextE3; c = alpha1 * GEQs[e1].coef[0] + alpha2 * GEQs[e2].coef[0]; if (c < alpha3 * (GEQs[e3].coef[0] + 1)) { if (DBUG) { printProblem(problemPtr); fprintf(outputFile, "found redundant inequality\n"); fprintf(outputFile, "alpha1, alpha2, alpha3 = %d,%d,%d\n", alpha1, alpha2, alpha3); printGEQ(&(GEQs[e1])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e2])); fprintf(outputFile, "\n=> "); printGEQ(&(GEQs[e3])); fprintf(outputFile, "\n\n"); }; isDead[e3] = 1; } } else { /* * trying to prove e3 <= 0 and therefore e3 = 0, or trying to prove e3 < 0, and * therefore the problem has no solutions * */ if (!implies(P[e3], PN) | !implies(N[e3], PP)) goto nextE3; if (GEQs[e1].color || GEQs[e2].color || GEQs[e3].color) goto nextE3; alpha3 = alpha3; /* verify alpha1*v1+alpha2*v2 = alpha3*v3 */ for (k = nVars; k >= 1; k--) if (alpha3 * GEQs[e3].coef[k] != alpha1 * GEQs[e1].coef[k] + alpha2 * GEQs[e2].coef[k]) goto nextE3; c = alpha1 * GEQs[e1].coef[0] + alpha2 * GEQs[e2].coef[0]; if (c < alpha3 * (GEQs[e3].coef[0])) { /* We just proved e3 < 0, so no solutions exist */ if (DBUG) { printProblem(problemPtr); fprintf(outputFile, "found implied over tight inequality\n"); fprintf(outputFile, "alpha1, alpha2, alpha3 = %d,%d,%d\n", alpha1, alpha2, -alpha3); printGEQ(&(GEQs[e1])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e2])); fprintf(outputFile, "\n=> not "); printGEQ(&(GEQs[e3])); fprintf(outputFile, "\n\n"); }; return (0); } else if (c < alpha3 * (GEQs[e3].coef[0] + 1)) { /* We just proved that e3 <=0, so e3 = 0 */ if (DBUG) { printProblem(problemPtr); fprintf(outputFile, "found implied tight inequality\n"); fprintf(outputFile, "alpha1, alpha2, alpha3 = %d,%d,%d\n", alpha1, alpha2, -alpha3); printGEQ(&(GEQs[e1])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e2])); fprintf(outputFile, "\n=> inverse "); printGEQ(&(GEQs[e3])); fprintf(outputFile, "\n\n"); }; //eqncpy(&EQs[nEQ++], &GEQs[e3]); const int numEQ = nEQ; problemPtr->addNumEqs(1); eqncpy(&EQs[numEQ], &GEQs[e3]); assert(nEQ <= maxEQs); addingEqualityConstraint(problemPtr, nEQ - 1); isDead[e3] = 1; } } nextE3:; } } for (e = nGEQ - 1; e >= 0; e--) if (isDead[e]) doDelete(e, nVars); /* if (nEQ) return (solve(problemPtr, SIMPLIFY)); */ if (!expensive) return (1); { Problem tmpProblem; int oldTrace = trace; trace = 0; /*tmpProblem = mallocProblem; if (tmpProblem == NULL) { printf("ERROR!!\n"); } tmpProblem->_init();*/ conservative++; for (e = nGEQ - 1; e >= 0; e--) { if (DEBUG) { fprintf(outputFile, "checking equation %d to see if it is redundant: ", e); printGEQ(&(GEQs[e])); fprintf(outputFile, "\n"); }; problemcpy(&tmpProblem, problemPtr); negateGEQ(&tmpProblem, e); tmpProblem._safeVars = 0; tmpProblem.variablesFreed = 0; if (!solve(&tmpProblem, FALSE)) doDelete(e, nVars); }; trace = oldTrace; //free(tmpProblem); conservative--; }; #if reduceWithSubstitutions #else resurrectSubs(problemPtr); assert(nSUB == 0); #endif return (1); } int smoothWeirdEquations(Problem *problemPtr) { int e1, e2, e3, p, q, k, alpha, alpha1, alpha2, alpha3; int c; int v; int result = 0; for (e1 = nGEQ - 1; e1 >= 0; e1--) if (!GEQs[e1].color) { int g = 999999; for (v = nVars; v >= 1; v--) if (GEQs[e1].coef[v] != 0 && abs(GEQs[e1].coef[v]) < g) g = abs(GEQs[e1].coef[v]); if (g > 20) { e3 = nGEQ; for (v = nVars; v >= 1; v--) GEQs[e3].coef[v] = intDiv(6 * GEQs[e1].coef[v] + g / 2, g); GEQs[e3].color = 0; GEQs[e3].touched = 1; GEQs[e3].coef[0] = 9997; if (DBUG) { fprintf(outputFile, "Checking to see if we can derive: "); printGEQ(&GEQs[e3]); fprintf(outputFile, "\n from: "); printGEQ(&GEQs[e1]); fprintf(outputFile, "\n"); }; for (e2 = nGEQ - 1; e2 >= 0; e2--) if (e1 != e2 && !GEQs[e2].color) { for (p = nVars; p > 1; p--) { for (q = p - 1; q > 0; q--) { alpha = (GEQs[e1].coef[p] * GEQs[e2].coef[q] - GEQs[e2].coef[p] * GEQs[e1].coef[q]); if (alpha != 0) goto foundPQ; }; }; continue; foundPQ: alpha1 = GEQs[e2].coef[q] * GEQs[e3].coef[p] - GEQs[e2].coef[p] * GEQs[e3].coef[q]; alpha2 = -(GEQs[e1].coef[q] * GEQs[e3].coef[p] - GEQs[e1].coef[p] * GEQs[e3].coef[q]); alpha3 = alpha; if (alpha1 * alpha2 <= 0) continue; if (alpha1 < 0) { alpha1 = -alpha1; alpha2 = -alpha2; alpha3 = -alpha3; } if (alpha3 > 0) { /* Trying to prove e3 is redundant */ /* verify alpha1*v1+alpha2*v2 = alpha3*v3 */ for (k = nVars; k >= 1; k--) if (alpha3 * GEQs[e3].coef[k] != alpha1 * GEQs[e1].coef[k] + alpha2 * GEQs[e2].coef[k]) goto nextE2; c = alpha1 * GEQs[e1].coef[0] + alpha2 * GEQs[e2].coef[0]; if (c < alpha3 * (GEQs[e3].coef[0] + 1)) GEQs[e3].coef[0] = intDiv(c, alpha3); } nextE2:; } if (GEQs[e3].coef[0] < 9997) { result++; problemPtr->addNumGEqs(1); //nGEQ++; if (DBUG) { fprintf(outputFile, "Smoothing wierd equations; adding:\n"); printGEQ(&GEQs[e3]); fprintf(outputFile, "\nto:\n"); printProblem(problemPtr); fprintf(outputFile, "\n\n"); }; }; } } return (result); } void coalesce(Problem * problemPtr) { int e, e2, colors; int isDead[maxGEQs]; colors = 0; for (e = 0; e < nGEQ; e++) if (GEQs[e].color) colors++; if (colors < 2) return; for (e = 0; e < nGEQ; e++) isDead[e] = 0; for (e = 0; e < nGEQ; e++) if (GEQs[e].color) for (e2 = e + 1; e2 < nGEQ; e2++) if (GEQs[e].key == -GEQs[e2].key && GEQs[e].coef[0] == -GEQs[e2].coef[0]) { const int numEQ = nEQ; problemPtr->addNumEqs(1); eqncpy(&EQs[numEQ], &GEQs[e]); assert(nEQ <= maxEQs); isDead[e] = 1; isDead[e2] = 1; }; for (e = nGEQ - 1; e >= 0; e--) if (isDead[e]) { doDelete(e, nVars); } } void eliminateRed(Problem *problemPtr, bool eliminateAll) { int e, e2, e3, i, j, k, a, alpha1, alpha2; int c = 0; int isDead[maxGEQs]; int deadCount = 0; if (DEBUG) { fprintf(outputFile, "in eliminate RED:\n"); printProblem(problemPtr); }; if (nEQ > 0) { simplifyProblem(problemPtr); }; for (e = nGEQ - 1; e >= 0; e--) isDead[e] = 0; for (e = nGEQ - 1; e >= 0; e--) if (!GEQs[e].color && !isDead[e]) for (e2 = e - 1; e2 >= 0; e2--) if (!GEQs[e2].color && !isDead[e2]) { a = 0; for (i = nVars; i > 1; i--) { for (j = i - 1; j > 0; j--) { a = (GEQs[e].coef[i] * GEQs[e2].coef[j] - GEQs[e2].coef[i] * GEQs[e].coef[j]); if (a != 0) goto foundPair; }; }; continue; foundPair: if (DEBUG) { fprintf(outputFile, "found two equations to combine, i = %s, ", variable(i)); fprintf(outputFile, "j = %s, alpha = %d\n", variable(j), a); printGEQ(&(GEQs[e])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e2])); fprintf(outputFile, "\n"); }; for (e3 = nGEQ - 1; e3 >= 0; e3--) if (GEQs[e3].color) { alpha1 = GEQs[e2].coef[j] * GEQs[e3].coef[i] - GEQs[e2].coef[i] * GEQs[e3].coef[j]; alpha2 = -(GEQs[e].coef[j] * GEQs[e3].coef[i] - GEQs[e].coef[i] * GEQs[e3].coef[j]); if ((a > 0 && alpha1 > 0 && alpha2 > 0) || (a < 0 && alpha1 < 0 && alpha2 < 0)) { if (DEBUG) { fprintf(outputFile, "alpha1 = %d, alpha2 = %d; comparing against: ", alpha1, alpha2); printGEQ(&(GEQs[e3])); fprintf(outputFile, "\n"); }; for (k = nVars; k >= 0; k--) { c = alpha1 * GEQs[e].coef[k] + alpha2 * GEQs[e2].coef[k]; if (c != a * GEQs[e3].coef[k]) break; if (DEBUG && k > 0) fprintf(outputFile, " %s: %d, %d\n", variable(k), c, a * GEQs[e3].coef[k]); }; if (k < 0 || (k == 0 && ((a > 0 && c < a * GEQs[e3].coef[k]) || (a < 0 && c > a * GEQs[e3].coef[k])))) { if (DEBUG) { deadCount++; fprintf(outputFile, "red equation#%d is dead (%d dead so far, %d remain)\n", e3, deadCount, nGEQ - deadCount); printGEQ(&(GEQs[e])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e2])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e3])); fprintf(outputFile, "\n"); }; isDead[e3] = 1; }; }; }; }; for (e = nGEQ - 1; e >= 0; e--) if (isDead[e]) doDelete(e, nVars); if (DBUG) { fprintf(outputFile, "in eliminate RED, easy tests done:\n"); printProblem(problemPtr); }; { int redFound = 0; for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].color) redFound = 1; if (!redFound) { if (DBUG) fprintf(outputFile, "fast checks worked\n"); #if reduceWithSubstitutions #else assert(pleaseNoEqualitiesInSimplifiedProblems || nSUB == 0); #endif return; }; } #ifndef verifySimplication if (!verifyProblem(problemPtr)) return; #endif { Problem tmpProblem; int oldTrace = trace; trace = 0; conservative++; /*tmpProblem = mallocProblem; if (tmpProblem == NULL) { printf("ERROR!!\n"); } tmpProblem->_init();*/ for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].color) { if (DBUG) { fprintf(outputFile, "checking equation %d to see if it is redundant: ", e); printGEQ(&(GEQs[e])); fprintf(outputFile, "\n"); }; problemcpy(&tmpProblem, problemPtr); negateGEQ(&tmpProblem, e); tmpProblem._safeVars = 0; tmpProblem.variablesFreed = 0; tmpProblem.setNumSUBs(0); if (!solve(&tmpProblem, FALSE)) { if (DBUG) fprintf(outputFile, "it is redundant\n"); doDelete(e, nVars); } else { if (DBUG) fprintf(outputFile, "it is not redundant\n"); if (!eliminateAll) { if (DBUG) fprintf(outputFile, "no need to check other red equations\n"); break; } }; }; trace = oldTrace; conservative--; //free(tmpProblem); }; /* simplifyProblem(problemPtr); */ #if reduceWithSubstitutions #else assert(pleaseNoEqualitiesInSimplifiedProblems || nSUB == 0); #endif } void swap(int *i, int *j) { int tmp; tmp = *i; *i = *j; *j = tmp; } void chainUnprotect(Problem *problemPtr) { int i, e; int unprotect[maxVars]; for (i = 1; i <= problemPtr->_safeVars; i++) { unprotect[i] = (problemPtr->_var[i] < 0); for (e = nSUB - 1; e >= 0; e--) if (SUBs[e].coef[i]) unprotect[i] = 0; }; if (DBUG) { fprintf(outputFile, "Doing chain reaction unprotection\n"); printProblem(problemPtr); for (i = 1; i <= problemPtr->_safeVars; i++) if (unprotect[i]) fprintf(outputFile, "unprotecting %s\n", variable(i)); }; for (i = 1; i <= problemPtr->_safeVars; i++) if (unprotect[i]) { /* wild card */ if (i < problemPtr->_safeVars) { int j = problemPtr->_safeVars; swap(&problemPtr->_var[i], &problemPtr->_var[j]); for (e = nGEQ - 1; e >= 0; e--) { GEQs[e].touched = 1; swap(&GEQs[e].coef[i], &GEQs[e].coef[j]); }; for (e = nEQ - 1; e >= 0; e--) swap(&EQs[e].coef[i], &EQs[e].coef[j]); for (e = nSUB - 1; e >= 0; e--) swap(&SUBs[e].coef[i], &SUBs[e].coef[j]); swap(&unprotect[i], &unprotect[j]); i--; }; problemPtr->_safeVars--; }; if (DBUG) { fprintf(outputFile, "After chain reactions\n"); printProblem(problemPtr); }; } void resurrectSubs(Problem * problemPtr) { if (problemPtr->getNumSUBs() > 0 && !pleaseNoEqualitiesInSimplifiedProblems) { int i, e, n, m; if (DBUG) { fprintf(outputFile, "problem reduced, bringing variables back to life\n"); printProblem(problemPtr); }; for (i = 1; i <= problemPtr->_safeVars; i++) if (problemPtr->_var[i] < 0) { /* wild card */ if (i < problemPtr->_safeVars) { int j = problemPtr->_safeVars; swap(&problemPtr->_var[i], &problemPtr->_var[j]); for (e = nGEQ - 1; e >= 0; e--) { GEQs[e].touched = 1; swap(&GEQs[e].coef[i], &GEQs[e].coef[j]); }; for (e = nEQ - 1; e >= 0; e--) swap(&EQs[e].coef[i], &EQs[e].coef[j]); for (e = nSUB - 1; e >= 0; e--) swap(&SUBs[e].coef[i], &SUBs[e].coef[j]); i--; }; problemPtr->_safeVars--; }; m = problemPtr->getNumSUBs(); n = max(nVars, problemPtr->_safeVars + m); for (e = nGEQ - 1; e >= 0; e--) { if (singleVarGEQ(GEQs[e], nVars)) { i = abs(GEQs[e].key); if (i >= problemPtr->_safeVars + 1) GEQs[e].key += (GEQs[e].key > 0 ? m : -m); } else { GEQs[e].touched = TRUE; GEQs[e].key = 0; } } const int tmpNV = nVars; problemPtr->addToVarsN(m); for (i = tmpNV; i >= problemPtr->_safeVars + 1; i--) { problemPtr->_var[i + m] = problemPtr->_var[i]; for (e = nGEQ - 1; e >= 0; e--) GEQs[e].coef[i + m] = GEQs[e].coef[i]; for (e = nEQ - 1; e >= 0; e--) EQs[e].coef[i + m] = EQs[e].coef[i]; for (e = nSUB - 1; e >= 0; e--) SUBs[e].coef[i + m] = SUBs[e].coef[i]; } for (i = problemPtr->_safeVars + m; i >= problemPtr->_safeVars + 1; i--) { for (e = nGEQ - 1; e >= 0; e--) GEQs[e].coef[i] = 0; for (e = nEQ - 1; e >= 0; e--) EQs[e].coef[i] = 0; for (e = nSUB - 1; e >= 0; e--) SUBs[e].coef[i] = 0; } //nVars += m; for (e = nSUB - 1; e >= 0; e--) { problemPtr->_var[problemPtr->_safeVars + 1 + e] = SUBs[e].key; const int numEQ = nEQ; problemPtr->addNumEqs(1); eqncpy(&(EQs[numEQ]), &(SUBs[e])); EQs[numEQ].coef[problemPtr->_safeVars + 1 + e] = -1; if (DBUG) { fprintf(outputFile, "brought back: "); printEQ(&EQs[numEQ]); fprintf(outputFile, "\n"); } //nEQ++; assert(nEQ <= maxEQs); } problemPtr->_safeVars += m; //nSUB = 0; problemPtr->setNumSUBs(0); for (i = problemPtr->_safeVars + 1; i <= nVars; i++) { for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].color && GEQs[e].coef[i]) { /* variable i is in red equations */ int e2; for (e2 = nEQ - 1; e2 >= 0; e2--) if (EQs[e2].coef[i]) EQs[e2].color = 1; break; } } if (DBUG) { fprintf(outputFile, "variables brought back to life\n"); printProblem(problemPtr); }; } } static void problemReduced(Problem *problemPtr) { #ifdef verifySimplification int result; result = verifyProblem(problemPtr); if (result && nEQ > 0) doItAgain = 1; else if (result) #endif { #ifdef eliminateRedundantConstraints if (!eliminateRedundant(problemPtr, 1)) return; #endif foundReduction = TRUE; if (!pleaseNoEqualitiesInSimplifiedProblems) coalesce(problemPtr); if (reduceWithSubs || pleaseNoEqualitiesInSimplifiedProblems) chainUnprotect(problemPtr); else resurrectSubs(problemPtr); #ifndef singleResult (*whenReduced) (problemPtr); #endif if (omegaPrintResult == 1) { fprintf(outputFile, "-------------------------------------------\n"); fprintf(outputFile, "problem reduced:\n"); printProblem(problemPtr); fprintf(outputFile, "-------------------------------------------\n"); }; }; } static void freeEliminations(Problem *problemPtr, int fv) /* do free eliminations */ { int tryAgain = 1; int i, e, e2; int nV = nVars; while (tryAgain) { tryAgain = 0; for (i = nV; i > fv; i--) { for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[i]) break; if (e < 0) e2 = e; else if (GEQs[e].coef[i] > 0) { for (e2 = e - 1; e2 >= 0; e2--) if (GEQs[e2].coef[i] < 0) break; } else { for (e2 = e - 1; e2 >= 0; e2--) if (GEQs[e2].coef[i] > 0) break; }; if (e2 < 0) { int e3; for (e3 = nSUB - 1; e3 >= 0; e3--) if (SUBs[e3].coef[i]) break; if (e3 >= 0) continue; for (e3 = nEQ - 1; e3 >= 0; e3--) if (EQs[e3].coef[i]) break; if (e3 >= 0) continue; if (DBUG) fprintf(outputFile, "a free elimination of %s\n", variable(i)); if (e >= 0) { doDelete(e, nV); for (e--; e >= 0; e--) if (GEQs[e].coef[i]) doDelete(e, nV); tryAgain = (i < nV); }; deleteVariable(problemPtr, i); nV = nVars; }; }; }; if (DEBUG) { fprintf(outputFile, "\nafter free eliminations:\n"); printProblem(problemPtr); fprintf(outputFile, "\n"); }; } static void freeRedEliminations(Problem * problemPtr) /* do free red eliminations */ { int tryAgain = 1; int i, e, e2; int nV = nVars; int isRedVar[maxVars]; int isDeadVar[maxVars]; int isDeadGEQ[maxGEQs]; for (i = nV; i > 0; i--) { isRedVar[i] = 0; isDeadVar[i] = 0; }; for (e = nGEQ - 1; e >= 0; e--) { isDeadGEQ[e] = 0; if (GEQs[e].color) for (i = nV; i > 0; i--) if (GEQs[e].coef[i] != 0) isRedVar[i] = 1; }; while (tryAgain) { tryAgain = 0; for (i = nV; i > 0; i--) if (!isRedVar[i] && !isDeadVar[i]) { for (e = nGEQ - 1; e >= 0; e--) if (!isDeadGEQ[e] && GEQs[e].coef[i]) break; if (e < 0) e2 = e; else if (GEQs[e].coef[i] > 0) { for (e2 = e - 1; e2 >= 0; e2--) if (!isDeadGEQ[e2] && GEQs[e2].coef[i] < 0) break; } else { for (e2 = e - 1; e2 >= 0; e2--) if (!isDeadGEQ[e2] && GEQs[e2].coef[i] > 0) break; }; if (e2 < 0) { int e3; for (e3 = nSUB - 1; e3 >= 0; e3--) if (SUBs[e3].coef[i]) break; if (e3 >= 0) continue; for (e3 = nEQ - 1; e3 >= 0; e3--) if (EQs[e3].coef[i]) break; if (e3 >= 0) continue; if (DBUG) fprintf(outputFile, "a free red elimination of %s\n", variable(i)); for (; e >= 0; e--) if (GEQs[e].coef[i]) isDeadGEQ[e] = 1; tryAgain = 1; isDeadVar[i] = 1; }; }; }; for (e = nGEQ - 1; e >= 0; e--) if (isDeadGEQ[e]) doDelete(e, nV); for (i = nV; i > 0; i--) if (isDeadVar[i]) deleteVariable(problemPtr, i); if (DEBUG) { fprintf(outputFile, "\nafter free red eliminations:\n"); printProblem(problemPtr); fprintf(outputFile, "\n"); }; } void addingEqualityConstraint(Problem *problemPtr, int e) { int e2, i, j; if (originalProblem != noProblem && originalProblem != problemPtr && !conservative) { //e2 = originalProblem->_numEQs++; e2 = originalProblem->getNumEqs(); originalProblem->addNumEqs(1); if (DBUG) fprintf(outputFile, "adding equality constraint %d to outer problem\n", e2); eqnnzero(&originalProblem->_EQs[e2], originalProblem->getVarsN()); for (i = nVars; i >= 1; i--) { for (j = originalProblem->getVarsN(); j >= 1; j--) if (originalProblem->_var[j] == problemPtr->_var[i]) break; if (j <= 0) { if (DBUG) fprintf(outputFile, "retracting\n"); //originalProblem->_numEQs--; originalProblem->addNumEqs(-1); return; }; originalProblem->_EQs[e2].coef[j] = EQs[e].coef[i]; }; originalProblem->_EQs[e2].coef[0] = EQs[e].coef[0]; if (DBUG) printProblem(originalProblem); }; } void substitute(Problem * problemPtr, Eqn sub, int i, int c) { int e, j, j0, k; int topVar; { int *p = &packing[0]; for (k = nVars; k >= 0; k--) if (sub->coef[k]) *(p++) = k; topVar = (p - &packing[0]) - 1; }; if (DBUG || doTrace) { fprintf(outputFile, "substituting using %s := ", variable(i)); printTerm(problemPtr, sub, -c); fprintf(outputFile, "\n"); printVars(problemPtr); }; if (topVar < 0) { for (e = nEQ - 1; e >= 0; e--) EQs[e].coef[i] = 0; for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[i] != 0) { GEQs[e].touched = TRUE; GEQs[e].coef[i] = 0; }; for (e = nSUB - 1; e >= 0; e--) SUBs[e].coef[i] = 0; if (i <= problemPtr->_safeVars && problemPtr->_var[i] >= 0) { //Eqn eqn = &(SUBs[nSUB++]); problemPtr->addNumSUBs(1); Eqn eqn = &(SUBs[nSUB - 1]); for (k = nVars; k >= 0; k--) eqn->coef[k] = 0; eqn->key = problemPtr->_var[i]; eqn->color = 0; }; } else if (topVar == 0 && packing[0] == 0) { c = -sub->coef[0] * c; for (e = nEQ - 1; e >= 0; e--) { EQs[e].coef[0] += EQs[e].coef[i] * c; EQs[e].coef[i] = 0; }; for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[i] != 0) { GEQs[e].coef[0] += GEQs[e].coef[i] * c; GEQs[e].coef[i] = 0; GEQs[e].touched = TRUE; }; for (e = nSUB - 1; e >= 0; e--) { SUBs[e].coef[0] += SUBs[e].coef[i] * c; SUBs[e].coef[i] = 0; }; if (i <= problemPtr->_safeVars && problemPtr->_var[i] >= 0) { //Eqn eqn = &(SUBs[nSUB++]); problemPtr->addNumSUBs(1); Eqn eqn = &(SUBs[nSUB - 1]); for (k = nVars; k >= 1; k--) eqn->coef[k] = 0; eqn->coef[0] = c; eqn->key = problemPtr->_var[i]; eqn->color = 0; }; } else { for (e = nEQ - 1; e >= 0; e--) { Eqn eqn = &(EQs[e]); k = eqn->coef[i]; if (k != 0) { k = c * k; eqn->coef[i] = 0; for (j = topVar; j >= 0; j--) { j0 = packing[j]; eqn->coef[j0] -= sub->coef[j0] * k; }; }; if (DEBUG) { printEQ(eqn); fprintf(outputFile, "\n"); }; }; for (e = nGEQ - 1; e >= 0; e--) { Eqn eqn = &(GEQs[e]); k = eqn->coef[i]; if (k != 0) { k = c * k; eqn->touched = TRUE; eqn->coef[i] = 0; for (j = topVar; j >= 0; j--) { j0 = packing[j]; eqn->coef[j0] -= sub->coef[j0] * k; }; }; if (DEBUG) { printGEQ(eqn); fprintf(outputFile, "\n"); }; }; for (e = nSUB - 1; e >= 0; e--) { Eqn eqn = &(SUBs[e]); k = eqn->coef[i]; if (k != 0) { k = c * k; eqn->coef[i] = 0; for (j = topVar; j >= 0; j--) { j0 = packing[j]; eqn->coef[j0] -= sub->coef[j0] * k; }; }; if (DEBUG) { fprintf(outputFile, "%s := ", orgVariable(eqn->key)); printTerm(problemPtr, eqn, 1); fprintf(outputFile, "\n"); }; }; if (DEBUG) fprintf(outputFile, "---\n\n"); if (i <= problemPtr->_safeVars && problemPtr->_var[i] >= 0) { Eqn eqn; //eqn = &(SUBs[nSUB++]); problemPtr->addNumSUBs(1); eqn = &(SUBs[nSUB - 1]); c = -c; for (k = nVars; k >= 0; k--) eqn->coef[k] = c * (sub->coef[k]); eqn->key = problemPtr->_var[i]; eqn->color = sub->color; }; }; } void substituteRed(Problem *problemPtr, Eqn sub, int i, int c, bool * foundBlack) { int e, j, j0, k; int topVar; { int *p = &packing[0]; for (k = nVars; k >= 0; k--) if (sub->coef[k]) *(p++) = k; topVar = (p - &packing[0]) - 1; }; *foundBlack = 0; if (DBUG || doTrace) { if (sub->color) fprintf(outputFile, "["); fprintf(outputFile, "substituting using %s := ", variable(i)); printTerm(problemPtr, sub, -c); if (sub->color) fprintf(outputFile, "]"); fprintf(outputFile, "\n"); printVars(problemPtr); }; for (e = nEQ - 1; e >= 0; e--) { Eqn eqn = &(EQs[e]); k = eqn->coef[i]; if (k != 0) { if (!eqn->color) *foundBlack = 1; else { k = c * k; eqn->coef[i] = 0; for (j = topVar; j >= 0; j--) { j0 = packing[j]; eqn->coef[j0] -= sub->coef[j0] * k; }; }; }; if (DEBUG) { printEQ(eqn); fprintf(outputFile, "\n"); }; }; for (e = nGEQ - 1; e >= 0; e--) { Eqn eqn = &(GEQs[e]); k = eqn->coef[i]; if (k != 0) { if (!eqn->color) *foundBlack = 1; else { k = c * k; eqn->touched = TRUE; eqn->coef[i] = 0; for (j = topVar; j >= 0; j--) { j0 = packing[j]; eqn->coef[j0] -= sub->coef[j0] * k; }; }; }; if (DEBUG) { printGEQ(eqn); fprintf(outputFile, "\n"); }; }; for (e = nSUB - 1; e >= 0; e--) { Eqn eqn = &(SUBs[e]); k = eqn->coef[i]; if (k != 0) { if (!eqn->color) *foundBlack = 1; else { k = c * k; eqn->coef[i] = 0; for (j = topVar; j >= 0; j--) { j0 = packing[j]; eqn->coef[j0] -= sub->coef[j0] * k; }; }; }; if (DEBUG) { fprintf(outputFile, "%s := ", orgVariable(eqn->key)); printTerm(problemPtr, eqn, 1); fprintf(outputFile, "\n"); }; }; if (DEBUG) fprintf(outputFile, "---\n\n"); if (i <= problemPtr->_safeVars && problemPtr->_var[i] >= 0) { *foundBlack = 1; }; } void deleteVariable(Problem *problemPtr, int i) { int nV = nVars; int e; if (i < safeVars) { int j = safeVars; for (e = nGEQ - 1; e >= 0; e--) { GEQs[e].touched = TRUE; GEQs[e].coef[i] = GEQs[e].coef[j]; GEQs[e].coef[j] = GEQs[e].coef[nV]; }; for (e = nEQ - 1; e >= 0; e--) { EQs[e].coef[i] = EQs[e].coef[j]; EQs[e].coef[j] = EQs[e].coef[nV]; }; for (e = nSUB - 1; e >= 0; e--) { SUBs[e].coef[i] = SUBs[e].coef[j]; SUBs[e].coef[j] = SUBs[e].coef[nV]; }; problemPtr->_var[i] = problemPtr->_var[j]; problemPtr->_var[j] = problemPtr->_var[nV]; } else if (i < nV) { for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[nV]) { GEQs[e].coef[i] = GEQs[e].coef[nV]; GEQs[e].touched = TRUE; }; for (e = nEQ - 1; e >= 0; e--) EQs[e].coef[i] = EQs[e].coef[nV]; for (e = nSUB - 1; e >= 0; e--) SUBs[e].coef[i] = SUBs[e].coef[nV]; problemPtr->_var[i] = problemPtr->_var[nV]; }; if (i <= safeVars) safeVars--; problemPtr->addToVarsN(-1); //nVars--; } static void convertEQtoGEQs(Problem * problemPtr, int eq) { int i; if (DBUG) fprintf(outputFile, "Converting Eq to GEQs\n"); int numGE = nGEQ; problemPtr->addNumGEqs(1); eqncpy(&GEQs[numGE], &EQs[eq]); GEQs[numGE].touched = 1; //nGEQ++; numGE = nGEQ; problemPtr->addNumGEqs(1); eqncpy(&GEQs[numGE], &EQs[eq]); GEQs[numGE].touched = 1; for (i = 0; i <= nVars; i++) GEQs[numGE].coef[i] = -GEQs[numGE].coef[i]; //nGEQ++; if (DBUG) printProblem(problemPtr); } static void doElimination(Problem *problemPtr, int e, int i) { struct _eqn sub; int c; int nV = nVars; if (DBUG || doTrace) fprintf(outputFile, "eliminating variable %s\n", variable(i)); eqncpy(&sub, &EQs[e]); c = sub.coef[i]; sub.coef[i] = 0; if (c == 1 || c == -1) { if (EQs[e].color) { bool fB; substituteRed(problemPtr, &sub, i, c, &fB); if (fB) convertEQtoGEQs(problemPtr, e); else deleteVariable(problemPtr, i); } else { substitute(problemPtr, &sub, i, c); deleteVariable(problemPtr, i); } } else { int a = abs(c); if (TRACE) fprintf(outputFile, "performing non-exact elimination, c = %d\n", c); assert(inApproximateMode); for (e = nEQ - 1; e >= 0; e--) if (EQs[e].coef[i]) { Eqn eqn = &(EQs[e]); int j, k; for (j = nV; j >= 0; j--) eqn->coef[j] *= a; k = eqn->coef[i]; eqn->coef[i] = 0; for (j = nV; j >= 0; j--) eqn->coef[j] -= sub.coef[j] * k / c; }; for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[i]) { Eqn eqn = &(GEQs[e]); int j, k; for (j = nV; j >= 0; j--) eqn->coef[j] *= a; k = eqn->coef[i]; eqn->coef[i] = 0; for (j = nV; j >= 0; j--) eqn->coef[j] -= sub.coef[j] * k / c; eqn->touched = 1; }; for (e = nSUB - 1; e >= 0; e--) if (SUBs[e].coef[i]) { Eqn eqn = &(SUBs[e]); int j, k; assert(0); for (j = nV; j >= 0; j--) eqn->coef[j] *= a; k = eqn->coef[i]; eqn->coef[i] = 0; for (j = nV; j >= 0; j--) eqn->coef[j] -= sub.coef[j] * k / c; }; deleteVariable(problemPtr, i); }; } static int solveEQ(Problem *problemPtr, int desiredResult) { int i, j, e; int g, g2; g = 0; if (DBUG && nEQ > 0) { fprintf(outputFile, "\nSolveEQ\n"); printProblem(problemPtr); fprintf(outputFile, "\n"); }; if (mayBeRed) { i = 0; j = nEQ - 1; while (1) { struct _eqn eq; while (i <= j && EQs[i].color) i++; while (i <= j && !EQs[j].color) j--; if (i >= j) break; eqncpy(&eq, &EQs[i]); eqncpy(&EQs[i], &EQs[j]); eqncpy(&EQs[j], &eq); i++; j--; }; }; /* Eliminate all EQ equations */ for (e = nEQ - 1; e >= 0; e--) { Eqn eqn = &(EQs[e]); int sv; if (inApproximateMode && !nGEQ && safeVars == nVars) return (TRUE); if (DEBUG) fprintf(outputFile, "----\n"); for (i = nVars; i > 0; i--) if ((g = eqn->coef[i]) != 0) break; /* * if (isRed(eqn)) { if (DBUG) fprintf(outputFile, "Can't handle Red equality\n"); * convertEQtoGEQs(problemPtr,eqn); if (DBUG) printProblem(problemPtr); continue; }; */ for (j = i - 1; j > 0; j--) if (eqn->coef[j]) break; if (j == 0) { if (eqn->coef[0] % g != 0) { if (DBUG) printEQ(eqn); if (DBUG) fprintf(outputFile, "\nequations have no solution \n"); return (FALSE); }; eqn->coef[0] = eqn->coef[0] / g; eqn->coef[i] = 1; //nEQ--; problemPtr->addNumEqs(-1); doElimination(problemPtr, e, i); continue; } else if (j == -1) { if (eqn->coef[0] != 0) { if (DBUG) printEQ(eqn); if (DBUG) fprintf(outputFile, "\nequations have no solution \n"); return (FALSE); }; //nEQ--; problemPtr->addNumEqs(-1); continue; }; /* i == position of last non-zero coef */ /* g == coef of i */ /* j == position of next non-zero coef */ if (g < 0) g = -g; if (g == 1) { //nEQ--; problemPtr->addNumEqs(-1); doElimination(problemPtr, e, i); } else { int k = j; bool promotionPossible = (j <= safeVars && safeVars + 1 == i && !isRed(eqn) && !inApproximateMode); if (DEBUG && promotionPossible) fprintf(outputFile, " Promotion possible\n"); normalizeEQ: if (j > safeVars) { for (; g != 1 && j > safeVars; j--) g = gcd(abs(eqn->coef[j]), g); g2 = g; } else if (i > safeVars) g2 = g; else g2 = 0; for (; g != 1 && j > 0; j--) g = gcd(abs(eqn->coef[j]), g); if (g > 1) { if (eqn->coef[0] % g != 0) { if (DBUG) printEQ(eqn); if (DBUG) fprintf(outputFile, "\nequations have no solution \n"); return (FALSE); }; for (j = 0; j <= nVars; j++) eqn->coef[j] /= g; g2 = g2 / g; }; if (g2 > 1) { int e2; for (e2 = e - 1; e2 >= 0; e2--) if (EQs[e2].coef[i]) break; if (e2 == -1) for (e2 = nGEQ - 1; e2 >= 0; e2--) if (GEQs[e2].coef[i]) break; if (e2 == -1) for (e2 = nSUB - 1; e2 >= 0; e2--) if (SUBs[e2].coef[i]) break; if (e2 == -1) { bool change = 0; if (DBUG) fprintf(outputFile, "Ha! We own it! \n"); if (DEBUG) printEQ(eqn); if (DEBUG) fprintf(outputFile, " \n"); g = eqn->coef[i]; g = abs(g); for (j = i - 1; j >= 0; j--) { int t = eqn->coef[j]; t = intMod(t, g); if (2 * t >= g) t -= g; if (t != eqn->coef[j]) { eqn->coef[j] = t; change = 1; }; }; if (!change) { if (DBUG) fprintf(outputFile, "So what?\n"); } else { nameWildcard(problemPtr, i); if (DEBUG) printEQ(eqn); if (DEBUG) fprintf(outputFile, " \n"); e++; continue; }; }; } if (promotionPossible) { if (DEBUG) { fprintf(outputFile, "promoting %s to safety\n", variable(i)); printVars(problemPtr); }; safeVars++; if (problemPtr->_var[i] > 0) nameWildcard(problemPtr, i); promotionPossible = 0; j = k; goto normalizeEQ; }; if (g2 > 1 && !inApproximateMode) { if (DEBUG) fprintf(outputFile, "adding equation to handle safe variable \n"); if (DEBUG) printEQ(eqn); if (DEBUG) fprintf(outputFile, "\n----\n"); i = addNewWildcard(problemPtr); //nEQ++; problemPtr->addNumEqs(1); assert(nEQ <= maxEQs); eqnzero(&EQs[e + 1]); eqnncpy(&EQs[e + 1], eqn, safeVars); for (j = nVars; j >= 0; j--) { EQs[e + 1].coef[j] = intMod(EQs[e + 1].coef[j], g2); if (2 * EQs[e + 1].coef[j] >= g2) EQs[e + 1].coef[j] -= g2; }; EQs[e + 1].coef[i] = g2; e += 2; if (DEBUG) printProblem(problemPtr); continue; }; sv = safeVars; if (g2 == 0) sv = 0; /* find variable to eliminate */ if (g2 > 1) { assert(inApproximateMode); if (TRACE) { fprintf(outputFile, "non-exact elimination: "); printEQ(eqn); fprintf(outputFile, "\n"); printProblem(problemPtr); fflush(outputFile); }; for (i = nVars; i > sv; i--) if (EQs[e].coef[i] != 0) break; } else for (i = nVars; i > sv; i--) if (EQs[e].coef[i] == 1 || EQs[e].coef[i] == -1) break; if (i > sv) { //nEQ--; problemPtr->addNumEqs(-1); doElimination(problemPtr, e, i); if (g2 > 1 && TRACE) { fprintf(outputFile, "result of non-exact elimination:\n"); printProblem(problemPtr); fflush(outputFile); }; } else { int factor = 100000; j = 0; if (DEBUG) fprintf(outputFile, "doing moding\n"); for (i = nVars; i != sv; i--) if ((EQs[e].coef[i] & 1) != 0) { j = i; i--; for (; i != sv; i--) if ((EQs[e].coef[i] & 1) != 0) break; break; }; if (j != 0 && i == sv) { doMod(problemPtr, 2, e, j); e++; continue; }; j = 0; for (i = nVars; i != sv; i--) if (EQs[e].coef[i] != 0 && factor > abs(EQs[e].coef[i]) + 1) { factor = abs(EQs[e].coef[i]) + 1; j = i; }; if (j == sv) { fprintf(outputFile, "should not have happened\n"); Exit(2); }; doMod(problemPtr, factor, e, j); /* go back and try this equation again */ e++; }; }; }; //nEQ = 0; problemPtr->setNumEqs(0); return (UNKNOWN); } static int solveGEQ(Problem *problemPtr, int desiredResult); static int solveDepth = 0; int solve(Problem *problemPtr, int desiredResult) { int result; assert(nVars >= safeVars); if (desiredResult != SIMPLIFY) safeVars = 0; solveDepth++; if (solveDepth > 50) { fprintf(outputFile, "Solve depth = %d, inApprox = %d, aborting\n", solveDepth, inApproximateMode); printProblem(problemPtr); fflush(outputFile); #ifndef SPEED debugLevel = 3; #else Exit(2); #endif if (solveDepth > 60) Exit(2); }; do { doItAgain = 0; if (solveEQ(problemPtr, desiredResult) == FALSE) { solveDepth--; return (FALSE); }; if (inApproximateMode && !nGEQ) { result = TRUE; foundReduction = 1; break; } else result = solveGEQ(problemPtr, desiredResult); } while (doItAgain && desiredResult == SIMPLIFY); solveDepth--; #if reduceWithSubstitutions #else resurrectSubs(problemPtr); assert(pleaseNoEqualitiesInSimplifiedProblems || !result || nSUB == 0); #endif return (result); } static int fastLookup[maxKeys * 2]; static int solveGEQ(Problem *problemPtr, int desiredResult) { int i, j, k, e; int nV, fv; int result; int coupledSubscripts; int eliminateAgain; int smoothed = 0; j = 0; solveGEQstart: while (1) { if (nGEQ > maxGEQs) { fprintf(outputFile, "TOO MANY EQUATIONS GENERATED\n"); Exit(2); }; if (DBUG) fprintf(outputFile, "\nSolveGEQ(%d):\n", desiredResult); if (DEBUG) printProblem(problemPtr); if (DBUG) fprintf(outputFile, "\n"); nV = nVars; if (nV == 1) { int uColor = black; int lColor = black; int upperBound = posInfinity; int lowerBound = negInfinity; for (e = nGEQ - 1; e >= 0; e--) { int a = GEQs[e].coef[1]; int c = GEQs[e].coef[0]; /* our equation is ax + c >= 0, or ax >= -c, or c >= -ax */ if (a == 0) { if (c < 0) { if (DBUG) fprintf(outputFile, "equations have no solution \n"); return (FALSE); }; } else if (a > 0) { if (a != 1) c = intDiv(c, a); if (lowerBound < -c || (lowerBound == -c && !isRed(&GEQs[e]))) { lowerBound = -c; lColor = GEQs[e].color; } } else { if (a != -1) c = intDiv(c, -a); if (upperBound > c || (upperBound == c && !isRed(&GEQs[e]))) { upperBound = c; uColor = GEQs[e].color; } }; }; if (DEBUG) fprintf(outputFile, "upper bound = %d\n", upperBound); if (DEBUG) fprintf(outputFile, "lower bound = %d\n", lowerBound); if (lowerBound > upperBound) { if (DBUG) fprintf(outputFile, "equations have no solution \n"); return (FALSE); }; if (desiredResult == SIMPLIFY) { //nGEQ = 0; problemPtr->setNumGEqs(0); if (safeVars == 1) { if (lowerBound == upperBound && !uColor && !lColor) { EQs[0].coef[0] = -lowerBound; EQs[0].coef[1] = 1; EQs[0].color = 0; //nEQ = 1; problemPtr->setNumEqs(1); return (solve(problemPtr, desiredResult)); } else { if (lowerBound > negInfinity) { GEQs[0].coef[0] = -lowerBound; GEQs[0].coef[1] = 1; GEQs[0].key = 1; GEQs[0].color = lColor; GEQs[0].touched = 0; //nGEQ = 1; problemPtr->setNumGEqs(1); } if (upperBound < posInfinity) { const int numGE = nGEQ; problemPtr->addNumGEqs(1); GEQs[numGE].coef[0] = upperBound; GEQs[numGE].coef[1] = -1; GEQs[numGE].key = -1; GEQs[numGE].color = uColor; GEQs[numGE].touched = 0; //nGEQ++; } } } else problemPtr->setVarsN(0); problemReduced(problemPtr); return (FALSE); }; if (originalProblem != noProblem && !lColor && !uColor && !conservative && lowerBound == upperBound) { EQs[0].coef[0] = -lowerBound; EQs[0].coef[1] = 1; //nEQ = 1; problemPtr->setNumEqs(1); addingEqualityConstraint(problemPtr, 0); }; return (TRUE); }; if (!problemPtr->variablesFreed) { problemPtr->variablesFreed = 1; if (desiredResult != SIMPLIFY) freeEliminations(problemPtr, 0); else freeEliminations(problemPtr, safeVars); nV = nVars; if (nV == 1) continue; }; coupledSubscripts = 0; for (e = 0; e < nGEQ; e++) { if (!GEQs[e].touched) { if (!singleVarGEQ(GEQs[e], nV)) coupledSubscripts = 1; } else { int g; int topVar; int i0; int hashCode; { int *p = &packing[0]; for (k = 1; k <= nV; k++) if (GEQs[e].coef[k]) { *(p++) = k; }; topVar = (p - &packing[0]) - 1; }; if (topVar == -1) { if (GEQs[e].coef[0] < 0) { if (DBUG) printGEQ(&GEQs[e]); if (DBUG) fprintf(outputFile, "\nequations have no solution \n"); return (FALSE); }; doDelete(e, nV); e--; continue; } else if (topVar == 0) { int singleVar = packing[0]; g = GEQs[e].coef[singleVar]; if (g > 0) { GEQs[e].coef[singleVar] = 1; GEQs[e].key = singleVar; } else { g = -g; GEQs[e].coef[singleVar] = -1; GEQs[e].key = -singleVar; }; if (g > 1) GEQs[e].coef[0] = intDiv(GEQs[e].coef[0], g); } else { coupledSubscripts = 1; i0 = topVar; i = packing[i0--]; g = GEQs[e].coef[i]; hashCode = g * (i + 3); if (g < 0) g = -g; for (; i0 >= 0; i0--) { int x; i = packing[i0]; x = GEQs[e].coef[i]; hashCode = hashCode * keyMult * (i + 3) + x; if (x < 0) x = -x; if (x == 1) { g = 1; i0--; break; } else g = gcd(x, g); }; for (; i0 >= 0; i0--) { int x; i = packing[i0]; x = GEQs[e].coef[i]; hashCode = hashCode * keyMult * (i + 3) + x; }; if (g > 1) { GEQs[e].coef[0] = intDiv(GEQs[e].coef[0], g); i0 = topVar; i = packing[i0--]; GEQs[e].coef[i] = GEQs[e].coef[i] / g; hashCode = GEQs[e].coef[i] * (i + 3); for (; i0 >= 0; i0--) { i = packing[i0]; GEQs[e].coef[i] = GEQs[e].coef[i] / g; hashCode = hashCode * keyMult * (i + 3) + GEQs[e].coef[i]; }; }; { int g2 = abs(hashCode); if (DEBUG) { fprintf(outputFile, "Hash code = %d, eqn = ", hashCode); printGEQ(&GEQs[e]); fprintf(outputFile, "\n"); }; j = g2 % hashTableSize; while (1) { Eqn proto = &(hashMaster[j]); if (proto->touched == g2) { if (proto->coef[0] == topVar) { if (hashCode >= 0) for (i0 = topVar; i0 >= 0; i0--) { i = packing[i0]; if (GEQs[e].coef[i] != proto->coef[i]) break; } else for (i0 = topVar; i0 >= 0; i0--) { i = packing[i0]; if (GEQs[e].coef[i] != -proto->coef[i]) break; }; if (i0 < 0) { if (hashCode >= 0) GEQs[e].key = proto->key; else GEQs[e].key = -proto->key; break; }; }; } else if (proto->touched < 0) { eqnzero(proto); if (hashCode >= 0) for (i0 = topVar; i0 >= 0; i0--) { i = packing[i0]; proto->coef[i] = GEQs[e].coef[i]; } else for (i0 = topVar; i0 >= 0; i0--) { i = packing[i0]; proto->coef[i] = -GEQs[e].coef[i]; } proto->coef[0] = topVar; proto->touched = g2; if (DEBUG) fprintf(outputFile, " constraint key = %d\n", nextKey); proto->key = nextKey++; if (proto->key > maxKeys) { fprintf(outputFile, "too many hash keys generated \n"); fflush(outputFile); Exit(2); }; if (hashCode >= 0) GEQs[e].key = proto->key; else GEQs[e].key = -proto->key; break; }; j = (j + 1) % hashTableSize; }; }; }; GEQs[e].touched = FALSE; }; { int eKey = GEQs[e].key; int e2; if (e > 0) { int cTerm = GEQs[e].coef[0]; e2 = fastLookup[maxKeys - eKey]; if (e2 < e && GEQs[e2].key == -eKey) { if (GEQs[e2].coef[0] < -cTerm) { if (DBUG) { printGEQ(&GEQs[e]); fprintf(outputFile, "\n"); printGEQ(&GEQs[e2]); fprintf(outputFile, "\nequations have no solution \n"); }; return (FALSE); }; if (GEQs[e2].coef[0] == -cTerm && !GEQs[e2].color && !GEQs[e].color) { /* * if (!addIt && 0) { int i; for (i = safeVars + 1; i <= nVars; i++) if (GEQs[e].coef[i] == * 1 || GEQs[e].coef[i] == -1) addIt = 1; }; */ const int numEQ = nEQ; problemPtr->addNumEqs(1); eqncpy(&EQs[numEQ], &GEQs[e]); if (!GEQs[e2].color) addingEqualityConstraint(problemPtr, numEQ); assert(!GEQs[e2].color); assert(!GEQs[e].color); //nEQ++; assert(nEQ <= maxEQs); } } e2 = fastLookup[maxKeys + eKey]; if (e2 < e && GEQs[e2].key == eKey) { if (GEQs[e2].coef[0] > cTerm) { GEQs[e2].coef[0] = cTerm; GEQs[e2].color = GEQs[e].color; } else if (GEQs[e2].coef[0] == cTerm) GEQs[e2].color &= GEQs[e].color; doDelete(e, nV); e--; continue; }; }; fastLookup[maxKeys + eKey] = e; }; }; nV = nVars; if ((doTrace && desiredResult == SIMPLIFY) || DBUG) { fprintf(outputFile, "\nafter normalization:\n"); printProblem(problemPtr); fprintf(outputFile, "\n"); fprintf(outputFile, "eliminating variable using fourier-motzkin elimination\n"); }; do { eliminateAgain = 0; if (nEQ > 0) return (solve(problemPtr, desiredResult)); if (!coupledSubscripts) { if (safeVars == 0) { //nGEQ = 0; problemPtr->setNumGEqs(0); } else for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].key > safeVars || -safeVars > GEQs[e].key) doDelete(e, nV); problemPtr->setVarsN(safeVars); //nVars = safeVars; if (desiredResult == SIMPLIFY) { problemReduced(problemPtr); return (FALSE); }; return (TRUE); }; if (desiredResult != SIMPLIFY) fv = 0; else fv = safeVars; if (nGEQ == 0) { if (desiredResult == SIMPLIFY) { problemPtr->setVarsN(safeVars); //nVars = safeVars; problemReduced(problemPtr); return (FALSE); }; return (TRUE); }; if (desiredResult == SIMPLIFY && nV == safeVars) { problemReduced(problemPtr); return (FALSE); }; if (nGEQ > maxGEQs - 30 || nGEQ > 2 * nV * nV + 4 * nV + 10) { if (DBUG) fprintf(outputFile, "TOO MANY EQUATIONS; %d equations, %d variables, ELIMINATING REDUNDANT ONES\n", nGEQ, nV); if (!eliminateRedundant(problemPtr, 0)) return 0; nV = nVars; if (nEQ > 0) return (solve(problemPtr, desiredResult)); if (DBUG) fprintf(outputFile, "END ELIMINATION OF REDUNDANT EQUATIONS\n"); }; { int minC, maxC, minCj; int lowerBoundCount; int e2, Le, Ue; int possibleEasyIntSolution; int exact = 0; int luckyExact = 0; int newEqns = 0; minCj = 0; Le = 0; lowerBoundCount = 0; if (desiredResult != SIMPLIFY) fv = 0; else fv = safeVars; { int best = 1000000; int jLe, jLowerBoundCount, upperBoundCount; jLe = 0; jLowerBoundCount = 0; for (i = nV; i != fv; i--) { int score; int ub = -2; int lb = -2; int lucky = 0; minC = maxC = 0; lowerBoundCount = 0; upperBoundCount = 0; for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[i] < 0) { setMin(minC, GEQs[e].coef[i]); upperBoundCount++; if (GEQs[e].coef[i] < -1) { if (ub == -2) ub = e; else ub = -1; }; } else if (GEQs[e].coef[i] > 0) { setMax(maxC, GEQs[e].coef[i]); lowerBoundCount++; Le = e; if (GEQs[e].coef[i] > 1) { if (lb == -2) lb = e; else lb = -1; }; }; if (lowerBoundCount == 0 || upperBoundCount == 0) { lowerBoundCount = 0; break; }; if (ub >= 0 && lb >= 0 && GEQs[lb].key == -GEQs[ub].key) { int Lc = GEQs[lb].coef[i]; int Uc = -GEQs[ub].coef[i]; int diff = Lc * GEQs[ub].coef[0] + Uc * GEQs[lb].coef[0]; lucky = (diff >= (Uc - 1) * (Lc - 1)); }; if (maxC == 1 || minC == -1 || lucky || APROX || inApproximateMode) { newEqns = score = upperBoundCount * lowerBoundCount; if (DEBUG) fprintf(outputFile, "For %s, exact, score = %d*%d, range = %d ... %d, \nlucky = %d, APROX = %d, inApproximateMode=%d \n", variable(i), upperBoundCount, lowerBoundCount, minC, maxC, lucky, APROX, inApproximateMode); if (!exact || score < best) { best = score; j = i; minCj = minC; jLe = Le; jLowerBoundCount = lowerBoundCount; exact = 1; luckyExact = lucky; if (score == 1) break; }; } else if (!exact) { if (DEBUG) fprintf(outputFile, "For %s, non-exact, score = %d*%d, range = %d ... %d \n", variable(i), upperBoundCount, lowerBoundCount, minC, maxC); newEqns = upperBoundCount * lowerBoundCount; score = maxC - minC; if (best > score) { best = score; j = i; minCj = minC; jLe = Le; jLowerBoundCount = lowerBoundCount; }; }; }; if (lowerBoundCount == 0) { freeEliminations(problemPtr, safeVars); nV = nVars; continue; }; i = j; minC = minCj; Le = jLe; lowerBoundCount = jLowerBoundCount; }; #ifdef singleResult if (desiredResult == SIMPLIFY && !exact) { nonConvex = 1; problemReduced(problemPtr); return (TRUE); }; #endif if ((doTrace && desiredResult == SIMPLIFY) || DBUG) { fprintf(outputFile, "going to eliminate %s\n", variable(i)); if (luckyExact) fprintf(outputFile, "(a lucky exact elimination)\n"); else if (exact) fprintf(outputFile, "(an exact elimination)\n"); }; smoothed = 0; if (i != nV) { int t; j = nVars; if (DEBUG) { fprintf(outputFile, "Swapping %d and %d\n", i, j); printProblem(problemPtr); }; swap(&problemPtr->_var[i], &problemPtr->_var[j]); for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[i] != GEQs[e].coef[j]) { GEQs[e].touched = TRUE; t = GEQs[e].coef[i]; GEQs[e].coef[i] = GEQs[e].coef[j]; GEQs[e].coef[j] = t; }; for (e = nSUB - 1; e >= 0; e--) if (SUBs[e].coef[i] != SUBs[e].coef[j]) { t = SUBs[e].coef[i]; SUBs[e].coef[i] = SUBs[e].coef[j]; SUBs[e].coef[j] = t; }; if (DEBUG) { fprintf(outputFile, "Swapping complete \n"); printProblem(problemPtr); fprintf(outputFile, "\n"); }; i = j; } else if (DEBUG) { fprintf(outputFile, "No swap needed\n"); printProblem(problemPtr); }; problemPtr->addToVarsN(-1); //nVars--; nV = nVars; if (exact) { #define maxDead maxGEQs if (nV == 1) { int upperBound = posInfinity; int lowerBound = negInfinity; int ub_color = -1; int lb_color = -1; int constantTerm, coefficient; int topEqn = nGEQ - 1; int Lc = GEQs[Le].coef[i]; for (Le = topEqn; Le >= 0; Le--) if ((Lc = GEQs[Le].coef[i]) == 0) { if (GEQs[Le].coef[1] == 1) { constantTerm = -GEQs[Le].coef[0]; if (constantTerm > lowerBound || (constantTerm == lowerBound && !isRed(&GEQs[Le]))) { lowerBound = constantTerm; lb_color = GEQs[Le].color; } if (DEBUG) { if (GEQs[Le].color == black) fprintf(outputFile, " :::=> %s >= %d\n", variable(1), constantTerm); else fprintf(outputFile, " :::=> [%s >= %d]\n", variable(1), constantTerm); } } else { constantTerm = GEQs[Le].coef[0]; if (constantTerm < upperBound || (constantTerm == upperBound && !isRed(&GEQs[Le]))) { upperBound = constantTerm; ub_color = GEQs[Le].color; } if (DEBUG) { if (GEQs[Le].color == black) fprintf(outputFile, " :::=> %s <= %d\n", variable(1), constantTerm); else fprintf(outputFile, " :::=> [%s <= %d]\n", variable(1), constantTerm); } }; } else if (Lc > 0) { for (Ue = topEqn; Ue >= 0; Ue--) if (GEQs[Ue].coef[i] < 0) { if (GEQs[Le].key != -GEQs[Ue].key) { int Uc = -GEQs[Ue].coef[i]; coefficient = GEQs[Ue].coef[1] * Lc + GEQs[Le].coef[1] * Uc; constantTerm = GEQs[Ue].coef[0] * Lc + GEQs[Le].coef[0] * Uc; if (DEBUG) { printGEQextra(&(GEQs[Ue])); fprintf(outputFile, "\n"); printGEQextra(&(GEQs[Le])); fprintf(outputFile, "\n"); }; if (coefficient > 0) { constantTerm = -(intDiv(constantTerm, coefficient)); /* assert(black == 0) */ if (constantTerm > lowerBound || (constantTerm == lowerBound && (desiredResult != SIMPLIFY || (GEQs[Ue].color == black && GEQs[Le].color == black)))) { lowerBound = constantTerm; lb_color = GEQs[Ue].color || GEQs[Le].color; } if (DEBUG) { if (GEQs[Ue].color || GEQs[Le].color) fprintf(outputFile, " ::=> [%s >= %d]\n", variable(1), constantTerm); else fprintf(outputFile, " ::=> %s >= %d\n", variable(1), constantTerm); } } else { constantTerm = (intDiv(constantTerm, -coefficient)); if (constantTerm < upperBound || (constantTerm == upperBound && GEQs[Ue].color == black && GEQs[Le].color == black)) { upperBound = constantTerm; ub_color = GEQs[Ue].color || GEQs[Le].color; } if (DEBUG) { if (GEQs[Ue].color || GEQs[Le].color) fprintf(outputFile, " ::=> [%s <= %d]\n", variable(1), constantTerm); else fprintf(outputFile, " ::=> %s <= %d\n", variable(1), constantTerm); } } }; }; }; //nGEQ = 0; problemPtr->setNumGEqs(0); if (DEBUG) fprintf(outputFile, " therefore, %c%d <= %c%s%c <= %d%c\n", lb_color ? '[' : ' ', lowerBound, (lb_color && !ub_color) ? ']' : ' ', variable(1), (!lb_color && ub_color) ? '[' : ' ', upperBound, ub_color ? ']' : ' '); if (lowerBound > upperBound) return (FALSE); if (safeVars == 1) { if (upperBound == lowerBound && !(ub_color | lb_color) && !pleaseNoEqualitiesInSimplifiedProblems) { //nEQ++; problemPtr->addNumEqs(1); EQs[0].coef[1] = -1; EQs[0].coef[0] = upperBound; EQs[0].color = ub_color | lb_color; if (desiredResult == SIMPLIFY && !EQs[0].color) return (solve(problemPtr, desiredResult)); }; if (upperBound != posInfinity) { GEQs[0].coef[1] = -1; GEQs[0].coef[0] = upperBound; GEQs[0].color = ub_color; GEQs[0].key = -1; GEQs[0].touched = 0; //nGEQ++; problemPtr->addNumGEqs(1); } if (lowerBound != negInfinity) { const int numGE = nGEQ; problemPtr->addNumGEqs(1); GEQs[numGE].coef[1] = 1; GEQs[numGE].coef[0] = -lowerBound; GEQs[numGE].color = lb_color; GEQs[numGE].key = 1; GEQs[numGE].touched = 0; //nGEQ++; } } if (desiredResult == SIMPLIFY) { problemReduced(problemPtr); return (FALSE); } else { if (!conservative && (desiredResult != SIMPLIFY || (!lb_color && !ub_color)) && originalProblem != noProblem && lowerBound == upperBound) { for (i = originalProblem->getVarsN(); i >= 0; i--) if (originalProblem->_var[i] == problemPtr->_var[1]) break; if (i == 0) break; //e = originalProblem->_numEQs++; e = originalProblem->getNumEqs(); problemPtr->addNumEqs(1); eqnnzero(&originalProblem->_EQs[e], originalProblem->getVarsN()); originalProblem->_EQs[e].coef[i] = -1; originalProblem->_EQs[e].coef[0] = upperBound; if (DEBUG) { fprintf(outputFile, "adding equality constraint %d to outer problem\n", e); printProblem(originalProblem); }; }; return (TRUE); }; }; eliminateAgain = 1; if (lowerBoundCount == 1) { struct _eqn lbEqn; int Lc = GEQs[Le].coef[i]; if (DBUG) fprintf(outputFile, "an inplace elimination\n"); eqnncpy(&lbEqn, &GEQs[Le], (nV + 1)); doDeleteExtra(Le, nV + 1); for (Ue = nGEQ - 1; Ue >= 0; Ue--) if (GEQs[Ue].coef[i] < 0) if (lbEqn.key == -GEQs[Ue].key) { doDeleteExtra(Ue, nV + 1); } else { int Uc = -GEQs[Ue].coef[i]; GEQs[Ue].touched = TRUE; GEQs[Ue].color |= lbEqn.color; eliminateAgain = 0; for (k = 0; k <= nV; k++) GEQs[Ue].coef[k] = GEQs[Ue].coef[k] * Lc + lbEqn.coef[k] * Uc; if (DEBUG) { printGEQ(&(GEQs[Ue])); fprintf(outputFile, "\n"); }; }; continue; } else { int deadEqns[maxDead]; int numDead = 0; int topEqn = nGEQ - 1; lowerBoundCount--; if (DEBUG) fprintf(outputFile, "lower bound count = %d\n", lowerBoundCount); for (Le = topEqn; Le >= 0; Le--) if (GEQs[Le].coef[i] > 0) { int Lc = GEQs[Le].coef[i]; for (Ue = topEqn; Ue >= 0; Ue--) if (GEQs[Ue].coef[i] < 0) { if (GEQs[Le].key != -GEQs[Ue].key) { int Uc = -GEQs[Ue].coef[i]; if (numDead == 0) { //e2 = nGEQ++; e2 = nGEQ; problemPtr->addNumGEqs(1); } else e2 = deadEqns[--numDead]; assert(e2 < maxGEQs); if (DEBUG) fprintf(outputFile, "Le = %d, Ue = %d, gen = %d\n", Le, Ue, e2); if (DEBUG) { printGEQextra(&(GEQs[Le])); fprintf(outputFile, "\n"); printGEQextra(&(GEQs[Ue])); fprintf(outputFile, "\n"); }; eliminateAgain = 0; for (k = nV; k >= 0; k--) GEQs[e2].coef[k] = GEQs[Ue].coef[k] * Lc + GEQs[Le].coef[k] * Uc; GEQs[e2].coef[nV + 1] = 0; GEQs[e2].touched = TRUE; GEQs[e2].color = GEQs[Ue].color | GEQs[Le].color; if (DEBUG) { printGEQ(&(GEQs[e2])); fprintf(outputFile, "\n"); }; }; if (lowerBoundCount == 0) { deadEqns[numDead++] = Ue; if (DEBUG) fprintf(outputFile, "Killed %d\n", Ue); }; }; lowerBoundCount--; deadEqns[numDead++] = Le; if (DEBUG) fprintf(outputFile, "Killed %d\n", Le); }; { int isDead[maxGEQs]; for (e = nGEQ - 1; e >= 0; e--) isDead[e] = FALSE; while (numDead > 0) { e = deadEqns[--numDead]; isDead[e] = TRUE; }; for (e = nGEQ - 1; e >= 0; e--) if (isDead[e]) doDeleteExtra(e, nV + 1); }; continue; }; } else { Problem *rS, *iS; rS = mallocProblem; #ifdef _WIN32 addToCollection(__LINE__, __FILE__, rS, 1); #endif initializeProblem(rS); iS = mallocProblem; #ifdef _WIN32 addToCollection(__LINE__, __FILE__, iS, 1); #endif initializeProblem(iS); rS->_getVarName = problemPtr->_getVarName; rS->_getVarNameArgs = problemPtr->_getVarNameArgs; iS->_getVarName = problemPtr->_getVarName; iS->_getVarNameArgs = problemPtr->_getVarNameArgs; e2 = 0; possibleEasyIntSolution = TRUE; for (e = 0; e < nGEQ; e++) if (GEQs[e].coef[i] == 0) { eqncpy(&(rS->_GEQs[e2]), &GEQs[e]); eqncpy(&(iS->_GEQs[e2]), &GEQs[e]); if (DEBUG) { int t; fprintf(outputFile, "Copying (%d, %d): ", i, GEQs[e].coef[i]); printGEQextra(&GEQs[e]); fprintf(outputFile, "\n"); for (t = 0; t <= nV + 1; t++) fprintf(outputFile, "%d ", GEQs[e].coef[t]); fprintf(outputFile, "\n"); }; e2++; assert(e2 < maxGEQs); }; for (Le = nGEQ - 1; Le >= 0; Le--) if (GEQs[Le].coef[i] > 0) { int Lc = GEQs[Le].coef[i]; for (Ue = nGEQ - 1; Ue >= 0; Ue--) if (GEQs[Ue].coef[i] < 0) if (GEQs[Le].key != -GEQs[Ue].key) { int Uc = -GEQs[Ue].coef[i]; rS->_GEQs[e2].touched = iS->_GEQs[e2].touched = TRUE; if (DEBUG) { fprintf(outputFile, "---\n"); fprintf(outputFile, "Le = %d, Ue = %d, gen = %d\n", Le, Ue, e2); printGEQextra(&GEQs[Le]); fprintf(outputFile, "\n"); printGEQextra(&GEQs[Ue]); fprintf(outputFile, "\n"); }; for (k = nV; k >= 0; k--) iS->_GEQs[e2].coef[k] = rS->_GEQs[e2].coef[k] = GEQs[Ue].coef[k] * Lc + GEQs[Le].coef[k] * Uc; iS->_GEQs[e2].coef[0] -= (Uc - 1) * (Lc - 1); iS->_GEQs[e2].color = rS->_GEQs[e2].color = GEQs[Ue].color || GEQs[Le].color; if (DEBUG) { printGEQ(&(rS->_GEQs[e2])); fprintf(outputFile, "\n"); }; e2++; assert(e2 < maxGEQs); } else { int Uc = -GEQs[Ue].coef[i]; if (GEQs[Ue].coef[0] * Lc + GEQs[Le].coef[0] * Uc - (Uc - 1) * (Lc - 1) < 0) possibleEasyIntSolution = FALSE; }; }; iS->variablesInitialized = rS->variablesInitialized = 1; iS->setVarsN(nVars); rS->setVarsN(nVars); //iS->_numGEQs = rS->_numGEQs = e2; //iS->_numEQs = rS->_numEQs = 0; //iS->_numSUBs = rS->_numSUBs = nSUB; iS->setNumGEqs(e2); rS->setNumGEqs(e2); iS->setNumEqs(0); rS->setNumEqs(0); iS->setNumSUBs(nSUB); rS->setNumSUBs(nSUB); iS->_safeVars = rS->_safeVars = safeVars; { int t; for (t = nV; t >= 0; t--) rS->_var[t] = problemPtr->_var[t]; for (t = nV; t >= 0; t--) iS->_var[t] = problemPtr->_var[t]; for (e = nSUB - 1; e >= 0; e--) { eqnncpy(&(rS->_SUBs[e]), &(SUBs[e]), nVars); eqnncpy(&(iS->_SUBs[e]), &(SUBs[e]), nVars); }; }; problemPtr->addToVarsN(1); //nVars++; nV = nVars; if (desiredResult != TRUE) { int t = trace; if (DBUG) fprintf(outputFile, "\nreal solution(%d):\n", depth); depth++; trace = 0; if (originalProblem == noProblem) { originalProblem = problemPtr; result = solveGEQ(rS, FALSE); originalProblem = noProblem; } else result = solveGEQ(rS, FALSE); trace = t; depth--; if (result == FALSE) { #ifdef _WIN32 removeFromCollection(rS); removeFromCollection(iS); #endif free(rS); free(iS); return (result); }; if (nEQ > 0) { #ifdef _WIN32 removeFromCollection(rS); removeFromCollection(iS); #endif /* An equality constraint must have been found */ free(rS); free(iS); return (solve(problemPtr, desiredResult)); }; }; if (desiredResult != FALSE) { if (possibleEasyIntSolution) { if (DBUG) fprintf(outputFile, "\ninteger solution(%d):\n", depth); depth++; conservative++; result = solveGEQ(iS, desiredResult); conservative--; depth--; if (result != FALSE) { #ifdef _WIN32 removeFromCollection(rS); removeFromCollection(iS); #endif free(rS); free(iS); return (result); }; }; if (DBUG) fprintf(outputFile, "have to do exact analysis\n"); { int worstLowerBoundConstant = -minC; int lowerBounds = 0; int lowerBound[maxGEQs]; int smallest; int t; conservative++; for (e = 0; e < nGEQ; e++) if (GEQs[e].coef[i] > 1) lowerBound[lowerBounds++] = e; /* sort array */ for (j = 0; j < lowerBounds; j++) { smallest = j; for (k = j + 1; k < lowerBounds; k++) if (GEQs[lowerBound[smallest]].coef[i] > GEQs[lowerBound[k]].coef[i]) smallest = k; t = lowerBound[smallest]; lowerBound[smallest] = lowerBound[j]; lowerBound[j] = t; }; if (DEBUG) { fprintf(outputFile, "lower bound coeeficients = "); for (j = 0; j < lowerBounds; j++) fprintf(outputFile, " %d", GEQs[lowerBound[j]].coef[i]); fprintf(outputFile, "\n"); }; for (j = 0; j < lowerBounds; j++) { int maxIncr; int c; e = lowerBound[j]; maxIncr = ((GEQs[e].coef[i] - 1) * (worstLowerBoundConstant - 1) - 1) / worstLowerBoundConstant; /* maxIncr += 2; */ if ((doTrace && desiredResult == SIMPLIFY) || DBUG) { fprintf(outputFile, "for equation "); printGEQ(&GEQs[e]); fprintf(outputFile, "\ntry decrements from 0 to %d\n", maxIncr); printProblem(problemPtr); }; if (maxIncr > 50) { if (!smoothed && smoothWeirdEquations(problemPtr)) { conservative--; #ifdef _WIN32 removeFromCollection(rS); removeFromCollection(iS); #endif free(rS); free(iS); smoothed = 1; goto solveGEQstart; }; }; eqncpy(&EQs[0], &GEQs[e]); /* * if (GEQs[e].color) fprintf(outputFile,"warning: adding black equality constraint * based on red inequality\n"); */ EQs[0].color = black; eqnzero(&GEQs[e]); GEQs[e].touched = TRUE; //nEQ = 1; problemPtr->setNumEqs(1); for (c = maxIncr; c >= 0; c--) { if (DBUG) fprintf(outputFile, "trying next decrement of %d\n", maxIncr - c); if (DBUG) printProblem(problemPtr); problemcpy(rS, problemPtr); if (DEBUG) printProblem(rS); result = solve(rS, desiredResult); if (result == TRUE) { #ifdef _WIN32 removeFromCollection(rS); removeFromCollection(iS); #endif free(rS); free(iS); conservative--; return (TRUE); }; EQs[0].coef[0]--; }; if (j + 1 < lowerBounds) { //nEQ = 0; problemPtr->setNumEqs(0); eqncpy(&GEQs[e], &EQs[0]); GEQs[e].touched = 1; GEQs[e].color = black; problemcpy(rS, problemPtr); if (DEBUG) fprintf(outputFile, "exhausted lower bound, checking if still feasible "); result = solve(rS, FALSE); if (result == FALSE) break; }; }; if ((doTrace && desiredResult == SIMPLIFY) || DBUG) fprintf(outputFile, "fall-off the end\n"); #ifdef _WIN32 removeFromCollection(rS); removeFromCollection(iS); #endif free(rS); free(iS); conservative--; return (FALSE); }; }; #ifdef _WIN32 removeFromCollection(rS); removeFromCollection(iS); #endif free(rS); free(iS); }; return (UNKNOWN); }; } while (eliminateAgain); }; } /* * Return 1 if red equations constrain the set of possible solutions. We assume that there are solutions to the black * equations by themselves, so if there is no solution to the combined problem, we return 1. */ int hasRedEquations(Problem * problemPtr, bool expensive) { int result; int e; int i; if (TRACE) { fprintf(outputFile, "Checking for red equations:\n"); printProblem(problemPtr); }; pleaseNoEqualitiesInSimplifiedProblems++; mayBeRed++; result = !simplifyProblem(problemPtr); mayBeRed--; pleaseNoEqualitiesInSimplifiedProblems--; if (result) { return 1; } freeRedEliminations(problemPtr); assert(nEQ == 0); for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].color == red) result = 1; if (!result) return 0; if (!expensive) for (i = safeVars; i >= 1; i--) { int ub = 0; int lb = 0; for (e = nGEQ - 1; e >= 0; e--) { if (GEQs[e].coef[i]) if (GEQs[e].coef[i] > 0) lb |= (1 + GEQs[e].color); else /* (GEQs[e].coef[i] < 0) */ ub |= (1 + GEQs[e].color); } if (ub == 2 || lb == 2) { if (DBUG) fprintf(outputFile, "checks for upper/lower bounds worked!\n"); #if reduceWithSubstitutions #else resurrectSubs(problemPtr); assert(nSUB == 0); #endif return 1; }; }; if (TRACE) fprintf(outputFile, "*** Doing potentially expensive elimination tests for red equations\n"); pleaseNoEqualitiesInSimplifiedProblems++; eliminateRed(problemPtr, expensive); pleaseNoEqualitiesInSimplifiedProblems--; result = 0; assert(nEQ == 0); for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].color == red) result = 1; if (TRACE) if (!result) fprintf(outputFile, "******************** Redudant Red Equations eliminated!!\n"); else fprintf(outputFile, "******************** Red Equations remain\n"); if (DEBUG) printProblem(problemPtr); #if reduceWithSubstitutions #else resurrectSubs(problemPtr); assert(nSUB == 0); #endif return result; } int simplifyApproximate(Problem *problemPtr) { int result; inApproximateMode = 1; if (TRACE) fprintf(outputFile, "Entering Approximate Mode\n"); result = simplifyProblem(problemPtr); if (nVars != safeVars) { fprintf(outputFile, "assertion blown!\n"); printProblem(problemPtr); fflush(outputFile); assert(nVars == safeVars); }; if (TRACE) fprintf(outputFile, "Leaving Approximate Mode\n"); inApproximateMode = 0; #if reduceWithSubstitutions #else assert(nSUB == 0); #endif return (result); } int simplifyProblem(Problem *problemPtr) { int i; foundReduction = FALSE; if (!problemPtr->variablesInitialized) { initializeVariables(problemPtr); }; #ifdef clearForwardingPointers for (i = 1; i <= nVars; i++) if (problemPtr->_var[i] > 0) problemPtr->forwardingAddress[problemPtr->_var[i]] = 0; #endif if (nextKey * 3 > maxKeys) { int e; hashVersion++; nextKey = maxVars + 1; for (e = nGEQ - 1; e >= 0; e--) GEQs[e].touched = TRUE; for (i = 0; i < hashTableSize; i++) hashMaster[i].touched = -1; problemPtr->hashVersion = hashVersion; } else if (problemPtr->hashVersion != hashVersion) { int e; for (e = nGEQ - 1; e >= 0; e--) GEQs[e].touched = TRUE; problemPtr->hashVersion = hashVersion; }; nonConvex = 0; if (nVars > nEQ + 3 * safeVars) freeEliminations(problemPtr, safeVars); solve(problemPtr, SIMPLIFY); if (foundReduction) { for (i = 1; i <= safeVars; i++) problemPtr->forwardingAddress[problemPtr->_var[i]] = i; for (i = 0; i < nSUB; i++) problemPtr->forwardingAddress[SUBs[i].key] = -i - 1; }; #if reduceWithSubstitutions #else assert(pleaseNoEqualitiesInSimplifiedProblems || !foundReduction || nSUB == 0); #endif return (foundReduction); } void unprotectVariable(Problem *problemPtr, int v) { int e, t, j, i; i = problemPtr->forwardingAddress[v]; if (i < 0) { i = -1 - i; //nSUB--; problemPtr->addNumSUBs(-1); if (i < nSUB) { eqncpy(&SUBs[i], &SUBs[nSUB]); problemPtr->forwardingAddress[SUBs[i].key] = -i - 1; }; } else { int bringToLife[maxVars]; int comingBack = 0; int e2; for (e = nSUB - 1; e >= 0; e--) if (bringToLife[e] = (SUBs[e].coef[i] != 0)) comingBack++; for (e2 = nSUB - 1; e2 >= 0; e2--) if (bringToLife[e2]) { problemPtr->addToVarsN(1); //nVars++; safeVars++; if (safeVars < nVars) { for (e = nGEQ - 1; e >= 0; e--) { GEQs[e].coef[nVars] = GEQs[e].coef[safeVars]; GEQs[e].coef[safeVars] = 0; }; for (e = nEQ - 1; e >= 0; e--) { EQs[e].coef[nVars] = EQs[e].coef[safeVars]; EQs[e].coef[safeVars] = 0; }; for (e = nSUB - 1; e >= 0; e--) { SUBs[e].coef[nVars] = SUBs[e].coef[safeVars]; SUBs[e].coef[safeVars] = 0; }; problemPtr->_var[nVars] = problemPtr->_var[safeVars]; problemPtr->forwardingAddress[problemPtr->_var[nVars]] = nVars; } else { for (e = nGEQ - 1; e >= 0; e--) { GEQs[e].coef[safeVars] = 0; }; for (e = nEQ - 1; e >= 0; e--) { EQs[e].coef[safeVars] = 0; }; for (e = nSUB - 1; e >= 0; e--) { SUBs[e].coef[safeVars] = 0; }; }; problemPtr->_var[safeVars] = SUBs[e2].key; problemPtr->forwardingAddress[SUBs[e2].key] = safeVars; const int numEQ = nEQ; problemPtr->addNumEqs(1); eqncpy(&(EQs[numEQ]), &(SUBs[e2])); //EQs[nEQ++].coef[problemPtr->_safeVars] = -1; EQs[numEQ].coef[problemPtr->_safeVars] = -1; assert(nEQ <= maxEQs); if (e2 < nSUB - 1) eqncpy(&(SUBs[e2]), &(SUBs[nSUB - 1])); //nSUB--; problemPtr->addNumSUBs(-1); }; if (i < safeVars) { j = safeVars; for (e = nSUB - 1; e >= 0; e--) { t = SUBs[e].coef[j]; SUBs[e].coef[j] = SUBs[e].coef[i]; SUBs[e].coef[i] = t; }; for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[j] != GEQs[e].coef[i]) { GEQs[e].touched = TRUE; t = GEQs[e].coef[j]; GEQs[e].coef[j] = GEQs[e].coef[i]; GEQs[e].coef[i] = t; }; for (e = nEQ - 1; e >= 0; e--) { t = EQs[e].coef[j]; EQs[e].coef[j] = EQs[e].coef[i]; EQs[e].coef[i] = t; }; t = problemPtr->_var[j]; problemPtr->_var[j] = problemPtr->_var[i]; problemPtr->_var[i] = t; problemPtr->forwardingAddress[problemPtr->_var[i]] = i; problemPtr->forwardingAddress[problemPtr->_var[j]] = j; }; safeVars--; }; chainUnprotect(problemPtr); } int constrainVariableSign(Problem *problemPtr, int color, int i, int sign) { int nV = nVars; int e, k, j; k = problemPtr->forwardingAddress[i]; if (k < 0) { k = -1 - k; if (sign != 0) { //e = nGEQ++; e = nGEQ; problemPtr->addNumGEqs(1); eqncpy(&GEQs[e], &SUBs[k]); for (j = 0; j <= nV; j++) GEQs[e].coef[j] *= sign; GEQs[e].coef[0]--; GEQs[e].touched = 1; GEQs[e].color = color; } else { //e = nEQ++; e = nEQ; problemPtr->addNumEqs(1); assert(nEQ <= maxEQs); eqncpy(&EQs[e], &SUBs[k]); EQs[e].color = color; }; } else if (sign != 0) { //e = nGEQ++; e = nGEQ; problemPtr->addNumGEqs(1); eqnzero(&GEQs[e]); GEQs[e].coef[k] = sign; GEQs[e].coef[0] = -1; GEQs[e].touched = 1; GEQs[e].color = color; } else { //e = nEQ++; e = nEQ; problemPtr->addNumEqs(1); assert(nEQ <= maxEQs); eqnzero(&EQs[e]); EQs[e].coef[k] = 1; EQs[e].color = color; }; unprotectVariable(problemPtr, i); return (simplifyProblem(problemPtr)); } void constrainVariableValue(Problem *problemPtr, int color, int i, int value) { int e, k; k = problemPtr->forwardingAddress[i]; if (k < 0) { k = -1 - k; //e = nEQ++; e = nEQ; problemPtr->addNumEqs(1); assert(nEQ <= maxEQs); eqncpy(&EQs[e], &SUBs[k]); EQs[e].coef[0] -= value; } else { //e = nEQ++; e = nEQ; problemPtr->addNumEqs(1); eqnzero(&EQs[e]); EQs[e].coef[k] = 1; EQs[e].coef[0] = -value; }; EQs[e].color = color; } int queryVariable(Problem *problemPtr, int i, int *lowerBound, int *upperBound) { int nV = nVars; int e, j; int isSimple; int coupled = FALSE; i = problemPtr->forwardingAddress[i]; (*lowerBound) = negInfinity; (*upperBound) = posInfinity; if (i < 0) { int easy = TRUE; i = -i - 1; for (j = 1; j <= nV; j++) if (SUBs[i].coef[j] != 0) easy = FALSE; if (easy) { *upperBound = *lowerBound = SUBs[i].coef[0]; return (FALSE); }; return (TRUE); }; for (e = nSUB - 1; e >= 0; e--) if (SUBs[e].coef[i] != 0) coupled = TRUE; for (e = nEQ - 1; e >= 0; e--) if (EQs[e].coef[i] != 0) { isSimple = TRUE; for (j = 1; j <= nV; j++) if (i != j && EQs[e].coef[j] != 0) { isSimple = FALSE; coupled = TRUE; break; }; if (!isSimple) continue; else { *lowerBound = *upperBound = -EQs[e].coef[i] * EQs[e].coef[0]; return (FALSE); }; }; for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[i] != 0) { if (GEQs[e].key == i) { setMax(*lowerBound, -GEQs[e].coef[0]); } else if (GEQs[e].key == -i) { setMin(*upperBound, GEQs[e].coef[0]); } else coupled = TRUE; }; return (coupled); } extern void queryCoupledVariable(Problem *problemPtr, int i, int *l, int *u, int *couldBeZero, int lowerBound, int upperBound); int queryVariableBounds(Problem *problemPtr, int i, int *l, int *u) { int coupled; *l = negInfinity; *u = posInfinity; coupled = queryVariable(problemPtr, i, l, u); if (!coupled || (nVars == 1 && problemPtr->forwardingAddress[i] == 1)) return 0; if (abs(problemPtr->forwardingAddress[i]) == 1 && nVars + nSUB == 2 && nEQ + nSUB == 1) { int couldBeZero; queryCoupledVariable(problemPtr, i, l, u, &couldBeZero, negInfinity, posInfinity); return 0; }; return 1; } void queryCoupledVariable(Problem *problemPtr, int i, int *l, int *u, int *couldBeZero, int lowerBound, int upperBound) { int e, b1, b2; Eqn eqn; int sign; int v; if (abs(problemPtr->forwardingAddress[i]) != 1 || nVars + nSUB != 2 || nEQ + nSUB != 1) { fprintf(outputFile, "queryCoupledVariablecalled with bad parameters\n"); printProblem(problemPtr); Exit(2); }; if (problemPtr->forwardingAddress[i] == -1) { eqn = &SUBs[0]; sign = 1; v = 1; } else { eqn = &EQs[0]; sign = -eqn->coef[1]; v = 2; }; /* Variable i is defined in terms of variable v */ for (e = nGEQ - 1; e >= 0; e--) if (GEQs[e].coef[v] != 0) { if (GEQs[e].coef[v] == 1) { setMax(lowerBound, -GEQs[e].coef[0]) } else { setMin(upperBound, GEQs[e].coef[0]); }; }; /* lowerBound and upperBound are bounds on the value of v */ if (lowerBound > upperBound) { *l = posInfinity; *u = negInfinity; *couldBeZero = 0; return; }; if (lowerBound == negInfinity) { if (eqn->coef[v] > 0) b1 = sign * negInfinity; else b1 = -sign * negInfinity; } else b1 = sign * (eqn->coef[0] + eqn->coef[v] * lowerBound); if (upperBound == posInfinity) { if (eqn->coef[v] > 0) b2 = sign * posInfinity; else b2 = -sign * posInfinity; } else b2 = sign * (eqn->coef[0] + eqn->coef[v] * upperBound); /* b1 and b2 are bounds on the value of i (don't know which is upper bound) */ if (b1 <= b2) { setMax(*l, b1); setMin(*u, b2); } else { setMax(*l, b2); setMin(*u, b1); }; *couldBeZero = *l <= 0 && 0 <= *u && intMod(eqn->coef[0], abs(eqn->coef[v])) == 0; } int queryVariableSigns(Problem *problemPtr, int i, int dd_lt, int dd_eq, int dd_gt, int lowerBound, int upperBound, bool *distKnown, int *dist) { int result; int l, u; int couldBeZero; l = negInfinity; u = posInfinity; queryCoupledVariable(problemPtr, i, &l, &u, &couldBeZero, lowerBound, upperBound); result = 0; if (l < 0) result |= dd_gt; if (u > 0) result |= dd_lt; if (couldBeZero) result |= dd_eq; if (l == u) { *distKnown = 1; *dist = l; } else *distKnown = 0; return (result); } static int omegaInitialized = 0; void initializeOmega() { int i; if (omegaInitialized) return; nextWildCard = 0; nextKey = maxVars + 1; for (i = 0; i < hashTableSize; i++) hashMaster[i].touched = -1; sprintf(wildName[1], "alpha"); sprintf(wildName[2], "beta"); sprintf(wildName[3], "gamma"); sprintf(wildName[4], "delta"); sprintf(wildName[5], "tau"); sprintf(wildName[6], "sigma"); sprintf(wildName[7], "chi"); sprintf(wildName[8], "omega"); sprintf(wildName[9], "pi"); sprintf(wildName[10], "ni"); sprintf(wildName[11], "Alpha"); sprintf(wildName[12], "Beta"); sprintf(wildName[13], "Gamma"); sprintf(wildName[14], "Delta"); sprintf(wildName[15], "Tau"); sprintf(wildName[16], "Sigma"); sprintf(wildName[17], "Chi"); sprintf(wildName[18], "Omega"); sprintf(wildName[19], "Pi"); omegaInitialized = 1; } void setOutputFile(FILE * file) { /* sets the file to which printProblem should send its output to "file" */ outputFile = file; } /* end setOutputFile(FILE *file) */