/** * \brief Remove overlaps function * * Authors: * Tim Dwyer * * Copyright (C) 2005 Authors * * Released under GNU GPL. Read the file 'COPYING' for more information. */ #include #include "constraint.h" #include "block.h" #include "blocks.h" #include "solve_VPSC.h" #ifdef RECTANGLE_OVERLAP_LOGGING #include using std::ios; using std::ofstream; using std::endl; #endif using std::list; using std::set; VPSC::VPSC(Variable *vs[], const int n, Constraint *cs[], const int m) : cs(cs), m(m) { //assert(!constraintGraphIsCyclic(vs,n)); bs=new Blocks(vs,n); #ifdef RECTANGLE_OVERLAP_LOGGING printBlocks(); #endif } VPSC::~VPSC() { delete bs; } // useful in debugging void VPSC::printBlocks() { #ifdef RECTANGLE_OVERLAP_LOGGING ofstream f(LOGFILE,ios::app); for(set::iterator i=bs->begin();i!=bs->end();i++) { Block *b=*i; f<<" "<<*b< *vs=bs->totalOrder(); for(list::iterator i=vs->begin();i!=vs->end();i++) { Variable *v=*i; if(!v->block->deleted) { bs->mergeLeft(v->block); } } bs->cleanup(); for(int i=0;islack()<-0.0000001) { #ifdef RECTANGLE_OVERLAP_LOGGING ofstream f(LOGFILE,ios::app); f<<"Error: Unsatisfied constraint: "<<*cs[i]<slack()>-0.0000001); throw "Unsatisfied constraint"; } } delete vs; } void VPSC::refine() { bool solved=false; // Solve shouldn't loop indefinately // ... but just to make sure we limit the number of iterations int maxtries=100; while(!solved&&maxtries>=0) { solved=true; maxtries--; for(set::const_iterator i=bs->begin();i!=bs->end();i++) { Block *b=*i; b->setUpInConstraints(); b->setUpOutConstraints(); } for(set::const_iterator i=bs->begin();i!=bs->end();i++) { Block *b=*i; Constraint *c=b->findMinLM(); if(c!=NULL && c->lm<0) { #ifdef RECTANGLE_OVERLAP_LOGGING ofstream f(LOGFILE,ios::app); f<<"Split on constraint: "<<*c<split(b,l,r,c); bs->cleanup(); // split alters the block set so we have to restart solved=false; break; } } } for(int i=0;islack()<-0.0000001) { assert(cs[i]->slack()>-0.0000001); throw "Unsatisfied constraint"; } } } /** * Calculate the optimal solution. After using satisfy() to produce a * feasible solution, refine() examines each block to see if further * refinement is possible by splitting the block. This is done repeatedly * until no further improvement is possible. */ void VPSC::solve() { satisfy(); refine(); } /** * incremental version of solve that should allow refinement after blocks are * moved. Work in progress. */ void VPSC::move_and_split() { //assert(!blockGraphIsCyclic()); for(set::const_iterator i=bs->begin();i!=bs->end();i++) { Block *b=*i; if(!b->deleted) { b->wposn = b->desiredWeightedPosition(); b->posn = b->wposn / b->weight; Variable *v=b->vars->front(); bs->mergeLeft(b); // b may be merged away, so get any new block from one of its members bs->mergeRight(v->block); } } bs->cleanup(); // assert(!blockGraphIsCyclic()); refine(); } #include using std::map; using std::vector; struct node { set in; set out; }; /* // useful in debugging - cycles would be BAD bool VPSC::constraintGraphIsCyclic(Variable *vs[], const int n) { map varmap; vector graph; for(int i=0;i::iterator c=vs[i]->in.begin();c!=vs[i]->in.end();c++) { Variable *l=(*c)->left; varmap[vs[i]]->in.insert(varmap[l]); } for(vector::iterator c=vs[i]->out.begin();c!=vs[i]->out.end();c++) { Variable *r=(*c)->right; varmap[vs[i]]->out.insert(varmap[r]); } } while(graph.size()>0) { node *u=NULL; vector::iterator i=graph.begin(); for(;i!=graph.end();i++) { u=*i; if(u->in.size()==0) { break; } } if(i==graph.end() && graph.size()>0) { //cycle found! return true; } else { graph.erase(i); for(set::iterator j=u->out.begin();j!=u->out.end();j++) { node *v=*j; v->in.erase(u); } delete u; } } for(unsigned i=0; i bmap; vector graph; for(set::const_iterator i=bs->begin();i!=bs->end();i++) { Block *b=*i; node *u=new node; graph.push_back(u); bmap[b]=u; } for(set::const_iterator i=bs->begin();i!=bs->end();i++) { Block *b=*i; b->setUpInConstraints(); Constraint *c=b->findMinInConstraint(); while(c!=NULL) { Block *l=c->left->block; bmap[b]->in.insert(bmap[l]); b->deleteMinInConstraint(); c=b->findMinInConstraint(); } b->setUpOutConstraints(); c=b->findMinOutConstraint(); while(c!=NULL) { Block *r=c->right->block; bmap[b]->out.insert(bmap[r]); b->deleteMinOutConstraint(); c=b->findMinOutConstraint(); } } while(graph.size()>0) { node *u=NULL; vector::iterator i=graph.begin(); for(;i!=graph.end();i++) { u=*i; if(u->in.size()==0) { break; } } if(i==graph.end() && graph.size()>0) { //cycle found! return true; } else { graph.erase(i); for(set::iterator j=u->out.begin();j!=u->out.end();j++) { node *v=*j; v->in.erase(u); } delete u; } } for(unsigned i=0; i