Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
solve_VPSC.cpp
Go to the documentation of this file.
1
20#include <cassert>
21#include <vpsc/constraint.h>
22#include <vpsc/block.h>
23#include <vpsc/blocks.h>
24#include <vpsc/solve_VPSC.h>
25#include <math.h>
26#include <memory>
27#include <sstream>
28#include <fstream>
29using std::ios;
30using std::ofstream;
31
32using std::ostringstream;
33using std::list;
34using std::set;
35
36#ifndef RECTANGLE_OVERLAP_LOGGING
37 #define RECTANGLE_OVERLAP_LOGGING 0
38#endif
39
40IncVPSC::IncVPSC(const unsigned n, Variable *vs[], const unsigned m, Constraint *cs[])
41 : VPSC(n,vs,m,cs) {
42 inactive.assign(cs,cs+m);
43 for(Constraint *c : inactive) {
44 c->active=false;
45 }
46}
47VPSC::VPSC(const unsigned n, Variable *vs[], const unsigned m, Constraint *cs[])
48 : bs(n, vs), cs(cs), m(m) {
51 assert(!constraintGraphIsCyclic(n,vs));
52 }
53}
54
55// useful in debugging
58 ofstream f(LOGFILE,ios::app);
59 for(Block *b : bs) {
60 f<<" "<<*b<<"\n";
61 }
62 for(unsigned i=0;i<m;i++) {
63 f<<" "<<*cs[i]<<"\n";
64 }
65 }
66}
78 list<Variable*> vs=bs.totalOrder();
79 for(Variable *v : vs) {
80 if(!v->block->deleted) {
81 bs.mergeLeft(v->block);
82 }
83 }
84 bs.cleanup();
85 for(unsigned i=0;i<m;i++) {
86 if(cs[i]->slack()<-0.0000001) {
88 ofstream f(LOGFILE,ios::app);
89 f<<"Error: Unsatisfied constraint: "<<*cs[i]<<"\n";
90 }
91 //assert(cs[i]->slack()>-0.0000001);
92 throw "Unsatisfied constraint";
93 }
94 }
95}
96
97void VPSC::refine() {
98 for (bool solved = false; !solved;) {
99 solved=true;
100 for(Block *b : bs) {
101 b->setUpInConstraints();
102 b->setUpOutConstraints();
103 }
104 for(Block *b : bs) {
105 Constraint *c=b->findMinLM();
106 if(c!=nullptr && c->lm<0) {
108 ofstream f(LOGFILE,ios::app);
109 f<<"Split on constraint: "<<*c<<"\n";
110 }
111 // Split on c
112 Block *l=nullptr, *r=nullptr;
113 bs.split(b,l,r,c);
114 bs.cleanup();
115 // split alters the block set so we have to restart
116 solved=false;
117 break;
118 }
119 }
120 }
121 for(unsigned i=0;i<m;i++) {
122 if(cs[i]->slack()<-0.0000001) {
123 assert(cs[i]->slack()>-0.0000001);
124 throw "Unsatisfied constraint";
125 }
126 }
127}
135 satisfy();
136 refine();
137}
138
141 ofstream f(LOGFILE,ios::app);
142 f<<"solve_inc()...\n";
143 }
144 double lastcost,cost = bs.cost();
145 do {
146 lastcost=cost;
147 satisfy();
148 splitBlocks();
149 cost = bs.cost();
151 ofstream f(LOGFILE,ios::app);
152 f<<" cost="<<cost<<"\n";
153 }
154 } while(fabs(lastcost-cost)>0.0001);
155}
171 ofstream f(LOGFILE,ios::app);
172 f<<"satisfy_inc()...\n";
173 }
174 splitBlocks();
175 long splitCtr = 0;
176 Constraint* v = nullptr;
177 while(mostViolated(inactive,v)<-0.0000001) {
178 assert(!v->active);
179 Block *lb = v->left->block, *rb = v->right->block;
180 if(lb != rb) {
181 lb->merge(rb,v);
182 } else {
183 if(splitCtr++>10000) {
184 throw "Cycle Error!";
185 }
186 // constraint is within block, need to split first
187 inactive.push_back(lb->splitBetween(v->left,v->right,lb,rb));
188 lb->merge(rb,v);
189 bs.insert(lb);
190 }
191 }
193 ofstream f(LOGFILE,ios::app);
194 f<<" finished merges.\n";
195 }
196 bs.cleanup();
197 for(unsigned i=0;i<m;i++) {
198 v=cs[i];
199 if(v->slack()<-0.0000001) {
200 //assert(cs[i]->slack()>-0.0000001);
201 ostringstream s;
202 s<<"Unsatisfied constraint: "<<*v;
203 throw s.str().c_str();
204 }
205 }
207 ofstream f(LOGFILE,ios::app);
208 f<<" finished cleanup.\n";
209 printBlocks();
210 }
211}
214 ofstream f(LOGFILE,ios::app);
215 f<<"moveBlocks()...\n";
216 }
217 for(Block *b : bs) {
218 b->wposn = b->desiredWeightedPosition();
219 b->posn = b->wposn / b->weight;
220 }
222 ofstream f(LOGFILE,ios::app);
223 f<<" moved blocks.\n";
224 }
225}
227 moveBlocks();
228 splitCnt=0;
229 // Split each block if necessary on min LM
230 for(Block *b : bs) {
231 Constraint* v=b->findMinLM();
232 if(v!=nullptr && v->lm < -0.0000001) {
234 ofstream f(LOGFILE,ios::app);
235 f<<" found split point: "<<*v<<" lm="<<v->lm<<"\n";
236 }
237 splitCnt++;
238 Block *b2 = v->left->block, *l=nullptr, *r=nullptr;
239 assert(v->left->block == v->right->block);
240 double pos = b2->posn;
241 b2->split(l,r,v);
242 l->posn=r->posn=pos;
243 l->wposn = l->posn * l->weight;
244 r->wposn = r->posn * r->weight;
245 bs.insert(l);
246 bs.insert(r);
247 b2->deleted=true;
248 inactive.push_back(v);
250 ofstream f(LOGFILE,ios::app);
251 f<<" new blocks: "<<*l<<" and "<<*r<<"\n";
252 }
253 }
254 }
256 ofstream f(LOGFILE,ios::app);
257 f<<" finished splits.\n";
258 }
259 bs.cleanup();
260}
261
266double IncVPSC::mostViolated(ConstraintList &l, Constraint* &v) {
267 double minSlack = DBL_MAX;
269 ofstream f(LOGFILE,ios::app);
270 f<<"Looking for most violated...\n";
271 }
272 ConstraintList::iterator end = l.end();
273 ConstraintList::iterator deletePoint = end;
274 for(ConstraintList::iterator i=l.begin();i!=end;i++) {
275 Constraint *c=*i;
276 double slack = c->slack();
277 if (slack < minSlack) {
278 minSlack=slack;
279 v=c;
280 deletePoint=i;
281 }
282 }
283 // Because the constraint list is not order dependent we just
284 // move the last element over the deletePoint and resize
285 // downwards. There is always at least 1 element in the
286 // vector because of search.
287 if(deletePoint != end && minSlack<-0.0000001) {
288 *deletePoint = l[l.size()-1];
289 l.resize(l.size()-1);
290 }
292 ofstream f(LOGFILE,ios::app);
293 f<<" most violated is: "<<*v<<"\n";
294 }
295 return minSlack;
296}
297
298#include <map>
299using std::map;
300using std::vector;
301struct node {
302 set<node*> in;
303 set<node*> out;
304};
305// useful in debugging - cycles would be BAD
306bool VPSC::constraintGraphIsCyclic(const unsigned n, Variable *vs[]) {
307 map<Variable*, node*> varmap;
308 vector<std::unique_ptr<node>> graph;
309 for(unsigned i=0;i<n;i++) {
310 graph.emplace_back(new node);
311 varmap[vs[i]]=graph.back().get();
312 }
313 for(unsigned i=0;i<n;i++) {
314 for(Constraint *c : vs[i]->in) {
315 Variable *l=c->left;
316 varmap[vs[i]]->in.insert(varmap[l]);
317 }
318
319 for(Constraint *c : vs[i]->out) {
320 Variable *r=c->right;
321 varmap[vs[i]]->out.insert(varmap[r]);
322 }
323 }
324 while(!graph.empty()) {
325 node *u=nullptr;
326 vector<std::unique_ptr<node>>::iterator i=graph.begin();
327 for(;i!=graph.end();i++) {
328 u=(*i).get();
329 if(u->in.empty()) {
330 break;
331 }
332 }
333 if(i==graph.end()) {
334 //cycle found!
335 return true;
336 } else {
337 graph.erase(i);
338 for(node *v : u->out) {
339 v->in.erase(u);
340 }
341 }
342 }
343 return false;
344}
345
346// useful in debugging - cycles would be BAD
347bool VPSC::blockGraphIsCyclic() {
348 map<Block*, node*> bmap;
349 vector<std::unique_ptr<node>> graph;
350 for(Block *b : bs) {
351 graph.emplace_back(new node);
352 bmap[b]=graph.back().get();
353 }
354 for(Block *b : bs) {
355 b->setUpInConstraints();
356 Constraint *c=b->findMinInConstraint();
357 while(c!=nullptr) {
358 Block *l=c->left->block;
359 bmap[b]->in.insert(bmap[l]);
360 b->deleteMinInConstraint();
361 c=b->findMinInConstraint();
362 }
363
364 b->setUpOutConstraints();
365 c=b->findMinOutConstraint();
366 while(c!=nullptr) {
367 Block *r=c->right->block;
368 bmap[b]->out.insert(bmap[r]);
369 b->deleteMinOutConstraint();
370 c=b->findMinOutConstraint();
371 }
372 }
373 while(!graph.empty()) {
374 node *u=nullptr;
375 vector<std::unique_ptr<node>>::iterator i=graph.begin();
376 for(;i!=graph.end();i++) {
377 u=(*i).get();
378 if(u->in.empty()) {
379 break;
380 }
381 }
382 if(i==graph.end()) {
383 //cycle found!
384 return true;
385 }
386 graph.erase(i);
387 for(node *v : u->out) {
388 v->in.erase(u);
389 }
390 }
391 return false;
392}
static void out(agerrlevel_t level, const char *fmt, va_list args)
Report messages using a user-supplied or default write function.
Definition agerror.c:84
#define RECTANGLE_OVERLAP_LOGGING
Definition block.cpp:31
#define LOGFILE
A block structure defined over the variables.
Definition blocks.h:24
Definition block.h:30
bool deleted
Definition block.h:55
void split(Block *&l, Block *&r, Constraint *c)
Definition block.cpp:361
double posn
Definition block.h:34
Constraint * splitBetween(Variable *vl, Variable *vr, Block *&lb, Block *&rb)
Definition block.cpp:342
std::unique_ptr< PairingHeap< Constraint * > > out
Definition block.h:58
void merge(Block *b, Constraint *c, double dist)
Definition block.cpp:102
std::unique_ptr< PairingHeap< Constraint * > > in
Definition block.h:57
void cleanup()
Definition blocks.cpp:156
double cost()
Definition blocks.cpp:195
void split(Block *b, Block *&l, Block *&r, Constraint *c)
Definition blocks.cpp:171
std::list< Variable * > totalOrder()
Definition blocks.cpp:55
void mergeLeft(Block *r)
Definition blocks.cpp:86
Agraph_t * graph(char *name)
Definition gv.cpp:31
A constraint determines a minimum or exact spacing required between two variables.
Definition constraint.h:25
Variable * right
Definition constraint.h:29
double lm
Definition constraint.h:31
Variable * left
Definition constraint.h:28
bool active
Definition constraint.h:36
double slack() const
Definition constraint.h:34
void satisfy()
IncVPSC(const unsigned n, Variable *vs[], const unsigned m, Constraint *cs[])
void moveBlocks()
unsigned splitCnt
Definition solve_VPSC.h:49
void solve()
void splitBlocks()
void printBlocks()
VPSC(const unsigned n, Variable *vs[], const unsigned m, Constraint *cs[])
virtual void solve()
virtual void satisfy()
Constraint ** cs
Definition solve_VPSC.h:38
Blocks bs
Definition solve_VPSC.h:37
unsigned m
Definition solve_VPSC.h:39
Constraints out
Definition variable.h:36
Block * block
Definition variable.h:33
Constraints in
Definition variable.h:35
set< node * > out
set< node * > in
Definition grammar.c:93