ACCExpr *invertExpr(ACCExpr *expr) { if (!expr) return allocExpr("1"); ACCExpr *lhs = expr->operands.front(); std::string v = expr->value; if (checkInteger(expr, "1")) return allocExpr("0"); if (checkInteger(expr, "0")) return allocExpr("1"); if (v == "!") return lhs; if (v == "^" && checkInteger(getRHS(expr), "1")) return lhs; if (v == "==") { if (expr->operands.size() == 1) return allocExpr("0"); return allocExpr("!=", lhs, getRHS(expr)); } if (v == "!=") { if (expr->operands.size() == 1) return allocExpr("1"); return allocExpr("==", lhs, getRHS(expr)); } if (v == "&" || v == "|") { ACCExpr *temp = allocExpr(v == "&" ? "|" : "&"); for (auto item: expr->operands) temp->operands.push_back(invertExpr(item)); return temp; } return allocExpr("^", expr, allocExpr("1")); }
/* int Dstar::computeShortestPath() * -------------------------- * As per [S. Koenig, 2002] except for 2 main modifications: * 1. We stop planning after a number of steps, 'maxsteps' we do this * because this algorithm can plan forever if the start is * surrounded by obstacles. * 2. We lazily remove states from the open list so we never have to * iterate through it. */ int Dstar::computeShortestPath() { list<state> s; list<state>::iterator i; if (openList.empty()) return 1; int k=0; while ((!openList.empty()) && (openList.top() < (s_start = calculateKey(s_start))) || (getRHS(s_start) != getG(s_start))) { if (k++ > maxSteps) { fprintf(stderr, "At maxsteps\n"); return -1; } state u; bool test = (getRHS(s_start) != getG(s_start)); // lazy remove while(1) { if (openList.empty()) return 1; u = openList.top(); openList.pop(); if (!isValid(u)) continue; if (!(u < s_start) && (!test)) return 2; break; } ds_oh::iterator cur = openHash.find(u); openHash.erase(cur); state k_old = u; if (k_old < calculateKey(u)) { // u is out of date insert(u); } else if (getG(u) > getRHS(u)) { // needs update (got better) setG(u,getRHS(u)); getPred(u,s); for (i=s.begin();i != s.end(); i++) { updateVertex(*i); } } else { // g <= rhs, state has got worse setG(u,INFINITY); getPred(u,s); for (i=s.begin();i != s.end(); i++) { updateVertex(*i); } updateVertex(u); } } return 0; }
/* int Dstar::computeShortestPath() * -------------------------- * As per [S. Koenig, 2002] except for 2 main modifications: * 1. We stop planning after a number of steps, 'maxsteps' we do this * because this algorithm can plan forever if the start is * surrounded by obstacles. * 2. We lazily remove states from the open list so we never have to * iterate through it. */ int Dstar::computeShortestPath() { list<state> s; list<state>::iterator i; if (openList.empty()) return 1; int k=0; while ((!openList.empty()) && (openList.top() < (calculateKey(s_start))) || (!isConsistent(s_start))) { if (k++ > maxSteps) { fprintf(stderr, "At maxsteps\n"); return -1; } state u; // check consistency (one of the loop conditions) bool test = isConsistent(s_start); //(getRHS(s_start) != getG(s_start)); // lazy remove while(1) { if (openList.empty()) return 1; // checks outer loop condition #1 u = openList.top(); if (!queuePop()) continue; if (!(u < s_start) && test) return 2; // checks outer loop conditions #2,3 still hold break; } state k_old = u; if (k_old < calculateKey(u)) { // u is out of date insert(u); // u has been removed already, reinsert into pq with new key } else if (getG(u) > getRHS(u)) { // needs update (got better) setG(u,getRHS(u)); getPred(u,s); for (i=s.begin();i != s.end(); i++) { updateVertex(*i); } } else { // g <= rhs, state has got worse setG(u,INFINITY); getPred(u,s); for (i=s.begin();i != s.end(); i++) { updateVertex(*i); } updateVertex(u); } } return 0; }
bool matchExpr(ACCExpr *lhs, ACCExpr *rhs) { if (!lhs && !rhs) return true; if (!lhs || !rhs || lhs->value != rhs->value || lhs->operands.size() != rhs->operands.size()) return false; if ((lhs->value == "&" || lhs->value == "|") && lhs->operands.size() == 2) // check commutativity if (matchExpr(getRHS(lhs), getRHS(rhs, 0)) && matchExpr(getRHS(lhs, 0), getRHS(rhs))) return true; for (auto lcur = lhs->operands.begin(), lend = lhs->operands.end(), rcur = rhs->operands.begin(); lcur != lend; lcur++, rcur++) if (!matchExpr(*lcur, *rcur)) return false; return true; }
int tGSLSolve::solveGaussSeidel(const double eps,const int maxIterations) { tJSolve lgs(N); for (int i=0;i<N;i++){ for (int j=0;j<N; j++){ lgs.setMATRIX(i,j,getMATRIX(i,j)); } for (int k=0;k<nRHS;k++){ lgs.setRHS(i, getRHS(i,k), k); lgs.setX(i, getX(i,k), k); } } int iterations = lgs.solveGS(eps, maxIterations); // x zurueckkopieren for (int i=0;i<N;i++){ for (int k=0;k<nRHS;k++){ setX(i, lgs.getX(i,k), k); } } return iterations; }
bool tGSLSolve::saveToFile(const char *fileName) { int i,j; FILE *file; file = fopen(fileName,"wt"); if (file){ for (i=0;i<N;i++){ for (j=0;j<N;j++){ fprintf(file,"%f\t",getMATRIX(i,j)); } if (nRHS>1){ fprintf(file,"\n"); } for (j=0;j<nRHS;j++){ fprintf(file,"x[%i]:\t%f\t",j,getX(i,j)); fprintf(file,"RHS[%i]:\t%f\t",j,getRHS(i,j)); fprintf(file,"\n"); } } fclose(file); return true; } else { return false; } }
/* state Dstar::calculateKey(state u) * -------------------------- * As per [S. Koenig, 2002] */ state Dstar::calculateKey(state u) { double val = fmin(getRHS(u),getG(u)); u.k.first = val + heuristic(u,s_start) + k_m; u.k.second = val; return u; }
/* void Dstar::updateVertex(state u) * -------------------------- * As per [S. Koenig, 2002] */ void Dstar::updateVertex(state u) { list<state> s; list<state>::iterator i; if (u != s_goal) { getSucc(u,s); double tmp = INFINITY; double tmp2; for (i=s.begin();i != s.end(); i++) { tmp2 = getG(*i) + cost(u,*i); if (tmp2 < tmp) tmp = tmp2; } if (!close(getRHS(u),tmp)) setRHS(u,tmp); } if (!close(getG(u),getRHS(u))) insert(u); }
void updateWidth(ACCExpr *expr, int len) { int ilen = exprWidth(expr); if (ilen < 0 || len < 0) { printf("[%s:%d] len %d ilen %d tree %s\n", __FUNCTION__, __LINE__, len, ilen, tree2str(expr).c_str()); exit(-1); } if (isdigit(expr->value[0]) && len > 0 && expr->value.find("'") == std::string::npos) expr->value = autostr(len) + "'d" + expr->value; else if (isIdChar(expr->value[0])) { if (trace_expr) printf("[%s:%d] ID %s ilen %d len %d\n", __FUNCTION__, __LINE__, tree2str(expr).c_str(), ilen, len); if (ilen > len && len > 0 && !expr->operands.size()) { ACCExpr *subexpr = allocExpr(":", allocExpr(autostr(len-1))); if (len > 1) subexpr->operands.push_back(allocExpr("0")); expr->operands.push_back(allocExpr("[", subexpr)); } } else if (expr->value == ":") // for __phi updateWidth(getRHS(expr), len); else if (expr->value == "?") { updateWidth(getRHS(expr), len); updateWidth(getRHS(expr, 2), len); } else if (arithOp(expr->value) || expr->value == "(") { if (expr->value == "-" && expr->operands.size() == 1 && isdigit(expr->operands.front()->value[0]) && len == 1) { /* hack to update width on "~foo", which translates to "foo ^ -1" in the IR */ expr->value = expr->operands.front()->value; expr->operands.clear(); updateWidth(expr, len); } else for (auto item: expr->operands) updateWidth(item, len); } }
int exprWidth(ACCExpr *expr, bool forceNumeric) { if (!expr) return 0; std::string op = expr->value; if (relationalOp(op)) return 1; if (isdigit(op[0])) { int ind = op.find("'"); if (ind > 0) { std::string temp = op.substr(0, ind); return atoi(temp.c_str()); } else if (forceNumeric) return 1; } if (isIdChar(op[0])) { ACCExpr *lhs = getRHS(expr, 0); if (lhs && lhs->value == "[" && lhs->operands.size() > 0) { ACCExpr *first = getRHS(lhs, 0); if (first->value == ":") { ACCExpr *second = getRHS(first); first = getRHS(first, 0); if (!second) return 1; if (isdigit(first->value[0]) && isdigit(second->value[0])) return atoi(first->value.c_str()) - atoi(second->value.c_str()) + 1; } else if (isdigit(first->value[0])) return 1; } return convertType(refList[op].type); } if (op == "?") { if (int len = exprWidth(getRHS(expr, 1), forceNumeric)) return len; if (int len = exprWidth(getRHS(expr, 2), forceNumeric)) return len; } if (op == "&" || op == "|" || op == "^") { for (auto item: expr->operands) if (exprWidth(item, forceNumeric) != 1) goto nextand; return 1; nextand:; } if (op == "!") { return exprWidth(expr->operands.front(), forceNumeric); } return 0; }
vector<Spec *> Reac::getAllSpecs(void) const { SpecPVec specs = SpecPVec(); bool first_occ = true; SpecPVec lhs = getLHS(); SpecPVecCI l_end = lhs.end(); for (SpecPVecCI l = lhs.begin(); l != l_end; ++l) { first_occ = true; SpecPVecCI s_end = specs.end(); for (SpecPVecCI s = specs.begin(); s != s_end; ++s) { if ((*s) == (*l)) { first_occ = false; break; } } if (first_occ == true) specs.push_back((*l)); } SpecPVec rhs = getRHS(); SpecPVecCI r_end = rhs.end(); for (SpecPVecCI r = rhs.begin(); r != r_end; ++r) { first_occ = true; SpecPVecCI s_end = specs.end(); for (SpecPVecCI s = specs.begin(); s != s_end; ++s) { if ((*s) == (*r)) { first_occ = false; break; } } if (first_occ == true) specs.push_back((*r)); } return specs; }
void Dstar::draw() const { ds_ch::const_iterator iter; ds_oh::const_iterator iter1; state t; list<state>::const_iterator iter2; glBegin(GL_QUADS); for(iter=cellHash.begin(); iter != cellHash.end(); iter++) { if (iter->second.cost == 1) glColor3f(0,1,0); else if (iter->second.cost < 0 ) glColor3f(1,0,0); else glColor3f(0,0,1); drawCell(iter->first,0.5); } glColor3f(1,1,0); drawCell(s_start,0.5); glColor3f(1,0,1); drawCell(s_goal,0.5); for(iter1=openHash.begin(); iter1 != openHash.end(); iter1++) { if (iter1->second.v[0] < iter1->second.v[1]) glColor3f(0.9,0.9,0.9); else glColor3f(0.0,0.0,0.0); drawCell(iter1->first, 0.2); } /* ds_pq Q = openList; while(!Q.empty()) { t = Q.top(); Q.pop(); glColor3f(0.0,0.0,1.0); drawCell(t, 0.15); } */ glColor3f(0,0,1); drawCell(qstate, .45); glEnd(); char str[256]; iter1 = openHash.find(qstate); iter = cellHash.find(qstate); float cury=0.01; ds_pq Q = openList; while(!Q.empty()) { t = Q.top(); Q.pop(); if (t == qstate) { sprintf(str,"openList: %d [%f,%f] \n", t.num, t.k.first, t.k.second); DisplayStr(str,GLUT_BITMAP_HELVETICA_12,1,1,1,0.01,cury+=0.02); } } if (iter1 == openHash.end()) sprintf(str,"openHash: NO [0,0] \n"); else sprintf(str,"openHash: YES [%d,%d] \n", iter1->second.v[0], iter1->second.v[1]); DisplayStr(str,GLUT_BITMAP_HELVETICA_12,1,1,1,0.01,cury+=0.02); if (iter == cellHash.end()) sprintf(str,"cellHash: NO g,rhs,cost: [%f,%f,%f] \n", getG(qstate), getRHS(qstate), C1); else sprintf(str,"cellHash: YES g,rhs,cost: [%f,%f,%f] \n", iter->second.g, iter->second.rhs, iter->second.cost); DisplayStr(str,GLUT_BITMAP_HELVETICA_12,1,1,1,0.01,cury+=0.02); sprintf(str,"cell: (%d,%d)\n", qstate.x, qstate.y); DisplayStr(str,GLUT_BITMAP_HELVETICA_12,1,1,1,0.01,cury+=0.02); glLineWidth(4); glBegin(GL_LINE_STRIP); glColor3f(0.6, 0.1, 0.4); for(iter2=path.path.begin(); iter2 != path.path.end(); iter2++) { glVertex3f(iter2->x, iter2->y, 0.2); } glEnd(); }
void walkReplaceBuiltin(ACCExpr *expr) { while(1) { if (expr->value == "__bitconcat") { ACCExpr *list = expr->operands.front(); if (list->value == PARAMETER_MARKER) list->value = "{"; expr->value = list->value; expr->operands = list->operands; } else if (expr->value == "__bitsubstr") { ACCExpr *list = expr->operands.front(); ACCExpr *bitem = list->operands.front(); if (!isIdChar(bitem->value[0])) { // can only do bit select on net or reg (not expressions) printf("[%s:%d] can only do __bitsubstr on elementary items\n", __FUNCTION__, __LINE__); dumpExpr("BITSUB", expr); exit(-1); } bitem->operands.push_back(allocExpr("[", allocExpr(":", getRHS(list), getRHS(list, 2)))); expr->value = bitem->value; expr->operands = bitem->operands; } else if (expr->value == "__phi") { ACCExpr *list = expr->operands.front(); // get "(" list of [":", cond, value] items int size = list->operands.size(); ACCExpr *firstInList = getRHS(list, 0), *secondInList = getRHS(list); ACCExpr *newe = nullptr; if (size == 2 && matchExpr(getRHS(firstInList, 0), invertExpr(getRHS(secondInList, 0)))) newe = allocExpr("?", getRHS(firstInList, 0), getRHS(firstInList), getRHS(secondInList)); else if (size == 2 && getRHS(firstInList, 0)->value == "__default" && exprWidth(getRHS(secondInList)) == 1) newe = allocExpr("&", getRHS(secondInList, 0), getRHS(secondInList)); else if (size == 1) newe = getRHS(firstInList); else { //dumpExpr("PHI", list); newe = allocExpr("|"); for (auto item: list->operands) { dumpExpr("PHIELEMENTBEF", item); if (checkInteger(getRHS(item), "0")) continue; // default value is already '0' item->value = "?"; // Change from ':' -> '?' item->operands.push_back(allocExpr("0")); updateWidth(item, exprWidth(getRHS(item))); newe->operands.push_back(item); if (trace_expr) dumpExpr("PHIELEMENT", item); } } expr->value = newe->value; expr->operands = newe->operands; } else break; } for (auto item: expr->operands) walkReplaceBuiltin(item); }
/** \brief Check that a node is consistent */ bool Dstar::isConsistent(const state &u) { return (getRHS(u) == getG(u)); }
//******************************************************* // Parser::parse //******************************************************* void Parser::parse() { static const uint32_t ACTION_WIDTH = 17; static const uint32_t STACK_WIDTH = 1; // Make the second column the correct maximum size, always. std::ostringstream dummy1; Token dummy2; printTokens(dummy1, dummy2); static uint32_t TOKENS_WIDTH = dummy1.str().size(); if (myPrintParse) { std::cout << std::left << std::setw(ACTION_WIDTH) << "Parser Action" << " | " << std::setw(TOKENS_WIDTH) << "Remaining Tokens" << " | " << std::setw(STACK_WIDTH) << "Stack" << std::endl << std::right; } mySemanticStack.initialize(); myStack.push(myGrammar.getStartSymbol()); Token token{myScanner.scan()}; printState(token); while (myStack.size() > 0) { // variables for printing the parse std::ostringstream stackContents; std::ostringstream remainingTokens; std::ostringstream predictValue; if (myPrintParse) { printTokens(remainingTokens, token); printStack(stackContents, myStack); } auto expectedSymbol = myStack.top(); if (typeid(*expectedSymbol.get()) == typeid(NonTerminalSymbol)) { auto productionNumber = myPredictTable.getProductionNumber( expectedSymbol, token.getTerminal()); if (productionNumber > 0) { predictValue << "Predict(" << productionNumber << ")"; myStack.pop(); myStack.push(mySemanticStack.getEOPSymbol()); auto production = myGrammar.getProduction(productionNumber); auto rhs = production->getRHS(); auto rhsIter = rhs.rbegin(); uint32_t numberGrammarSymbols = 0; while (rhsIter != rhs.rend()) { std::shared_ptr<Symbol> rhsSymbol = *rhsIter; if (GrammarAnalyzer::isGrammarSymbol(rhsSymbol)) { ++numberGrammarSymbols; } if (!(*rhsSymbol == *Lambda::getInstance())) { myStack.push(rhsSymbol); } ++rhsIter; } mySemanticStack.expand(numberGrammarSymbols); } else { std::ostringstream error; error << "No production found for symbol " << *expectedSymbol << " and token " << *(token.getTerminal()) << "."; myEWTracker.reportError(token.getLine(), token.getColumn(), error.str()); // Error recovery myStack.pop(); // Move past the bad symbol. } } else if (typeid(*expectedSymbol.get()) == typeid(TerminalSymbol)) { if (*expectedSymbol == *(token.getTerminal())) { predictValue << "Match"; mySemanticStack.replaceAtCurrentIndex(SemanticRecord( PlaceholderRecord(token))); myStack.pop(); token = myScanner.scan(); } else { std::ostringstream error; error << "Expected " << *expectedSymbol << ", instead found " << *(token.getTerminal()) << "."; myEWTracker.reportError(token.getLine(), token.getColumn(), error.str()); // Error recovery myStack.pop(); // Move past the bad symbol. } } else if (typeid(*expectedSymbol.get()) == typeid(ActionSymbol)) { myStack.pop(); mySemanticRoutines.executeSemanticRoutine(expectedSymbol); } else if (typeid(*expectedSymbol.get()) == typeid(EOPSymbol)) { mySemanticStack.restore(expectedSymbol); myStack.pop(); } if (myPrintParse && ! myEWTracker.hasError()) { std::cout << std::setw(ACTION_WIDTH) << predictValue.str() << " | " << std::setw(TOKENS_WIDTH) << remainingTokens.str() << " | " << std::setw(STACK_WIDTH) << stackContents.str() << std::endl; } printState(token); } }
void ExprOpUnaryRight::onToString (std::ostream &os, unsigned int indent) const { os << getSourceToken ().getText () << "(" << getRHS ()->toString (indent) << ")"; }
/** @note There will always be a BOUNDS section, even if there are no bounds. */ void SPxLP::writeMPS( std::ostream& p_output, ///< output stream. const NameSet* p_rnames, ///< row names. const NameSet* p_cnames, ///< column names. const DIdxSet* p_intvars) ///< integer variables. const { METHOD("writeMPS"); const char* indicator; char name [16]; char name1[16]; char name2[16]; bool has_ranges = false; int i; int k; // --- NAME Section --- p_output << "NAME MPSDATA" << std::endl; // --- ROWS Section --- p_output << "ROWS" << std::endl; for(i = 0; i < nRows(); i++) { if (lhs(i) == rhs(i)) indicator = "E"; else if ((lhs(i) > -infinity) && (rhs(i) < infinity)) { indicator = "E"; has_ranges = true; } else if (lhs(i) > -infinity) indicator = "G"; else if (rhs(i) < infinity) indicator = "L"; else throw SPxInternalCodeException("XMPSWR02 This should never happen."); writeRecord(p_output, indicator, getRowName(*this, i, p_rnames, name)); } writeRecord(p_output, "N", "MINIMIZE"); // --- COLUMNS Section --- p_output << "COLUMNS" << std::endl; bool has_intvars = (p_intvars != 0) && (p_intvars->size() > 0); for(int j = 0; j < (has_intvars ? 2 : 1); j++) { bool is_intrun = has_intvars && (j == 1); if (is_intrun) p_output << " MARK0001 'MARKER' 'INTORG'" << std::endl; for(i = 0; i < nCols(); i++) { bool is_intvar = has_intvars && (p_intvars->number(i) >= 0); if ( ( is_intrun && !is_intvar) || (!is_intrun && is_intvar)) continue; const SVector& col = colVector(i); int colsize2 = (col.size() / 2) * 2; assert(colsize2 % 2 == 0); for(k = 0; k < colsize2; k += 2) writeRecord(p_output, 0, getColName(*this, i, p_cnames, name), getRowName(*this, col.index(k), p_rnames, name1), col.value(k), getRowName(*this, col.index(k + 1), p_rnames, name2), col.value(k + 1)); if (colsize2 != col.size()) writeRecord(p_output, 0, getColName(*this, i, p_cnames, name), getRowName(*this, col.index(k), p_rnames, name1), col.value(k)); if (isNotZero(maxObj(i))) writeRecord(p_output, 0, getColName(*this, i, p_cnames, name), "MINIMIZE", -maxObj(i)); } if (is_intrun) p_output << " MARK0001 'MARKER' 'INTEND'" << std::endl; } // --- RHS Section --- p_output << "RHS" << std::endl; i = 0; while(i < nRows()) { Real rhsval1 = 0.0; Real rhsval2 = 0.0; for(; i < nRows(); i++) if ((rhsval1 = getRHS(lhs(i), rhs(i))) != 0.0) break; if (i < nRows()) { for(k = i + 1; k < nRows(); k++) if ((rhsval2 = getRHS(lhs(k), rhs(k))) != 0.0) break; if (k < nRows()) writeRecord(p_output, 0, "RHS", getRowName(*this, i, p_rnames, name1), rhsval1, getRowName(*this, k, p_rnames, name2), rhsval2); else writeRecord(p_output, 0, "RHS", getRowName(*this, i, p_rnames, name1), rhsval1); i = k + 1; } } // --- RANGES Section --- if (has_ranges) { p_output << "RANGES" << std::endl; for(i = 0; i < nRows(); i++) if ((lhs(i) > -infinity) && (rhs(i) < infinity)) writeRecord(p_output, "", "RANGE", getRowName(*this, i, p_rnames, name1), rhs(i) - lhs(i)); } // --- BOUNDS Section --- p_output << "BOUNDS" << std::endl; for(i = 0; i < nCols(); i++) { // skip variables that do not appear in the objective function or any constraint const SVector& col = colVector(i); if (col.size() == 0 && isZero(maxObj(i))) continue; if (lower(i) == upper(i)) { writeRecord(p_output, "FX", "BOUND", getColName(*this, i, p_cnames, name1), lower(i)); continue; } if ((lower(i) <= -infinity) && (upper(i) >= infinity)) { writeRecord(p_output, "FR", "BOUND", getColName(*this, i, p_cnames, name1)); continue; } if (lower(i) != 0.0) { if (lower(i) > -infinity) writeRecord(p_output, "LO", "BOUND", getColName(*this, i, p_cnames, name1), lower(i)); else writeRecord(p_output, "MI", "BOUND", getColName(*this, i, p_cnames, name1)); } if (has_intvars && (p_intvars->number(i) >= 0)) { // Integer variables have default upper bound 1.0, but we should write // it nevertheless since CPLEX seems to assume infinity otherwise. writeRecord(p_output, "UP", "BOUND", getColName(*this, i, p_cnames, name1), upper(i)); } else { // Continous variables have default upper bound infinity if (upper(i) < infinity) writeRecord(p_output, "UP", "BOUND", getColName(*this, i, p_cnames, name1), upper(i)); } } // --- ENDATA Section --- p_output << "ENDATA" << std::endl; // Output warning when writing a maximisation problem if(spxSense() == SPxLP::MAXIMIZE) { MSG_WARNING( spxout << "XMPSWR03 Warning: objective function inverted when writing maximization problem in MPS file format" << std::endl; ) }
static DdNode *tree2BDD(DdManager *mgr, ACCExpr *expr, VarMap &varMap) { std::string op = expr->value; DdNode *ret = nullptr; if (op == "&&") op = "&"; else if (op == "||") op = "|"; if (checkInteger(expr, "1")) ret = Cudd_ReadOne(mgr); else if (checkInteger(expr, "0")) ret = Cudd_ReadLogicZero(mgr); else if (op == "!") return Cudd_Not(tree2BDD(mgr, expr->operands.front(), varMap)); // Not passes through ref count else if (op != "&" && op != "|" && op != "^") { if ((op == "!=" || op == "==")) { ACCExpr *lhs = getRHS(expr, 0); if (boolPossible(lhs) && boolPossible(getRHS(expr,1))) goto next; // we can analyze relops on booleans if (trace_bool) printf("[%s:%d] boolnot %d %d = %s\n", __FUNCTION__, __LINE__, boolPossible(getRHS(expr,0)), boolPossible(getRHS(expr,1)), tree2str(expr).c_str()); if (isIdChar(lhs->value[0])) { if (trace_bool) printf("[%s:%d] name %s type %s\n", __FUNCTION__, __LINE__, lhs->value.c_str(), refList[lhs->value].type.c_str()); } } if (op == "!=") // normalize comparison strings expr->value = "=="; std::string name = "( " + tree2str(expr) + " )"; if (!varMap[name]) { varMap[name] = new MapItem; varMap[name]->index = varMap.size(); varMap[name]->node = Cudd_bddIthVar(mgr, varMap[name]->index); } ret = varMap[name]->node; if (op == "!=") { // normalize comparison strings expr->value = op; // restore ret = Cudd_Not(ret); } } if (ret) { Cudd_Ref(ret); return ret; } next:; for (auto item: expr->operands) { DdNode *operand = tree2BDD(mgr, item, varMap), *next; if (!ret) ret = operand; else { if (op == "&") next = Cudd_bddAnd(mgr, ret, operand); else if (op == "|") next = Cudd_bddOr(mgr, ret, operand); else if (op == "^" || op == "!=") next = Cudd_bddXor(mgr, ret, operand); else if (op == "==") next = Cudd_bddXnor(mgr, ret, operand); else { printf("[%s:%d] unknown operator\n", __FUNCTION__, __LINE__); exit(-1); } Cudd_Ref(next); Cudd_RecursiveDeref(mgr, operand); Cudd_RecursiveDeref(mgr, ret); ret = next; } } return ret; }