/** * incremental version of satisfy that allows refinement after blocks are * moved. * * - move blocks to new positions * - repeatedly merge across most violated constraint until no more * violated constraints exist * * Note: there is a special case to handle when the most violated constraint * is between two variables in the same block. Then, we must split the block * over an active constraint between the two variables. We choose the * constraint with the most negative lagrangian multiplier. */ void IncSolver::satisfy() { #ifdef RECTANGLE_OVERLAP_LOGGING ofstream f(LOGFILE,ios::app); f<<"satisfy_inc()..."<<endl; #endif splitBlocks(); long splitCtr = 0; Constraint* v = NULL; while((v=mostViolated(inactive))&&(v->equality || v->slack() < ZERO_UPPERBOUND)) { assert(!v->active); Block *lb = v->left->block, *rb = v->right->block; if(lb != rb) { lb->merge(rb,v); } else { if(lb->isActiveDirectedPathBetween(v->right,v->left)) { // cycle found, relax the violated, cyclic constraint v->gap = v->slack(); continue; } if(splitCtr++>10000) { throw "Cycle Error!"; } // constraint is within block, need to split first inactive.push_back(lb->splitBetween(v->left,v->right,lb,rb)); lb->merge(rb,v); bs->insert(lb); } } #ifdef RECTANGLE_OVERLAP_LOGGING f<<" finished merges."<<endl; #endif bs->cleanup(); for(unsigned i=0; i<m; i++) { v=cs[i]; if(v->slack() < ZERO_UPPERBOUND) { ostringstream s; s<<"Unsatisfied constraint: "<<*v; #ifdef RECTANGLE_OVERLAP_LOGGING ofstream f(LOGFILE,ios::app); f<<s.str()<<endl; #endif throw s.str().c_str(); } } #ifdef RECTANGLE_OVERLAP_LOGGING f<<" finished cleanup."<<endl; printBlocks(); #endif }
void IncSolver::solve() { #ifdef RECTANGLE_OVERLAP_LOGGING ofstream f(LOGFILE,ios::app); f<<"solve_inc()..."<<endl; #endif double lastcost,cost = bs->cost(); do { lastcost=cost; satisfy(); splitBlocks(); cost = bs->cost(); #ifdef RECTANGLE_OVERLAP_LOGGING f<<" cost="<<cost<<endl; #endif } while(fabs(lastcost-cost)>0.0001); }