68 for(
unsigned i=0;i<
n;++i) {
75 for(
unsigned i=0;i<
m;++i) {
78 c->right->in.push_back(
c);
101 c->left->out.push_back(
c);
102 c->right->in.push_back(
c);
108#ifdef LIBVPSC_LOGGING
109 ofstream f(LOGFILE,ios::app);
110 for(set<Block*>::iterator i=
bs->begin();i!=
bs->end();++i) {
114 for(
unsigned i=0;i<
m;i++) {
115 f<<
" "<<*
cs[i]<<endl;
125 for(Variables::const_iterator i=
vs.begin();i!=
vs.end();++i) {
127 v->finalPosition=v->position();
128 COLA_ASSERT(v->finalPosition==v->finalPosition);
138 map<Variable*, node*> varmap;
140 for(
unsigned i=0;i<
n;i++) {
145 for(
unsigned i=0;i<
n;i++) {
146 for(vector<Constraint*>::iterator
c=
vs[i]->in.begin();
c!=
vs[i]->in.end();++
c) {
148 varmap[
vs[i]]->
in.insert(varmap[l]);
151 for(vector<Constraint*>::iterator
c=
vs[i]->out.begin();
c!=
vs[i]->out.end();++
c) {
153 varmap[
vs[i]]->
out.insert(varmap[r]);
156 while(graph.size()>0) {
158 vector<node*>::iterator i=graph.
begin();
159 for(;i!=graph.end();++i) {
161 if(u->in.size()==0) {
165 if(i==graph.end() && graph.size()>0) {
170 for(set<node*>::iterator j=u->out.begin();j!=u->out.end();++j) {
177 for(
unsigned i=0; i<graph.size(); ++i) {
185 map<Block*, node*> bmap;
187 size_t length =
bs->
size();
188 for (
size_t i = 0; i < length; ++i)
195 for (
size_t i = 0; i < length; ++i)
202 bmap[b]->
in.insert(bmap[l]);
211 bmap[b]->
out.insert(bmap[r]);
216 while(graph.size()>0) {
218 vector<node*>::iterator i=graph.
begin();
219 for(;i!=graph.end();++i) {
221 if(u->in.size()==0) {
225 if(i==graph.end() && graph.size()>0) {
230 for(set<node*>::iterator j=u->out.begin();j!=u->out.end();++j) {
237 for(
unsigned i=0; i<graph.size(); i++) {
244#ifdef LIBVPSC_LOGGING
245 ofstream f(LOGFILE,ios::app);
246 f<<
"solve_inc()..."<<endl;
250 while(fabs(lastcost-
cost)>0.0001) {
254#ifdef LIBVPSC_LOGGING
255 f<<
" bs->size="<<
bs->
size()<<
", cost="<<
cost<<endl;
275#ifdef LIBVPSC_LOGGING
276 ofstream f(LOGFILE,ios::app);
277 f<<
"satisfy_inc()..."<<endl;
286 COLA_ASSERT(!v->active);
287 Block *lb = v->left->block, *rb = v->right->block;
293 v->unsatisfiable=
true;
307 if(splitConstraint!=
nullptr) {
308 COLA_ASSERT(!splitConstraint->
active);
309 inactive.push_back(splitConstraint);
311 v->unsatisfiable=
true;
324 v->unsatisfiable=
true;
328 COLA_ASSERT(!v->active);
335 delete ((lb->
deleted) ? lb : rb);
338#ifdef LIBVPSC_LOGGING
339 f<<
"...remaining blocks="<<
bs->
size()<<
", cost="<<
bs->
cost()<<endl;
342#ifdef LIBVPSC_LOGGING
343 f<<
" finished merges."<<endl;
346 bool activeConstraints=
false;
347 for(
unsigned i=0;i<
m;i++) {
349 if(v->active) activeConstraints=
true;
352 s<<
"Unsatisfied constraint: "<<*v;
353#ifdef LIBVPSC_LOGGING
354 ofstream f(LOGFILE,ios::app);
357 throw s.str().c_str();
360#ifdef LIBVPSC_LOGGING
361 f<<
" finished cleanup."<<endl;
365 return activeConstraints;
368#ifdef LIBVPSC_LOGGING
369 ofstream f(LOGFILE,ios::app);
370 f<<
"moveBlocks()..."<<endl;
372 size_t length =
bs->
size();
373 for (
size_t i = 0; i < length; ++i)
379#ifdef LIBVPSC_LOGGING
380 f<<
" moved blocks."<<endl;
384#ifdef LIBVPSC_LOGGING
385 ofstream f(LOGFILE,ios::app);
390 size_t length =
bs->
size();
391 for (
size_t i = 0; i < length; ++i)
396 COLA_ASSERT(!v->equality);
397#ifdef LIBVPSC_LOGGING
398 f<<
" found split point: "<<*v<<
" lm="<<v->lm<<endl;
401 Block *b = v->left->block, *l=
nullptr, *r=
nullptr;
402 COLA_ASSERT(v->left->block == v->right->block);
408 l->updateWeightedPosition();
409 r->updateWeightedPosition();
413 COLA_ASSERT(!v->active);
415#ifdef LIBVPSC_LOGGING
416 f<<
" new blocks: "<<*l<<
" and "<<*r<<endl;
421#ifdef LIBVPSC_LOGGING
422 f<<
" finished splits."<<endl;
433 double slackForMostViolated = DBL_MAX;
435#ifdef LIBVPSC_LOGGING
436 ofstream f(LOGFILE,ios::app);
437 f <<
"Looking for most violated..." << endl;
439 size_t lSize = l.size();
440 size_t deleteIndex = lSize;
445 constraint = l[
index];
446 slack = constraint->
slack();
447 if (constraint->
equality || slack < slackForMostViolated)
449 slackForMostViolated = slack;
462 if ( (deleteIndex < lSize) &&
466 l[deleteIndex] = l[lSize-1];
469#ifdef LIBVPSC_LOGGING
476 f <<
" non found." << endl;
488#define __NOTNAN(p) (p)==(p)
493 m_blocks.resize(nvs);
494 for(
size_t i=0;i<nvs;i++) {
495 m_blocks[i] =
new Block(
this,
vs[i]);
502 for (
size_t i = 0; i < length; ++i)
514 list<Variable*> *
order =
new list<Variable*>;
515 for(
size_t i=0;i<
nvs;i++) {
516 vs[i]->visited=
false;
518 for(
size_t i=0;i<
nvs;i++) {
519 if(
vs[i]->in.size()==0) {
529 vector<Constraint*>::iterator it=v->out.begin();
530 for(;it!=v->out.end();++it) {
532 if(!
c->right->visited) {
536#ifdef LIBVPSC_LOGGING
537 ofstream f(LOGFILE,ios::app);
538 f<<
" order="<<*v<<endl;
540 order->push_front(v);
547#ifdef LIBVPSC_LOGGING
548 ofstream f(LOGFILE,ios::app);
549 f<<
"mergeLeft called on "<<*r<<endl;
554 while (
c !=
nullptr &&
c->slack()<0) {
555#ifdef LIBVPSC_LOGGING
556 f<<
"mergeLeft on constraint: "<<*
c<<endl;
559 Block *l =
c->left->block;
561 double dist =
c->right->offset -
c->left->offset -
c->gap;
562 if (r->
vars->size() < l->
vars->size()) {
573#ifdef LIBVPSC_LOGGING
574 f<<
"merged "<<*r<<endl;
581#ifdef LIBVPSC_LOGGING
582 ofstream f(LOGFILE,ios::app);
583 f<<
"mergeRight called on "<<*l<<endl;
587 while (
c !=
nullptr &&
c->slack()<0) {
588#ifdef LIBVPSC_LOGGING
589 f<<
"mergeRight on constraint: "<<*
c<<endl;
592 Block *r =
c->right->block;
594 double dist =
c->left->offset +
c->gap -
c->right->offset;
595 if (l->
vars->size() > r->
vars->size()) {
604#ifdef LIBVPSC_LOGGING
605 f<<
"merged "<<*l<<endl;
624 for (
size_t j = 0; j < length; )
655#ifdef LIBVPSC_LOGGING
656 ofstream f(LOGFILE,ios::app);
657 f<<
"Split left: "<<*l<<endl;
658 f<<
"Split right: "<<*r<<endl;
671 COLA_ASSERT(__NOTNAN(l->
posn));
672 COLA_ASSERT(__NOTNAN(r->
posn));
681 for (
size_t i = 0; i < length; ++i)
689 double ai=
scale/v->scale;
690 double bi=v->offset/v->scale;
693 AD+=wi*ai*v->desiredPosition;
713 COLA_ASSERT(__NOTNAN(
posn));
746 COLA_ASSERT(__NOTNAN(
posn));
747#ifdef LIBVPSC_LOGGING
748 ofstream f(LOGFILE,ios::app);
749 f <<
", posn=" <<
posn << endl;
769 vector<Constraint*> *cs=
in?&(v->in):&(v->out);
770 for (
Cit j=cs->begin();j!=cs->end();++j) {
773 if ( ((
c->left->block !=
this) &&
in) ||
774 ((
c->right->block !=
this) && !
in) )
782#ifdef LIBVPSC_LOGGING
783 ofstream f(LOGFILE,ios::app);
784 f<<
" merging on: "<<*
c<<
",c->left->offset="<<
c->left->offset<<
",c->right->offset="<<
c->right->offset<<endl;
786 double dist =
c->right->offset -
c->left->offset -
c->gap;
789 if (l->
vars->size() < r->
vars->size()) {
795#ifdef LIBVPSC_LOGGING
796 f<<
" merged block="<<*mergeBlock<<endl;
808#ifdef LIBVPSC_LOGGING
809 ofstream f(LOGFILE,ios::app);
810 f<<
" merging: "<<*b<<
"dist="<<
dist<<endl;
815 for(
Vit i=b->
vars->begin();i!=b->
vars->end();++i) {
822#ifdef LIBVPSC_LOGGING
825 f<<
" v["<<v->id<<
"]: d="<<v->desiredPosition
826 <<
" a="<<v->scale<<
" o="<<v->offset
834 COLA_ASSERT(__NOTNAN(
posn));
839#ifdef LIBVPSC_LOGGING
840 ofstream f(LOGFILE,ios::app);
841 f<<
" merging constraint heaps... "<<endl;
846 while (!b->
in->empty())
848 in->push(b->
in->top());
851#ifdef LIBVPSC_LOGGING
852 f<<
" merged heap: "<<*
in<<endl;
858 while (!b->
out->empty())
866 vector<Constraint*> outOfDate;
867 while (!
in->empty()) {
869 Block *lb=v->left->block;
870 Block *rb=v->right->block;
872#ifdef LIBVPSC_LOGGING
873 ofstream f(LOGFILE,ios::app);
874 f<<
" checking constraint ... "<<*v;
875 f<<
" timestamps: left="<<lb->
timeStamp<<
" right="<<rb->
timeStamp<<
" constraint="<<v->timeStamp<<endl;
879#ifdef LIBVPSC_LOGGING
881 f<<
" violated internal constraint found! "<<*v<<endl;
882 f<<
" lb="<<*lb<<endl;
883 f<<
" rb="<<*rb<<endl;
887#ifdef LIBVPSC_LOGGING
888 f<<
" ... skipping internal constraint"<<endl;
890 }
else if(v->timeStamp < lb->
timeStamp) {
893 outOfDate.push_back(v);
894#ifdef LIBVPSC_LOGGING
895 f<<
" reinserting out of date (reinsert later)"<<endl;
901 for(
Cit i=outOfDate.begin();i!=outOfDate.end();++i) {
914 if(
out->empty())
return nullptr;
916 while (v->left->block == v->right->block) {
918 if(
out->empty())
return nullptr;
925#ifdef LIBVPSC_LOGGING
926 ofstream f(LOGFILE,ios::app);
927 f<<
"deleteMinInConstraint... "<<endl;
928 f<<
" result: "<<*
in<<endl;
935 return c->left->block==
this &&
c->active && last!=
c->left;
938 return c->right->
block==
this &&
c->active && last!=
c->right;
948 double dfdv=v->dfdv();
949 for(
Cit it=v->out.begin();it!=v->out.end();++it) {
953 dfdv+=
c->lm*
c->left->scale;
954 if(!
c->equality&&(min_lm==
nullptr||
c->
lm<min_lm->
lm)) min_lm=
c;
957 for(
Cit it=v->in.begin();it!=v->in.end();++it) {
961 dfdv-=
c->lm*
c->right->scale;
962 if(!
c->equality&&(min_lm==
nullptr||
c->
lm<min_lm->
lm)) min_lm=
c;
965 return dfdv/v->scale;
968 double dfdv = v->dfdv();
969 for(
Cit it = v->out.begin(); it != v->out.end(); ++it) {
973 dfdv +=
c->lm *
c->left->scale;
976 for(
Cit it=v->in.begin();it!=v->in.end();++it) {
980 dfdv -=
c->lm *
c->right->scale;
983 return dfdv/v->scale;
1000 bool desperation=
false
1003 for(
Cit it(v->in.begin());it!=v->in.end();++it) {
1006#ifdef LIBVPSC_LOGGING
1007 ofstream f(LOGFILE,ios::app);
1008 f<<
" left split path: "<<*
c<<endl;
1011 if(desperation&&!
c->equality) m=
c;
1015 if(desperation && !
c->equality && (!m||
c->
lm<m->
lm)) {
1023 for(
Cit it(v->out.begin());it!=v->out.end();++it) {
1026#ifdef LIBVPSC_LOGGING
1027 ofstream f(LOGFILE,ios::app);
1028 f<<
" right split path: "<<*
c<<endl;
1031 if(!
c->equality) m=
c;
1035 if(!
c->equality && (!m||
c->
lm<m->
lm))
1094 for(
Cit it=v->out.begin();it!=v->out.end();++it) {
1101 for(
Cit it=v->in.begin();it!=v->in.end();++it) {
1110 for(
Cit it=v->out.begin();it!=v->out.end();++it) {
1113#ifdef LIBVPSC_LOGGING
1114 ofstream f(LOGFILE,ios::app);
1120 for(
Cit it=v->in.begin();it!=v->in.end();++it) {
1123#ifdef LIBVPSC_LOGGING
1124 ofstream f(LOGFILE,ios::app);
1139#ifdef LIBVPSC_LOGGING
1140 ofstream f(LOGFILE,ios::app);
1141 f<<
" langrangians: "<<endl;
1152 if(min_lm==
nullptr) {
1156 if(min_lm==
nullptr) {
1162 COLA_ASSERT(min_lm!=
nullptr);
1171 for (
Cit c=v->in.begin();
c!=v->in.end();++
c) {
1175 for (
Cit c=v->out.begin();
c!=v->out.end();++
c) {
1185 if(u==v)
return true;
1208 if(u==v)
return true;
1220 if(u==v)
return true;
1239#ifdef LIBVPSC_LOGGING
1240 ofstream f(LOGFILE,ios::app);
1241 f<<
" need to split between: "<<*vl<<
" and "<<*vr<<endl;
1244#ifdef LIBVPSC_LOGGING
1245 f<<
" going to split on: "<<*
c<<endl;
1276 double diff = (*v)->position() - (*v)->desiredPosition;
1277 c += (*v)->weight * diff * diff;
1281ostream& operator <<(ostream &os,
const Block& b)
1283 os<<
"Block(posn="<<b.
posn<<
"):";
1300 unsatisfiable(false),
1325 std::stringstream stream;
1326 stream <<
"Constraint: var(" <<
left->
id <<
") ";
1329 stream <<
"- " << -
gap <<
" ";
1333 stream <<
"+ " <<
gap <<
" ";
1335 stream << ((
equality) ?
"==" :
"<=");
1336 stream <<
" var(" <<
right->
id <<
") ";
1337 return stream.str();
1342 const char *type =
c.equality ?
"=" :
"<=";
1343 std::ostringstream lscale, rscale;
1344 if (
c.left->scale != 1)
1346 lscale <<
c.left->scale <<
"*";
1348 if (
c.right->scale != 1)
1350 rscale <<
c.right->scale <<
"*";
1352 os << lscale.str() << *
c.left <<
"+" <<
c.gap << type <<
1353 rscale.str() << *
c.right;
1354 if (
c.left->block &&
c.right->block)
1356 os <<
"(" <<
c.slack() <<
")" << (
c.active ?
"-active" :
"") <<
1357 "(lm=" <<
c.lm <<
")";
1361 os <<
"(vars have no position)";
1372 ?-DBL_MAX:l->
slack();
1376 ?-DBL_MAX:r->
slack();
1389std::ostream& operator <<(std::ostream &os,
const Variable &v) {
1391 os <<
"(" << v.id <<
"=" << v.position() <<
")";
1393 os <<
"(" << v.id <<
"=" << v.desiredPosition <<
")";
1399class EqualityConstraintSet
1404 for (
size_t i = 0; i < vs.size(); ++i)
1406 std::map<Variable *, double> varSet;
1408 variableGroups.push_back(varSet);
1413 VarOffsetMapList::iterator lhsSet = setForVar(lhs);
1414 VarOffsetMapList::iterator rhsSet = setForVar(rhs);
1415 if (lhsSet == rhsSet)
1418 if (fabs(((*lhsSet)[lhs] + sep) - (*rhsSet)[rhs]) < 0.0001)
1428 VarOffsetMapList::iterator lhsSet = setForVar(lhs);
1429 VarOffsetMapList::iterator rhsSet = setForVar(rhs);
1430 if (lhsSet == rhsSet)
1435 double rhsOldOffset = (*rhsSet)[rhs];
1436 double rhsNewOffset = (*lhsSet)[lhs] + sep;
1437 double offset = rhsNewOffset - rhsOldOffset;
1440 for (std::map<Variable *, double>::iterator it = rhsSet->begin();
1441 it != rhsSet->end(); ++it)
1447 lhsSet->insert(rhsSet->begin(), rhsSet->end());
1448 variableGroups.erase(rhsSet);
1452 VarOffsetMapList::iterator setForVar(
Variable *var)
1454 for (VarOffsetMapList::iterator it = variableGroups.begin();
1455 it != variableGroups.end(); ++it)
1457 if (it->find(var) != it->end())
1462 return variableGroups.end();
1471 EqualityConstraintSet equalitySets(vars);
1475 for (
unsigned i = 0; i < constraints.size(); ++i)
1480 if (!equalitySets.isRedundant(
c->left,
c->right,
c->gap))
1483 equalitySets.mergeSets(
c->left,
c->right,
c->gap);
void split(Block *&l, Block *&r, Constraint *c)
Constraint * splitBetween(Variable *vl, Variable *vr, Block *&lb, Block *&rb)
bool canFollowLeft(Constraint const *c, Variable const *last) const
Constraint * findMinInConstraint()
bool canFollowRight(Constraint const *c, Variable const *last) const
bool getActivePathBetween(Constraints &path, Variable const *u, Variable const *v, Variable const *w) const
void setUpInConstraints()
void reset_active_lm(Variable *const v, Variable *const u)
void list_active(Variable *const v, Variable *const u)
Block(Blocks *blocks, Variable *const v=nullptr)
void merge(Block *b, Constraint *c, double dist)
Constraint * findMinLMBetween(Variable *const lv, Variable *const rv)
void populateSplitBlock(Block *b, Variable *v, Variable const *u)
void updateWeightedPosition()
Constraints::iterator Cit
bool getActiveDirectedPathBetween(Constraints &path, Variable const *u, Variable const *v) const
Constraints::const_iterator Cit_const
bool isActiveDirectedPathBetween(Variable const *u, Variable const *v) const
void deleteMinInConstraint()
void setUpOutConstraints()
bool split_path(Variable *, Variable *const, Variable *const, Constraint *&min_lm, bool desperation)
Constraint * findMinOutConstraint()
double compute_dfdv(Variable *const v, Variable *const u)
void addVariable(Variable *v)
void deleteMinOutConstraint()
void setUpConstraintHeap(Heap *&h, bool in)
void dfsVisit(Variable *v, std::list< Variable * > *order)
Blocks(Variables const &vs)
void split(Block *b, Block *&l, Block *&r, Constraint *c)
std::vector< Block * > m_blocks
void mergeRight(Block *l)
void removeBlock(Block *doomed)
std::list< Variable * > * totalOrder()
void insert(Block *block)
Block * at(size_t index) const
bool operator()(Constraint *const &l, Constraint *const &r) const
Constraint(Variable *left, Variable *right, double gap, bool equality=false)
std::string toString(void) const
void addConstraint(Constraint *constraint)
bool constraintGraphIsCyclic(const unsigned n, Variable *const vs[])
IncSolver(Variables const &vs, Constraints const &cs)
bool blockGraphIsCyclic()
Constraint * mostViolated(Constraints &l)
iterator begin()
Iterator over children.
Inkscape::XML::Node * node
libavoid: Object-avoiding orthogonal and polyline connector routing library.
static const double LAGRANGIAN_TOLERANCE
static double cost(ConnRef *lineRef, const double dist, VertInf *inf2, VertInf *inf3, ANode *inf1Node)
Constraints constraintsRemovingRedundantEqualities(Variables const &vars, Constraints const &constraints)
std::vector< Variable * > Variables
std::list< std::map< Variable *, double > > VarOffsetMapList
std::vector< Constraint * > Constraints
std::priority_queue< Constraint *, std::vector< Constraint * >, CompareConstraints > Heap
static const double ZERO_UPPERBOUND
double dist(const Point &a, const Point &b)
void addVariable(Variable *const v)