diff options
Diffstat (limited to 'omegalib/omega/src/omega_core')
-rw-r--r-- | omegalib/omega/src/omega_core/oc.cc | 754 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_eq.cc | 653 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_exp_kill.cc | 297 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_global.cc | 45 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_print.cc | 686 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_problems.cc | 198 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_query.cc | 478 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_quick_kill.cc | 775 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_simple.cc | 1373 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_solve.cc | 1378 | ||||
-rw-r--r-- | omegalib/omega/src/omega_core/oc_util.cc | 327 |
11 files changed, 6964 insertions, 0 deletions
diff --git a/omegalib/omega/src/omega_core/oc.cc b/omegalib/omega/src/omega_core/oc.cc new file mode 100644 index 0000000..0dc9b49 --- /dev/null +++ b/omegalib/omega/src/omega_core/oc.cc @@ -0,0 +1,754 @@ +/***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team + Copyright (C) 2005-2011 Chun Chen + All Rights Reserved. + + Purpose: + Simplify a problem. + + Notes: + + History: + 12/10/06 Improved gist function, by Chun Chen. +*****************************************************************************/ + +#include <omega/omega_core/oc_i.h> + +namespace omega { + +eqn SUBs[maxVars+1]; +Memory redMemory[maxVars+1]; + +int Problem::reduceProblem() { + int result; + checkVars(nVars+1); + assert(omegaInitialized); + if (nVars > nEQs + 3 * safeVars) + freeEliminations(safeVars); + + check(); + if (!mayBeRed && nSUBs == 0 && safeVars == 0) { + result = solve(OC_SOLVE_UNKNOWN); + nGEQs = 0; + nEQs = 0; + nSUBs = 0; + nMemories = 0; + if (!result) { + int e = newEQ(); + assert(e == 0); + eqnnzero(&EQs[0], nVars); + EQs[0].color = EQ_BLACK; + EQs[0].coef[0] = 1; + } + check(); + return result; + } + return solve(OC_SOLVE_SIMPLIFY); +} + + +int Problem::simplifyProblem(int verify, int subs, int redundantElimination) { + checkVars(nVars+1); + assert(omegaInitialized); + setInternals(); + check(); + if (!reduceProblem()) goto returnFalse; + if (verify) { + addingOuterEqualities++; + int r = verifyProblem(); + addingOuterEqualities--; + if (!r) goto returnFalse; + if (nEQs) { // found some equality constraints during verification + int numRed = 0; + if (mayBeRed) + for (int e = nGEQs - 1; e >= 0; e--) if (GEQs[e].color == EQ_RED) numRed++; + if (mayBeRed && nVars == safeVars && numRed == 1) + nEQs = 0; // discard them + else if (!reduceProblem()) { + assert(0 && "Added equality constraint to verified problem generates false"); + } + } + } + if (redundantElimination) { + if (redundantElimination > 1) { + if (!expensiveEqualityCheck()) goto returnFalse; + } + if (!quickKill(0)) goto returnFalse; + if (redundantElimination > 1) { + if (!expensiveKill()) goto returnFalse; + } + } + resurrectSubs(); + if (redundantElimination) + simplifyStrideConstraints(); + if (redundantElimination > 2 && safeVars < nVars) { + if (!quickKill(0)) goto returnFalse; + return simplifyProblem(verify, subs, redundantElimination-2); + } + setExternals(); + assert(nMemories == 0); + return (1); + +returnFalse: + nGEQs = 0; + nEQs = 0; + resurrectSubs(); + nGEQs = 0; + nEQs = 0; + int neweq = newEQ(); + assert(neweq == 0); + eqnnzero(&EQs[neweq], nVars); + EQs[neweq].color = EQ_BLACK; + EQs[neweq].coef[0] = 1; + nMemories = 0; + return 0; +} + +int Problem::simplifyApproximate(bool strides_allowed) { + int result; + checkVars(nVars+1); + assert(inApproximateMode == 0); + + inApproximateMode = 1; + inStridesAllowedMode = strides_allowed; + if (TRACE) + fprintf(outputFile, "Entering Approximate Mode [\n"); + + assert(omegaInitialized); + result = simplifyProblem(0,0,0); + + while (result && !strides_allowed && nVars > safeVars) { + int e; + for (e = nGEQs - 1; e >= 0; e--) + if (GEQs[e].coef[nVars]) deleteGEQ(e); + for (e = nEQs - 1; e >= 0; e--) + if (EQs[e].coef[nVars]) deleteEQ(e); + nVars--; + result = simplifyProblem(0,0,0); + } + + if (TRACE) + fprintf(outputFile, "] Leaving Approximate Mode\n"); + + assert(inApproximateMode == 1); + inApproximateMode=0; + inStridesAllowedMode = 0; + + assert(nMemories == 0); + return (result); +} + + + + +/* + * 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. + */ + +#ifdef GIST_CHECK +Problem full_answer, context; +Problem redProblem; +#endif + +redCheck Problem::redSimplifyProblem(int effort, int computeGist) { + int result; + int e; + + checkVars(nVars+1); + assert(mayBeRed >= 0); + mayBeRed++; + + assert(omegaInitialized); + if (TRACE) { + fprintf(outputFile, "Checking for red equations:\n"); + printProblem(); + } + setInternals(); + +#ifdef GIST_CHECK + int r1,r2; + if (TRACE) + fprintf(outputFile,"Set-up for gist invariant checking[\n"); + redProblem = *this; + redProblem.check(); + full_answer = *this; + full_answer.check(); + full_answer.turnRedBlack(); + full_answer.check(); + r1 = full_answer.simplifyProblem(1,0,1); + full_answer.check(); + if (DBUG) fprintf(outputFile,"Simplifying context [\n"); + context = *this; + context.check(); + context.deleteRed(); + context.check(); + r2 = context.simplifyProblem(1,0,1); + context.check(); + if (DBUG) fprintf(outputFile,"] Simplifying context\n"); + + if (!r2 && TRACE) fprintf(outputFile, "WARNING: Gist context is false!\n"); + if (TRACE) + fprintf(outputFile,"] Set-up for gist invariant checking done\n"); +#endif + + // Save known integer modular equations, -- by chun 12/10/2006 + eqn ModularEQs[nEQs]; + int nModularEQs = 0; + int old_nVars = nVars; + for (int e = 0; e < nEQs; e++) + if (EQs[e].color != EQ_RED) + for (int i = safeVars+1; i <= nVars; i++) + if (EQs[e].coef[i] != 0) { + eqnncpy(&(ModularEQs[nModularEQs++]), &(EQs[e]), nVars); + break; + } + + + if (solveEQ() == false) { + if (TRACE) + fprintf(outputFile, "Gist is FALSE\n"); + if (computeGist) { + nMemories = 0; + nGEQs = 0; + nEQs = 0; + resurrectSubs(); + nGEQs = 0; + nEQs = 0; + int neweq = newEQ(); + assert(neweq == 0); + eqnnzero(&EQs[neweq], nVars); + EQs[neweq].color = EQ_RED; + EQs[neweq].coef[0] = 1; + } + mayBeRed--; + return redFalse; + } + + if (!computeGist && nMemories) + return redConstraints; + if (normalize() == normalize_false) { + if (TRACE) + fprintf(outputFile, "Gist is FALSE\n"); + if (computeGist) { + nGEQs = 0; + nEQs = 0; + resurrectSubs(); + nMemories = 0; + nGEQs = 0; + nEQs = 0; + int neweq = newEQ(); + assert(neweq == 0); + eqnnzero(&EQs[neweq], nVars); + EQs[neweq].color = EQ_RED; + EQs[neweq].coef[0] = 1; + } + mayBeRed--; + return redFalse; + } + + result = 0; + for (e = nGEQs - 1; e >= 0; e--) if (GEQs[e].color == EQ_RED) result = 1; + for (e = nEQs - 1; e >= 0; e--) if (EQs[e].color == EQ_RED) result = 1; + if (nMemories) result = 1; + if (!result) { + if (computeGist) { + nGEQs = 0; + nEQs = 0; + resurrectSubs(); + nGEQs = 0; + nMemories = 0; + nEQs = 0; + } + mayBeRed--; + return noRed; + } + + result = simplifyProblem(effort?1:0,1,0); +#ifdef GIST_CHECK + if (!r1 && TRACE && result) + fprintf(outputFile, "Gist is False but not detected\n"); +#endif + if (!result) { + if (TRACE) + fprintf(outputFile, "Gist is FALSE\n"); + if (computeGist) { + nGEQs = 0; + nEQs = 0; + resurrectSubs(); + nGEQs = 0; + nEQs = 0; + int neweq = newEQ(); + assert(neweq == 0); + nMemories = 0; + eqnnzero(&EQs[neweq], nVars); + EQs[neweq].color = EQ_RED; + EQs[neweq].coef[0] = 1; + } + mayBeRed--; + return redFalse; + } + + freeRedEliminations(); + + result = 0; + for (e = nGEQs - 1; e >= 0; e--) if (GEQs[e].color == EQ_RED) result = 1; + for (e = nEQs - 1; e >= 0; e--) if (EQs[e].color == EQ_RED) result = 1; + if (nMemories) result = 1; + if (!result) { + if (computeGist) { + nGEQs = 0; + nEQs = 0; + resurrectSubs(); + nGEQs = 0; + nMemories = 0; + nEQs = 0; + } + mayBeRed--; + return noRed; + } + + if (effort && (computeGist || !nMemories)) { + if (TRACE) + fprintf(outputFile, "*** Doing potentially expensive elimination tests for red equations [\n"); + quickRedKill(computeGist); + checkGistInvariant(); + result = nMemories; + for (e = nGEQs - 1; e >= 0; e--) if (GEQs[e].color == EQ_RED) result++; + for (e = nEQs - 1; e >= 0; e--) if (EQs[e].color == EQ_RED) result++; + if (result && effort > 1 && (computeGist || !nMemories)) { + expensiveRedKill(); + result = nMemories; + for (e = nGEQs-1; e >= 0; e--) if (GEQs[e].color == EQ_RED) result++; + for (e = nEQs-1; e >= 0; e--) if (EQs[e].color == EQ_RED) result++; + } + + if (!result) { + if (TRACE) + fprintf(outputFile, "]******************** Redudant Red Equations eliminated!!\n"); + if (computeGist) { + nGEQs = 0; + nEQs = 0; + resurrectSubs(); + nGEQs = 0; + nMemories = 0; + nEQs = 0; + } + mayBeRed--; + return noRed; + } + + if (TRACE) fprintf(outputFile, "]******************** Red Equations remain\n"); + if (DEBUG) printProblem(); + } + + if (computeGist) { + resurrectSubs(); + cleanoutWildcards(); + + + // Restore saved modular equations into EQs without affecting the problem + if (nEQs+nModularEQs > allocEQs) { + allocEQs = padEQs(allocEQs, nEQs+nModularEQs); + eqn *new_eqs = new eqn[allocEQs]; + for (int e = 0; e < nEQs; e++) + eqnncpy(&(new_eqs[e]), &(EQs[e]), nVars); + delete[] EQs; + EQs= new_eqs; + } + + for (int e = 0; e < nModularEQs; e++) { + eqnncpy(&(EQs[nEQs+e]), &(ModularEQs[e]), old_nVars); + EQs[nEQs+e].color = EQ_RED; + Tuple<coef_t> t(safeVars); + for (int i = 1; i <= safeVars; i++) + t[i] = ModularEQs[e].coef[var[i]]; + for (int i = 1; i <= safeVars; i++) + EQs[nEQs+e].coef[i] = t[i]; + } + + + // Now simplify modular equations using Chinese remainder theorem -- by chun 12/10/2006 + for (int e = 0; e < nEQs; e++) + if (EQs[e].color == EQ_RED) { + int wild_pos = -1; + for (int i = safeVars+1; i <= nVars; i++) + if (EQs[e].coef[i] != 0) { + wild_pos = i; + break; + } + + if (wild_pos == -1) + continue; + + for (int e2 = e+1; e2 < nEQs+nModularEQs; e2++) + if (EQs[e2].color == EQ_RED) { + int wild_pos2 = -1; + for (int i = safeVars+1; i <= ((e2<nEQs)?nVars:old_nVars); i++) + if (EQs[e2].coef[i] != 0) { + wild_pos2 = i; + break; + } + + if (wild_pos2 == -1) + continue; + + coef_t g = gcd(abs(EQs[e].coef[wild_pos]), abs(EQs[e2].coef[wild_pos2])); + coef_t g2 = 1; + coef_t g3; + EQs[e].color = EQs[e2].color = EQ_BLACK; + while ((g3 = factor(g)) != 1) { + coef_t gg = g2 * g3; + g = g/g3; + + bool match = true; + coef_t c = EQs[e].coef[0]; + coef_t c2 = EQs[e2].coef[0]; + bool change_sign = false; + for (int i = 1; i <= safeVars; i++) { + coef_t coef = int_mod_hat(EQs[e].coef[i], gg); + coef_t coef2 = int_mod_hat(EQs[e2].coef[i], gg); + + if (coef == 0 && coef2 == 0) + continue; + + if (change_sign && coef == -coef2) + continue; + + if (!change_sign) { + if (coef == coef2) + continue; + else if (coef == -coef2) { + change_sign = true; + continue; + } + } + + if (coef != 0) { + coef_t t = query_variable_mod(i, gg/gcd(abs(coef), gg), EQ_RED, nModularEQs, old_nVars); + if (t == posInfinity) { + match = false; + break; + } + + c += coef * t; + } + if (coef2 != 0) { + coef_t t = query_variable_mod(i, gg/gcd(abs(coef2), gg), EQ_RED, nModularEQs, old_nVars); + if (t == posInfinity) { + match = false; + break; + } + + c2 += coef2 * t; + } + } + if ((change_sign && int_mod_hat(c, gg) != -int_mod_hat(c2, gg)) || + (!change_sign && int_mod_hat(c, gg) != int_mod_hat(c2, gg))) + match = false; + + if (match) + g2 = gg; + } + EQs[e].color = EQs[e2].color = EQ_RED; + + if (g2 == 1) + continue; + + if (g2 == abs(EQs[e].coef[wild_pos])) { + EQs[e].color = EQ_BLACK; + break; + } + else if (e2 < nEQs && g2 == abs(EQs[e2].coef[wild_pos2])) + EQs[e2].color = EQ_BLACK; + else { + coef_t g4 = abs(EQs[e].coef[wild_pos])/g2; + while (lcm(g2, g4) != abs(EQs[e].coef[wild_pos])) { + assert(lcm(g2, g4) < abs(EQs[e].coef[wild_pos])); + g4 *= abs(EQs[e].coef[wild_pos])/lcm(g2, g4); + } + + for (int i = 0; i <= safeVars; i++) + EQs[e].coef[i] = int_mod_hat(EQs[e].coef[i], g4); + EQs[e].coef[wild_pos] = (EQs[e].coef[wild_pos]>0?1:-1)*g4; + } + } + } + + deleteBlack(); + } + + setExternals(); + mayBeRed--; + assert(nMemories == 0); + return redConstraints; +} + + +void Problem::convertEQstoGEQs(bool excludeStrides) { + int i; + int e; + if (DBUG) + fprintf(outputFile, "Converting all EQs to GEQs\n"); + simplifyProblem(0,0,0); + for(e=0;e<nEQs;e++) { + bool isStride = 0; + int e2 = newGEQ(); + if (excludeStrides) + for(i = safeVars+1; i <= nVars; i++) + isStride = isStride || (EQs[e].coef[i] != 0); + if (isStride) continue; + eqnncpy(&GEQs[e2], &EQs[e], nVars); + GEQs[e2].touched = 1; + e2 = newGEQ(); + eqnncpy(&GEQs[e2], &EQs[e], nVars); + GEQs[e2].touched = 1; + for (i = 0; i <= nVars; i++) + GEQs[e2].coef[i] = -GEQs[e2].coef[i]; + } + // If we have eliminated all EQs, can set nEQs to 0 + // If some strides are left, we don't know the position of them in the EQs + // array, so decreasing nEQs might remove wrong EQs -- we just leave them + // all in. (could sort the EQs to move strides to the front, but too hard.) + if (!excludeStrides) nEQs=0; + if (DBUG) + printProblem(); +} + + +void Problem::convertEQtoGEQs(int eq) { + int i; + if (DBUG) + fprintf(outputFile, "Converting EQ %d to GEQs\n",eq); + int e2 = newGEQ(); + eqnncpy(&GEQs[e2], &EQs[eq], nVars); + GEQs[e2].touched = 1; + e2 = newGEQ(); + eqnncpy(&GEQs[e2], &EQs[eq], nVars); + GEQs[e2].touched = 1; + for (i = 0; i <= nVars; i++) + GEQs[e2].coef[i] = -GEQs[e2].coef[i]; + if (DBUG) + printProblem(); +} + + +/* + * Calculate value of variable modulo integer from problem's equation + * set plus additional saved modular equations embedded in the same + * EQs array (hinted by nModularEQs) if available. If there is no + * solution, return posInfinity. + */ +coef_t Problem::query_variable_mod(int v, coef_t factor, int color, int nModularEQs, int nModularVars) const { + if (safeVars < v) + return posInfinity; + + Tuple<bool> working_on(safeVars); + for (int i = 1; i <= safeVars; i++) + working_on[i] = false; + + return query_variable_mod(v, factor, color, nModularEQs, nModularVars, working_on); +} + +coef_t Problem::query_variable_mod(int v, coef_t factor, int color, int nModularEQs, int nModularVars, Tuple<bool> &working_on) const { + working_on[v] = true; + + for (int e = 0; e < nEQs+nModularEQs; e++) + if (EQs[e].color == color) { + coef_t coef = int_mod_hat(EQs[e].coef[v], factor); + if (abs(coef) != 1) + continue; + + bool wild_factored = true; + for (int i = safeVars+1; i <= ((e<nEQs)?nVars:nModularVars); i++) + if (int_mod_hat(EQs[e].coef[i], factor) != 0) { + wild_factored = false; + break; + } + if (!wild_factored) + continue; + + coef_t result = 0; + for (int i = 1; i <= safeVars; i++) + if (i != v) { + coef_t p = int_mod_hat(EQs[e].coef[i], factor); + + if (p == 0) + continue; + + if (working_on[i] == true) { + result = posInfinity; + break; + } + + coef_t q = query_variable_mod(i, factor, color, nModularEQs, nModularVars, working_on); + if (q == posInfinity) { + result = posInfinity; + break; + } + result += p*q; + } + + if (result != posInfinity) { + result += EQs[e].coef[0]; + if (coef == 1) + result = -result; + working_on[v] = false; + + return int_mod_hat(result, factor); + } + } + + working_on[v] = false; + return posInfinity; +} + + + +#ifdef GIST_CHECK +enum compareAnswer {apparentlyEqual, mightNotBeEqual, NotEqual}; + +static compareAnswer checkEquiv(Problem *p1, Problem *p2) { + int r1,r2; + + p1->check(); + p2->check(); + p1->resurrectSubs(); + p2->resurrectSubs(); + p1->check(); + p2->check(); + p1->putVariablesInStandardOrder(); + p2->putVariablesInStandardOrder(); + p1->check(); + p2->check(); + p1->ordered_elimination(0); + p2->ordered_elimination(0); + p1->check(); + p2->check(); + r1 = p1->simplifyProblem(1,1,0); + r2 = p2->simplifyProblem(1,1,0); + p1->check(); + p2->check(); + + if (!r1 || !r2) { + if (r1 == r2) return apparentlyEqual; + return NotEqual; + } + if (p1->nVars != p2->nVars + || p1->nGEQs != p2->nGEQs + || p1->nSUBs != p2->nSUBs + || p1->checkSum() != p2->checkSum()) { + r1 = p1->simplifyProblem(0,1,1); + r2 = p2->simplifyProblem(0,1,1); + assert(r1 && r2); + p1->check(); + p2->check(); + if (p1->nVars != p2->nVars + || p1->nGEQs != p2->nGEQs + || p1->nSUBs != p2->nSUBs + || p1->checkSum() != p2->checkSum()) { + r1 = p1->simplifyProblem(0,1,2); + r2 = p2->simplifyProblem(0,1,2); + p1->check(); + p2->check(); + assert(r1 && r2); + if (p1->nVars != p2->nVars + || p1->nGEQs != p2->nGEQs + || p1->nSUBs != p2->nSUBs + || p1->checkSum() != p2->checkSum()) { + p1->check(); + p2->check(); + p1->resurrectSubs(); + p2->resurrectSubs(); + p1->check(); + p2->check(); + p1->putVariablesInStandardOrder(); + p2->putVariablesInStandardOrder(); + p1->check(); + p2->check(); + p1->ordered_elimination(0); + p2->ordered_elimination(0); + p1->check(); + p2->check(); + r1 = p1->simplifyProblem(1,1,0); + r2 = p2->simplifyProblem(1,1,0); + p1->check(); + p2->check(); + } + } + } + + if (p1->nVars != p2->nVars + || p1->nSUBs != p2->nSUBs + || p1->nGEQs != p2->nGEQs + || p1->nSUBs != p2->nSUBs) return NotEqual; + if (p1->checkSum() != p2->checkSum()) return mightNotBeEqual; + return apparentlyEqual; +} +#endif + +void Problem::checkGistInvariant() const { +#ifdef GIST_CHECK + Problem new_answer; + int r; + + check(); + fullAnswer.check(); + context.check(); + + if (safeVars < nVars) { + if (DBUG) { + fprintf(outputFile,"Can't check gist invariant due to wildcards\n"); + printProblem(); + } + return; + } + if (DBUG) { + fprintf(outputFile,"Checking gist invariant on: [\n"); + printProblem(); + } + + new_answer = *this; + new_answer->resurrectSubs(); + new_answer->cleanoutWildcards(); + if (DEBUG) { + fprintf(outputFile,"which is: \n"); + printProblem(); + } + deleteBlack(&new_answer); + turnRedBlack(&new_answer); + if (DEBUG) { + fprintf(outputFile,"Black version of answer: \n"); + printProblem(&new_answer); + } + problem_merge(&new_answer,&context); + + r = checkEquiv(&full_answer,&new_answer); + if (r != apparentlyEqual) { + fprintf(outputFile,"GIST INVARIANT REQUIRES MANUAL CHECK:[\n"); + fprintf(outputFile,"Original problem:\n"); + printProblem(&redProblem); + + fprintf(outputFile,"Context:\n"); + printProblem(&context); + + fprintf(outputFile,"Computed gist:\n"); + printProblem(); + + fprintf(outputFile,"Combined answer:\n"); + printProblem(&full_answer); + + fprintf(outputFile,"Context && red constraints:\n"); + printProblem(&new_answer); + fprintf(outputFile,"]\n"); + } + + if (DBUG) { + fprintf(outputFile,"] Done checking gist invariant on\n"); + } +#endif +} + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_eq.cc b/omegalib/omega/src/omega_core/oc_eq.cc new file mode 100644 index 0000000..dc595ea --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_eq.cc @@ -0,0 +1,653 @@ +/***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team + Copyright (C) 2005-2011 Chun Chen + All Rights Reserved. + + Purpose: + Solve equalities. + + Notes: + + History: + *****************************************************************************/ + +#include <omega/omega_core/oc_i.h> + +namespace omega { + +void Problem::simplifyStrideConstraints() { + int e, e2, i; + if (DBUG) + fprintf(outputFile, "Checking for stride constraints\n"); + for (i = safeVars + 1; i <= nVars; i++) { + if (DBUG) + fprintf(outputFile, "checking %s\n", variable(i)); + for (e = 0; e < nGEQs; e++) + if (GEQs[e].coef[i]) + break; + if (e >= nGEQs) { + if (DBUG) + fprintf(outputFile, "%s passed GEQ test\n", variable(i)); + e2 = -1; + for (e = 0; e < nEQs; e++) + if (EQs[e].coef[i]) { + if (e2 == -1) + e2 = e; + else { + e2 = -1; + break; + } + } + if (e2 >= 0) { + if (DBUG) { + fprintf(outputFile, "Found stride constraint: "); + printEQ(&EQs[e2]); + fprintf(outputFile, "\n"); + } + /* Is a stride constraint */ + coef_t g = abs(EQs[e2].coef[i]); + assert(g>0); + int j; + for (j = 0; j <= nVars; j++) + if (i != j) + EQs[e2].coef[j] = int_mod_hat(EQs[e2].coef[j], g); + } + } + } +} + +void Problem::doMod(coef_t factor, int e, int j) { + /* Solve e = factor alpha for x_j and substitute */ + int k; + eqn eq; + coef_t nFactor; + + int alpha; + + // if (j > safeVars) alpha = j; + // else + if (EQs[e].color) { + rememberRedConstraint(&EQs[e], redEQ, 0); + EQs[e].color = EQ_BLACK; + } + alpha = addNewUnprotectedWildcard(); + eqnncpy(&eq, &EQs[e], nVars); + newVar = alpha; + + if (DEBUG) { + fprintf(outputFile, "doing moding: "); + fprintf(outputFile, "Solve "); + printTerm(&eq, 1); + fprintf(outputFile, " = " coef_fmt " %s for %s and substitute\n", + factor, variable(alpha), variable(j)); + } + for (k = nVars; k >= 0; k--) + eq.coef[k] = int_mod_hat(eq.coef[k], factor); + nFactor = eq.coef[j]; + assert(nFactor == 1 || nFactor == -1); + eq.coef[alpha] = factor / nFactor; + if (DEBUG) { + fprintf(outputFile, "adjusted: "); + fprintf(outputFile, "Solve "); + printTerm(&eq, 1); + fprintf(outputFile, " = 0 for %s and substitute\n", variable(j)); + } + + eq.coef[j] = 0; + substitute(&eq, j, nFactor); + newVar = -1; + deleteVariable(j); + for (k = nVars; k >= 0; k--) { + assert(EQs[e].coef[k] % factor == 0); + EQs[e].coef[k] = EQs[e].coef[k] / factor; + } + if (DEBUG) { + fprintf(outputFile, "Mod-ing and normalizing produces:\n"); + printProblem(); + } +} + +void Problem::substitute(eqn *sub, int i, coef_t c) { + int e, j; + coef_t k; + int recordSubstitution = (i <= safeVars && var[i] >= 0); + + redType clr; + if (sub->color) + clr = redEQ; + else + clr = notRed; + + assert(c == 1 || c == -1); + + if (DBUG || doTrace) { + if (sub->color) + fprintf(outputFile, "RED SUBSTITUTION\n"); + fprintf(outputFile, "substituting using %s := ", variable(i)); + printTerm(sub, -c); + fprintf(outputFile, "\n"); + printVars(); + } +#ifndef NDEBUG + if (i > safeVars && clr) { + bool unsafeSub = false; + for (e = nEQs - 1; e >= 0; e--) + if (!(EQs[e].color || !EQs[e].coef[i])) + unsafeSub = true; + for (e = nGEQs - 1; e >= 0; e--) + if (!(GEQs[e].color || !GEQs[e].coef[i])) + unsafeSub = true; + for (e = nSUBs - 1; e >= 0; e--) + if (SUBs[e].coef[i]) + unsafeSub = true; + if (unsafeSub) { + fprintf(outputFile, "UNSAFE RED SUBSTITUTION\n"); + fprintf(outputFile, "substituting using %s := ", variable(i)); + printTerm(sub, -c); + fprintf(outputFile, "\n"); + printProblem(); + assert(0 && "UNSAFE RED SUBSTITUTION"); + } + } +#endif + + for (e = nEQs - 1; e >= 0; e--) { + eqn *eq; + eq = &(EQs[e]); + k = eq->coef[i]; + if (k != 0) { + k = check_mul(k, c); // Should be k = k/c, but same effect since abs(c) == 1 + eq->coef[i] = 0; + for (j = nVars; j >= 0; j--) { + eq->coef[j] -= check_mul(sub->coef[j], k); + } + } + if (DEBUG) { + printEQ(eq); + fprintf(outputFile, "\n"); + } + } + for (e = nGEQs - 1; e >= 0; e--) { + int zero; + eqn *eq; + eq = &(GEQs[e]); + k = eq->coef[i]; + if (k != 0) { + k = check_mul(k, c); // Should be k = k/c, but same effect since abs(c) == 1 + eq->touched = true; + eq->coef[i] = 0; + zero = 1; + for (j = nVars; j >= 0; j--) { + eq->coef[j] -= check_mul(sub->coef[j], k); + if (j > 0 && eq->coef[j]) + zero = 0; + } + if (zero && clr != notRed && !eq->color) { + coef_t z = int_div(eq->coef[0], abs(k)); + if (DBUG || doTrace) { + fprintf(outputFile, + "Black inequality matches red substitution\n"); + if (z < 0) + fprintf(outputFile, "System is infeasible\n"); + else if (z > 0) + fprintf(outputFile, "Black inequality is redundant\n"); + else { + fprintf(outputFile, + "Black constraint partially implies red equality\n"); + if (k < 0) { + fprintf(outputFile, "Black constraints tell us "); + assert(sub->coef[i] == 0); + sub->coef[i] = c; + printTerm(sub, 1); + sub->coef[i] = 0; + fprintf(outputFile, "<= 0\n"); + } else { + fprintf(outputFile, "Black constraints tell us "); + assert(sub->coef[i] == 0); + sub->coef[i] = c; + printTerm(sub, 1); + sub->coef[i] = 0; + fprintf(outputFile, " >= 0\n"); + } + } + } + if (z == 0) { + if (k < 0) { + if (clr == redEQ) + clr = redGEQ; + else if (clr == redLEQ) + clr = notRed; + } else { + if (clr == redEQ) + clr = redLEQ; + else if (clr == redGEQ) + clr = notRed; + } + } + + } + } + if (DEBUG) { + printGEQ(eq); + fprintf(outputFile, "\n"); + } + } + if (i <= safeVars && clr) { + assert(sub->coef[i] == 0); + sub->coef[i] = c; + rememberRedConstraint(sub, clr, 0); + sub->coef[i] = 0; + } + + if (recordSubstitution) { + int s = nSUBs++; + int kk; + eqn *eq = &(SUBs[s]); + for (kk = nVars; kk >= 0; kk--) + eq->coef[kk] = check_mul(-c, (sub->coef[kk])); + eq->key = var[i]; + if (DEBUG) { + fprintf(outputFile, "Recording substition as: "); + printSubstitution(s); + fprintf(outputFile, "\n"); + } + } + if (DEBUG) { + fprintf(outputFile, "Ready to update subs\n"); + if (sub->color) + fprintf(outputFile, "RED SUBSTITUTION\n"); + fprintf(outputFile, "substituting using %s := ", variable(i)); + printTerm(sub, -c); + fprintf(outputFile, "\n"); + printVars(); + } + + for (e = nSUBs - 1; e >= 0; e--) { + eqn *eq = &(SUBs[e]); + k = eq->coef[i]; + if (k != 0) { + k = check_mul(k, c); // Should be k = k/c, but same effect since abs(c) == 1 + eq->coef[i] = 0; + for (j = nVars; j >= 0; j--) { + eq->coef[j] -= check_mul(sub->coef[j], k); + } + } + if (DEBUG) { + fprintf(outputFile, "updated sub (" coef_fmt "): ", c); + printSubstitution(e); + fprintf(outputFile, "\n"); + } + } + + if (DEBUG) { + fprintf(outputFile, "---\n\n"); + printProblem(); + fprintf(outputFile, "===\n\n"); + } +} + + +void Problem::doElimination(int e, int i) { + if (DBUG || doTrace) + fprintf(outputFile, "eliminating variable %s\n", variable(i)); + + eqn sub; + eqnncpy(&sub, &EQs[e], nVars); + coef_t c = sub.coef[i]; + sub.coef[i] = 0; + + if (c == 1 || c == -1) { + substitute(&sub, i, c); + } else { + coef_t a = abs(c); + if (TRACE) + fprintf(outputFile, + "performing non-exact elimination, c = " coef_fmt "\n", c); + if (DBUG) + printProblem(); + assert(inApproximateMode); + + for (int e2 = nEQs - 1; e2 >= 0; e2--) { + eqn *eq = &(EQs[e2]); + coef_t k = eq->coef[i]; + if (k != 0) { + coef_t l = lcm(abs(k), a); + coef_t scale1 = l / abs(k); + for (int j = nVars; j >= 0; j--) + eq->coef[j] = check_mul(eq->coef[j], scale1); + eq->coef[i] = 0; + coef_t scale2 = l / c; + if (k < 0) + scale2 = -scale2; + for (int j = nVars; j >= 0; j--) + eq->coef[j] -= check_mul(sub.coef[j], scale2); + eq->color |= sub.color; + } + } + for (int e2 = nGEQs - 1; e2 >= 0; e2--) { + eqn *eq = &(GEQs[e2]); + coef_t k = eq->coef[i]; + if (k != 0) { + coef_t l = lcm(abs(k), a); + coef_t scale1 = l / abs(k); + for (int j = nVars; j >= 0; j--) + eq->coef[j] = check_mul(eq->coef[j], scale1); + eq->coef[i] = 0; + coef_t scale2 = l / c; + if (k < 0) + scale2 = -scale2; + for (int j = nVars; j >= 0; j--) + eq->coef[j] -= check_mul(sub.coef[j], scale2); + eq->color |= sub.color; + eq->touched = 1; + } + } + for (int e2 = nSUBs - 1; e2 >= 0; e2--) + if (SUBs[e2].coef[i]) { + eqn *eq = &(EQs[e2]); + assert(0); + // We can't handle this since we can't multiply + // the coefficient of the left-hand side + assert(!sub.color); + for (int j = nVars; j >= 0; j--) + eq->coef[j] = check_mul(eq->coef[j], a); + coef_t k = eq->coef[i]; + eq->coef[i] = 0; + for (int j = nVars; j >= 0; j--) + eq->coef[j] -= check_mul(sub.coef[j], k / c); + } + } + deleteVariable(i); +} + +int Problem::solveEQ() { + check(); + + // Reorder equations according to complexity. + { + int delay[nEQs]; + + for (int e = 0; e < nEQs; e++) { + delay[e] = 0; + if (EQs[e].color) + delay[e] += 8; + int nonunitWildCards = 0; + int unitWildCards = 0; + for (int i = nVars; i > safeVars; i--) + if (EQs[e].coef[i]) { + if (EQs[e].coef[i] == 1 || EQs[e].coef[i] == -1) + unitWildCards++; + else + nonunitWildCards++; + } + int unit = 0; + int nonUnit = 0; + for (int i = safeVars; i > 0; i--) + if (EQs[e].coef[i]) { + if (EQs[e].coef[i] == 1 || EQs[e].coef[i] == -1) + unit++; + else + nonUnit++; + } + if (unitWildCards == 1 && nonunitWildCards == 0) + delay[e] += 0; + else if (unitWildCards >= 1 && nonunitWildCards == 0) + delay[e] += 1; + else if (inApproximateMode && nonunitWildCards > 0) + delay[e] += 2; + else if (unit == 1 && nonUnit == 0 && nonunitWildCards == 0) + delay[e] += 3; + else if (unit > 1 && nonUnit == 0 && nonunitWildCards == 0) + delay[e] += 4; + else if (unit >= 1 && nonunitWildCards <= 1) + delay[e] += 5; + else + delay[e] += 6; + } + + for (int e = 0; e < nEQs; e++) { + int e2, slowest; + slowest = e; + for (e2 = e + 1; e2 < nEQs; e2++) + if (delay[e2] > delay[slowest]) + slowest = e2; + if (slowest != e) { + int tmp = delay[slowest]; + delay[slowest] = delay[e]; + delay[e] = tmp; + eqn eq; + eqnncpy(&eq, &EQs[slowest], nVars); + eqnncpy(&EQs[slowest], &EQs[e], nVars); + eqnncpy(&EQs[e], &eq, nVars); + } + } + } + + // Eliminate all equations. + while (nEQs != 0) { + int e = nEQs - 1; + eqn *eq = &(EQs[e]); + coef_t g, g2; + + assert(mayBeRed || !eq->color); + + check(); + + // get gcd of coefficients of all unprotected variables + g2 = 0; + for (int i = nVars; i > safeVars; i--) + if (eq->coef[i] != 0) { + g2 = gcd(abs(eq->coef[i]), g2); + if (g2 == 1) + break; + } + + // get gcd of coefficients of all variables + g = g2; + if (g != 1) + for (int i = safeVars; i >= 1; i--) + if (eq->coef[i] != 0) { + g = gcd(abs(eq->coef[i]), g); + if (g == 1) + break; + } + + // approximate mode bypass integer modular test; in Farkas(), + // existential variable lambda's are rational numbers. + if (inApproximateMode && g2 != 0) + g = gcd(abs(eq->coef[0]), g); + + // simple test to see if the equation is satisfiable + if (g == 0) { + if (eq->coef[0] != 0) { + return (false); + } else { + nEQs--; + continue; + } + } else if (abs(eq->coef[0]) % g != 0) { + return (false); + } + + // set gcd of all coefficients to 1 + if (g != 1) { + for (int i = nVars; i >= 0; i--) + eq->coef[i] /= g; + g2 = g2 / g; + } + + // exact elimination of unit coefficient variable + if (g2 != 0) { // for constraint with unprotected variable + int i; + for (i = nVars; i > safeVars; i--) + if (abs(eq->coef[i]) == 1) + break; + if (i > safeVars) { + nEQs--; + doElimination(e, i); + continue; + } + } else { // for constraint without unprotected variable + + // pick the unit coefficient variable with complex inequalites + // to eliminate, this will make inequalities tighter. e.g. + // {[t4,t6,t10]:exists (alpha: 0<=t6<=3 && t10=4alpha+t6 && + // 64t4<=t10<=64t4+15)} + int unit_var; + int cost = -1; + + for (int i = safeVars; i > 0; i--) + + if (abs(eq->coef[i]) == 1) { + int cur_cost = 0; + for (int j = 0; j < nGEQs; j++) + if (GEQs[j].coef[i] != 0) { + for (int k = safeVars; k > 0; k--) + if (GEQs[j].coef[k] != 0) { + if (abs(GEQs[j].coef[k]) != 1){ + + cur_cost += 3; + + } + else + cur_cost += 1; + } + } + + if (cur_cost > cost) { + cost = cur_cost; + unit_var = i; + } + + } + + if (cost != -1) { + nEQs--; + doElimination(e, unit_var); + continue; + } + + + } + + // check if there is an unprotected variable as wildcard + if (g2 > 0) { + int pos = 0; + coef_t g3; + for (int k = nVars; k > safeVars; k--) + if (eq->coef[k] != 0) { + int e2; + for (e2 = e - 1; e2 >= 0; e2--) + if (EQs[e2].coef[k]) + break; + if (e2 >= 0) + continue; + for (e2 = nGEQs - 1; e2 >= 0; e2--) + if (GEQs[e2].coef[k]) + break; + if (e2 >= 0) + continue; + for (e2 = nSUBs - 1; e2 >= 0; e2--) + if (SUBs[e2].coef[k]) + break; + if (e2 >= 0) + continue; + + if (pos == 0) { + g3 = abs(eq->coef[k]); + pos = k; + } else { + if (abs(eq->coef[k]) < g3) { + g3 = abs(eq->coef[k]); + pos = k; + } + } + } + + if (pos != 0) { + bool change = false; + for (int k2 = nVars; k2 >= 0; k2--) + if (k2 != pos && eq->coef[k2] != 0) { + coef_t t = int_mod_hat(eq->coef[k2], g3); + if (t != eq->coef[k2]) { + eq->coef[k2] = t; + change = true; + } + } + + // strength reduced, try this equation again + if (change) { + // nameWildcard(pos); + continue; + } + } + } + + // insert new stride constraint + if (g2 > 1 && !(inApproximateMode && !inStridesAllowedMode)) { + int newvar = addNewProtectedWildcard(); + int neweq = newEQ(); + assert(neweq == e+1); + // we were working on highest-numbered EQ + eqnnzero(&EQs[neweq], nVars); + eqnncpy(&EQs[neweq], eq, safeVars); + + for (int k = nVars; k >= 0; k--) { + EQs[neweq].coef[k] = int_mod_hat(EQs[neweq].coef[k], g2); + } + if (EQs[e].color) + rememberRedConstraint(&EQs[neweq], redStride, g2); + EQs[neweq].coef[newvar] = g2; + EQs[neweq].color = EQ_BLACK; + continue; + } + + // inexact elimination of unprotected variable + if (g2 > 0 && inApproximateMode) { + int pos = 0; + for (int k = nVars; k > safeVars; k--) + if (eq->coef[k] != 0) { + pos = k; + break; + } + assert(pos > safeVars); + + // special handling for wildcard used in breaking down + // diophantine equation + if (abs(eq->coef[pos]) > 1) { + int e2; + for (e2 = nSUBs - 1; e2 >= 0; e2--) + if (SUBs[e2].coef[pos]) + break; + if (e2 >= 0) { + protectWildcard(pos); + continue; + } + } + + nEQs--; + doElimination(e, pos); + continue; + } + + // now solve linear diophantine equation using least remainder + // algorithm + { + coef_t factor = (posInfinity); // was MAXINT + int pos = 0; + for (int k = nVars; k > (g2 > 0 ? safeVars : 0); k--) + if (eq->coef[k] != 0 && factor > abs(eq->coef[k]) + 1) { + factor = abs(eq->coef[k]) + 1; + pos = k; + } + assert(pos > (g2>0?safeVars:0)); + doMod(factor, e, pos); + continue; + } + } + + assert(nEQs == 0); + return (OC_SOLVE_UNKNOWN); +} + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_exp_kill.cc b/omegalib/omega/src/omega_core/oc_exp_kill.cc new file mode 100644 index 0000000..fdb2718 --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_exp_kill.cc @@ -0,0 +1,297 @@ +/***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team + Copyright (C) 2005-2011 Chun Chen + All Rights Reserved. + + Purpose: + Expensive inequality elimination. + + Notes: + + History: + 03/31/09 Use BoolSet, Chun Chen +*****************************************************************************/ + +#include <omega/omega_core/oc_i.h> +#include <basic/BoolSet.h> +#include <vector> + +namespace omega { + +int Problem::expensiveKill() { + int e; + if (TRACE) fprintf(outputFile,"Performing expensive kill tests: [\n"); + if (DBUG) printProblem(); + Problem tmpProblem; + int oldTrace = trace; + int constraintsRemoved = 0; + + trace = 0; + conservative++; + + for (e = nGEQs - 1; e >= 0; e--) + if (!GEQs[e].essential) { + if (DBUG) { + fprintf(outputFile, "checking equation %d to see if it is redundant: ", e); + printGEQ(&(GEQs[e])); + fprintf(outputFile, "\n"); + } + tmpProblem = *this; + tmpProblem.negateGEQ(e); + tmpProblem.varsOfInterest = 0; + tmpProblem.nSUBs = 0; + tmpProblem.nMemories = 0; + tmpProblem.safeVars = 0; + tmpProblem.variablesFreed = 0; + tmpProblem.isTemporary = true; + + if (!tmpProblem.solve(false)) { + if (DBUG) + fprintf(outputFile, "redundant!\n"); + constraintsRemoved++; + deleteGEQ(e); + } + } + + if (constraintsRemoved) { + if (TRACE) fprintf(outputFile,"%d Constraints removed!!\n",constraintsRemoved); + } + + trace = oldTrace; + conservative--; + if (TRACE) fprintf(outputFile,"] expensive kill tests done\n"); + return 1; +} + +int Problem::expensiveRedKill() { + int e; + if (TRACE) fprintf(outputFile,"Performing expensive red kill tests: [\n"); + Problem tmpProblem; + int oldTrace = trace; + int constraintsRemoved = 0; + + trace = 0; + conservative++; + + for (e = nGEQs - 1; e >= 0; e--) + if (!GEQs[e].essential && GEQs[e].color) { + if (DEBUG) { + fprintf(outputFile, "checking equation %d to see if it is redundant: ", e); + printGEQ(&(GEQs[e])); + fprintf(outputFile, "\n"); + } + tmpProblem = *this; + tmpProblem.negateGEQ(e); + tmpProblem.varsOfInterest = 0; + tmpProblem.nSUBs = 0; + tmpProblem.nMemories = 0; + tmpProblem.safeVars = 0; + tmpProblem.variablesFreed = 0; + tmpProblem.isTemporary = true; + tmpProblem.turnRedBlack(); + if (!tmpProblem.solve(false)) { + constraintsRemoved++; + deleteGEQ(e); + } + } + + if (constraintsRemoved) { + if (TRACE) fprintf(outputFile,"%d Constraints removed!!\n",constraintsRemoved); + } + + trace = oldTrace; + conservative--; + if (TRACE) fprintf(outputFile,"] expensive red kill tests done\n"); + return 1; +} + + +int Problem::expensiveEqualityCheck() { + int e; + return 1; + if (TRACE) fprintf(outputFile,"Performing expensive equality tests: [\n"); + Problem tmpProblem; + int oldTrace = trace; + int equalitiesFound = 0; + + trace = 0; + conservative++; + + for (e = nGEQs - 1; e >= 0; e--) { + if (DEBUG) { + fprintf(outputFile, "checking equation %d to see if it is an equality: ", e); + printGEQ(&(GEQs[e])); + fprintf(outputFile, "\n"); + } + tmpProblem = *this; + tmpProblem.GEQs[e].coef[0]--; + tmpProblem.varsOfInterest = 0; + tmpProblem.nSUBs = 0; + tmpProblem.nMemories = 0; + tmpProblem.safeVars = 0; + tmpProblem.variablesFreed = 0; + tmpProblem.isTemporary = true; + if (!tmpProblem.solve(false)) { + int neweq = newEQ(); + eqnncpy(&EQs[neweq], &GEQs[e], nVars); + equalitiesFound++; + addingEqualityConstraint(neweq); + } + } + if (equalitiesFound) { + if (TRACE) fprintf(outputFile,"%d Equalities found!!\n",equalitiesFound); + } + + trace = oldTrace; + conservative--; + if (equalitiesFound) { + if (!solveEQ()) return 0; + if (!normalize()) return 0; + } + if (TRACE) fprintf(outputFile,"] expensive equality tests done\n"); + return 1; +} + + +void Problem::quickRedKill(int computeGist) { + if (DBUG) { + fprintf(outputFile, "in quickRedKill: [\n"); + printProblem(); + } + + noteEssential(0); + int moreToDo = chainKill(1,0); + +#ifdef NDEBUG + if (!moreToDo) { + if (DBUG) fprintf(outputFile, "] quickRedKill\n"); + return; + } +#endif + + int isDead[nGEQs]; + int deadCount = 0; + std::vector<BoolSet<> > P(nGEQs, BoolSet<>(nVars)), Z(nGEQs, BoolSet<>(nVars)), N(nGEQs, BoolSet<>(nVars)); + BoolSet<> PP, PZ, PN; /* possible Positives, possible zeros & possible negatives */ + BoolSet<> MZ; /* must zeros */ + + int equationsToKill = 0; + for (int e = nGEQs - 1; e >= 0; e--) { + isDead[e] = 0; + if (GEQs[e].color && !GEQs[e].essential) equationsToKill++; + if (GEQs[e].color && GEQs[e].essential && !computeGist) + if (!moreToDo) { + if (DBUG) fprintf(outputFile, "] quickRedKill\n"); + return; + } + for (int i = nVars; i >= 1; i--) { + if (GEQs[e].coef[i] > 0) + P[e].set(i-1); + else if (GEQs[e].coef[i] < 0) + N[e].set(i-1); + else + Z[e].set(i-1); + } + } + + if (!equationsToKill) + if (!moreToDo) { + if (DBUG) fprintf(outputFile, "] quickRedKill\n"); + return; + } + + for (int e = nGEQs - 1; e > 0; e--) + if (!isDead[e]) + for (int e2 = e - 1; e2 >= 0; e2--) + if (!isDead[e2]) { + coef_t a = 0; + int i, j; + 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 = " coef_fmt "\n", variable(j), a); + printGEQ(&(GEQs[e])); + fprintf(outputFile, "\n"); + printGEQ(&(GEQs[e2])); + fprintf(outputFile, "\n"); + } + + MZ = (Z[e] & Z[e2]); + PZ = MZ | (P[e] & N[e2]) | (N[e] & P[e2]); + PP = P[e] | P[e2]; + PN = N[e] | N[e2]; + + for (int e3 = nGEQs - 1; e3 >= 0; e3--) + if (e3 != e && e3 != e2 && GEQs[e3].color && !GEQs[e3].essential) { + coef_t alpha1, alpha2, alpha3; + + if (!PZ.imply(Z[e3]) || MZ.imply(~Z[e3])) continue; + if (!PP.imply(P[e3]) || !PN.imply(N[e3])) continue; + + if (a > 0) { + 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]); + alpha3 = a; + } + else { + 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])); + alpha3 = -a; + } + + if (alpha1 > 0 && alpha2 > 0) { + if (DEBUG) { + fprintf(outputFile, "alpha1 = " coef_fmt ", alpha2 = " coef_fmt "; comparing against: ", alpha1, alpha2); + printGEQ(&(GEQs[e3])); + fprintf(outputFile, "\n"); + } + coef_t c; + int k; + for (k = nVars; k >= 0; k--) { + c = alpha1 * GEQs[e].coef[k] + alpha2 * GEQs[e2].coef[k]; + if (DEBUG) { + if (k>0) + fprintf(outputFile, " %s: " coef_fmt ", " coef_fmt "\n", variable(k), c, alpha3 * GEQs[e3].coef[k]); + else fprintf(outputFile, " constant: " coef_fmt ", " coef_fmt "\n", c, alpha3 * GEQs[e3].coef[k]); + } + if (c != alpha3 * GEQs[e3].coef[k]) + break; + } + if (k < 0 || (k == 0 && c < alpha3 * (GEQs[e3].coef[k]+1))) { + if (DEBUG) { + deadCount++; + fprintf(outputFile, "red equation#%d is dead (%d dead so far, %d remain)\n", e3, deadCount, nGEQs - deadCount); + printGEQ(&(GEQs[e])); + fprintf(outputFile, "\n"); + printGEQ(&(GEQs[e2])); + fprintf(outputFile, "\n"); + printGEQ(&(GEQs[e3])); + fprintf(outputFile, "\n"); + assert(moreToDo); + } + isDead[e3] = 1; + } + } + } + } + + for (int e = nGEQs - 1; e >= 0; e--) + if (isDead[e]) + deleteGEQ(e); + + if (DBUG) { + fprintf(outputFile,"] quickRedKill\n"); + printProblem(); + } +} + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_global.cc b/omegalib/omega/src/omega_core/oc_global.cc new file mode 100644 index 0000000..17d8a0c --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_global.cc @@ -0,0 +1,45 @@ +#include <omega/omega_core/oc_i.h> + +namespace omega { + +const int Problem::min_alloc = 10; +const int Problem::first_alloc_pad = 5; + +int omega_core_debug = 0; // 3: full debugging info + +int maxEQs = 100; // original 35, increased by chun +int maxGEQs = 200; // original 70, increased by chun + +int newVar = -1; +int findingImplicitEqualities = 0; +int firstCheckForRedundantEquations = 0; +int doItAgain; +int conservative = 0; +FILE *outputFile = stderr; /* printProblem writes its output to this file */ +char wildName[200][20]; +int nextWildcard = 0; +int trace = 1; +int depth = 0; +int headerLevel; +int inApproximateMode = 0; +int inStridesAllowedMode = 0; +int addingOuterEqualities = 0; +int outerColor = 0; +int reduceWithSubs = 1; +int pleaseNoEqualitiesInSimplifiedProblems = 0; +Problem *originalProblem = noProblem; +int omegaInitialized = 0; +int mayBeRed = 0; + + +// Hash table is used to hash all inequalties for all problems. It +// persists across problems for quick problem merging in case. When +// the table is filled to 1/3 full, it is flushed and the filling +// process starts all over again. +int packing[maxVars]; +int hashVersion = 0; +eqn hashMaster[hashTableSize]; +int fastLookup[maxKeys*2]; +int nextKey; + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_print.cc b/omegalib/omega/src/omega_core/oc_print.cc new file mode 100644 index 0000000..7934713 --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_print.cc @@ -0,0 +1,686 @@ +#include <omega/omega_core/oc_i.h> + +namespace omega { + +int print_in_code_gen_style = 0; + +void Problem::initializeVariables() const { + Problem *p = (Problem *)this; + int i; + assert(!p->variablesInitialized); + for (i = p->nVars; i >= 0; i--) + p->forwardingAddress[i] = p->var[i] = i; + p->variablesInitialized = 1; +} + + +std::string Problem::print_term_to_string(const eqn *e, int c) const { + std::string s=""; + 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) + s+= variable(i); + else { + s += to_string(c * e->coef[i]); + if (print_in_code_gen_style) s += "*"; + s += variable(i); + } + break; + } + for (i = 1; i <= n; i++) + if (i != wentFirst && c * e->coef[i] != 0) { + if (!first && c * e->coef[i] > 0) + s += "+"; + + first = 0; + + if (c * e->coef[i] == 1) + s += variable(i); + else if (c * e->coef[i] == -1) { + s += "-"; s += variable(i); + } + else { + s += to_string(c * e->coef[i]); + if (print_in_code_gen_style) s += "*"; + s += variable(i); + } + } + if (!first && c * e->coef[0] > 0) + s += "+"; + if (first || c * e->coef[0] != 0) + s += to_string(c * e->coef[0]); + return s; +} + + +void Problem::printTerm(const eqn * e, int c) const { + std::string s = print_term_to_string(e, c); + fprintf(outputFile, "%s", s.c_str()); +} + + +void Problem::printSub(int v) const { + std::string s = print_sub_to_string(v); + fprintf(outputFile, "%s", s.c_str()); +} + + +std::string Problem::print_sub_to_string(int v) const { + std::string s; + + if (v > 0) + s = variable(v); + else + s = print_term_to_string(&SUBs[-v-1], 1); + return s; +} + + +void Problem::clearSubs() { + nSUBs = 0; + nMemories = 0; +} + + +void Problem::printEqn(const eqn *e, int test, int extra) const { + char buf[maxVars * 12 + 180]; // original buf[maxVars * 12 + 80] + + sprintEqn(buf, e, test, extra); + fprintf(outputFile, "%s", buf); +} + + +std::string Problem::printEqnToString(const eqn *e, int test, int extra) const { + char buf[maxVars * 12 + 180]; // original buf[maxVars * 12 + 80] + sprintEqn(buf, e, test, extra); + return std::string(buf); +} + + +void Problem::sprintEqn(char *str, const eqn *e, int test, int extra) const { + int i; + int first; + int n = nVars + extra; + int isLT; + + isLT = test && e->coef[0] == -1; + if (isLT) + isLT = 1; +#if 0 + 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++; + } + } +#endif + if (e->color) { + sprintf(str, "["); + while (*str) + str++; + } + first = 1; + for (i = isLT; i <= n; i++) + if (e->coef[i] < 0) { + if (!first) { + sprintf(str, "+"); + while (*str) + str++; + } + else + first = 0; + if (i == 0) { + sprintf(str, coef_fmt, -e->coef[i]); + while (*str) + str++; + } + else if (e->coef[i] == -1) { + sprintf(str, "%s", variable(i)); + while (*str) + str++; + } + else { + if (print_in_code_gen_style) + sprintf(str, coef_fmt "*%s", -e->coef[i], variable(i)); + else sprintf(str, coef_fmt "%s", -e->coef[i], variable(i)); + while (*str) + str++; + } + } + if (first) { + if (isLT) { + sprintf(str, "1"); + isLT = 0; + } + else + sprintf(str, "0"); + while (*str) + str++; + } + if (test == 0) { + if (print_in_code_gen_style) sprintf(str, " == "); + else sprintf(str, " = "); + while (*str) + str++; + } + else { + if (isLT) + sprintf(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, coef_fmt , e->coef[i]); + while (*str) + str++; + } + else if (e->coef[i] == 1) { + sprintf(str, "%s", variable(i)); + while (*str) + str++; + } + else { + if (print_in_code_gen_style) + sprintf(str, coef_fmt "*%s", e->coef[i], variable(i)); + else + sprintf(str, coef_fmt "%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 Problem::printSubstitution(int s) const { + const eqn * eq = &(SUBs[s]); + assert(eq->key > 0); + fprintf(outputFile, "%s := ", orgVariable(eq->key)); + printTerm(eq, 1); +} + + +void Problem::printVars(int /*debug*/) const { + int i; + fprintf(outputFile, "variables = "); + if (safeVars > 0) + fprintf(outputFile, "("); + for (i = 1; i <= nVars; i++) { + fprintf(outputFile, "%s", variable(i)); + if (i == safeVars) + fprintf(outputFile, ")"); + if (i < nVars) + fprintf(outputFile, ", "); + } + fprintf(outputFile, "\n"); + /* + fprintf(outputFile, "forward addresses = "); + if (safeVars > 0) + fprintf(outputFile, "("); + for (i = 1; i <= nVars; i++) + { + int v = forwardingAddress[i]; + if (v > 0) fprintf(outputFile, "%s", variable(i)); + else fprintf(outputFile, "*"); + if (i == safeVars) + fprintf(outputFile, ")"); + if (i < nVars) + fprintf(outputFile, ", "); + }; + fprintf(outputFile, "\n"); + */ +} + + +void printHeader() { + int i; + for(i=0; i<headerLevel; i++) { + fprintf(outputFile, ". "); + } +} + + +void Problem::printProblem(int debug) const { + int e; + + if (!variablesInitialized) + initializeVariables(); + if (debug) { + printHeader(); + fprintf(outputFile, "#vars = %d, #EQ's = %d, #GEQ's = %d, # SUB's = %d, ofInterest = %d\n", + nVars,nEQs,nGEQs,nSUBs,varsOfInterest); + printHeader(); + printVars(debug); + } + for (e = 0; e < nEQs; e++) { + printHeader(); + printEQ(&EQs[e]); + fprintf(outputFile, "\n"); + } + for (e = 0; e < nGEQs; e++) { + printHeader(); + printGEQ(&GEQs[e]); + fprintf(outputFile, "\n"); + } + for (e = 0; e < nSUBs; e++) { + printHeader(); + printSubstitution(e); + fprintf(outputFile, "\n"); + } + + for (e = 0; e < nMemories; e++) { + int i; + printHeader(); + switch(redMemory[e].kind) { + case notRed: + fprintf(outputFile,"notRed: "); + break; + case redGEQ: + fprintf(outputFile,"Red: 0 <= "); + break; + case redLEQ: + fprintf(outputFile,"Red ??: 0 >= "); + break; + case redEQ: + fprintf(outputFile,"Red: 0 == "); + break; + case redStride: + fprintf(outputFile,"Red stride " coef_fmt ": ", redMemory[e].stride); + break; + } + fprintf(outputFile," " coef_fmt, redMemory[e].constantTerm); + for(i=0;i< redMemory[e].length; i++) + if(redMemory[e].coef[i] >= 0) + fprintf(outputFile,"+" coef_fmt "%s", redMemory[e].coef[i], orgVariable(redMemory[e].var[i])); + else + fprintf(outputFile,"-" coef_fmt "%s", -redMemory[e].coef[i], orgVariable(redMemory[e].var[i])); + fprintf(outputFile, "\n"); + } + fflush(outputFile); + + CHECK_FOR_DUPLICATE_VARIABLE_NAMES; +} + + +void Problem::printRedEquations() const { + int e; + + if (!variablesInitialized) + initializeVariables(); + printVars(1); + for (e = 0; e < nEQs; e++) { + if (EQs[e].color == EQ_RED) { + printEQ(&EQs[e]); + fprintf(outputFile, "\n"); + } + } + for (e = 0; e < nGEQs; e++) { + if (GEQs[e].color == EQ_RED) { + printGEQ(&GEQs[e]); + fprintf(outputFile, "\n"); + } + } + for (e = 0; e < nSUBs; e++) { + if (SUBs[e].color) { + printSubstitution(e); + fprintf(outputFile, "\n"); + } + } + fflush(outputFile); +} + + +int Problem::prettyPrintProblem() const { + std::string s = prettyPrintProblemToString(); + fprintf(outputFile, "%s", s.c_str()); + fflush(outputFile); + return 0; +} + + +std::string Problem::prettyPrintProblemToString() const { + std::string s=""; + int e; + int v; + int live[maxmaxGEQs]; + int v1, v2, v3; + int t, change; + int stuffPrinted = 0; + const char *connector = " && "; + + 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 varCount[maxVars]; + int i, m, multiprint; + + + if (!variablesInitialized) + initializeVariables(); + + if (nVars > 0) { + for (e = 0; e < nEQs; e++) { + if (stuffPrinted) + s += connector; + stuffPrinted = 1; + s += print_EQ_to_string(&EQs[e]); + } + + for (e = 0; e < nGEQs; e++) { + live[e] = true; + varCount[e] = 0; + for (v = 1; v <= nVars; v++) + if (GEQs[e].coef[v]) varCount[e]++; + } + + if (!print_in_code_gen_style) + 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 < nGEQs; e++) + if (live[e] && varCount[e] <= 2) { + 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]; + + /* + * printf("\n\nPartial order:\n"); printf(" "); for (v1 = 1; v1 <= nVars; v1++) + * printf("%7s",variable(v1)); printf("\n"); for (v1 = 1; v1 <= nVars; v1++) { printf("%6s: + * ",variable(v1)); for (v2 = 1; v2 <= nVars; v2++) switch (po[v1][v2]) { case none: printf(" "); + * break; case le: printf(" <= "); break; case lt: printf(" < "); break; } printf("\n"); } + */ + + + /* 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 */ + +#if 0 + printf("\n\nPartial order:\n"); printf(" "); + for (v1 = 1; v1 <= nVars; v1++) printf("%7s",variable(v1)); printf("\n"); + for (v1 = 1; v1 <= nVars; v1++) { + printf("%6s: ",variable(v1)); + for (v2 = 1; v2 <= nVars; v2++) switch (po[v1][v2]) { + case none: printf(" "); break; + case le: printf(" <= "); break; + case lt: printf(" < "); break; + } + printf("\n"); + } + + printProblem(1); +#endif + break; + } + + for (v1 = 1; v1 <= nVars; v1++) + if (chainLength[v1] == 0) + firstLinks[v1] = 0; + + v = 1; + for (v1 = 2; v1 <= nVars; v1++) + if (chainLength[v1] + firstLinks[v1] > chainLength[v] + firstLinks[v]) + v = v1; + + if (chainLength[v] + firstLinks[v] == 0) + break; + + if (stuffPrinted) + s += connector; + stuffPrinted = 1; + /* chain starts at v */ + /* print firstLinks */ + { + coef_t tmp; + int first; + first = 1; + for (e = 0; e < nGEQs; e++) + if (live[e] && GEQs[e].coef[v] == 1 && varCount[e] <= 2) { + if (!first) + s += ", "; + tmp = GEQs[e].coef[v]; + ((Problem *)this)-> + GEQs[e].coef[v] = 0; + s += print_term_to_string(&GEQs[e], -1); + ((Problem *)this)-> + GEQs[e].coef[v] = tmp; + live[e] = false; + first = 0; + } + if (!first) + s += " <= "; + } + + + /* 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; + } + + s += variable(chain[0]); + + multiprint = 0; + for (i = 1; i < m; i++) { + v = chain[i - 1]; + v2 = chain[i]; + if (po[v][v2] == le) + s += " <= "; + else + s += " < "; + 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; + s += ","; 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 */ + { + coef_t tmp; + int first; + first = 1; + for (e = 0; e < nGEQs; e++) + if (live[e] && GEQs[e].coef[v] == -1 && varCount[e] <= 2) { + if (!first) + s += ", "; + else + s += " <= "; + tmp = GEQs[e].coef[v]; + ((Problem *)this)-> + GEQs[e].coef[v] = 0; + s += print_term_to_string(&GEQs[e], 1); + ((Problem *)this)-> + GEQs[e].coef[v] = tmp; + live[e] = false; + first = 0; + } + } + } + + + for (e = 0; e < nGEQs; e++) + if (live[e]) { + if (stuffPrinted) + s += connector; + stuffPrinted = 1; + s += print_GEQ_to_string(&GEQs[e]); + } + + for (e = 0; e < nSUBs; e++) { + const eqn * eq = &SUBs[e]; + if (stuffPrinted) + s += connector; + stuffPrinted = 1; + if (eq->key > 0) { + s += orgVariable(eq->key); s += " := "; + } + else { + s += "#"; s += to_string(eq->key); s += " := "; + } + s += print_term_to_string(eq, 1); + } + } + return s; +} + + +int Problem::prettyPrintRedEquations() const { + int e, stuffPrinted = 0; + const char *connector = " && "; + + if (!variablesInitialized) + initializeVariables(); + + for (e = 0; e < nEQs; e++) { + if (EQs[e].color == EQ_RED) { + if (stuffPrinted) + fprintf(outputFile, "%s", connector); + stuffPrinted = 1; + ((Problem *)this)-> + EQs[e].color = EQ_BLACK; + printEQ(&EQs[e]); + ((Problem *)this)-> + EQs[e].color = EQ_RED; + } + } + for (e = 0; e < nGEQs; e++) { + if (GEQs[e].color == EQ_RED) { + if (stuffPrinted) + fprintf(outputFile, "%s", connector); + stuffPrinted = 1; + ((Problem *)this)-> + GEQs[e].color = EQ_BLACK; + printGEQ(&GEQs[e]); + ((Problem *)this)-> + GEQs[e].color = EQ_RED; + } + } + for (e = 0; e < nSUBs; e++) { + if (SUBs[e].color) { + if (stuffPrinted) + fprintf(outputFile, "%s", connector); + stuffPrinted = 1; + printSubstitution(e); + } + } + fflush(outputFile); + + return 0; +} + +} diff --git a/omegalib/omega/src/omega_core/oc_problems.cc b/omegalib/omega/src/omega_core/oc_problems.cc new file mode 100644 index 0000000..8b6e04c --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_problems.cc @@ -0,0 +1,198 @@ +#include <omega/omega_core/oc_i.h> +#include <basic/omega_error.h> + +namespace omega { + +Problem::~Problem() { + delete[] EQs; + delete[] GEQs; +} + + +void check_number_EQs(int n) { + if (n < 0) { + fprintf(stderr,"ERROR: nEQs < 0??\n"); + exit(1); + } + + if (n > maxmaxEQs) { + // clear global variables + inApproximateMode = 0; + outerColor = 0; + + throw presburger_error("\nERROR:\n" + "An attempt was made to set the number of available equality constraints to " + to_string(n) + ".\n" + "The maximum number of equality constraints in a conjunction is " + to_string(maxmaxEQs) + ".\n" + "This limit can be changed by redefining maxmaxEQs in oc.h and recompiling.\n\n"); + + // fprintf(stderr, "\nERROR:\n"); + // fprintf(stderr, "An attempt was made to set the number of available equality constraints to %d.\n", n); + // fprintf(stderr, "The maximum number of equality constraints in a conjunction is %d.\n", maxmaxEQs); + // fprintf(stderr, "This limit can be changed by redefining maxmaxEQs in oc.h and recompiling.\n\n"); + // exit(2); + } +} + +void check_number_GEQs(int n) { + if (n < 0) { + fprintf(stderr,"ERROR: nGEQs < 0??\n"); + exit(1); + } + + if (n > maxmaxGEQs) { + // clear global variables + inApproximateMode = 0; + outerColor = 0; + + throw presburger_error("\nERROR:\n" + "An attempt was made to set the number of available inequality constraints to " + to_string(n) +".\n" + "The maximum number of inequality constraints in a conjunction is " + to_string(maxmaxGEQs) +".\n" + "This limit can be changed by redefining maxmaxGEQs in oc.h and recompiling.\n\n"); + + // fprintf(stderr, "\nERROR:\n"); + // fprintf(stderr, "An attempt was made to set the number of available inequality constraints to %d.\n", n); + // fprintf(stderr, "The maximum number of inequality constraints in a conjunction is %d.\n", maxmaxGEQs); + // fprintf(stderr, "This limit can be changed by redefining maxmaxGEQs in oc.h and recompiling.\n\n"); + // exit(2); + } +} + + +void check_number_EQs_GEQs(int e, int g) { + check_number_EQs(e); + check_number_GEQs(g); +} + + +Problem::Problem(int in_eqs, int in_geqs) { + check_number_EQs_GEQs(in_eqs, in_geqs); + allocEQs = padEQs(in_eqs); + allocGEQs = padGEQs(in_geqs); + assert(allocEQs > 0 && allocGEQs > 0); + EQs = new eqn[allocEQs]; + GEQs = new eqn[allocGEQs]; + nVars = 0; + hashVersion = omega::hashVersion; + variablesInitialized = 0; + variablesFreed = 0; + varsOfInterest = 0; + safeVars = 0; + nEQs = 0; + nGEQs = 0; + nSUBs = 0; + nMemories = 0; + isTemporary = false; +} + +Problem::Problem(const Problem & p2) { + allocEQs = padEQs(p2.nEQs); // Don't over-allocate; p2 might have too many! + allocGEQs = padGEQs(p2.nGEQs); + assert(allocEQs > 0 && allocGEQs > 0); + EQs = new eqn[allocEQs]; + GEQs = new eqn[allocGEQs]; + int e, i; + nVars = p2.nVars; + hashVersion = p2.hashVersion; + variablesInitialized = p2.variablesInitialized; + variablesFreed = p2.variablesFreed; + varsOfInterest = p2.varsOfInterest; + safeVars = p2.safeVars; + nEQs = p2.nEQs; + isTemporary = p2.isTemporary; + //nSUBs = 0; + for (e = p2.nEQs - 1; e >= 0; e--) + eqnncpy(&(EQs[e]), &(p2.EQs[e]), p2.nVars); + nGEQs = p2.nGEQs; + for (e = p2.nGEQs - 1; e >= 0; e--) + eqnncpy(&(GEQs[e]), &(p2.GEQs[e]), p2.nVars); + for (i = 0; i <= p2.nVars; i++) + var[i] = p2.var[i]; + for (i = 0; i <= maxVars; i++) + forwardingAddress[i] = p2.forwardingAddress[i]; + //nMemories = 0; + get_var_name = p2.get_var_name; + getVarNameArgs = p2.getVarNameArgs; +} + +Problem & Problem::operator=(const Problem & p2) { + if (this != &p2) { + if(allocEQs < p2.nEQs) { + delete[] EQs; + allocEQs = padEQs(p2.nEQs); + EQs = new eqn[allocEQs]; + } + if(allocGEQs < p2.nGEQs) { + delete[] GEQs; + allocGEQs = padGEQs(p2.nGEQs); + GEQs = new eqn[allocGEQs]; + } + int e, i; + nVars = p2.nVars; + hashVersion = p2.hashVersion; + variablesInitialized = p2.variablesInitialized; + variablesFreed = p2.variablesFreed; + varsOfInterest = p2.varsOfInterest; + safeVars = p2.safeVars; + nEQs = p2.nEQs; + isTemporary = p2.isTemporary; + //nSUBs = 0; + for (e = p2.nEQs - 1; e >= 0; e--) + eqnncpy(&(EQs[e]), &(p2.EQs[e]), p2.nVars); + nGEQs = p2.nGEQs; + for (e = p2.nGEQs - 1; e >= 0; e--) + eqnncpy(&(GEQs[e]), &(p2.GEQs[e]), p2.nVars); + for (i = 0; i <= p2.nVars; i++) + var[i] = p2.var[i]; + for (i = 0; i <= maxVars; i++) + forwardingAddress[i] = p2.forwardingAddress[i]; + //nMemories = 0; + get_var_name = p2.get_var_name; + getVarNameArgs = p2.getVarNameArgs; + } + return *this; +} + + +void Problem::zeroVariable(int i) { + int e; + for (e = nGEQs - 1; e >= 0; e--) GEQs[e].coef[i] = 0; + for (e = nEQs - 1; e >= 0; e--) EQs[e].coef[i] = 0; + for (e = nSUBs - 1; e >= 0; e--) SUBs[e].coef[i] = 0; +} + +/* Functions for allocating EQ's and GEQ's */ + +int Problem::newGEQ() { + if (++nGEQs > allocGEQs) { + check_number_GEQs(nGEQs); + allocGEQs = padGEQs(allocGEQs, nGEQs); + assert(allocGEQs >= nGEQs); + eqn *new_geqs = new eqn[allocGEQs]; + for (int e = nGEQs - 2; e >= 0; e--) + eqnncpy(&(new_geqs[e]), &(GEQs[e]), nVars); + delete[] GEQs; + GEQs = new_geqs; + } +// problem->GEQs[nGEQs-1].color = black; +// eqnnzero(&problem->GEQs[nGEQs-1],problem->nVars); + return nGEQs-1; +} + +int Problem::newEQ() { + if (++nEQs > allocEQs) { + check_number_EQs(nEQs); + allocEQs = padEQs(allocEQs, nEQs); + assert(allocEQs >= nEQs); + eqn *new_eqs = new eqn[allocEQs]; + for (int e = nEQs - 2; e >= 0; e--) + eqnncpy(&(new_eqs[e]), &(EQs[e]), nVars); + delete[] EQs; + EQs = new_eqs; + } +// Could do this here, but some calls to newEQ do a copy instead of a zero; +// problem->EQs[nEQs-1].color = black; +// eqnnzero(&problem->EQs[nEQs-1],problem->nVars); + return nEQs-1; +} + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_query.cc b/omegalib/omega/src/omega_core/oc_query.cc new file mode 100644 index 0000000..528b297 --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_query.cc @@ -0,0 +1,478 @@ +#include <omega/omega_core/oc_i.h> + +namespace omega { + +void Problem::unprotectVariable( int v) { + int e, j, i; + coef_t t; + i = forwardingAddress[v]; + if (i < 0) { + i = -1 - i; + nSUBs--; + if (i < nSUBs) { + eqnncpy(&SUBs[i], &SUBs[nSUBs], nVars); + forwardingAddress[SUBs[i].key] = -i - 1; + } + } + else { + int bringToLife[maxVars]; + int comingBack = 0; + int e2; + for (e = nSUBs - 1; e >= 0; e--) + if ((bringToLife[e] = (SUBs[e].coef[i] != 0))) + comingBack++; + + for (e2 = nSUBs - 1; e2 >= 0; e2--) + if (bringToLife[e2]) { + + nVars++; + safeVars++; + if (safeVars < nVars) { + for (e = nGEQs - 1; e >= 0; e--) { + GEQs[e].coef[nVars] = GEQs[e].coef[safeVars]; + GEQs[e].coef[safeVars] = 0; + } + for (e = nEQs - 1; e >= 0; e--) { + EQs[e].coef[nVars] = EQs[e].coef[safeVars]; + EQs[e].coef[safeVars] = 0; + } + for (e = nSUBs - 1; e >= 0; e--) { + SUBs[e].coef[nVars] = SUBs[e].coef[safeVars]; + SUBs[e].coef[safeVars] = 0; + } + var[nVars] = var[safeVars]; + forwardingAddress[var[nVars]] = nVars; + } + else { + for (e = nGEQs - 1; e >= 0; e--) { + GEQs[e].coef[safeVars] = 0; + } + for (e = nEQs - 1; e >= 0; e--) { + EQs[e].coef[safeVars] = 0; + } + for (e = nSUBs - 1; e >= 0; e--) { + SUBs[e].coef[safeVars] = 0; + } + } + + var[safeVars] = SUBs[e2].key; + forwardingAddress[SUBs[e2].key] = safeVars; + + int neweq = newEQ(); + eqnncpy(&(EQs[neweq]), &(SUBs[e2]), nVars); + EQs[neweq].coef[safeVars] = -1; + if (e2 < nSUBs - 1) + eqnncpy(&(SUBs[e2]), &(SUBs[nSUBs - 1]), nVars); + nSUBs--; + } + + if (i < safeVars) { + j = safeVars; + for (e = nSUBs - 1; e >= 0; e--) { + t = SUBs[e].coef[j]; + SUBs[e].coef[j] = SUBs[e].coef[i]; + SUBs[e].coef[i] = t; + } + for (e = nGEQs - 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 = nEQs - 1; e >= 0; e--) { + t = EQs[e].coef[j]; + EQs[e].coef[j] = EQs[e].coef[i]; + EQs[e].coef[i] = t; + } + { + short t; + t = var[j]; + var[j] = var[i]; + var[i] = t; + } + forwardingAddress[var[i]] = i; + forwardingAddress[var[j]] = j; + } + safeVars--; + } + chainUnprotect(); +} + +void Problem::constrainVariableSign( int color, int i, int sign) { + int nV = nVars; + int e, k, j; + + k = forwardingAddress[i]; + if (k < 0) { + k = -1 - k; + + if (sign != 0) { + e = newGEQ(); + eqnncpy(&GEQs[e], &SUBs[k], nVars); + 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 = newEQ(); + eqnncpy(&EQs[e], &SUBs[k], nVars); + EQs[e].color = color; + } + } + else if (sign != 0) { + e = newGEQ(); + eqnnzero(&GEQs[e], nVars); + GEQs[e].coef[k] = sign; + GEQs[e].coef[0] = -1; + GEQs[e].touched = 1; + GEQs[e].color = color; + } + else { + e = newEQ(); + eqnnzero(&EQs[e], nVars); + EQs[e].coef[k] = 1; + EQs[e].color = color; + } + /* + unprotectVariable(i); + return (simplifyProblem(0,1,0)); + */ +} + +void Problem::constrainVariableValue( int color, int i, int value) { + int e, k; + + k = forwardingAddress[i]; + if (k < 0) { + k = -1 - k; + + e = newEQ(); + eqnncpy(&EQs[e], &SUBs[k], nVars); + EQs[e].coef[0] -= value; + + } + else { + e = newEQ(); + eqnnzero(&EQs[e], nVars); + EQs[e].coef[k] = 1; + EQs[e].coef[0] = -value; + } + EQs[e].color = color; +} + +// Analyze v1-v2 +void Problem:: query_difference(int v1, int v2, coef_t &lowerBound, coef_t &upperBound, bool &guaranteed) { + int nV = nVars; + int e,i,e2; + + coef_t lb1,ub1; + coef_t lb2,ub2; + assert(nSUBs == 0); + lowerBound = negInfinity; + lb1 = lb2 = negInfinity; + upperBound = posInfinity; + ub1 = ub2 = posInfinity; + guaranteed = true; + for (e = nEQs - 1; e >= 0; e--) { + if (EQs[e].coef[v1] == 0 && EQs[e].coef[v2] == 0) + continue; + for(i=nV;i>0;i--) + if (EQs[e].coef[i] && i!=v1 && i != v2) { + break; + } + if (i != 0) { + if (i > safeVars) { + // check to see if this variable appears anywhere else + for(e2 = nEQs-1; e2>=0;e2--) if (e != e2 && EQs[e2].coef[i]) break; + if (e2 < 0) + for(e2 = nGEQs-1; e2>=0;e2--) if (e != e2 && GEQs[e2].coef[i]) break; + if (e2 < 0) + for(e2 = nSUBs-1; e2>=0;e2--) if (e != e2 && SUBs[e2].coef[i]) break; + if (e2 >= 0) guaranteed = false; + } + else guaranteed = false; + continue; + } + if (EQs[e].coef[v1]*EQs[e].coef[v2] == -1) { + // found exact difference + coef_t d = - EQs[e].coef[v1] * EQs[e].coef[0]; + set_max(lowerBound, d); + set_min(upperBound, d); + guaranteed =true; + return; + } + else if (EQs[e].coef[v1] == 0) + lb2 = ub2 = -EQs[e].coef[0]/ EQs[e].coef[v2]; + else if (EQs[e].coef[v2] == 0) + lb1 = ub1 = -EQs[e].coef[0]/ EQs[e].coef[v1]; + else guaranteed = false; + } + + bool isDead[maxmaxGEQs]; + + for (e = nGEQs - 1; e >= 0; e--) isDead[e] = false; + int tryAgain = 1; + while (tryAgain) { + tryAgain = 0; + for (i = nVars; i > 0;i--) + if (i!= v1 && i != v2) { + for (e = nGEQs - 1; e >= 0; e--) + if (!isDead[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 (!isDead[e2] && GEQs[e2].coef[i] < 0) + break; + } + else { + for (e2 = e - 1; e2 >= 0; e2--) + if (!isDead[e2] && GEQs[e2].coef[i] > 0) + break; + } + if (e2 < 0) { + int e3; + for (e3 = nSUBs - 1; e3 >= 0; e3--) + if (SUBs[e3].coef[i]) + break; + if (e3 >= 0) + continue; + for (e3 = nEQs - 1; e3 >= 0; e3--) + if (EQs[e3].coef[i]) + break; + if (e3 >= 0) + continue; + if (e >= 0) { + isDead[e] = true; + for (e--; e >= 0; e--) + if (GEQs[e].coef[i]) isDead[e] = true; + } + } + } + } + + for (e = nGEQs - 1; e >= 0; e--) + if (!isDead[e]) { + if (GEQs[e].coef[v1] == 0 && GEQs[e].coef[v2] == 0) + continue; + for(i=nV;i>0;i--) + if (GEQs[e].coef[i] && i!=v1 && i != v2) + break; + if (i != 0) { + guaranteed = false; + continue; + } + if (GEQs[e].coef[v1]*GEQs[e].coef[v2] == -1) { + // found relative difference + if (GEQs[e].coef[v1] == 1) { + // v1 - v2 + c >= 0 + set_max(lowerBound, - GEQs[e].coef[0]); + } + else { + // v2 - v1 + c >= 0 + // c >= v1-v2 + set_min(upperBound, GEQs[e].coef[0]); + } + } + else if (GEQs[e].coef[v1] == 0 && GEQs[e].coef[v2] > 0) + lb2 = -GEQs[e].coef[0]/ GEQs[e].coef[v2]; + else if (GEQs[e].coef[v1] == 0 && GEQs[e].coef[v2] < 0) + ub2 = -GEQs[e].coef[0]/ GEQs[e].coef[v2]; + else if (GEQs[e].coef[v2] == 0 && GEQs[e].coef[v1] > 0) + lb1 = -GEQs[e].coef[0]/ GEQs[e].coef[v1]; + else if (GEQs[e].coef[v2] == 0 && GEQs[e].coef[v1] < 0) + ub1 = -GEQs[e].coef[0]/ GEQs[e].coef[v1]; + else guaranteed = false; + } + + // ub1-lb2 >= v1-v2 >= lb1-ub2 + + if (negInfinity < lb2 && ub1 < posInfinity) set_min(upperBound, ub1-lb2); + if (negInfinity < lb1 && ub2 < posInfinity) set_max(lowerBound, lb1-ub2); + if (lowerBound >= upperBound) guaranteed = 1; +} + + +int Problem::queryVariable(int i, coef_t *lowerBound, coef_t *upperBound) { + int nV = nVars; + int e, j; + int isSimple; + int coupled = false; + for(j=1;j<=safeVars;j++) + if (var[j] > 0) + assert(forwardingAddress[var[j]] == j); + + assert(i > 0); + i = forwardingAddress[i]; + assert(i != 0); + + (*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 = nSUBs - 1; e >= 0; e--) + if (SUBs[e].coef[i] != 0) + coupled = true; + + for (e = nEQs - 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 = nGEQs - 1; e >= 0; e--) + if (GEQs[e].coef[i] != 0) { + if (GEQs[e].key == i) { + set_max(*lowerBound, -GEQs[e].coef[0]); + } + else if (GEQs[e].key == -i) { + set_min(*upperBound, GEQs[e].coef[0]); + } + else + coupled = true; + } + return (coupled); +} + +int Problem::query_variable_bounds(int i, coef_t *l, coef_t *u) { + int coupled; + *l = negInfinity; + *u = posInfinity; + coupled = queryVariable(i, l, u); + if (!coupled || (nVars == 1 && forwardingAddress[i] == 1)) + return 0; + if (abs(forwardingAddress[i]) == 1 && nVars + nSUBs == 2 && nEQs + nSUBs == 1) { + int couldBeZero; + queryCoupledVariable(i, l, u, &couldBeZero, negInfinity, posInfinity); + return 0; + } + return 1; +} + +void Problem::queryCoupledVariable(int i, coef_t *l, coef_t *u, int *couldBeZero, coef_t lowerBound, coef_t upperBound) { + int e; + coef_t b1, b2; + const eqn *eqn; + coef_t sign; + int v; + + if (abs(forwardingAddress[i]) != 1 || nVars + nSUBs != 2 || nEQs + nSUBs != 1) { + fprintf(outputFile, "queryCoupledVariablecalled with bad parameters\n"); + printProblem(); + exit(2); + } + + if (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 = nGEQs - 1; e >= 0; e--) + if (GEQs[e].coef[v] != 0) { + if (GEQs[e].coef[v] == 1) { + set_max(lowerBound, -GEQs[e].coef[0]); + } + else { + set_min(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) { + set_max(*l, b1); + set_min(*u, b2); + } + else { + set_max(*l, b2); + set_min(*u, b1); + } + *couldBeZero = *l <= 0 && 0 <= *u && int_mod(eqn->coef[0], abs(eqn->coef[v])) == 0; +} + + +int Problem::queryVariableSigns(int i, int dd_lt, int dd_eq, int dd_gt, coef_t lowerBound, coef_t upperBound, bool *distKnown, coef_t *dist) { + int result; + coef_t l, u; + int couldBeZero; + + l = negInfinity; + u = posInfinity; + + queryVariable(i, &l, &u); + queryCoupledVariable(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); +} + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_quick_kill.cc b/omegalib/omega/src/omega_core/oc_quick_kill.cc new file mode 100644 index 0000000..1b988d4 --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_quick_kill.cc @@ -0,0 +1,775 @@ +/***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team + Copyright (C) 2005-2011 Chun Chen + All Rights Reserved. + + Purpose: + Quick inequality elimination. + + Notes: + + History: + 03/31/09 Use BoolSet, Chun Chen +*****************************************************************************/ + +#include <omega/omega_core/oc_i.h> +#include <vector> +#include <algorithm> +#include <basic/BoolSet.h> + +namespace omega { + +int Problem::combineToTighten() { + int effort = min(12+5*(nVars-safeVars),23); + + if (DBUG) { + fprintf(outputFile, "\nin combineToTighten (%d,%d):\n",effort,nGEQs); + printProblem(); + fprintf(outputFile, "\n"); + } + if (nGEQs > effort) { + if (TRACE) { + fprintf(outputFile, "too complicated to tighten\n"); + } + return 1; + } + + for(int e = 1; e < nGEQs; e++) { + for(int e2 = 0; e2 < e; e2++) { + coef_t g = 0; + + bool has_wildcard = false; + bool has_wildcard2 = false; + for (int i = nVars; i > safeVars; i--) { + coef_t a = GEQs[e].coef[i]; + coef_t b = GEQs[e2].coef[i]; + g = gcd(g, abs(a+b)); + if (a != 0) + has_wildcard = true; + if (b != 0) + has_wildcard2 = true; + } + + coef_t c, c2; + if ((has_wildcard && !has_wildcard2) || (!has_wildcard && has_wildcard2)) + c = 0; + else + c = -1; + for (int i = safeVars; i >= 1; i--) { + coef_t a = GEQs[e].coef[i]; + coef_t b = GEQs[e2].coef[i]; + if (a != 0 || b != 0) { + g = gcd(g, abs(a+b)); + + if (c < 0) { + if (g == 1) + break; + } + else if ((a>0 && b<0) || (a<0 && b>0)) { + if (c == 0) { + try { + coef_t prod = lcm(abs(a), abs(b)); + c = prod/abs(a); + c2 = prod/abs(b); + } + catch (std::overflow_error) { + c = -1; + } + } + else { + if (c*a+c2*b != 0) + c = -1; + } + } + else { + c = -1; + } + } + } + + bool done_unit_combine = false; + if (g > 1 && (GEQs[e].coef[0] + GEQs[e2].coef[0]) % g != 0) { + int e3 = newGEQ(); + for(int i = nVars; i >= 1; i--) { + GEQs[e3].coef[i] = (GEQs[e].coef[i] + GEQs[e2].coef[i])/g; + } + GEQs[e3].coef[0] = int_div(GEQs[e].coef[0] + GEQs[e2].coef[0], g); + GEQs[e3].color = GEQs[e].color || GEQs[e2].color; + GEQs[e3].touched = 1; + if (DBUG) { + fprintf(outputFile, "Combined "); + printGEQ(&GEQs[e]); + fprintf(outputFile,"\n and "); + printGEQ(&GEQs[e2]); + fprintf(outputFile,"\n to get #%d: ",e3); + printGEQ(&GEQs[e3]); + fprintf(outputFile,"\n\n"); + } + + done_unit_combine = true; + if (nGEQs > effort+5 || nGEQs > maxmaxGEQs-10) goto doneCombining; + } + + if (c > 0 && !(c == 1 && c2 == 1 && done_unit_combine)) { + bool still_has_wildcard = false; + coef_t p[nVars-safeVars]; + for (int i = nVars; i > safeVars; i--) { + p[i-safeVars-1] = c * GEQs[e].coef[i] + c2 * GEQs[e2].coef[i]; + if (p[i-safeVars-1] != 0) + still_has_wildcard = true; + } + if (still_has_wildcard) { + int e3 = newGEQ(); + for(int i = nVars; i > safeVars; i--) + GEQs[e3].coef[i] = p[i-safeVars-1]; + for (int i = safeVars; i > 0; i--) + GEQs[e3].coef[i] = 0; + GEQs[e3].coef[0] = c * GEQs[e].coef[0] + c2 * GEQs[e2].coef[0]; + GEQs[e3].color = GEQs[e].color || GEQs[e2].color; + GEQs[e3].touched = 1; + if (DBUG) { + fprintf(outputFile, "Additionally combined "); + printGEQ(&GEQs[e]); + fprintf(outputFile,"\n and "); + printGEQ(&GEQs[e2]); + fprintf(outputFile,"\n to get #%d: ",e3); + printGEQ(&GEQs[e3]); + fprintf(outputFile,"\n\n"); + } + + if (nGEQs > effort+5 || nGEQs > maxmaxGEQs-10) goto doneCombining; + } + } + } + } + +doneCombining: + if (normalize() == normalize_false) return 0; + while (nEQs) { + if (!solveEQ()) return 0; + if (normalize() == normalize_false) return 0; + } + return 1; +} + + +void Problem::noteEssential(int onlyWildcards) { + for (int e = nGEQs - 1; e >= 0; e--) { + GEQs[e].essential = 0; + GEQs[e].varCount = 0; + } + if (onlyWildcards) { + for (int e = nGEQs - 1; e >= 0; e--) { + GEQs[e].essential = 1; + for (int i = nVars; i > safeVars; i--) + if (GEQs[e].coef[i] < -1 || GEQs[e].coef[i] > 1) { + GEQs[e].essential = 0; + break; + } + } + } + for (int i = nVars; i >= 1; i--) { + int onlyLB = -1; + int onlyUB = -1; + for (int e = nGEQs - 1; e >= 0; e--) + if (GEQs[e].coef[i] > 0) { + GEQs[e].varCount ++; + if (onlyLB == -1) onlyLB = e; + else onlyLB = -2; + } + else if (GEQs[e].coef[i] < 0) { + GEQs[e].varCount ++; + if (onlyUB == -1) onlyUB = e; + else onlyUB = -2; + } + if (onlyUB >= 0) { + if (DBUG) { + fprintf(outputFile,"only UB: "); + printGEQ(&GEQs[onlyUB]); + fprintf(outputFile,"\n"); + } + GEQs[onlyUB].essential = 1; + } + if (onlyLB >= 0) { + if (DBUG) { + fprintf(outputFile,"only LB: "); + printGEQ(&GEQs[onlyLB]); + fprintf(outputFile,"\n"); + } + GEQs[onlyLB].essential = 1; + } + } + for (int e = nGEQs - 1; e >= 0; e--) + if (!GEQs[e].essential && GEQs[e].varCount > 1) { + int i1,i2,i3; + for (i1 = nVars; i1 >= 1; i1--) if (GEQs[e].coef[i1]) break; + for (i2 = i1-1; i2 >= 1; i2--) if (GEQs[e].coef[i2]) break; + for (i3 = i2-1; i3 >= 1; i3--) if (GEQs[e].coef[i3]) break; + assert(i2 >= 1); + int e2; + for (e2 = nGEQs - 1; e2 >= 0; e2--) + if (e!=e2) { + coef_t crossProduct; + crossProduct = GEQs[e].coef[i1]*GEQs[e2].coef[i1]; + crossProduct += GEQs[e].coef[i2]*GEQs[e2].coef[i2]; + for (int i = i3; i >= 1; i--) + if (GEQs[e2].coef[i]) + crossProduct += GEQs[e].coef[i]*GEQs[e2].coef[i]; + if (crossProduct > 0) { + if (DBUG) fprintf(outputFile,"Cross product of %d and %d is " coef_fmt "\n", e, e2, crossProduct); + break; + } + } + if (e2 < 0) GEQs[e].essential = 1; + } + if (DBUG) { + fprintf(outputFile,"Computed essential equations\n"); + fprintf(outputFile,"essential equations:\n"); + for (int e = 0; e < nGEQs; e++) + if (GEQs[e].essential) { + printGEQ(&GEQs[e]); + fprintf(outputFile,"\n"); + } + fprintf(outputFile,"potentially redundant equations:\n"); + for (int e = 0; e < nGEQs; e++) + if (!GEQs[e].essential) { + printGEQ(&GEQs[e]); + fprintf(outputFile,"\n"); + } + } +} + + +int Problem::findDifference(int e, int &v1, int &v2) { + // if 1 returned, eqn E is of form v1 -coef >= v2 + for(v1=1;v1<=nVars;v1++) + if (GEQs[e].coef[v1]) break; + for(v2=v1+1;v2<=nVars;v2++) + if (GEQs[e].coef[v2]) break; + if (v2 > nVars) { + if (GEQs[e].coef[v1] == -1) { + v2 = v1; + v1 = 0; + return 1; + } + if (GEQs[e].coef[v1] == 1) { + v2 = 0; + return 1; + } + return 0; + } + if (GEQs[e].coef[v1] * GEQs[e].coef[v2] != -1) return 0; + if (GEQs[e].coef[v1] < 0) std::swap(v1,v2); + return 1; +} + + +namespace { + struct succListStruct { + int num; + int notEssential; + int var[maxVars]; + coef_t diff[maxVars]; + int eqn[maxVars]; + }; +} + + +int Problem::chainKill(int color, int onlyWildcards) { + int v1,v2,e; + int essentialPred[maxVars]; + int redundant[maxmaxGEQs]; + int inChain[maxVars]; + int goodStartingPoint[maxVars]; + int tryToEliminate[maxmaxGEQs]; + int triedDoubleKill = 0; + + succListStruct succ[maxVars]; + +restart: + + int anyToKill = 0; + int anyKilled = 0; + int canHandle = 0; + + for(v1=0;v1<=nVars;v1++) { + succ[v1].num = 0; + succ[v1].notEssential = 0; + goodStartingPoint[v1] = 0; + inChain[v1] = -1; + essentialPred[v1] = 0; + } + + int essentialEquations = 0; + for (e = 0; e < nGEQs; e++) { + redundant[e] = 0; + tryToEliminate[e] = !GEQs[e].essential; + if (GEQs[e].essential) essentialEquations++; + if (color && !GEQs[e].color) tryToEliminate[e] = 0; + } + if (essentialEquations == nGEQs) return 0; + if (2*essentialEquations < nVars) return 1; + + for (e = 0; e < nGEQs; e++) + if (tryToEliminate[e] && GEQs[e].varCount <= 2 && findDifference(e,v1,v2)) { + assert(v1 == 0 || GEQs[e].coef[v1] == 1); + assert(v2 == 0 || GEQs[e].coef[v2] == -1); + succ[v2].notEssential++; + int s = succ[v2].num++; + succ[v2].eqn[s] = e; + succ[v2].var[s] = v1; + succ[v2].diff[s] = -GEQs[e].coef[0]; + goodStartingPoint[v2] = 1; + anyToKill++; + canHandle++; + } + if (!anyToKill) { + return canHandle < nGEQs; + } + for (e = 0; e < nGEQs; e++) + if (!tryToEliminate[e] && GEQs[e].varCount <= 2 && findDifference(e,v1,v2)) { + assert(v1 == 0 || GEQs[e].coef[v1] == 1); + assert(v2 == 0 || GEQs[e].coef[v2] == -1); + int s = succ[v2].num++; + essentialPred[v1]++; + succ[v2].eqn[s] = e; + succ[v2].var[s] = v1; + succ[v2].diff[s] = -GEQs[e].coef[0]; + canHandle++; + } + + + if (DBUG) { + int s; + fprintf(outputFile,"In chainkill: [\n"); + for(v1 = 0;v1<=nVars;v1++) { + fprintf(outputFile,"#%d <= %s: ",essentialPred[v1],variable(v1)); + for(s=0;s<succ[v1].notEssential;s++) + fprintf(outputFile," %s(" coef_fmt ") ",variable(succ[v1].var[s]), succ[v1].diff[s]); + for(;s<succ[v1].num;s++) + fprintf(outputFile," %s[" coef_fmt "] ",variable(succ[v1].var[s]), succ[v1].diff[s]); + fprintf(outputFile,"\n"); + } + } + + for(;v1<=nVars;v1++) + if (succ[v1].num == 1 && succ[v1].notEssential == 1) { + succ[v1].notEssential--; + essentialPred[succ[v1].var[succ[v1].notEssential]]++; + } + + if (DBUG) fprintf(outputFile,"Trying quick double kill:\n"); + int s1a,s1b,s2; + int v3; + for(v1 = 0;v1<=nVars;v1++) + for(s1a=0;s1a<succ[v1].notEssential;s1a++) { + v3 = succ[v1].var[s1a]; + for(s1b=0;s1b<succ[v1].num;s1b++) + if (s1a != s1b) { + v2 = succ[v1].var[s1b]; + for(s2=0;s2<succ[v2].num;s2++) + if (succ[v2].var[s2] == v3 && succ[v1].diff[s1b] + succ[v2].diff[s2] >= succ[v1].diff[s1a]) { + if (DBUG) { + fprintf(outputFile,"quick double kill: "); + printGEQ(&GEQs[succ[v1].eqn[s1a]]); + fprintf(outputFile,"\n"); + } + redundant[succ[v1].eqn[s1a]] = 1; + anyKilled++; + anyToKill--; + goto nextVictim; + } + } + nextVictim: v1 = v1; + } + if (anyKilled) { + for (e = nGEQs-1; e >= 0;e--) + if (redundant[e]) { + if (DBUG) { + fprintf(outputFile,"Deleting "); + printGEQ(&GEQs[e]); + fprintf(outputFile,"\n"); + } + deleteGEQ(e); + } + + if (!anyToKill) return canHandle < nGEQs; + noteEssential(onlyWildcards); + triedDoubleKill = 1; + goto restart; + } + + for(v1 = 0;v1<=nVars;v1++) + if (succ[v1].num == succ[v1].notEssential && succ[v1].notEssential > 0) { + succ[v1].notEssential--; + essentialPred[succ[v1].var[succ[v1].notEssential]]++; + } + + while (1) { + int chainLength; + int chain[maxVars]; + coef_t distance[maxVars]; + // pick a place to start + for(v1 = 0;v1<=nVars;v1++) + if (essentialPred[v1] == 0 && succ[v1].num > succ[v1].notEssential) + break; + if (v1 > nVars) + for(v1 = 0;v1<=nVars;v1++) + if (goodStartingPoint[v1] && succ[v1].num > succ[v1].notEssential) + break; + if (v1 > nVars) break; + + chainLength = 1; + chain[0] = v1; + distance[0] = 0; + inChain[v1] = 0; + int s; + + while (succ[v1].num > succ[v1].notEssential) { + s = succ[v1].num-1; + if (inChain[succ[v1].var[s]] >= 0) { + // Found cycle, don't do anything with them yet + break; + } + succ[v1].num = s; + + distance[chainLength]= distance[chainLength-1] + succ[v1].diff[s]; + v1 = chain[chainLength] = succ[v1].var[s]; + essentialPred[v1]--; + assert(essentialPred[v1] >= 0); + inChain[v1] = chainLength; + chainLength++; + } + + + int c; + if (DBUG) { + fprintf(outputFile,"Found chain: \n"); + for (c = 0; c < chainLength; c++) + fprintf(outputFile,"%s:" coef_fmt " ",variable(chain[c]), distance[c]); + fprintf(outputFile,"\n"); + } + + + for (c = 0; c < chainLength; c++) { + v1 = chain[c]; + for(s=0;s<succ[v1].notEssential;s++) { + if (DBUG) + fprintf(outputFile,"checking for %s + " coef_fmt " <= %s \n", variable(v1), succ[v1].diff[s], variable(succ[v1].var[s])); + if (inChain[succ[v1].var[s]] > c+1) { + if (DBUG) + fprintf(outputFile,"%s + " coef_fmt " <= %s is in chain\n", variable(v1), distance[inChain[succ[v1].var[s]]]- distance[c], variable(succ[v1].var[s])); + if ( distance[inChain[succ[v1].var[s]]]- distance[c] >= succ[v1].diff[s]) { + if (DBUG) + fprintf(outputFile,"%s + " coef_fmt " <= %s is redundant\n", variable(v1),succ[v1].diff[s], variable(succ[v1].var[s])); + redundant[succ[v1].eqn[s]] = 1; + } + } + } + } + for (c = 0; c < chainLength; c++) + inChain[chain[c]] = -1; + } + + for (e = nGEQs-1; e >= 0;e--) + if (redundant[e]) { + if (DBUG) { + fprintf(outputFile,"Deleting "); + printGEQ(&GEQs[e]); + fprintf(outputFile,"\n"); + } + deleteGEQ(e); + anyKilled = 1; + } + + if (anyKilled) noteEssential(onlyWildcards); + + if (anyKilled && DBUG) { + fprintf(outputFile,"\nResult:\n"); + printProblem(); + } + if (DBUG) { + fprintf(outputFile,"] end chainkill\n"); + printProblem(); + } + return canHandle < nGEQs; +} + + +namespace { + struct varCountStruct { + int e; + int safeVarCount; + int wildVarCount; + varCountStruct(int e_, int count1_, int count2_) { + e = e_; + safeVarCount = count1_; + wildVarCount = count2_; } + }; + bool operator<(const varCountStruct &a, const varCountStruct &b) { + if (a.wildVarCount < b.wildVarCount) + return true; + else if (a.wildVarCount > b.wildVarCount) + return false; + else + return a.safeVarCount < b.safeVarCount; + } +} + + +// +// Deduct redundant inequalities by combination of any two inequalities. +// Return value: 0 (no solution), +// 1 (nothing killed), +// 2 (some inequality killed). +// +int Problem::quickKill(int onlyWildcards, bool desperate) { + if (!onlyWildcards && !combineToTighten()) + return 0; + noteEssential(onlyWildcards); + int moreToDo = chainKill(0, onlyWildcards); + +#ifdef NDEBUG + if (!moreToDo) return 1; +#endif + + + if (!desperate && nGEQs > 256) { // original 60, increased by chun + if (TRACE) { + fprintf(outputFile, "%d inequalities are too complicated to quick kill\n", nGEQs); + } + return 1; + } + + if (DBUG) { + fprintf(outputFile, "in eliminate Redudant:\n"); + printProblem(); + } + + int isDead[nGEQs]; + std::vector<varCountStruct> killOrder; + std::vector<BoolSet<> > P(nGEQs, BoolSet<>(nVars)), Z(nGEQs, BoolSet<>(nVars)), N(nGEQs, BoolSet<>(nVars)); + BoolSet<> PP, PZ, PN; // possible Positives, possible zeros & possible negatives + + for (int e = nGEQs - 1; e >= 0; e--) { + isDead[e] = 0; + int safeVarCount = 0; + int wildVarCount = 0; + for (int i = nVars; i >= 1; i--) { + if (GEQs[e].coef[i] == 0) + Z[e].set(i-1); + else { + if (i > safeVars) + wildVarCount++; + else + safeVarCount++; + if (GEQs[e].coef[i] < 0) + N[e].set(i-1); + else + P[e].set(i-1); + } + } + + if (!GEQs[e].essential || wildVarCount > 0) + killOrder.push_back(varCountStruct(e, safeVarCount, wildVarCount)); + } + + sort(killOrder.begin(), killOrder.end()); + + if (DEBUG) { + fprintf(outputFile,"Prefered kill order:\n"); + for (int e3I = killOrder.size()-1; e3I >= 0; e3I--) { + fprintf(outputFile,"%2d: ",nGEQs-1-e3I); + printGEQ(&GEQs[killOrder[e3I].e]); + fprintf(outputFile,"\n"); + } + } + + int e3U = killOrder.size()-1; + while (e3U >= 0) { + // each round of elimination is for inequalities of same complexity and rounds are at descending complexity order + int e3L = e3U-1; + for(; e3L >= 0; e3L--) + if (killOrder[e3L].safeVarCount+killOrder[e3L].wildVarCount != killOrder[e3U].safeVarCount + killOrder[e3U].wildVarCount) + break; + + // check if e3 can be eliminated from combination of e1 and e2 + for (int e1 = 0; e1 < nGEQs; e1++) + if (!isDead[e1]) + for (int e2 = e1+1; e2 < nGEQs; e2++) + if (!isDead[e2]) { + coef_t alpha = 0; + int p, q; + for (p = nVars; p > 1; p--) + for (q = p - 1; q > 0; q--) { + try { + alpha = check_mul(GEQs[e1].coef[p], GEQs[e2].coef[q]) - check_mul(GEQs[e2].coef[p], GEQs[e1].coef[q]); + } + catch (std::overflow_error) { + continue; + } + 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]; + if (DEBUG) { + fprintf(outputFile,"Considering combination of "); + printGEQ(&(GEQs[e1])); + fprintf(outputFile," and "); + printGEQ(&(GEQs[e2])); + fprintf(outputFile,"\n"); + } + + for (int e3I = e3U; e3I > e3L; e3I--) { + int e3 = killOrder[e3I].e; + if (!isDead[e3] && e3 != e1 && e3 != e2) + try { + coef_t alpha1, alpha2, alpha3; + + if (!PZ.imply(Z[e3])) + goto nextE3; + + alpha1 = check_mul(GEQs[e2].coef[q], GEQs[e3].coef[p]) - check_mul(GEQs[e2].coef[p], GEQs[e3].coef[q]); + alpha2 = -(check_mul(GEQs[e1].coef[q], GEQs[e3].coef[p]) - check_mul(GEQs[e1].coef[p], GEQs[e3].coef[q])); + alpha3 = alpha; + + if (alpha1 < 0) { + alpha1 = -alpha1; + alpha2 = -alpha2; + alpha3 = -alpha3; + } + if (alpha1 == 0 || alpha2 <= 0) + goto nextE3; + + { + coef_t g = gcd(gcd(alpha1, alpha2), abs(alpha3)); + alpha1 /= g; + alpha2 /= g; + alpha3 /= g; + } + + if (DEBUG) { + fprintf(outputFile, coef_fmt "e1 + " coef_fmt "e2 = " coef_fmt "e3: ",alpha1,alpha2,alpha3); + printGEQ(&(GEQs[e3])); + fprintf(outputFile,"\n"); + } + + if (alpha3 > 0) { // trying to prove e3 is redundant + if (!GEQs[e3].color && (GEQs[e1].color || GEQs[e2].color)) { + goto nextE3; + } + if (!PP.imply(P[e3]) | !PN.imply(N[e3])) + goto nextE3; + + // verify alpha1*v1+alpha2*v2 = alpha3*v3 + for (int k = nVars; k >= 1; k--) + if (check_mul(alpha3, GEQs[e3].coef[k]) != check_mul(alpha1, GEQs[e1].coef[k]) + check_mul(alpha2, GEQs[e2].coef[k])) + goto nextE3; + + coef_t c = check_mul(alpha1, GEQs[e1].coef[0]) + check_mul(alpha2, GEQs[e2].coef[0]); + if (c < check_mul(alpha3, (GEQs[e3].coef[0] + 1))) { + if (DBUG) { + fprintf(outputFile, "found redundant inequality\n"); + fprintf(outputFile, "alpha1, alpha2, alpha3 = " coef_fmt "," coef_fmt "," coef_fmt "\n", alpha1, alpha2, alpha3); + printGEQ(&(GEQs[e1])); + fprintf(outputFile, "\n"); + printGEQ(&(GEQs[e2])); + fprintf(outputFile, "\n=> "); + printGEQ(&(GEQs[e3])); + fprintf(outputFile, "\n\n"); + assert(moreToDo); + } + + isDead[e3] = 1; + } + } + else { // trying to prove e3 <= 0 or e3 = 0 + if (!PN.imply(P[e3]) | !PP.imply(N[e3])) + goto nextE3; + + // verify alpha1*v1+alpha2*v2 = alpha3*v3 + for (int k = nVars; k >= 1; k--) + if (check_mul(alpha3, GEQs[e3].coef[k]) != check_mul(alpha1, GEQs[e1].coef[k]) + check_mul(alpha2, GEQs[e2].coef[k])) + goto nextE3; + + if (DEBUG) { + fprintf(outputFile,"All but constant term checked\n"); + } + coef_t c = check_mul(alpha1, GEQs[e1].coef[0]) + check_mul(alpha2, GEQs[e2].coef[0]); + if (DEBUG) { + fprintf(outputFile,"All but constant term checked\n"); + fprintf(outputFile,"Constant term is " coef_fmt " vs " coef_fmt "\n", + alpha3*GEQs[e3].coef[0], + alpha3*(GEQs[e3].coef[0]-1)); + } + if (c < check_mul(alpha3, (GEQs[e3].coef[0]))) { + // we just proved e3 < 0, so no solutions exist + if (DBUG) { + fprintf(outputFile, "found implied over tight inequality\n"); + fprintf(outputFile, "alpha1, alpha2, alpha3 = " coef_fmt "," coef_fmt "," coef_fmt "\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 (!GEQs[e3].color && (GEQs[e1].color || GEQs[e2].color)) { + goto nextE3; + } + else if (c < check_mul(alpha3, (GEQs[e3].coef[0] - 1))) { + // we just proved e3 <= 0, so e3 = 0 + if (DBUG) { + fprintf(outputFile, "found implied tight inequality\n"); + fprintf(outputFile, "alpha1, alpha2, alpha3 = " coef_fmt "," coef_fmt "," coef_fmt "\n", alpha1, alpha2, -alpha3); + printGEQ(&(GEQs[e1])); + fprintf(outputFile, "\n"); + printGEQ(&(GEQs[e2])); + fprintf(outputFile, "\n=> inverse "); + printGEQ(&(GEQs[e3])); + fprintf(outputFile, "\n\n"); + } + int neweq = newEQ(); + eqnncpy(&EQs[neweq], &GEQs[e3], nVars); + addingEqualityConstraint(neweq); + isDead[e3] = 1; + } + } + nextE3:; + } + catch (std::overflow_error) { + continue; + } + } + } + + e3U = e3L; + } + + bool anything_killed = false; + for (int e = nGEQs - 1; e >= 0; e--) { + if (isDead[e]) { + anything_killed = true; + deleteGEQ(e); + } + } + + if (DBUG) { + fprintf(outputFile,"\nResult:\n"); + printProblem(); + } + + if (anything_killed) + return 2; + else + return 1; +} + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_simple.cc b/omegalib/omega/src/omega_core/oc_simple.cc new file mode 100644 index 0000000..0e492db --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_simple.cc @@ -0,0 +1,1373 @@ +/***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team + Copyright (C) 2005-2011 Chun Chen + All Rights Reserved. + + Purpose: + Support functions for solving a problem. + + Notes: + + History: + 10/13/08 Complete back substitution process, Chun Chen. + 05/28/09 Extend normalize process to handle redundancy involving + wilddcards, Chun Chen +*****************************************************************************/ + +#include <omega/omega_core/oc_i.h> +#include <basic/BoolSet.h> +#include <algorithm> +#include <vector> + +namespace omega { + +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); +} + + +int singleVarGEQ(eqn* e) { + return !e->touched && e->key != 0 && -maxVars <= e->key && e->key <= maxVars; +} + + +void checkVars(int nVars) { + if (nVars > maxVars) { + fprintf(stderr, "\nERROR:\n"); + fprintf(stderr, "An attempt was made to create a conjunction with %d variables.\n", nVars); + fprintf(stderr, "The current limit on variables in a single conjunction is %d.\n", maxVars); + fprintf(stderr, "This limit can be changed by changing the #define of maxVars in oc.h.\n\n"); + exit(2); + } +} + + +void Problem::difficulty(int &numberNZs, coef_t &maxMinAbsCoef, coef_t &sumMinAbsCoef) const { + numberNZs=0; + maxMinAbsCoef=0; + sumMinAbsCoef=0; + for (int e = 0; e < nGEQs; e++) { + coef_t maxCoef = 0; + for(int i = 1;i <= nVars;i++) + if (GEQs[e].coef[i]!=0) { + coef_t a = abs(GEQs[e].coef[i]); + maxCoef = max(maxCoef,a); + numberNZs++; + } + coef_t nextCoef = 0; + for(int i = 1;i <= nVars;i++) + if (GEQs[e].coef[i]!=0) { + coef_t a = abs(GEQs[e].coef[i]); + if (a < maxCoef) nextCoef = max(nextCoef,a); + else if (a == maxCoef) maxCoef = 0x7fffffff; + } + maxMinAbsCoef = max(maxMinAbsCoef,nextCoef); + sumMinAbsCoef += nextCoef; + } + + for (int e = 0; e < nEQs; e++) { + coef_t maxCoef = 0; + for(int i = 1;i <= nVars;i++) + if (EQs[e].coef[i]!=0) { + coef_t a = abs(EQs[e].coef[i]); + maxCoef = max(maxCoef,a); + numberNZs++; + } + coef_t nextCoef = 0; + for(int i = 1;i <= nVars;i++) + if (EQs[e].coef[i]!=0) { + coef_t a = abs(EQs[e].coef[i]); + if (a < maxCoef) nextCoef = max(nextCoef,a); + else if (a == maxCoef) maxCoef = 0x7fffffff; + } + maxMinAbsCoef = max(maxMinAbsCoef,nextCoef); + sumMinAbsCoef += nextCoef; + } +} + +int Problem::countRedGEQs() const { + int result = 0; + for (int e = 0; e < nGEQs; e++) + if (GEQs[e].color == EQ_RED) result++; + return result; +} + +int Problem::countRedEQs() const { + int result = 0; + for (int e = 0; e < nEQs; e++) + if (EQs[e].color == EQ_RED) result++; + return result; +} + +int Problem::countRedEquations() const { + int result = 0; + for (int e = 0; e < nEQs; e++) + if (EQs[e].color == EQ_RED) { + int i; + for (i = nVars; i > 0; i--) if (EQs[e].coef[i]) break; + if (i == 0 && EQs[e].coef[0] != 0) return 0; + else result+=2; + } + for (int e = 0; e < nGEQs; e++) + if (GEQs[e].color == EQ_RED) result+=1; + for (int e = 0; e < nMemories; e++) + switch(redMemory[e].kind ) { + case redEQ: + case redStride: + e++; + case redLEQ: + case redGEQ: + e++; + case notRed: + ; /* avoid warning about notRed not handled */ + } + return result; +} + +void Problem::deleteBlack() { + int RedVar[maxVars]; + for(int i = safeVars+1;i <= nVars;i++) RedVar[i] = 0; + + assert(nSUBs == 0); + + for (int e = nEQs-1; e >= 0; e--) + if (EQs[e].color != EQ_RED) { + eqnncpy(&EQs[e],&EQs[nEQs-1], nVars); + nEQs--; + } + else + for(int i = safeVars+1;i <= nVars;i++) + if (EQs[e].coef[i]) RedVar[i] = 1; + + for (int e = nGEQs-1; e >= 0; e--) + if (GEQs[e].color != EQ_RED) { + eqnncpy(&GEQs[e],&GEQs[nGEQs-1], nVars); + nGEQs--; + } + else + for(int i = safeVars+1;i <= nVars;i++) + if (GEQs[e].coef[i]) RedVar[i] = 1; + + assert(nSUBs == 0); + + for(int i = nVars; i > safeVars;i--) { + if (!RedVar[i]) deleteVariable(i); + } +} + + +void Problem::deleteRed() { + int BlackVar[maxVars]; + for(int i = safeVars+1;i <= nVars;i++) BlackVar[i] = 0; + + assert(nSUBs == 0); + for (int e = nEQs-1; e >=0; e--) + if (EQs[e].color) { + eqnncpy(&EQs[e],&EQs[nEQs-1], nVars); + nEQs--; + } + else + for(int i = safeVars+1;i <= nVars;i++) + if (EQs[e].coef[i]) BlackVar[i] = 1; + + for (int e = nGEQs-1; e >=0; e--) + if (GEQs[e].color) { + eqnncpy(&GEQs[e],&GEQs[nGEQs-1], nVars); + nGEQs--; + } + else + for(int i = safeVars+1;i <= nVars;i++) + if (GEQs[e].coef[i]) BlackVar[i] = 1; + + assert(nSUBs == 0); + + for(int i = nVars; i> safeVars;i--) { + if (!BlackVar[i]) deleteVariable(i); + } +} + + +void Problem::turnRedBlack() { + for (int e = nEQs-1; e >= 0; e--) EQs[e].color = 0; + for (int e = nGEQs-1; e >= 0; e--) GEQs[e].color = 0; +} + + +void Problem::useWildNames() { + for(int i = safeVars+1; i <= nVars; i++) nameWildcard(i); +} + + +void negateCoefficients(eqn* eqn, int nVars) { + for (int i = nVars; i >= 0; i--) + eqn-> coef[i] = -eqn->coef[i]; + eqn->touched = true; +} + + +void Problem::negateGEQ(int e) { + negateCoefficients(&GEQs[e],nVars); + GEQs[e].coef[0]--; +} + + +void Problem:: deleteVariable(int i) { + if (i < safeVars) { + int j = safeVars; + for (int e = nGEQs - 1; e >= 0; e--) { + GEQs[e].touched = true; + GEQs[e].coef[i] = GEQs[e].coef[j]; + GEQs[e].coef[j] = GEQs[e].coef[nVars]; + } + for (int e = nEQs - 1; e >= 0; e--) { + EQs[e].coef[i] = EQs[e].coef[j]; + EQs[e].coef[j] = EQs[e].coef[nVars]; + } + for (int e = nSUBs - 1; e >= 0; e--) { + SUBs[e].coef[i] = SUBs[e].coef[j]; + SUBs[e].coef[j] = SUBs[e].coef[nVars]; + } + var[i] = var[j]; + var[j] = var[nVars]; + } + else if (i < nVars) { + for (int e = nGEQs - 1; e >= 0; e--) + if (GEQs[e].coef[nVars]) { + GEQs[e].coef[i] = GEQs[e].coef[nVars]; + GEQs[e].touched = true; + } + for (int e = nEQs - 1; e >= 0; e--) + EQs[e].coef[i] = EQs[e].coef[nVars]; + for (int e = nSUBs - 1; e >= 0; e--) + SUBs[e].coef[i] = SUBs[e].coef[nVars]; + var[i] = var[nVars]; + } + if (i <= safeVars) + safeVars--; + nVars--; +} + + +void Problem::setInternals() { + if (!variablesInitialized) { + initializeVariables(); + } + + var[0] = 0; + nextWildcard = 0; + for(int i = 1;i <= nVars;i++) + if (var[i] < 0) + var[i] = --nextWildcard; + + assert(nextWildcard >= -maxWildcards); + + CHECK_FOR_DUPLICATE_VARIABLE_NAMES; + + int v = nSUBs; + for(int i = 1;i <= safeVars;i++) if (var[i] > 0) v++; + varsOfInterest = v; + + if (nextKey * 3 > maxKeys) { + omega::hashVersion++; + nextKey = maxVars + 1; + for (int e = nGEQs - 1; e >= 0; e--) + GEQs[e].touched = true; + for (int i = 0; i < hashTableSize; i++) + hashMaster[i].touched = -1; + hashVersion = omega::hashVersion; + } + else if (hashVersion != omega::hashVersion) { + for (int e = nGEQs - 1; e >= 0; e--) + GEQs[e].touched = true; + hashVersion = omega::hashVersion; + } +} + + +void Problem::setExternals() { + for (int i = 1; i <= safeVars; i++) + forwardingAddress[var[i]] = i; + for (int i = 0; i < nSUBs; i++) + forwardingAddress[SUBs[i].key] = -i - 1; +} + + +void setOutputFile(FILE * file) { + /* sets the file to which printProblem should send its output to "file" */ + + outputFile = file; +} + + +void setPrintLevel(int level) { + /* Sets the nber of points printed before constraints in printProblem */ + headerLevel = level; +} + + +void Problem::putVariablesInStandardOrder() { + for(int i = 1;i <= safeVars;i++) { + int b = i; + for(int j=i+1;j<=safeVars;j++) { + if (var[b] < var[j]) b = j; + } + if (b != i) swapVars(i,b); + } +} + + +void Problem::nameWildcard(int i) { + int j; + do { + --nextWildcard; + if (nextWildcard < -maxWildcards) + nextWildcard = -1; + var[i] = nextWildcard; + for(j = nVars; j > 0;j--) if (i!=j && var[j] == nextWildcard) break; + } while (j != 0); +} + + +int Problem::protectWildcard(int i) { + assert (i > safeVars); + if (i != safeVars+1) swapVars(i,safeVars+1); + safeVars++; + nameWildcard(safeVars); + return safeVars; +} + + +int Problem::addNewProtectedWildcard() { + int i = ++safeVars; + nVars++; + if (nVars != i) { + for (int e = nGEQs - 1; e >= 0; e--) { + if (GEQs[e].coef[i] != 0) + GEQs[e].touched = true; + GEQs[e].coef[nVars] = GEQs[e].coef[i]; + } + for (int e = nEQs - 1; e >= 0; e--) { + EQs[e].coef[nVars] = EQs[e].coef[i]; + } + for (int e = nSUBs - 1; e >= 0; e--) { + SUBs[e].coef[nVars] = SUBs[e].coef[i]; + } + var[nVars] = var[i]; + } + for (int e = nGEQs - 1; e >= 0; e--) + GEQs[e].coef[i] = 0; + for (int e = nEQs - 1; e >= 0; e--) + EQs[e].coef[i] = 0; + for (int e = nSUBs - 1; e >= 0; e--) + SUBs[e].coef[i] = 0; + nameWildcard(i); + return (i); +} + + +int Problem::addNewUnprotectedWildcard() { + int i = ++nVars; + for (int e = nGEQs - 1; e >= 0; e--) GEQs[e].coef[i] = 0; + for (int e = nEQs - 1; e >= 0; e--) EQs[e].coef[i] = 0; + for (int e = nSUBs - 1; e >= 0; e--) SUBs[e].coef[i] = 0; + nameWildcard(i); + return i; +} + + +void Problem::cleanoutWildcards() { + bool renormalize = false; + + // substituting wildcard equality + for (int e = nEQs-1; e >= 0; e--) { + for (int i = nVars; i >= safeVars+1; i--) + if (EQs[e].coef[i] != 0) { + coef_t c = EQs[e].coef[i]; + coef_t a = abs(c); + + bool preserveThisConstraint = true; + for (int e2 = nEQs-1; e2 >= 0; e2--) + if (e2 != e && EQs[e2].coef[i] != 0 && EQs[e2].color >= EQs[e].color) { + preserveThisConstraint = preserveThisConstraint && (gcd(a,abs(EQs[e2].coef[i])) != 1); + coef_t k = lcm(a, abs(EQs[e2].coef[i])); + coef_t coef1 = (EQs[e2].coef[i]>0?1:-1) * k / c; + coef_t coef2 = k / abs(EQs[e2].coef[i]); + for (int j = nVars; j >= 0; j--) + EQs[e2].coef[j] = EQs[e2].coef[j] * coef2 - EQs[e].coef[j] * coef1; + + coef_t g = 0; + for (int j = nVars; j >= 0; j--) { + g = gcd(abs(EQs[e2].coef[j]), g); + if (g == 1) + break; + } + if (g != 0 && g != 1) + for (int j = nVars; j >= 0; j--) + EQs[e2].coef[j] /= g; + } + + for (int e2 = nGEQs-1; e2 >= 0; e2--) + if (GEQs[e2].coef[i] != 0 && GEQs[e2].color >= EQs[e].color) { + coef_t k = lcm(a, abs(GEQs[e2].coef[i])); + coef_t coef1 = (GEQs[e2].coef[i]>0?1:-1) * k / c; + coef_t coef2 = k / abs(GEQs[e2].coef[i]); + for (int j = nVars; j >= 0; j--) + GEQs[e2].coef[j] = GEQs[e2].coef[j] * coef2 - EQs[e].coef[j] * coef1; + + GEQs[e2].touched = 1; + renormalize = true; + } + + for (int e2 = nSUBs-1; e2 >= 0; e2--) + if (SUBs[e2].coef[i] != 0 && SUBs[e2].color >= EQs[e].color) { + coef_t k = lcm(a, abs(SUBs[e2].coef[i])); + coef_t coef1 = (SUBs[e2].coef[i]>0?1:-1) * k / c; + coef_t coef2 = k / abs(SUBs[e2].coef[i]); + for (int j = nVars; j >= 0; j--) + SUBs[e2].coef[j] = SUBs[e2].coef[j] * coef2 - EQs[e].coef[j] * coef1; + + coef_t g = 0; + for (int j = nVars; j >= 0; j--) { + g = gcd(abs(SUBs[e2].coef[j]), g); + if (g == 1) + break; + } + if (g != 0 && g != 1) + for (int j = nVars; j >= 0; j--) + SUBs[e2].coef[j] /= g; + } + + // remove redundent wildcard equality + if (!preserveThisConstraint) { + if (e < nEQs-1) + eqnncpy (&EQs[e], &EQs[nEQs-1], nVars); + nEQs--; + deleteVariable(i); + } + + break; + } + } + + // remove multi-wildcard equality in approximation mode + if (inApproximateMode) + for (int e = nEQs-1; e >= 0; e--) + for (int i = nVars; i >= safeVars+1; i--) + if (EQs[e].coef[i] != 0) { + int j = i-1; + for (; j >= safeVars+1; j--) + if (EQs[e].coef[j] != 0) + break; + + if (j != safeVars) { + if (e < nEQs-1) + eqnncpy (&EQs[e], &EQs[nEQs-1], nVars); + nEQs--; + } + + break; + } + + if (renormalize) + normalize(); +} + + +void Problem:: check() const { +#ifndef NDEBUG + int v = nSUBs; + checkVars(nVars+1); + for(int i = 1; i <= safeVars; i++) if (var[i] > 0) v++; + assert(v == varsOfInterest); + for(int e = 0; e < nGEQs; e++) assert(GEQs[e].touched || GEQs[e].key != 0); + if(!mayBeRed) { + for(int e = 0; e < nEQs; e++) assert(!EQs[e].color); + for(int e = 0; e < nGEQs; e++) assert(!GEQs[e].color); + } + else + for(int i = safeVars+1; i <= nVars; i++) { + int isBlack = 0; + int isRed = 0; + for(int e = 0; e < nEQs; e++) + if (EQs[e].coef[i]) { + if (EQs[e].color) isRed = 1; + else isBlack = 1; + } + for(int e = 0; e < nGEQs; e++) + if (GEQs[e].coef[i]) { + if (GEQs[e].color) isRed = 1; + else isBlack = 1; + } + if (isBlack && isRed && 0) { + fprintf(outputFile,"Mixed Red and Black variable:\n"); + printProblem(); + } + } +#endif +} + + +void Problem::rememberRedConstraint(eqn *e, redType type, coef_t stride) { + // Check if this is really a stride constraint + if (type == redEQ && newVar == nVars && e->coef[newVar]) { + type = redStride; + stride = e->coef[newVar]; + } + // else for(int i = safeVars+1; i <= nVars; i++) assert(!e->coef[i]); // outdated -- by chun 10/30/2008 + + assert(type != notRed); + assert(type == redStride || stride == 0); + + if (TRACE) { + fprintf(outputFile,"being asked to remember red constraint:\n"); + switch(type) { + case notRed: fprintf(outputFile,"notRed: "); + break; + case redGEQ: fprintf(outputFile,"Red: 0 <= "); + break; + case redLEQ: fprintf(outputFile,"Red: 0 >= "); + break; + case redEQ: fprintf(outputFile,"Red: 0 == "); + break; + case redStride: fprintf(outputFile,"Red stride " coef_fmt ": ",stride); + break; + } + printTerm(e,1); + fprintf(outputFile,"\n"); + printProblem(); + fprintf(outputFile,"----\n"); + } + + // Convert redLEQ to redGEQ + eqn mem; + eqnncpy(&mem,e, nVars); + e = &mem; + if (type == redLEQ) { + for(int i = 0; i <= safeVars; i++) + e->coef[i] = -e->coef[i]; + type = redGEQ; + } + + // Prepare coefficient array for red constraint + bool has_wildcard = false; + coef_t coef[varsOfInterest-nextWildcard+1]; + for (int i = 0; i <= varsOfInterest-nextWildcard; i++) + coef[i] = 0; + for (int i = 0; i <= safeVars; i++) { + if (var[i] < 0) { + if (e->coef[i] != 0) { + coef[varsOfInterest-var[i]] = e->coef[i]; + has_wildcard = true; + } + } + else + coef[var[i]] = e->coef[i]; + } + + // Sophisticated back substituion for wildcards, use Gaussian elimination + // as a fallback if no simple equations available. -- by chun 10/13/2008 + if (has_wildcard) { + // Find substitutions involving wildcard + coef_t *repl_subs[nSUBs]; + int num_wild_in_repl_subs[nSUBs]; + int num_repl_subs = 0; + for (int i = 0; i < nSUBs; i++) { + int t = 0; + for (int j = 1; j <= safeVars; j++) { + if (var[j] < 0 && SUBs[i].coef[j] != 0) + t++; + } + if (t > 0) { + repl_subs[num_repl_subs] = new coef_t[varsOfInterest-nextWildcard+1]; + for (int j = 0; j <= varsOfInterest-nextWildcard; j++) + repl_subs[num_repl_subs][j] = 0; + + for (int k = 0; k <= safeVars; k++) + repl_subs[num_repl_subs][(var[k]<0)?varsOfInterest-var[k]:var[k]] = SUBs[i].coef[k]; + repl_subs[num_repl_subs][SUBs[i].key] = -1; + num_wild_in_repl_subs[num_repl_subs] = t; + num_repl_subs++; + } + } + + int wild_solved[-nextWildcard+1]; + bool has_unsolved = false; + for (int i = 1; i <= -nextWildcard; i++) { + int minimum_wild = 0; + int pos; + for (int j = 0; j < num_repl_subs; j++) + if (repl_subs[j][varsOfInterest+i] != 0 && (minimum_wild == 0 || num_wild_in_repl_subs[j] < minimum_wild)) { + minimum_wild = num_wild_in_repl_subs[j]; + pos = j; + } + + if (minimum_wild == 0) { + wild_solved[i] = -1; + if (coef[varsOfInterest+i] != 0) { + fprintf(outputFile,"No feasible back substitutions available\n"); + printProblem(); + exit(1); + } + } + else if (minimum_wild == 1) + wild_solved[i] = pos; + else { + wild_solved[i] = -1; + if (coef[varsOfInterest+i] != 0) + has_unsolved = true; + } + } + + // Gaussian elimination + while (has_unsolved) { + for (int i = 0; i < num_repl_subs; i++) + if (num_wild_in_repl_subs[i] > 1) { + for (int j = 1; j <= -nextWildcard; j++) { + if (repl_subs[i][varsOfInterest+j] != 0 && wild_solved[j] >= 0) { + int s = wild_solved[j]; + coef_t l = lcm(abs(repl_subs[i][varsOfInterest+j]), abs(repl_subs[s][varsOfInterest+j])); + coef_t scale_1 = l/abs(repl_subs[i][varsOfInterest+j]); + coef_t scale_2 = l/abs(repl_subs[s][varsOfInterest+j]); + int sign = ((repl_subs[i][varsOfInterest+j]>0)?1:-1) * ((repl_subs[s][varsOfInterest+j]>0)?1:-1); + for (int k = 0; k <= varsOfInterest-nextWildcard; k++) + repl_subs[i][k] = scale_1*repl_subs[i][k] - sign*scale_2*repl_subs[s][k]; + num_wild_in_repl_subs[i]--; + } + } + + if (num_wild_in_repl_subs[i] == 1) { + for (int j = 1; j <= -nextWildcard; j++) + if (repl_subs[i][varsOfInterest+j] != 0) { + assert(wild_solved[j]==-1); + wild_solved[j] = i; + break; + } + } + else if (num_wild_in_repl_subs[i] > 1) { + int pos = 0; + for (int j = 1; j <= -nextWildcard; j++) + if (repl_subs[i][varsOfInterest+j] != 0) { + pos = j; + break; + } + assert(pos > 0); + + for (int j = i+1; j < num_repl_subs; j++) + if (repl_subs[j][varsOfInterest+pos] != 0) { + coef_t l = lcm(abs(repl_subs[i][varsOfInterest+pos]), abs(repl_subs[j][varsOfInterest+pos])); + coef_t scale_1 = l/abs(repl_subs[i][varsOfInterest+pos]); + coef_t scale_2 = l/abs(repl_subs[j][varsOfInterest+pos]); + int sign = ((repl_subs[i][varsOfInterest+pos]>0)?1:-1) * ((repl_subs[j][varsOfInterest+pos]>0)?1:-1); + for (int k = 0; k <= varsOfInterest-nextWildcard; k++) + repl_subs[j][k] = scale_2*repl_subs[j][k] - sign*scale_1*repl_subs[i][k]; + + num_wild_in_repl_subs[j] = 0; + int first_wild = 0; + for (int k = 1; k <= -nextWildcard; k++) + if (repl_subs[j][varsOfInterest+k] != 0) { + num_wild_in_repl_subs[j]++; + first_wild = k; + } + + if (num_wild_in_repl_subs[j] == 1) { + if (wild_solved[first_wild] < 0) + wild_solved[first_wild] = j; + } + } + } + } + + has_unsolved = false; + for (int i = 1; i <= -nextWildcard; i++) + if (coef[varsOfInterest+i] != 0 && wild_solved[i] < 0) { + has_unsolved = true; + break; + } + } + + // Substitute all widecards in the red constraint + for (int i = 1; i <= -nextWildcard; i++) { + if (coef[varsOfInterest+i] != 0) { + int s = wild_solved[i]; + assert(s >= 0); + + coef_t l = lcm(abs(coef[varsOfInterest+i]), abs(repl_subs[s][varsOfInterest+i])); + coef_t scale_1 = l/abs(coef[varsOfInterest+i]); + coef_t scale_2 = l/abs(repl_subs[s][varsOfInterest+i]); + int sign = ((coef[varsOfInterest+i]>0)?1:-1) * ((repl_subs[s][varsOfInterest+i]>0)?1:-1); + for (int j = 0; j <= varsOfInterest-nextWildcard; j++) + coef[j] = scale_1*coef[j] - sign*scale_2*repl_subs[s][j]; + + if (scale_1 != 1) + stride *= scale_1; + } + } + + for (int i = 0; i < num_repl_subs; i++) + delete []repl_subs[i]; + } + + // Ready to insert into redMemory + int m = nMemories++; + redMemory[m].length = 0; + redMemory[m].kind = type; + redMemory[m].constantTerm = coef[0]; + for(int i = 1; i <= varsOfInterest; i++) + if (coef[i]) { + int j = redMemory[m].length++; + redMemory[m].coef[j] = coef[i]; + redMemory[m].var[j] = i; + } + if (type == redStride) redMemory[m].stride = stride; + if (DBUG) { + fprintf(outputFile,"Red constraint remembered\n"); + printProblem(); + } +} + +void Problem::recallRedMemories() { + if (nMemories) { + if (TRACE) { + fprintf(outputFile,"Recalling red memories\n"); + printProblem(); + } + + eqn* e = 0; + for(int m = 0; m < nMemories; m++) { + switch(redMemory[m].kind) { + case redGEQ: + { + int temporary_eqn = newGEQ(); + e = &GEQs[temporary_eqn]; + eqnnzero(e, nVars); + e->touched = 1; + break; + } + case redEQ: + { + int temporary_eqn = newEQ(); + e = &EQs[temporary_eqn]; + eqnnzero(e, nVars); + break; + } + case redStride: + { + int temporary_eqn = newEQ(); + e = &EQs[temporary_eqn]; + eqnnzero(e, nVars); + int i = addNewUnprotectedWildcard(); + e->coef[i] = -redMemory[m].stride; + break; + } + default: + assert(0); + } + e->color = EQ_RED; + e->coef[0] = redMemory[m].constantTerm; + for(int i = 0; i < redMemory[m].length; i++) { + int v = redMemory[m].var[i]; + assert(var[forwardingAddress[v]] == v); + e->coef[forwardingAddress[v]] = redMemory[m].coef[i]; + } + } + + nMemories = 0; + if (TRACE) { + fprintf(outputFile,"Red memories recalled\n"); + printProblem(); + } + } +} + +void Problem::swapVars(int i, int j) { + if (DEBUG) { + use_ugly_names++; + fprintf(outputFile, "Swapping %d and %d\n", i, j); + printProblem(); + use_ugly_names--; + } + std::swap(var[i], var[j]); + for (int e = nGEQs - 1; e >= 0; e--) + if (GEQs[e].coef[i] != GEQs[e].coef[j]) { + GEQs[e].touched = true; + coef_t t = GEQs[e].coef[i]; + GEQs[e].coef[i] = GEQs[e].coef[j]; + GEQs[e].coef[j] = t; + } + for (int e = nEQs - 1; e >= 0; e--) + if (EQs[e].coef[i] != EQs[e].coef[j]) { + coef_t t = EQs[e].coef[i]; + EQs[e].coef[i] = EQs[e].coef[j]; + EQs[e].coef[j] = t; + } + for (int e = nSUBs - 1; e >= 0; e--) + if (SUBs[e].coef[i] != SUBs[e].coef[j]) { + coef_t t = SUBs[e].coef[i]; + SUBs[e].coef[i] = SUBs[e].coef[j]; + SUBs[e].coef[j] = t; + } + if (DEBUG) { + use_ugly_names++; + fprintf(outputFile, "Swapping complete \n"); + printProblem(); + fprintf(outputFile, "\n"); + use_ugly_names--; + } +} + +void Problem::addingEqualityConstraint(int e) { + if (addingOuterEqualities && originalProblem != noProblem && + originalProblem != this && !conservative) { + int e2 = originalProblem->newEQ(); + if (TRACE) + fprintf(outputFile, "adding equality constraint %d to outer problem\n", e2); + eqnnzero(&originalProblem->EQs[e2], originalProblem->nVars); + for (int i = nVars; i >= 1; i--) { + int j; + for (j = originalProblem->nVars; j >= 1; j--) + if (originalProblem->var[j] == var[i]) + break; + if (j <= 0 || (outerColor && j > originalProblem->safeVars)) { + if (DBUG) + fprintf(outputFile, "retracting\n"); + originalProblem->nEQs--; + return; + } + originalProblem->EQs[e2].coef[j] = EQs[e].coef[i]; + } + originalProblem->EQs[e2].coef[0] = EQs[e].coef[0]; + + originalProblem->EQs[e2].color = outerColor; + if (DBUG) + originalProblem->printProblem(); + } +} + + +// Initialize hash codes for inequalities, remove obvious redundancy. +// Case 1: +// a1*x1+a2*x2+...>=c (1) +// a1*x2+a2*x2+...>=c' (2) +// if c>=c' then (2) is redundant, and vice versa. +// +// case 2: +// a1*x1+a2*x2+...>=c (1) +// a1*x1+a2*x2+...<=c' (2) +// if c=c' then add equality of (1) or (2), +// if c>c' then no solution. +// +// Finally it calls extended normalize process which handles +// wildcards in redundacy removal. +normalizeReturnType Problem::normalize() { + int i, j; + bool coupledSubscripts = false; + + check(); + + for (int e = 0; e < nGEQs; e++) { + if (!GEQs[e].touched) { + if (!singleVarGEQ(&GEQs[e])) + coupledSubscripts = true; + } + else { // normalize e + coef_t g; + int topVar; + int i0; + coef_t hashCode; + + { + int *p = &packing[0]; + for (int k = 1; k <= nVars; k++) + if (GEQs[e].coef[k]) { + *(p++) = k; + } + topVar = (p - &packing[0]) - 1; + } + + if (topVar == -1) { + if (GEQs[e].coef[0] < 0) { + // e has no solution + return (normalize_false); + } + deleteGEQ(e); + 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] = int_div(GEQs[e].coef[0], g); + } + else { + coupledSubscripts = true; + i0 = topVar; + i = packing[i0--]; + g = GEQs[e].coef[i]; + hashCode = g * (i + 3); + if (g < 0) + g = -g; + for (; i0 >= 0; i0--) { + coef_t 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--) { + coef_t x; + i = packing[i0]; + x = GEQs[e].coef[i]; + hashCode = hashCode * keyMult * (i + 3) + x; + } + if (g > 1) { + GEQs[e].coef[0] = int_div(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]; + } + } + + { + coef_t g2 = abs(hashCode); // get e's hash code + j = static_cast<int>(g2 % static_cast<coef_t>(hashTableSize)); + assert (g2 % (coef_t) hashTableSize == j); + 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) { //insert e into the empty entry in hash table + eqnnzero(proto, nVars); + 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; + 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) { + e2 = fastLookup[maxKeys - eKey]; + if (e2 >= 0 && e2 < e && GEQs[e2].key == -eKey) { + // confirm it is indeed a match -- by chun 10/29/2008 + int k; + for (k = nVars; k >= 1; k--) + if (GEQs[e2].coef[k] != -GEQs[e].coef[k]) + break; + + if (k == 0) { + if (GEQs[e2].coef[0] < -GEQs[e].coef[0]) { + // there is no solution from e and e2 + return (normalize_false); + } + else if (GEQs[e2].coef[0] == -GEQs[e].coef[0]) { + // reduce e and e2 to an equation + int neweq = newEQ(); + eqnncpy(&EQs[neweq], &GEQs[e], nVars); + EQs[neweq].color = GEQs[e].color || GEQs[e2].color; + addingEqualityConstraint(neweq); + } + } + } + + e2 = fastLookup[maxKeys + eKey]; + if (e2 >= 0 && e2 < e && GEQs[e2].key == eKey) { + // confirm it is indeed a match -- by chun 10/29/2008 + int k; + for (k = nVars; k >= 1; k--) + if (GEQs[e2].coef[k] != GEQs[e].coef[k]) + break; + + if (k == 0) { + if (GEQs[e2].coef[0] > GEQs[e].coef[0] || + (GEQs[e2].coef[0] == GEQs[e].coef[0] && GEQs[e2].color)) { + // e2 is redundant + GEQs[e2].coef[0] = GEQs[e].coef[0]; + GEQs[e2].color = GEQs[e].color; + deleteGEQ(e); + e--; + continue; + } + else { + // e is redundant + deleteGEQ(e); + e--; + continue; + } + } + } + } + fastLookup[maxKeys + eKey] = e; + } + } + + // bypass entended normalization for temporary problem + if (!isTemporary && !inApproximateMode) + normalize_ext(); + + return coupledSubscripts ? normalize_coupled : normalize_uncoupled; +} + +// +// Extended normalize process, remove redundancy involving wildcards. +// e.g. +// exists alpha, beta: +// v1+8*alpha<=v2<=15+8*alpha (1) +// v1+8*beta<=v2<=15+8*beta (2) +// if there are no other inequalities involving alpha or beta, +// then either (1) or (2) is redundant. Such case can't be simplified +// by fourier-motzkin algorithm due to special meanings of existentials. +// +void Problem::normalize_ext() { + std::vector<BoolSet<> > disjoint_wildcards(nVars-safeVars, BoolSet<>(nVars-safeVars)); + std::vector<BoolSet<> > wildcards_in_inequality(nVars-safeVars, BoolSet<>(nGEQs)); + for (int i = 0; i < nVars-safeVars; i++) { + disjoint_wildcards[i].set(i); + } + + // create disjoint wildcard sets according to inequalities + for (int e = 0; e < nGEQs; e++) { + std::vector<BoolSet<> >::iterator first_set = disjoint_wildcards.end(); + for (int i = 0; i < nVars-safeVars; i++) + if (GEQs[e].coef[i+safeVars+1] != 0) { + wildcards_in_inequality[i].set(e); + + std::vector<BoolSet<> >::iterator cur_set = disjoint_wildcards.end(); + for (std::vector<BoolSet<> >::iterator j = disjoint_wildcards.begin(); j != disjoint_wildcards.end(); j++) + if ((*j).get(i)) { + cur_set = j; + break; + } + assert(cur_set!=disjoint_wildcards.end()); + if (first_set == disjoint_wildcards.end()) + first_set = cur_set; + else if (first_set != cur_set) { + *first_set |= *cur_set; + disjoint_wildcards.erase(cur_set); + } + } + } + + // do not consider wildcards appearing in equalities + for (int e = 0; e < nEQs; e++) + for (int i = 0; i < nVars-safeVars; i++) + if (EQs[e].coef[i+safeVars+1] != 0) { + for (std::vector<BoolSet<> >::iterator j = disjoint_wildcards.begin(); j != disjoint_wildcards.end(); j++) + if ((*j).get(i)) { + disjoint_wildcards.erase(j); + break; + } + } + + // create disjoint inequality sets + std::vector<BoolSet<> > disjoint_inequalities(disjoint_wildcards.size()); + for (size_t i = 0; i < disjoint_wildcards.size(); i++) + for (int j = 0; j < nVars-safeVars; j++) + if (disjoint_wildcards[i].get(j)) + disjoint_inequalities[i] |= wildcards_in_inequality[j]; + + // hash the inequality again, this time separate wildcard variables from + // regular variables + coef_t hash_safe[nGEQs]; + coef_t hash_wild[nGEQs]; + for (int e = 0; e < nGEQs; e++) { + coef_t hashCode = 0; + for (int i = 1; i <= safeVars; i++) + if (GEQs[e].coef[i] != 0) + hashCode = hashCode * keyMult * (i+3) + GEQs[e].coef[i]; + hash_safe[e] = hashCode; + + hashCode = 0; + for (int i = safeVars+1; i <= nVars; i++) + if (GEQs[e].coef[i] != 0) + hashCode = hashCode * keyMult + GEQs[e].coef[i]; + hash_wild[e] = hashCode; + } + + // sort hash keys for each disjoint set + std::vector<std::vector<std::pair<int, std::pair<coef_t, coef_t> > > > disjoint_hash(disjoint_inequalities.size()); + for (size_t i = 0; i < disjoint_inequalities.size(); i++) + for (int e = 0; e < nGEQs; e++) + if (disjoint_inequalities[i].get(e)) { + std::vector<std::pair<int, std::pair<coef_t, coef_t> > >::iterator j = disjoint_hash[i].begin(); + for (; j != disjoint_hash[i].end(); j++) + if ((hash_safe[e] > (*j).second.first) || + (hash_safe[e] == (*j).second.first && hash_wild[e] > (*j).second.second)) + break; + disjoint_hash[i].insert(j, std::make_pair(e, std::make_pair(hash_safe[e], hash_wild[e]))); + } + + // test wildcard equivalance + std::vector<bool> is_dead(nGEQs, false); + for (size_t i = 0; i < disjoint_wildcards.size(); i++) { + if (disjoint_inequalities[i].num_elem() == 0) + continue; + + for (size_t j = i+1; j < disjoint_wildcards.size(); j++) { + if (disjoint_wildcards[i].num_elem() != disjoint_wildcards[j].num_elem() || + disjoint_hash[i].size() != disjoint_hash[j].size()) + continue; + + bool match = true; + for (size_t k = 0; k < disjoint_hash[i].size(); k++) { + if (disjoint_hash[i][k].second != disjoint_hash[j][k].second) { + match = false; + break; + } + } + if (!match) + continue; + + // confirm same coefficients for regular variables + for (size_t k = 0; k < disjoint_hash[i].size(); k++) { + for (int p = 1; p <= safeVars; p++) + if (GEQs[disjoint_hash[i][k].first].coef[p] != GEQs[disjoint_hash[j][k].first].coef[p]) { + match = false; + break; + } + if (!match) + break; + } + if (!match) + continue; + + // now try combinatory wildcard matching + std::vector<int> wild_map(nVars-safeVars, -1); + for (size_t k = 0; k < disjoint_hash[i].size(); k++) { + int e1 = disjoint_hash[i][k].first; + int e2 = disjoint_hash[j][k].first; + + for (int p = 0; p < nVars-safeVars; p++) + if (GEQs[e1].coef[p+safeVars+1] != 0) { + if (wild_map[p] == -1) { + for (int q = 0; q < nVars-safeVars; q++) + if (wild_map[q] == -1 && + GEQs[e2].coef[q+safeVars+1] == GEQs[e1].coef[p+safeVars+1]) { + wild_map[p] = q; + wild_map[q] = p; + break; + } + if (wild_map[p] == -1) { + match = false; + break; + } + } + else if (GEQs[e2].coef[wild_map[p]+safeVars+1] != GEQs[e1].coef[p+safeVars+1]) { + match = false; + break; + } + } + if (!match) + break; + + for (int p = 0; p < nVars-safeVars; p++) + if (GEQs[e2].coef[p+safeVars+1] != 0 && + (wild_map[p] == -1 || GEQs[e2].coef[p+safeVars+1] != GEQs[e1].coef[wild_map[p]+safeVars+1])) { + match = false; + break; + } + if (!match) + break; + } + if (!match) + continue; + + // check constants + int dir = 0; + for (size_t k = 0; k < disjoint_hash[i].size(); k++) { + if (GEQs[disjoint_hash[i][k].first].coef[0] > GEQs[disjoint_hash[j][k].first].coef[0]) { + if (dir == 0) + dir = 1; + else if (dir == -1) { + match = false; + break; + } + } + else if (GEQs[disjoint_hash[i][k].first].coef[0] < GEQs[disjoint_hash[j][k].first].coef[0]) { + if (dir == 0) + dir = -1; + else if (dir == 1) { + match = false; + break; + } + } + } + if (!match) + continue; + + // check redness + int red_dir = 0; + for (size_t k = 0; k < disjoint_hash[i].size(); k++) { + if (GEQs[disjoint_hash[i][k].first].color > GEQs[disjoint_hash[j][k].first].color) { + if (red_dir == 0) + red_dir = 1; + else if (red_dir == -1) { + match = false; + break; + } + } + else if (GEQs[disjoint_hash[i][k].first].color < GEQs[disjoint_hash[j][k].first].color) { + if (red_dir == 0) + red_dir = -1; + else if (red_dir == 1) { + match = false; + break; + } + } + } + if (!match) + continue; + + // remove redundant inequalities + if (dir == 1 || (dir == 0 && red_dir == 1)) { + for (size_t k = 0; k < disjoint_hash[i].size(); k++) { + GEQs[disjoint_hash[i][k].first].coef[0] = GEQs[disjoint_hash[j][k].first].coef[0]; + GEQs[disjoint_hash[i][k].first].color = GEQs[disjoint_hash[j][k].first].color; + is_dead[disjoint_hash[j][k].first] = true; + } + } + else { + for (size_t k = 0; k < disjoint_hash[i].size(); k++) { + is_dead[disjoint_hash[j][k].first] = true; + } + } + } + } + + // eliminate dead inequalities + for (int e = nGEQs-1; e >= 0; e--) + if (is_dead[e]) { + deleteGEQ(e); + } +} + + +void initializeOmega(void) { + if (omegaInitialized) + return; + +// assert(sizeof(eqn)==sizeof(int)*(headerWords)+sizeof(coef_t)*(1+maxVars)); + nextWildcard = 0; + nextKey = maxVars + 1; + for (int 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; +} + +// +// This is experimental (I would say, clinical) fact: +// If the code below is removed then simplifyProblem cycles. +// +class brainDammage { +public: + brainDammage(); +}; + +brainDammage::brainDammage() { + initializeOmega(); +} + +static brainDammage Podgorny; + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_solve.cc b/omegalib/omega/src/omega_core/oc_solve.cc new file mode 100644 index 0000000..c25b6d0 --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_solve.cc @@ -0,0 +1,1378 @@ +/***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team + Copyright (C) 2005-2011 Chun Chen + All Rights Reserved. + + Purpose: + Solve ineqalities. + + Notes: + + History: +*****************************************************************************/ + +#include <omega/omega_core/oc_i.h> + +namespace omega { + +static int solveDepth = 0; +#define maxDead maxmaxGEQs + +int Problem::solve(int desiredResult) { + assert(omegaInitialized); + int result; + + checkVars(nVars+1); + assert(nVars >= safeVars); + if (desiredResult != OC_SOLVE_SIMPLIFY) + safeVars = 0; + + solveDepth++; + if (solveDepth > 50) { + fprintf(outputFile, "Solve depth = %d, inApprox = %d, aborting\n", solveDepth, inApproximateMode); + printProblem(); + fflush(outputFile); + + if (solveDepth > 60) + exit(2); + } + + check(); + do { + doItAgain = 0; + check(); + if (solveEQ() == false) { + solveDepth--; + return (false); + } + check(); + if (!nGEQs) { + result = true; + nVars = safeVars; + break; + } + else + result = solveGEQ(desiredResult); + check(); + } + while (doItAgain && desiredResult == OC_SOLVE_SIMPLIFY); + solveDepth--; + + return (result); +} + + +// Supporting functions of solveGEQ +int Problem::smoothWeirdEquations() { + int e1, e2, e3, p, q, k; + coef_t alpha, alpha1, alpha2, alpha3; + coef_t c; + int v; + int result = 0; + + for (e1 = nGEQs - 1; e1 >= 0; e1--) + if (!GEQs[e1].color) { + coef_t 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 = newGEQ(); /* Create a scratch GEQ,not part of the prob.*/ + nGEQs--; + for (v = nVars; v >= 1; v--) + GEQs[e3].coef[v] = int_div(6 * GEQs[e1].coef[v] + g / 2, g); + GEQs[e3].color = EQ_BLACK; + 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 = nGEQs - 1; e2 >= 0; e2--) + if (e1 != e2 && !GEQs[e2].color) { + for (p = nVars; p > 1; p--) { + for (q = p - 1; q > 0; q--) { + alpha = check_mul(GEQs[e1].coef[p], GEQs[e2].coef[q]) - check_mul(GEQs[e2].coef[p], GEQs[e1].coef[q]); + if (alpha != 0) + goto foundPQ; + } + } + continue; + + foundPQ: + + alpha1 = check_mul(GEQs[e2].coef[q], GEQs[e3].coef[p]) - check_mul(GEQs[e2].coef[p], GEQs[e3].coef[q]); + alpha2 = -(check_mul(GEQs[e1].coef[q], GEQs[e3].coef[p]) - check_mul(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 (check_mul(alpha3, GEQs[e3].coef[k]) + != check_mul(alpha1, GEQs[e1].coef[k]) + check_mul(alpha2, GEQs[e2].coef[k])) + goto nextE2; + + c = check_mul(alpha1, GEQs[e1].coef[0]) + check_mul(alpha2, GEQs[e2].coef[0]); + if (c < check_mul(alpha3, (GEQs[e3].coef[0] + 1))) + GEQs[e3].coef[0] = int_div(c, alpha3); + + } + nextE2:; + } + if (GEQs[e3].coef[0] < 9997) { + result++; +#if !defined NDEBUG + int e4 = +#endif + newGEQ(); +#if !defined NDEBUG + assert(e3 == e4); +#endif + if (DBUG) { + fprintf(outputFile, "Smoothing wierd equations; adding:\n"); + printGEQ(&GEQs[e3]); + fprintf(outputFile, "\nto:\n"); + printProblem(); + fprintf(outputFile, "\n\n"); + } + } + } + } + return (result); +} + + +void Problem::analyzeElimination( + int &v, + int &darkConstraints, + int &darkShadowFeasible, + int &unit, + coef_t ¶llelSplinters, + coef_t &disjointSplinters, + coef_t &lbSplinters, + coef_t &ubSplinters, + int ¶llelLB) { + + parallelSplinters = (posInfinity); // was MAXINT + disjointSplinters = 0; + lbSplinters = 0; + ubSplinters = 0; + + darkConstraints = 0; + darkShadowFeasible = 1; + coef_t maxUBc = 0; + coef_t maxLBc = 0; + int e,e2; + unit = 0; + int exact = 1; + + for (e = nGEQs - 1; e >= 0; e--) { + coef_t c = GEQs[e].coef[v]; + + if (c < 0) { + coef_t Lc, Uc, g, diff, grey; + + set_max(maxUBc, -c); + Uc = -c; + for (e2 = nGEQs - 1; e2 >= 0; e2--) + if (GEQs[e2].coef[v] > 0) { + Lc = GEQs[e2].coef[v]; + g = 0; + grey = (Lc - 1) * (Uc - 1); + + for (int j = nVars; j >= 1; j--) { + coef_t diff = check_mul(Lc, GEQs[e].coef[j]) + check_mul(Uc, GEQs[e2].coef[j]); + if (diff < 0) diff = -diff; + g = gcd(g, diff); + if (g == 1) + break; + } + diff = check_mul(Lc, GEQs[e].coef[0]) + check_mul(Uc, GEQs[e2].coef[0]); + if (g == 0) { + if (diff < 0) { + /* Real shadow must be true */ + /* otherwise we would have found it during */ + /* check for opposing constraints */ + fprintf(outputFile, "Found conflicting constraints "); + printGEQ(&GEQs[e]); + fprintf(outputFile," and "); + printGEQ(&GEQs[e2]); + fprintf(outputFile,"\nin\n"); + printProblem(); + assert(diff >= 0); + } + if (diff < grey) { + darkShadowFeasible = 0; + if (parallelSplinters > diff+1) { + parallelSplinters = diff + 1; + parallelLB = e2; + } + } + else {/* dark shadow is true, don't need to worry about this constraint pair */ + } + } + else { + coef_t splinters= int_div(diff, g) - int_div(diff - grey, g); + if (splinters) exact = 0; + disjointSplinters += splinters; + if (g > 1) unit++; + darkConstraints++; + } + } + } + else if (c > 0) { + set_max(maxLBc, c); + } /* else + darkConstraints++; */ + } + + if (darkShadowFeasible) { + disjointSplinters++; + ubSplinters++; + lbSplinters++; + } + else disjointSplinters = (posInfinity); // was MAXINT + + + if (!darkShadowFeasible || !exact) + for (e = nGEQs - 1; e >= 0; e--) { + coef_t c = GEQs[e].coef[v]; + if (c < -1) { + c = -c; + ubSplinters += 1+(check_mul(c, maxLBc) - c - maxLBc) / maxLBc; + } + else if (c > 1) { + lbSplinters += 1+ (check_mul(c, maxUBc) - c - maxUBc) / maxUBc; + } + } + + if (DEBUG) { + fprintf(outputFile,"analyzing elimination of %s(%d)\n",variable(v),v); + if (darkShadowFeasible) + fprintf(outputFile," # dark constraints = %d\n", darkConstraints); + else + fprintf(outputFile," dark shadow obviously unfeasible\n"); + + fprintf(outputFile," " coef_fmt " LB splinters\n", lbSplinters); + fprintf(outputFile," " coef_fmt " UB splinters\n", ubSplinters); + if (disjointSplinters != (posInfinity)) + fprintf(outputFile," " coef_fmt " disjoint splinters\n", disjointSplinters); + if (parallelSplinters != (posInfinity)) + fprintf(outputFile," " coef_fmt " parallel splinters\n", parallelSplinters); + fprintf(outputFile, "\n"); + fprintf(outputFile," %3d unit score \n", unit); + } +} + + +void Problem::partialElimination() { + if (DBUG) { + fprintf(outputFile, "Performing Partial elimination\n"); + printProblem(); + } + int fv; + if (0) + fv = 0; + else + fv = safeVars; + bool somethingHappened = false; + for (int i = nVars; i > fv; i--) { + bool isDead[maxmaxGEQs]; + int e; + for (e = nGEQs-1; e >= 0; e--) isDead[e] = false; + int deadEqns[maxDead]; + int numDead = 0; + for (int e1 = nGEQs-1; e1 >= 0; e1--) + if (abs(GEQs[e1].coef[i]) == 1) { + bool isGood = true; + for (int e2 = nGEQs-1; e2 >= 0; e2--) + if (check_mul(GEQs[e2].coef[i], GEQs[e1].coef[i]) < 0) + if (GEQs[e1].key != -GEQs[e2].key) { + coef_t Uc = abs(GEQs[e2].coef[i]); + for (int k = nVars; k > fv; k--) + if (GEQs[e2].coef[k] + check_mul(GEQs[e1].coef[k], Uc) != 0) + isGood = false; + } + if (isGood) { + somethingHappened = true; + for (int e2 = nGEQs-1; e2 >= 0; e2--) + if (check_mul(GEQs[e2].coef[i], GEQs[e1].coef[i]) < 0) { + if (GEQs[e1].key != -GEQs[e2].key) { + coef_t Uc = abs(GEQs[e2].coef[i]); + int new_eqn; + if (numDead == 0) { + new_eqn = newGEQ(); + } + else { + new_eqn = deadEqns[--numDead]; + } + isDead[new_eqn] = false; + if (DBUG) { + fprintf(outputFile,"Eliminating constraint on %s\n", variable(i)); + fprintf(outputFile, "e1 = %d, e2 = %d, gen = %d\n", e1, e2, new_eqn); + printGEQ(&(GEQs[e1])); + fprintf(outputFile, "\n"); + printGEQ(&(GEQs[e2])); + fprintf(outputFile, "\n"); + } + + for (int k = nVars; k >= 0; k--) + GEQs[new_eqn].coef[k] = GEQs[e2].coef[k] + check_mul(GEQs[e1].coef[k], Uc); + GEQs[new_eqn].touched = true; + GEQs[new_eqn].color = GEQs[e2].color | GEQs[e1].color; + if (DBUG) { + fprintf(outputFile, "give "); + printGEQ(&(GEQs[new_eqn])); + fprintf(outputFile, "\n"); + } + assert(GEQs[new_eqn].coef[i] == 0); + } + } + deadEqns[numDead++] = e1; + isDead[e1] = true; + if (DEBUG) + fprintf(outputFile, "Killed %d\n", e1); + } + } + for (e = nGEQs - 1; e >= 0; e--) + if (isDead[e]) { + deleteGEQ(e); + } + } + if (somethingHappened && DBUG) { + fprintf(outputFile, "Result of Partial elimination\n"); + printProblem(); + } +} + + +int Problem:: solveGEQ(int desiredResult) { + int i, j, k, e; + int fv; + int result; + int coupledSubscripts; + int eliminateAgain; + int smoothed = 0; + int triedEliminatingRedundant = 0; + j = 0; + + if (desiredResult != OC_SOLVE_SIMPLIFY) { + nSUBs = 0; + nMemories = 0; + safeVars = 0; + varsOfInterest = 0; + } + +solveGEQstart: + while (1) { + assert(desiredResult == OC_SOLVE_SIMPLIFY || nSUBs == 0); + check_number_GEQs(nGEQs); + + if (DEBUG) { + fprintf(outputFile, "\nSolveGEQ(%d,%d):\n", desiredResult, pleaseNoEqualitiesInSimplifiedProblems); + printProblem(); + fprintf(outputFile, "\n"); + } + +#ifndef NDEBUG + for(e=0;e<nSUBs;e++) + for(i=safeVars+1;i<=nVars;i++) + assert(!SUBs[e].coef[i]); +#endif + + check(); + + if (nVars == 1) { + int uColor = EQ_BLACK; + int lColor = EQ_BLACK; + coef_t upperBound = posInfinity; + coef_t lowerBound = negInfinity; + for (e = nGEQs - 1; e >= 0; e--) { + coef_t a = GEQs[e].coef[1]; + coef_t c = GEQs[e].coef[0]; + /* our equation is ax + c >= 0, or ax >= -c, or c >= -ax */ + if (a == 0) { + if (c < 0) { + if (TRACE) + fprintf(outputFile, "equations have no solution (G)\n"); + return (false); + } + } + else if (a > 0) { + if (a != 1) + c = int_div(c, a); + if (lowerBound < -c || (lowerBound == -c && !isRed(&GEQs[e]))) { + lowerBound = -c; + lColor = GEQs[e].color; + } + } + else { + if (a != -1) + c = int_div(c, -a); + if (upperBound > c || (upperBound == c && !isRed(&GEQs[e]))) { + upperBound = c; + uColor = GEQs[e].color; + } + } + } + if (DEBUG) + fprintf(outputFile, "upper bound = " coef_fmt "\n", upperBound); + if (DEBUG) + fprintf(outputFile, "lower bound = " coef_fmt "\n", lowerBound); + if (lowerBound > upperBound) { + if (TRACE) + fprintf(outputFile, "equations have no solution (H)\n"); + return (false); + } + if (desiredResult == OC_SOLVE_SIMPLIFY) { + nGEQs = 0; + if (safeVars == 1) { + if (lowerBound == upperBound && !uColor && !lColor) { + int e = newEQ(); + assert(e == 0); + EQs[e].coef[0] = -lowerBound; + EQs[e].coef[1] = 1; + EQs[e].color = lColor | uColor; + return (solve(desiredResult)); + } + else { + if (lowerBound > negInfinity) { + int e = newGEQ(); + assert(e == 0); + GEQs[e].coef[0] = -lowerBound; + GEQs[e].coef[1] = 1; + GEQs[e].key = 1; + GEQs[e].color = lColor; + GEQs[e].touched = 0; + } + if (upperBound < posInfinity) { + int e = newGEQ(); + GEQs[e].coef[0] = upperBound; + GEQs[e].coef[1] = -1; + GEQs[e].key = -1; + GEQs[e].color = uColor; + GEQs[e].touched = 0; + } + } + } + else + nVars = 0; + return (true); + } + if (originalProblem != noProblem && !lColor && !uColor && !conservative && lowerBound == upperBound) { + int e = newEQ(); + assert(e == 0); + EQs[e].coef[0] = -lowerBound; + EQs[e].coef[1] = 1; + EQs[e].color = EQ_BLACK; + addingEqualityConstraint(0); + } + return (true); + } + + if (!variablesFreed) { + variablesFreed = 1; + if (desiredResult != OC_SOLVE_SIMPLIFY) + freeEliminations(0); + else + freeEliminations(safeVars); + if (nVars == 1) + continue; + } + + + switch (normalize()) { + case normalize_false: + return (false); + break; + case normalize_coupled: + coupledSubscripts = true; + break; + case normalize_uncoupled: + coupledSubscripts = false; + break; + default: + coupledSubscripts = false; + assert(0 && "impossible case in SolveGEQ"); + } + + + if ((doTrace && desiredResult == OC_SOLVE_SIMPLIFY) || DBUG) { + fprintf(outputFile, "\nafter normalization:\n"); + printProblem(); + fprintf(outputFile, "\n"); + for(e=0;e<nGEQs;e++) assert(!GEQs[e].touched); + fprintf(outputFile, "eliminating variable using fourier-motzkin elimination\n"); + } + + // eliminating variable using fourier-motzkin elimination + do { + eliminateAgain = 0; + + if (nEQs > 0) + return (solve(desiredResult)); + + if (!coupledSubscripts) { + if (safeVars == 0) + nGEQs = 0; + else + for (e = nGEQs - 1; e >= 0; e--) + if (GEQs[e].key > safeVars || -safeVars > GEQs[e].key) + deleteGEQ(e); + nVars = safeVars; + return (true); + } + + if (desiredResult != OC_SOLVE_SIMPLIFY) + fv = 0; + else + fv = safeVars; + + if (nVars == 0 || nGEQs == 0) { + nGEQs = 0; + if (desiredResult == OC_SOLVE_SIMPLIFY) + nVars = safeVars; + return (true); + } + if (desiredResult == OC_SOLVE_SIMPLIFY && nVars == safeVars) { + return (true); + } + + + if (nGEQs+6 > maxGEQs || nGEQs > 2 * nVars * nVars + 4 * nVars + 10) { + if (TRACE) + fprintf(outputFile, "TOO MANY EQUATIONS; %d equations, %d variables, ELIMINATING REDUNDANT ONES\n", nGEQs, nVars); + if (!quickKill(0,true)) + return 0; + if (nEQs > 0) + return (solve(desiredResult)); + if (TRACE) + fprintf(outputFile, "END ELIMINATION OF REDUNDANT EQUATIONS\n"); + if (DBUG) printProblem(); + } + + + { + int darkConstraints, darkShadowFeasible, unit, parallelLB; + coef_t parallelSplinters, disjointSplinters, lbSplinters, ubSplinters, splinters; + coef_t bestScore, score; + int bestVar; + int exact; + int Ue,Le; + + if (desiredResult != OC_SOLVE_SIMPLIFY) fv = 0; + else fv = safeVars; + + if (DEBUG) { + fprintf(outputFile,"Considering elimination possibilities[ \n"); + printProblem(); + } + + analyzeGEQstart: + try { + bestScore = posInfinity; + bestVar = -1; + for (i = nVars; i != fv; i--) { + analyzeElimination(i, darkConstraints, darkShadowFeasible, unit, parallelSplinters, disjointSplinters, lbSplinters, ubSplinters, parallelLB); + + score = min(min(parallelSplinters,disjointSplinters), + min(lbSplinters,ubSplinters)); + exact = score == 1; + score = 10000*(score-1) + darkConstraints; + if (score >= posInfinity) // too big the score + score = posInfinity - 1; + score -= 3*unit; + + if (score < bestScore) { + bestScore = score; + bestVar = i; + if (i > 4 && score < nGEQs) break; + } + } + assert(bestVar>=0); + exact = bestScore < 10000; + i = bestVar; + assert(i<=nVars); + analyzeElimination(i, darkConstraints, darkShadowFeasible, unit, parallelSplinters, disjointSplinters, lbSplinters, ubSplinters, parallelLB); + if (DEBUG) { + fprintf(outputFile,"] Choose to eliminate %s \n",variable(i)); + } + splinters = lbSplinters; + if (splinters <= parallelSplinters) + parallelSplinters = posInfinity; + else splinters = parallelSplinters; + if (disjointSplinters == 1) splinters = 1; + exact = splinters == 1; + if (inApproximateMode) exact = 1; + } + catch (std::overflow_error) { + int result = quickKill(0, true); + if (result == 0) + return 0; + else if (result == 1) + return true; + else { + if (nEQs > 0) + return (solve(desiredResult)); + triedEliminatingRedundant = 1; + goto analyzeGEQstart; + } + } + + if (!triedEliminatingRedundant && darkConstraints > maxGEQs) { + if (TRACE) + fprintf(outputFile, "Elimination will create TOO MANY EQUATIONS; %d equations, %d variables, %d new constraints, ELIMINATING REDUNDANT ONES\n", nGEQs, nVars,darkConstraints); + if (!quickKill(0)) + return 0; + if (nEQs > 0) + return (solve(desiredResult)); + if (TRACE) + fprintf(outputFile, "END ELIMINATION OF REDUNDANT EQUATIONS\n"); + if (DBUG) printProblem(); + + triedEliminatingRedundant = 1; + eliminateAgain = 1; + continue; + } + + if (!exact && !triedEliminatingRedundant && + safeVars > 0 && desiredResult == OC_SOLVE_SIMPLIFY) { + if (TRACE) + fprintf(outputFile, "Trying to produce exact elimination by finding redundant constraints [\n"); + if (!quickKill(1)) return 0; + if (TRACE) + fprintf(outputFile, "]\n"); + triedEliminatingRedundant = 1; + eliminateAgain = 1; + continue; + } + triedEliminatingRedundant = 0; + + if (desiredResult == OC_SOLVE_SIMPLIFY && !exact) { + partialElimination(); + switch (normalize()) { + case normalize_false: + return (false); + break; + case normalize_coupled: + case normalize_uncoupled: + break; + } + if (nEQs) return solveEQ(); + if (DBUG) fprintf(outputFile,"Stopping short due to non-exact elimination\n"); + return (true); + } + + if ( desiredResult == OC_SOLVE_SIMPLIFY && darkConstraints > maxGEQs) { + if (DBUG) fprintf(outputFile,"Stopping short due to overflow of GEQs: %d\n", darkConstraints); + return (true); + } + + if ((doTrace && desiredResult == OC_SOLVE_SIMPLIFY) || DBUG) { + fprintf(outputFile, "going to eliminate %s, (%d)\n", variable(i), i); + if (DEBUG) + printProblem(); + fprintf(outputFile, "score = " coef_fmt "/" coef_fmt "\n", bestScore,splinters); + } + + if (!exact && desiredResult == OC_SOLVE_SIMPLIFY && parallelSplinters == splinters) { + return parallelSplinter(parallelLB, parallelSplinters, desiredResult); + } + + // smoothed = 0; // what a bug!!! -- by chun 6/10/2008 + + if (i != nVars) { + j = nVars; + swapVars(i,j); + + i = j; + } + else if (DEBUG) { + printVars(); + fprintf(outputFile, "No swap needed before eliminating %s(%d/%d)\n",variable(i),i,nVars); + for(j=1;j<=i;j++) fprintf(outputFile,"var #%d = %s(%x)\n",j,variable(j),var[j]); + printProblem(); + } + nVars--; + + if (exact) { + if (nVars == 1) { + coef_t upperBound = posInfinity; + coef_t lowerBound = negInfinity; + int ub_color = 0; + int lb_color = 0; + coef_t constantTerm, coefficient; + int topEqn = nGEQs - 1; + coef_t Lc; + 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 == EQ_BLACK) + fprintf(outputFile, " :::=> %s >= " coef_fmt "\n", variable(1), constantTerm); + else + fprintf(outputFile, " :::=> [%s >= " coef_fmt "]\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 == EQ_BLACK) + fprintf(outputFile, " :::=> %s <= " coef_fmt "\n", variable(1), constantTerm); + else + fprintf(outputFile, " :::=> [%s <= " coef_fmt "]\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) { + coef_t Uc = -GEQs[Ue].coef[i]; + coefficient = check_mul(GEQs[Ue].coef[1], Lc) + check_mul(GEQs[Le].coef[1], Uc); + constantTerm = check_mul(GEQs[Ue].coef[0], Lc) + check_mul(GEQs[Le].coef[0], Uc); + if (DEBUG) { + printGEQextra(&(GEQs[Ue])); + fprintf(outputFile, "\n"); + printGEQextra(&(GEQs[Le])); + fprintf(outputFile, "\n"); + } + if (coefficient > 0) { + constantTerm = -(int_div(constantTerm, coefficient)); + /* assert(black == 0) */ + if (constantTerm > lowerBound || + (constantTerm == lowerBound && + (desiredResult != OC_SOLVE_SIMPLIFY || (GEQs[Ue].color == EQ_BLACK && GEQs[Le].color == EQ_BLACK)))) { + lowerBound = constantTerm; + lb_color = GEQs[Ue].color || GEQs[Le].color; + } + if (DEBUG) { + if (GEQs[Ue].color || GEQs[Le].color) + fprintf(outputFile, " ::=> [%s >= " coef_fmt "]\n", variable(1), constantTerm); + else + fprintf(outputFile, " ::=> %s >= " coef_fmt "\n", variable(1), constantTerm); + } + } + else if (coefficient < 0) { + constantTerm = (int_div(constantTerm, -coefficient)); + if (constantTerm < upperBound || + (constantTerm == upperBound && GEQs[Ue].color == EQ_BLACK && GEQs[Le].color == EQ_BLACK)) { + upperBound = constantTerm; + ub_color = GEQs[Ue].color || GEQs[Le].color; + } + if (DEBUG) { + if (GEQs[Ue].color || GEQs[Le].color) + fprintf(outputFile, " ::=> [%s <= " coef_fmt "]\n", variable(1), constantTerm); + else + fprintf(outputFile, " ::=> %s <= " coef_fmt "\n", variable(1), constantTerm); + } + } + } + } + } + nGEQs = 0; + if (DEBUG) + fprintf(outputFile, " therefore, %c" coef_fmt " <= %c%s%c <= " coef_fmt "%c\n", lb_color ? '[' : ' ', lowerBound, (lb_color && !ub_color) ? ']' : ' ', variable(1), (!lb_color && ub_color) ? '[' : ' ', upperBound, ub_color ? ']' : ' '); + if (lowerBound > upperBound) + return (false); + + if (upperBound == lowerBound) { + int e = newEQ(); + assert(e == 0); + EQs[e].coef[1] = -1; + EQs[e].coef[0] = upperBound; + EQs[e].color = ub_color | lb_color; + addingEqualityConstraint(0); + } + else if (safeVars == 1) { + if (upperBound != posInfinity) { + int e = newGEQ(); + assert(e == 0); + GEQs[e].coef[1] = -1; + GEQs[e].coef[0] = upperBound; + GEQs[e].color = ub_color; + GEQs[e].key = -1; + GEQs[e].touched = 0; + } + if (lowerBound != negInfinity) { + int e = newGEQ(); + GEQs[e].coef[1] = 1; + GEQs[e].coef[0] = -lowerBound; + GEQs[e].color = lb_color; + GEQs[e].key = 1; + GEQs[e].touched = 0; + } + } + if (safeVars == 0) + nVars = 0; + return (true); + } + eliminateAgain = 1; + + { + int deadEqns[maxDead]; + int numDead = 0; + int topEqn = nGEQs - 1; + int lowerBoundCount = 0; + for (Le = topEqn; Le >= 0; Le--) + if (GEQs[Le].coef[i] > 0) + lowerBoundCount++; + if (DEBUG) + fprintf(outputFile, "lower bound count = %d\n", lowerBoundCount); + if (lowerBoundCount == 0) { + if (desiredResult != OC_SOLVE_SIMPLIFY) fv = 0; + else fv = safeVars; + nVars++; + freeEliminations(fv); + continue; + } + for (Le = topEqn; Le >= 0; Le--) + if (GEQs[Le].coef[i] > 0) { + coef_t Lc = GEQs[Le].coef[i]; + for (Ue = topEqn; Ue >= 0; Ue--) + if (GEQs[Ue].coef[i] < 0) { + if (GEQs[Le].key != -GEQs[Ue].key) { + coef_t Uc = -GEQs[Ue].coef[i]; + int e2; + if (numDead == 0) { + /*( Big kludge warning ) */ + /* this code is still using location nVars+1 */ + /* but newGEQ, if it reallocates, only copies*/ + /* locations up to nVars. This fixes that. */ + nVars++; + e2 = newGEQ(); + nVars--; + } + else { + e2 = deadEqns[--numDead]; + } + 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; + coef_t g = gcd(Lc,Uc); + coef_t Lc_over_g = Lc/g; + coef_t Uc_over_g = Uc/g; + + for (k = nVars; k >= 0; k--) + GEQs[e2].coef[k] = + check_mul(GEQs[Ue].coef[k], Lc_over_g) + check_mul(GEQs[Le].coef[k], Uc_over_g); + + GEQs[e2].coef[nVars + 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 == 1) { + 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[maxmaxGEQs]; + for (e = nGEQs - 1; e >= 0; e--) + isDead[e] = false; + while (numDead > 0) { + e = deadEqns[--numDead]; + isDead[e] = true; + } + for (e = nGEQs - 1; e >= 0; e--) + if (isDead[e]) { + nVars++; + deleteGEQ(e); + nVars--; + } + } + continue; + } + } + else { + Problem *rS, *iS; + + rS = new Problem; + iS = new Problem; + + iS->nVars = rS->nVars = nVars; // do this immed.; in case of reallocation, we + // need to know how much to copy + rS->get_var_name = get_var_name; + rS->getVarNameArgs = getVarNameArgs; + iS->get_var_name = get_var_name; + iS->getVarNameArgs = getVarNameArgs; + + for (e = 0; e < nGEQs; e++) + if (GEQs[e].coef[i] == 0) { + int re2 = rS->newGEQ(); + int ie2 = iS->newGEQ(); + eqnncpy(&(rS->GEQs[re2]), &GEQs[e], nVars); + eqnncpy(&(iS->GEQs[ie2]), &GEQs[e], nVars); + if (DEBUG) { + int t; + fprintf(outputFile, "Copying (%d, " coef_fmt "): ", i, GEQs[e].coef[i]); + printGEQextra(&GEQs[e]); + fprintf(outputFile, "\n"); + for (t = 0; t <= nVars + 1; t++) + fprintf(outputFile, coef_fmt " ", GEQs[e].coef[t]); + fprintf(outputFile, "\n"); + } + } + for (Le = nGEQs - 1; Le >= 0; Le--) + if (GEQs[Le].coef[i] > 0) { + coef_t Lc = GEQs[Le].coef[i]; + for (Ue = nGEQs - 1; Ue >= 0; Ue--) + if (GEQs[Ue].coef[i] < 0) + if (GEQs[Le].key != -GEQs[Ue].key) { + coef_t Uc = -GEQs[Ue].coef[i]; + coef_t g = gcd(Lc,Uc); + coef_t Lc_over_g = Lc/g; + coef_t Uc_over_g = Uc/g; + int re2 = rS->newGEQ(); + int ie2 = iS->newGEQ(); + rS->GEQs[re2].touched = iS->GEQs[ie2].touched = true; + if (DEBUG) { + fprintf(outputFile, "---\n"); + fprintf(outputFile, "Le(Lc) = %d(" coef_fmt "), Ue(Uc) = %d(" coef_fmt "), gen = %d\n", Le, Lc, Ue, Uc, ie2); + printGEQextra(&GEQs[Le]); + fprintf(outputFile, "\n"); + printGEQextra(&GEQs[Ue]); + fprintf(outputFile, "\n"); + } + + if (Uc == Lc) { + for (k = nVars; k >= 0; k--) + iS->GEQs[ie2].coef[k] = rS->GEQs[re2].coef[k] = + GEQs[Ue].coef[k] + GEQs[Le].coef[k]; + iS->GEQs[ie2].coef[0] -= (Uc - 1); + } + else { + for (k = nVars; k >= 0; k--) + iS->GEQs[ie2].coef[k] = rS->GEQs[re2].coef[k] = + check_mul(GEQs[Ue].coef[k], Lc_over_g) + check_mul(GEQs[Le].coef[k], Uc_over_g); + iS->GEQs[ie2].coef[0] -= check_mul(Uc_over_g-1, Lc_over_g-1); + } + + iS->GEQs[ie2].color = rS->GEQs[re2].color + = GEQs[Ue].color || GEQs[Le].color; + + if (DEBUG) { + printGEQ(&(rS->GEQs[re2])); + fprintf(outputFile, "\n"); + } + // ie2 = iS->newGEQ(); + // re2 = rS->newGEQ(); + } + + } + iS->variablesInitialized = rS->variablesInitialized = 1; + iS->nEQs = rS->nEQs = 0; + assert(desiredResult != OC_SOLVE_SIMPLIFY); + assert(nSUBs == 0); + iS->nSUBs = rS->nSUBs = nSUBs; + iS->safeVars = rS->safeVars = safeVars; + int t; + for (t = nVars; t >= 0; t--) + rS->var[t] = var[t]; + for (t = nVars; t >= 0; t--) + iS->var[t] = var[t]; + nVars++; + if (desiredResult != true) { + int t = trace; + if (TRACE) + fprintf(outputFile, "\nreal solution(%d):\n", depth); + depth++; + trace = 0; + if (originalProblem == noProblem) { + originalProblem = this; + result = rS->solveGEQ(false); + originalProblem = noProblem; + } + else + result = rS->solveGEQ(false); + trace = t; + depth--; + if (result == false) { + delete rS; + delete iS; + return (result); + } + + if (nEQs > 0) { + /* An equality constraint must have been found */ + delete rS; + delete iS; + return (solve(desiredResult)); + } + } + if (desiredResult != false) { + if (darkShadowFeasible) { + if (TRACE) + fprintf(outputFile, "\ninteger solution(%d):\n", depth); + depth++; + conservative++; + result = iS->solveGEQ(desiredResult); + conservative--; + depth--; + if (result != false) { + delete rS; + delete iS; + return (result); + } + } + if (TRACE) + fprintf(outputFile, "have to do exact analysis\n"); + + { + coef_t worstLowerBoundConstant=1; + int lowerBounds = 0; + int lowerBound[maxmaxGEQs]; + int smallest; + int t; + conservative++; + for (e = 0; e < nGEQs; e++) + if (GEQs[e].coef[i] < -1) { + set_max(worstLowerBoundConstant, + -GEQs[e].coef[i]); + } + else 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, " " coef_fmt, GEQs[lowerBound[j]].coef[i]); + fprintf(outputFile, "\n"); + } + + + for (j = 0; j < lowerBounds; j++) { + coef_t maxIncr; + coef_t c; + e = lowerBound[j]; + maxIncr = (check_mul(GEQs[e].coef[i]-1, worstLowerBoundConstant-1) - 1) / worstLowerBoundConstant; + + /* maxIncr += 2; */ + if ((doTrace && desiredResult == OC_SOLVE_SIMPLIFY) || DBUG) { + fprintf(outputFile, "for equation "); + printGEQ(&GEQs[e]); + fprintf(outputFile, "\ntry decrements from 0 to " coef_fmt "\n", maxIncr); + printProblem(); + } + if (maxIncr > 50) { + if (!smoothed && smoothWeirdEquations()) { + conservative--; + delete rS; + delete iS; + smoothed = 1; + goto solveGEQstart; + } + } + int neweq = newEQ(); + assert(neweq == 0); + eqnncpy(&EQs[neweq], &GEQs[e], nVars); + /* + * if (GEQs[e].color) fprintf(outputFile,"warning: adding black equality constraint + * based on red inequality\n"); + */ + EQs[neweq].color = EQ_BLACK; + eqnnzero(&GEQs[e], nVars); + GEQs[e].touched = true; + for (c = maxIncr; c >= 0; c--) { + if (DBUG) + fprintf(outputFile, "trying next decrement of " coef_fmt "\n", maxIncr - c); + if (DBUG) + printProblem(); + *rS = *this; + if (DEBUG) + rS->printProblem(); + result = rS->solve(desiredResult); + if (result == true) { + delete rS; + delete iS; + conservative--; + return (true); + } + EQs[0].coef[0]--; + } + if (j + 1 < lowerBounds) { + nEQs = 0; + eqnncpy(&GEQs[e], &EQs[0], nVars); + GEQs[e].touched = 1; + GEQs[e].color = EQ_BLACK; + *rS = *this; + if (DEBUG) + fprintf(outputFile, "exhausted lower bound, checking if still feasible "); + result = rS->solve(false); + if (result == false) + break; + } + } + if ((doTrace && desiredResult == OC_SOLVE_SIMPLIFY) || DBUG) + fprintf(outputFile, "fall-off the end\n"); + delete rS; + delete iS; + + conservative--; + return (false); + } + } + delete rS; + delete iS; + } + return (OC_SOLVE_UNKNOWN); + } + } + while (eliminateAgain); + } +} + + +int Problem::parallelSplinter(int e, int diff, int desiredResult) { + Problem *tmpProblem; + int i; + if (DBUG) { + fprintf(outputFile, "Using parallel splintering\n"); + printProblem(); + } + tmpProblem = new Problem; + int neweq = newEQ(); + assert(neweq == 0); + eqnncpy(&EQs[0], &GEQs[e], nVars); + for (i = 0; i <= diff; i++) { + *tmpProblem = * this; + tmpProblem->isTemporary = true; + if (DBUG) { + fprintf(outputFile, "Splinter # %i\n", i); + printProblem(); + } + if (tmpProblem->solve(desiredResult)) { + delete tmpProblem; + return true; + } + EQs[0].coef[0]--; + } + delete tmpProblem; + return false; +} + + +int Problem::verifyProblem() { + int result; + int e; + int areRed; + check(); + Problem tmpProblem(*this); + tmpProblem.varsOfInterest = 0; + tmpProblem.safeVars = 0; + tmpProblem.nSUBs = 0; + tmpProblem.nMemories = 0; + tmpProblem.isTemporary = true; + areRed = 0; + if (mayBeRed) { + for(e=0; e<nEQs; e++) if (EQs[e].color) areRed = 1; + for(e=0; e<nGEQs; e++) if (GEQs[e].color) areRed = 1; + if (areRed) tmpProblem.turnRedBlack(); + } + originalProblem = this; + assert(!outerColor); + outerColor = areRed; + if (TRACE) { + fprintf(outputFile, "verifying problem: [\n"); + printProblem(); + } + tmpProblem.check(); + tmpProblem.freeEliminations(0); + result = tmpProblem.solve(OC_SOLVE_UNKNOWN); + originalProblem = noProblem; + outerColor = 0; + if (TRACE) { + if (result) + fprintf(outputFile, "] verified problem\n"); + else + fprintf(outputFile, "] disproved problem\n"); + printProblem(); + } + check(); + return result; +} + + +void Problem:: freeEliminations(int fv) { + int tryAgain = 1; + int i, e, e2; + while (tryAgain) { + tryAgain = 0; + for (i = nVars; i > fv; i--) { + for (e = nGEQs - 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 = nSUBs - 1; e3 >= 0; e3--) + if (SUBs[e3].coef[i]) + break; + if (e3 >= 0) + continue; + for (e3 = nEQs - 1; e3 >= 0; e3--) + if (EQs[e3].coef[i]) + break; + if (e3 >= 0) + continue; + if (DBUG) + fprintf(outputFile, "a free elimination of %s (%d)\n", variable(i),e); + if (e >= 0) { + deleteGEQ(e); + for (e--; e >= 0; e--) + if (GEQs[e].coef[i]) { + deleteGEQ(e); + } + tryAgain = (i < nVars); + } + deleteVariable(i); + } + } + } + + if (DEBUG) { + fprintf(outputFile, "\nafter free eliminations:\n"); + printProblem(); + fprintf(outputFile, "\n"); + } +} + + +void Problem::freeRedEliminations() { + int tryAgain = 1; + int i, e, e2; + int isRedVar[maxVars]; + int isDeadVar[maxVars]; + int isDeadGEQ[maxmaxGEQs]; + for (i = nVars; i > 0; i--) { + isRedVar[i] = 0; + isDeadVar[i] = 0; + } + for (e = nGEQs - 1; e >= 0; e--) { + isDeadGEQ[e] = 0; + if (GEQs[e].color) + for (i = nVars; i > 0; i--) + if (GEQs[e].coef[i] != 0) + isRedVar[i] = 1; + } + + while (tryAgain) { + tryAgain = 0; + for (i = nVars; i > 0; i--) + if (!isRedVar[i] && !isDeadVar[i]) { + for (e = nGEQs - 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 = nSUBs - 1; e3 >= 0; e3--) + if (SUBs[e3].coef[i]) + break; + if (e3 >= 0) + continue; + for (e3 = nEQs - 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 = nGEQs - 1; e >= 0; e--) + if (isDeadGEQ[e]) + deleteGEQ(e); + + for (i = nVars; i > safeVars; i--) + if (isDeadVar[i]) + deleteVariable(i); + + + if (DEBUG) { + fprintf(outputFile, "\nafter free red eliminations:\n"); + printProblem(); + fprintf(outputFile, "\n"); + } +} + +} // namespace diff --git a/omegalib/omega/src/omega_core/oc_util.cc b/omegalib/omega/src/omega_core/oc_util.cc new file mode 100644 index 0000000..a7d21be --- /dev/null +++ b/omegalib/omega/src/omega_core/oc_util.cc @@ -0,0 +1,327 @@ +/***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team + Copyright (C) 2005-2011 Chun Chen + All Rights Reserved. + + Purpose: + + Notes: + + History: +*****************************************************************************/ + +#include <omega/omega_core/oc_i.h> +#include <algorithm> + +namespace omega { + +void Problem:: problem_merge(Problem &p2) { + int newLocation[maxVars]; + int i,e2; + + resurrectSubs(); + p2.resurrectSubs(); + setExternals(); + p2.setExternals(); + + assert(safeVars == p2.safeVars); + if(DBUG) { + fprintf(outputFile,"Merging:\n"); + printProblem(); + fprintf(outputFile,"and\n"); + p2.printProblem(); + } + for(i=1; i<= p2.safeVars; i++) { + assert(p2.var[i] > 0) ; + newLocation[i] = forwardingAddress[p2.var[i]]; + } + for(; i<= p2.nVars; i++) { + int j = ++(nVars); + newLocation[i] = j; + zeroVariable(j); + var[j] = -1; + } + newLocation[0] = 0; + + for (e2 = p2.nEQs - 1; e2 >= 0; e2--) { + int e1 = newEQ(); + eqnnzero(&(EQs[e1]), nVars); + for(i=0;i<=p2.nVars;i++) + EQs[e1].coef[newLocation[i]] = p2.EQs[e2].coef[i]; + } + for (e2 = p2.nGEQs - 1; e2 >= 0; e2--) { + int e1 = newGEQ(); + eqnnzero(&(GEQs[e1]), nVars); + GEQs[e1].touched = 1; + for(i=0;i<=p2.nVars;i++) + GEQs[e1].coef[newLocation[i]] = p2.GEQs[e2].coef[i]; + } + int w = -1; + for (i = 1; i <= nVars; i++) + if (var[i] < 0) var[i] = w--; + if(DBUG) { + fprintf(outputFile,"to get:\n"); + printProblem(); + } +} + + + +void Problem::chainUnprotect() { + int i, e; + int unprotect[maxVars]; + int any = 0; + for (i = 1; i <= safeVars; i++) { + unprotect[i] = (var[i] < 0); + for (e = nSUBs - 1; e >= 0; e--) + if (SUBs[e].coef[i]) + unprotect[i] = 0; + } + for (i = 1; i <= safeVars; i++) if (unprotect[i]) any=1; + if (!any) return; + + if (DBUG) { + fprintf(outputFile, "Doing chain reaction unprotection\n"); + printProblem(); + for (i = 1; i <= safeVars; i++) + if (unprotect[i]) + fprintf(outputFile, "unprotecting %s\n", variable(i)); + } + for (i = 1; i <= safeVars; i++) + if (unprotect[i]) { + /* wild card */ + if (i < safeVars) { + int j = safeVars; + std::swap(var[i], var[j]); + for (e = nGEQs - 1; e >= 0; e--) { + GEQs[e].touched = 1; + std::swap(GEQs[e].coef[i], GEQs[e].coef[j]); + } + for (e = nEQs - 1; e >= 0; e--) + std::swap(EQs[e].coef[i], EQs[e].coef[j]); + for (e = nSUBs - 1; e >= 0; e--) + std::swap(SUBs[e].coef[i], SUBs[e].coef[j]); + std::swap(unprotect[i], unprotect[j]); + i--; + } + safeVars--; + } + if (DBUG) { + fprintf(outputFile, "After chain reactions\n"); + printProblem(); + } +} + +void Problem::resurrectSubs() { + if (nSUBs > 0 && !pleaseNoEqualitiesInSimplifiedProblems) { + int i, e, n, m,mbr; + mbr = 0; + for (e = nGEQs - 1; e >= 0; e--) if (GEQs[e].color) mbr=1; + for (e = nEQs - 1; e >= 0; e--) if (EQs[e].color) mbr=1; + if (nMemories) mbr = 1; + + assert(!mbr || mayBeRed); + + if (DBUG) { + fprintf(outputFile, "problem reduced, bringing variables back to life\n"); + if(mbr && !mayBeRed) fprintf(outputFile, "Red equations we don't expect\n"); + printProblem(); + } + if (DBUG && nEQs > 0) + fprintf(outputFile,"This is wierd: problem has equalities\n"); + + for (i = 1; i <= safeVars; i++) + if (var[i] < 0) { + /* wild card */ + if (i < safeVars) { + int j = safeVars; + std::swap(var[i], var[j]); + for (e = nGEQs - 1; e >= 0; e--) { + GEQs[e].touched = 1; + std::swap(GEQs[e].coef[i], GEQs[e].coef[j]); + } + for (e = nEQs - 1; e >= 0; e--) + std::swap(EQs[e].coef[i], EQs[e].coef[j]); + for (e = nSUBs - 1; e >= 0; e--) + std::swap(SUBs[e].coef[i], SUBs[e].coef[j]); + i--; + } + safeVars--; + } + + m = nSUBs; + n = nVars; + if (n < safeVars + m) + n = safeVars + m; + for (e = nGEQs - 1; e >= 0; e--) { + if (singleVarGEQ(&GEQs[e])) { + i = abs(GEQs[e].key); + if (i >= safeVars + 1) + GEQs[e].key += (GEQs[e].key > 0 ? m : -m); + } + else { + GEQs[e].touched = true; + GEQs[e].key = 0; + } + } + for (i = nVars; i >= safeVars + 1; i--) { + var[i + m] = var[i]; + for (e = nGEQs - 1; e >= 0; e--) + GEQs[e].coef[i + m] = GEQs[e].coef[i]; + for (e = nEQs - 1; e >= 0; e--) + EQs[e].coef[i + m] = EQs[e].coef[i]; + for (e = nSUBs - 1; e >= 0; e--) + SUBs[e].coef[i + m] = SUBs[e].coef[i]; + } + for (i = safeVars + m; i >= safeVars + 1; i--) { + for (e = nGEQs - 1; e >= 0; e--) GEQs[e].coef[i] = 0; + for (e = nEQs - 1; e >= 0; e--) EQs[e].coef[i] = 0; + for (e = nSUBs - 1; e >= 0; e--) SUBs[e].coef[i] = 0; + } + nVars += m; + safeVars += m; + for (e = nSUBs - 1; e >= 0; e--) + var[safeVars -m + 1 + e] = SUBs[e].key; + for (i = 1; i <= safeVars; i++) + forwardingAddress[var[i]] = i; + if (DBUG) { + fprintf(outputFile,"Ready to wake substitutions\n"); + printProblem(); + } + for (e = nSUBs - 1; e >= 0; e--) { + int neweq = newEQ(); + eqnncpy(&(EQs[neweq]), &(SUBs[e]), nVars); + EQs[neweq].coef[safeVars -m + 1 + e] = -1; + EQs[neweq].color = EQ_BLACK; + if (DBUG) { + fprintf(outputFile, "brought back: "); + printEQ(&EQs[neweq]); + fprintf(outputFile, "\n"); + } + } + nSUBs = 0; + + if (DBUG) { + fprintf(outputFile, "variables brought back to life\n"); + printProblem(); + } + } + + coalesce(); + recallRedMemories(); + cleanoutWildcards(); +} + + +void Problem::reverseProtectedVariables() { + int v1,v2,e,i; + coef_t t; + for (v1 = 1; v1 <= safeVars; v1++) { + v2 = safeVars+1-v1; + if (v2>=v1) break; + for(e=0;e<nEQs;e++) { + t = EQs[e].coef[v1]; + EQs[e].coef[v1] = EQs[e].coef[v2]; + EQs[e].coef[v2] = t; + } + for(e=0;e<nGEQs;e++) { + t = GEQs[e].coef[v1]; + GEQs[e].coef[v1] = GEQs[e].coef[v2]; + GEQs[e].coef[v2] = t; + GEQs[e].touched = 1; + } + for(e=0;e<nSUBs;e++) { + t = SUBs[e].coef[v1]; + SUBs[e].coef[v1] = SUBs[e].coef[v2]; + SUBs[e].coef[v2] = t; + } + } + + for (i = 1; i <= safeVars; i++) + forwardingAddress[var[i]] = i; + for (i = 0; i < nSUBs; i++) + forwardingAddress[SUBs[i].key] = -i - 1; +} + +void Problem::ordered_elimination(int symbolic) { + int i,j,e; + int isDead[maxmaxGEQs]; + for(e=0;e<nEQs;e++) isDead[e] = 0; + + if (!variablesInitialized) { + initializeVariables(); + } + + for(i=nVars;i>symbolic;i--) + for(e=0;e<nEQs;e++) + if (EQs[e].coef[i] == 1 || EQs[e].coef[i] == -1) { + for(j=nVars;j>i;j--) if (EQs[e].coef[j]) break; + if (i==j) { + doElimination(e, i); + isDead[e] = 1; + break; + } + } + + for(e=nEQs-1;e>=0;e--) + if (isDead[e]) { + nEQs--; + if (e < nEQs) eqnncpy(&EQs[e], &EQs[nEQs], nVars); + } + + for (i = 1; i <= safeVars; i++) + forwardingAddress[var[i]] = i; + for (i = 0; i < nSUBs; i++) + forwardingAddress[SUBs[i].key] = -i - 1; +} + + +coef_t Problem::checkSum() const { + coef_t cs; + int e; + cs = 0; + for(e=0;e<nGEQs;e++) { + coef_t c = GEQs[e].coef[0]; + cs += c*c*c; + } + return cs; +} + + +void Problem::coalesce() { + int e, e2, colors; + int isDead[maxmaxGEQs]; + int foundSomething = 0; + + + colors = 0; + for (e = 0; e < nGEQs; e++) + if (GEQs[e].color) + colors++; + if (colors < 2) + return; + for (e = 0; e < nGEQs; e++) + isDead[e] = 0; + for (e = 0; e < nGEQs; e++) + if (!GEQs[e].touched) + for (e2 = e + 1; e2 < nGEQs; e2++) + if (!GEQs[e2].touched && GEQs[e].key == -GEQs[e2].key + && GEQs[e].coef[0] == -GEQs[e2].coef[0]) { + int neweq = newEQ(); + eqnncpy(&EQs[neweq], &GEQs[e], nVars); + EQs[neweq].color = GEQs[e].color || GEQs[e2].color; + foundSomething++; + isDead[e] = 1; + isDead[e2] = 1; + } + for (e = nGEQs - 1; e >= 0; e--) + if (isDead[e]) { + deleteGEQ(e); + } + if (DEBUG && foundSomething) { + fprintf(outputFile, "Coalesced GEQs into %d EQ's:\n", foundSomething); + printProblem(); + } +} + +} // namespace |