Graphviz 13.0.0~dev.20241220.2304
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_,
41 Constraint *cs_[])
42 : VPSC(n, vs, m_, cs_) {
43 inactive.assign(cs_, cs_ + m_);
44 for(Constraint *c : inactive) {
45 c->active=false;
46 }
47}
48
49VPSC::VPSC(const unsigned n, Variable *vs[], const unsigned m_,
50 Constraint *cs_[])
51 : bs(n, vs), cs(cs_), m(m_) {
54 assert(!constraintGraphIsCyclic(n,vs));
55 }
56}
57
58// useful in debugging
61 ofstream f(LOGFILE,ios::app);
62 for(Block *b : bs) {
63 f<<" "<<*b<<"\n";
64 }
65 for(unsigned i=0;i<m;i++) {
66 f<<" "<<*cs[i]<<"\n";
67 }
68 }
69}
81 list<Variable*> vs=bs.totalOrder();
82 for(Variable *v : vs) {
83 if(!v->block->deleted) {
84 bs.mergeLeft(v->block);
85 }
86 }
87 bs.cleanup();
88 for(unsigned i=0;i<m;i++) {
89 if(cs[i]->slack()<-0.0000001) {
91 ofstream f(LOGFILE,ios::app);
92 f<<"Error: Unsatisfied constraint: "<<*cs[i]<<"\n";
93 }
94 //assert(cs[i]->slack()>-0.0000001);
95 throw "Unsatisfied constraint";
96 }
97 }
98}
99
100void VPSC::refine() {
101 for (bool solved = false; !solved;) {
102 solved=true;
103 for(Block *b : bs) {
104 b->setUpInConstraints();
105 b->setUpOutConstraints();
106 }
107 for(Block *b : bs) {
108 Constraint *c=b->findMinLM();
109 if(c!=nullptr && c->lm<0) {
111 ofstream f(LOGFILE,ios::app);
112 f<<"Split on constraint: "<<*c<<"\n";
113 }
114 // Split on c
115 Block *l=nullptr, *r=nullptr;
116 bs.split(b,l,r,c);
117 bs.cleanup();
118 // split alters the block set so we have to restart
119 solved=false;
120 break;
121 }
122 }
123 }
124 for(unsigned i=0;i<m;i++) {
125 if(cs[i]->slack()<-0.0000001) {
126 assert(cs[i]->slack()>-0.0000001);
127 throw "Unsatisfied constraint";
128 }
129 }
130}
138 satisfy();
139 refine();
140}
141
144 ofstream f(LOGFILE,ios::app);
145 f<<"solve_inc()...\n";
146 }
147 double lastcost,cost = bs.cost();
148 do {
149 lastcost=cost;
150 satisfy();
151 splitBlocks();
152 cost = bs.cost();
154 ofstream f(LOGFILE,ios::app);
155 f<<" cost="<<cost<<"\n";
156 }
157 } while(fabs(lastcost-cost)>0.0001);
158}
174 ofstream f(LOGFILE,ios::app);
175 f<<"satisfy_inc()...\n";
176 }
177 splitBlocks();
178 long splitCtr = 0;
179 Constraint* v = nullptr;
180 while(mostViolated(inactive,v)<-0.0000001) {
181 assert(!v->active);
182 Block *lb = v->left->block, *rb = v->right->block;
183 if(lb != rb) {
184 lb->merge(rb,v);
185 } else {
186 if(splitCtr++>10000) {
187 throw "Cycle Error!";
188 }
189 // constraint is within block, need to split first
190 inactive.push_back(lb->splitBetween(v->left,v->right,lb,rb));
191 lb->merge(rb,v);
192 bs.insert(lb);
193 }
194 }
196 ofstream f(LOGFILE,ios::app);
197 f<<" finished merges.\n";
198 }
199 bs.cleanup();
200 for(unsigned i=0;i<m;i++) {
201 v=cs[i];
202 if(v->slack()<-0.0000001) {
203 //assert(cs[i]->slack()>-0.0000001);
204 ostringstream s;
205 s<<"Unsatisfied constraint: "<<*v;
206 throw s.str().c_str();
207 }
208 }
210 ofstream f(LOGFILE,ios::app);
211 f<<" finished cleanup.\n";
212 printBlocks();
213 }
214}
217 ofstream f(LOGFILE,ios::app);
218 f<<"moveBlocks()...\n";
219 }
220 for(Block *b : bs) {
221 b->wposn = b->desiredWeightedPosition();
222 b->posn = b->wposn / b->weight;
223 }
225 ofstream f(LOGFILE,ios::app);
226 f<<" moved blocks.\n";
227 }
228}
230 moveBlocks();
231 splitCnt=0;
232 // Split each block if necessary on min LM
233 for(Block *b : bs) {
234 Constraint* v=b->findMinLM();
235 if(v!=nullptr && v->lm < -0.0000001) {
237 ofstream f(LOGFILE,ios::app);
238 f<<" found split point: "<<*v<<" lm="<<v->lm<<"\n";
239 }
240 splitCnt++;
241 Block *b2 = v->left->block, *l=nullptr, *r=nullptr;
242 assert(v->left->block == v->right->block);
243 double pos = b2->posn;
244 b2->split(l,r,v);
245 l->posn=r->posn=pos;
246 l->wposn = l->posn * l->weight;
247 r->wposn = r->posn * r->weight;
248 bs.insert(l);
249 bs.insert(r);
250 b2->deleted=true;
251 inactive.push_back(v);
253 ofstream f(LOGFILE,ios::app);
254 f<<" new blocks: "<<*l<<" and "<<*r<<"\n";
255 }
256 }
257 }
259 ofstream f(LOGFILE,ios::app);
260 f<<" finished splits.\n";
261 }
262 bs.cleanup();
263}
264
269double IncVPSC::mostViolated(ConstraintList &l, Constraint* &v) {
270 double minSlack = DBL_MAX;
272 ofstream f(LOGFILE,ios::app);
273 f<<"Looking for most violated...\n";
274 }
275 ConstraintList::iterator end = l.end();
276 ConstraintList::iterator deletePoint = end;
277 for(ConstraintList::iterator i=l.begin();i!=end;i++) {
278 Constraint *c=*i;
279 double slack = c->slack();
280 if (slack < minSlack) {
281 minSlack=slack;
282 v=c;
283 deletePoint=i;
284 }
285 }
286 // Because the constraint list is not order dependent we just
287 // move the last element over the deletePoint and resize
288 // downwards. There is always at least 1 element in the
289 // vector because of search.
290 if(deletePoint != end && minSlack<-0.0000001) {
291 *deletePoint = l[l.size()-1];
292 l.resize(l.size()-1);
293 }
295 ofstream f(LOGFILE,ios::app);
296 f<<" most violated is: "<<*v<<"\n";
297 }
298 return minSlack;
299}
300
301#include <map>
302using std::map;
303using std::vector;
304struct node {
305 set<node*> in;
306 set<node*> out;
307};
308// useful in debugging - cycles would be BAD
309bool VPSC::constraintGraphIsCyclic(const unsigned n, Variable *vs[]) {
310 map<Variable*, node*> varmap;
311 vector<std::unique_ptr<node>> graph;
312 for(unsigned i=0;i<n;i++) {
313 graph.emplace_back(new node);
314 varmap[vs[i]]=graph.back().get();
315 }
316 for(unsigned i=0;i<n;i++) {
317 for(Constraint *c : vs[i]->in) {
318 Variable *l=c->left;
319 varmap[vs[i]]->in.insert(varmap[l]);
320 }
321
322 for(Constraint *c : vs[i]->out) {
323 Variable *r=c->right;
324 varmap[vs[i]]->out.insert(varmap[r]);
325 }
326 }
327 while(!graph.empty()) {
328 node *u=nullptr;
329 vector<std::unique_ptr<node>>::iterator i=graph.begin();
330 for(;i!=graph.end();i++) {
331 u=(*i).get();
332 if(u->in.empty()) {
333 break;
334 }
335 }
336 if(i==graph.end()) {
337 //cycle found!
338 return true;
339 } else {
340 graph.erase(i);
341 for(node *v : u->out) {
342 v->in.erase(u);
343 }
344 }
345 }
346 return false;
347}
348
349// useful in debugging - cycles would be BAD
350bool VPSC::blockGraphIsCyclic() {
351 map<Block*, node*> bmap;
352 vector<std::unique_ptr<node>> graph;
353 for(Block *b : bs) {
354 graph.emplace_back(new node);
355 bmap[b]=graph.back().get();
356 }
357 for(Block *b : bs) {
358 b->setUpInConstraints();
359 Constraint *c=b->findMinInConstraint();
360 while(c!=nullptr) {
361 Block *l=c->left->block;
362 bmap[b]->in.insert(bmap[l]);
363 b->deleteMinInConstraint();
364 c=b->findMinInConstraint();
365 }
366
367 b->setUpOutConstraints();
368 c=b->findMinOutConstraint();
369 while(c!=nullptr) {
370 Block *r=c->right->block;
371 bmap[b]->out.insert(bmap[r]);
372 b->deleteMinOutConstraint();
373 c=b->findMinOutConstraint();
374 }
375 }
376 while(!graph.empty()) {
377 node *u=nullptr;
378 vector<std::unique_ptr<node>>::iterator i=graph.begin();
379 for(;i!=graph.end();i++) {
380 u=(*i).get();
381 if(u->in.empty()) {
382 break;
383 }
384 }
385 if(i==graph.end()) {
386 //cycle found!
387 return true;
388 }
389 graph.erase(i);
390 for(node *v : u->out) {
391 v->in.erase(u);
392 }
393 }
394 return false;
395}
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:33
#define LOGFILE
A block structure defined over the variables.
Definition blocks.h:24
Definition block.h:28
std::vector< Constraint * > out
Definition block.h:56
bool deleted
Definition block.h:53
void split(Block *&l, Block *&r, Constraint *c)
Definition block.cpp:396
double posn
Definition block.h:32
Constraint * splitBetween(Variable *vl, Variable *vr, Block *&lb, Block *&rb)
Definition block.cpp:377
std::vector< Constraint * > in
Definition block.h:55
void merge(Block *b, Constraint *c, double dist)
Definition block.cpp:146
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:30
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