void LpSub::addCons(ArrayBuffer<Constraint*> &newCons) { // LpSub::addCons(): local variables ArrayBuffer<Row*> newRows(newCons.size(),false); //!< the new constraints in row format ArrayBuffer<int> delVar(sub_->nVar(),false); //!< buffer of deletable components of row format double rhsDelta; //!< correction of right hand side InfeasCon::INFEAS infeas; //!< infeasibility mode (TooLarge, TooSmall) Row *nr; constraint2row(newCons, newRows); // eliminate variables in added constraints /* Also the elimination of variables in an added constraint might * cause a void left hand side (interpreted as 0) violated the right hand * side of the constraint. These infeasible constraints are recognized, * but the resolution is currently not implemented. */ const int nNewRows = newRows.size(); for (int c = 0; c < nNewRows; c++) { //! eliminate variables in constraint \a c delVar.clear(); rhsDelta = 0.0; nr = newRows[c]; const int nrNnz = nr->nnz(); for(int i = 0; i < nrNnz; i++) if(eliminated(nr->support(i))) { delVar.push(i); rhsDelta += nr->coeff(i)*elimVal(nr->support(i)); } nr->delInd(delVar,rhsDelta); nr->rename(orig2lp_); // check if constraint \a c has become infeasible if(nr->nnz() == 0) { infeas = newCons[c]->voidLhsViolated(nr->rhs()); if (infeas != InfeasCon::Feasible) { infeasCons_.push(new InfeasCon(master_, newCons[c], infeas)); Logger::ifout() << "LpSub::addCons(): infeasible constraint added.\nAll variables with nonzero coefficients are eliminated and constraint is violated.\nSorry, resolution not implemented yet.\n"; OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::afcLpSub); } } } LP::addRows(newRows); for (int i = 0; i < newRows.size(); i++) delete newRows[i]; }
/* * The cost will be used in many places to make decisions. * Access should be fast. * The SQL front-end also makes the BAT index available as the * property bid. This can be used to access the BAT and involve * more properties into the decision procedure. * [to be done] * Also make sure you don't re-use variables, because then the * row count becomes non-deterministic. */ int OPTcostModelImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i; BUN c1, c2; InstrPtr p; (void) cntxt; (void) stk; (void) pci; if ( mb->inlineProp ) return 0; for (i = 0; i < mb->stop; i++) { p = getInstrPtr(mb, i); if (getModuleId(p)==algebraRef) { if (getFunctionId(p) == subselectRef || getFunctionId(p) == thetasubselectRef) { newRows(1,2, (c1 > 2 ? c2 / 2 +1: c1/2+1),0); } else if ( getFunctionId(p) == selectNotNilRef || getFunctionId(p) == sortRef || getFunctionId(p) == subsortRef || getFunctionId(p) == projectRef ){ newRows(1,1,c1,0); } else if (getFunctionId(p) == subjoinRef || getFunctionId(p) == projectionRef || getFunctionId(p) == subbandjoinRef || getFunctionId(p) == projectionpathRef ) { /* assume 1-1 joins */ newRows(1,2,(c1 < c2 ? c1 : c2),0); } else if (getFunctionId(p) == crossRef) { newRows(1,2,((log((double) c1) + log((double) c2) > log(INT_MAX) ? INT_MAX : c1 * c2 +1)),0); /* log sets errno if it cannot compute the log. This will then screw with code that checks errno */ if (errno == ERANGE || errno == EDOM) { errno = 0; } } } else if (getModuleId(p) == batcalcRef) { if( getFunctionId(p) == ifthenelseRef) { if( isaBatType(getArgType(mb,p,2) ) ) { newRows(2,2, c1,0); } else { newRows(3,3, c1,0); } } else if( isaBatType(getArgType(mb,p,1)) ){ newRows(1,1, c1,0); } else { newRows(2, 2, c2,0); } } else if (getModuleId(p) == batstrRef) { newRows(1,1, c1,0); } else if (getModuleId(p) == batRef) { if (getFunctionId(p) == appendRef || getFunctionId(p) == insertRef ){ /* * Updates are a little more complicated, because you have to * propagate changes in the expected size up the expression tree. * For example, the SQL snippet: * _49:bat[:oid,:oid]{rows=0,bid=622} := sql.bind_dbat("sys","example",3); * _54 := bat.setWriteMode(_49); * bat.append(_54,_47,true); * shows what is produced when it encounters a deletion. If a non-empty * append is not properly passed back to _49, the emptySet * optimizer might remove the complete deletion code. * The same holds for replacement operations, which add information to * an initially empty insertion BAT. */ if( isaBatType(getArgType(mb,p,2)) ){ /* insert BAT */ newRows(1,2, (c1 + c2+1),1); } else { /* insert scalars */ newRows(1,1, (c1 +1),1); } } else if (getFunctionId(p) == deleteRef){ if( isaBatType(getArgType(mb,p,2)) ){ /* delete BAT */ newRows(1, 2, (c2 >= c1 ? 1 : c1 - c2), 1); } else { /* insert scalars */ newRows(1, 1, (c1 <= 1 ? 1 : c1 - 1), 1); } } else if (getFunctionId(p) == insertRef){ newRows(1,1,( c1 + 1),0); /* faked */ } } else if (getModuleId(p)==groupRef) { if (getFunctionId(p) ==subgroupRef ) { newRows(1,1,( c1 / 10+1),0); } else { newRows(1,1, c1,0); } } else if (getModuleId(p)== aggrRef) { if (getFunctionId(p) == sumRef || getFunctionId(p) == minRef || getFunctionId(p) == maxRef || getFunctionId(p) == avgRef) { newRows(1, 1, (c1 != 0 ? c1 : 1), 0); } else if (getFunctionId(p) == countRef){ newRows(1,1, 1,0); } } else if( p->token == ASSIGNsymbol && p->argc== 2){ /* copy the rows property */ c1 = getRowCnt(mb, getArg(p,1)); /* just to ensure that rowcnt was/is never set to -1 */ assert(c1 != (BUN) -1); if (c1 != BUN_NONE) setRowCnt(mb, getArg(p,0), c1); } } return 1; }