Graphviz 14.1.3~dev.20260206.1255
Loading...
Searching...
No Matches
solve_VPSC.cpp
Go to the documentation of this file.
1
20#include "config.h"
21
22#include <cassert>
23#include <vpsc/constraint.h>
24#include <vpsc/block.h>
25#include <vpsc/blocks.h>
26#include <vpsc/solve_VPSC.h>
27#include <math.h>
28#include <memory>
29#include <sstream>
30#include <fstream>
31#include <stdexcept>
32using std::ios;
33using std::ofstream;
34
35using std::ostringstream;
36using std::list;
37using std::set;
38
39#ifndef RECTANGLE_OVERLAP_LOGGING
40 #define RECTANGLE_OVERLAP_LOGGING 0
41#endif
42
43IncVPSC::IncVPSC(const unsigned n, Variable *vs[], const unsigned m_,
44 Constraint *cs_[])
45 : VPSC(n, vs, m_, cs_) {
46 inactive.assign(cs_, cs_ + m_);
47 for(Constraint *c : inactive) {
48 c->active=false;
49 }
50}
51
52VPSC::VPSC(const unsigned n, Variable *vs[], const unsigned m_,
53 Constraint *cs_[])
54 : bs(n, vs), cs(cs_), m(m_) {
57 assert(!constraintGraphIsCyclic(n,vs));
58 }
59}
60
61// useful in debugging
64 ofstream f(LOGFILE,ios::app);
65 for(Block *b : bs) {
66 f<<" "<<*b<<"\n";
67 }
68 for(unsigned i=0;i<m;i++) {
69 f<<" "<<*cs[i]<<"\n";
70 }
71 }
72}
84 list<Variable*> vs=bs.totalOrder();
85 for(Variable *v : vs) {
86 if(!v->block->deleted) {
87 bs.mergeLeft(v->block);
88 }
89 }
90 bs.cleanup();
91 for(unsigned i=0;i<m;i++) {
92 if(cs[i]->slack()<-0.0000001) {
94 ofstream f(LOGFILE,ios::app);
95 f<<"Error: Unsatisfied constraint: "<<*cs[i]<<"\n";
96 }
97 //assert(cs[i]->slack()>-0.0000001);
98 throw std::runtime_error("Unsatisfied constraint");
99 }
100 }
101}
102
103void VPSC::refine() {
104 for (bool solved = false; !solved;) {
105 solved=true;
106 for(Block *b : bs) {
107 b->setUpInConstraints();
108 b->setUpOutConstraints();
109 }
110 for(Block *b : bs) {
111 Constraint *c=b->findMinLM();
112 if(c!=nullptr && c->lm<0) {
114 ofstream f(LOGFILE,ios::app);
115 f<<"Split on constraint: "<<*c<<"\n";
116 }
117 // Split on c
118 Block *l=nullptr, *r=nullptr;
119 bs.split(b,l,r,c);
120 bs.cleanup();
121 // split alters the block set so we have to restart
122 solved=false;
123 break;
124 }
125 }
126 }
127 for(unsigned i=0;i<m;i++) {
128 if(cs[i]->slack()<-0.0000001) {
129 assert(cs[i]->slack()>-0.0000001);
130 throw std::runtime_error("Unsatisfied constraint");
131 }
132 }
133}
141 satisfy();
142 refine();
143}
144
147 ofstream f(LOGFILE,ios::app);
148 f<<"solve_inc()...\n";
149 }
150 double lastcost,cost = bs.cost();
151 do {
152 lastcost=cost;
153 satisfy();
154 splitBlocks();
155 cost = bs.cost();
157 ofstream f(LOGFILE,ios::app);
158 f<<" cost="<<cost<<"\n";
159 }
160 } while(fabs(lastcost-cost)>0.0001);
161}
177 ofstream f(LOGFILE,ios::app);
178 f<<"satisfy_inc()...\n";
179 }
180 splitBlocks();
181 long splitCtr = 0;
182 Constraint* v = nullptr;
183 while(mostViolated(inactive,v)<-0.0000001) {
184 assert(!v->active);
185 Block *lb = v->left->block, *rb = v->right->block;
186 if(lb != rb) {
187 lb->merge(rb,v);
188 } else {
189 if(splitCtr++>10000) {
190 throw std::runtime_error("Cycle Error!");
191 }
192 // constraint is within block, need to split first
193 inactive.push_back(lb->splitBetween(v->left,v->right,lb,rb));
194 lb->merge(rb,v);
195 bs.insert(lb);
196 }
197 }
199 ofstream f(LOGFILE,ios::app);
200 f<<" finished merges.\n";
201 }
202 bs.cleanup();
203 for(unsigned i=0;i<m;i++) {
204 v=cs[i];
205 if(v->slack()<-0.0000001) {
206 //assert(cs[i]->slack()>-0.0000001);
207 ostringstream s;
208 s<<"Unsatisfied constraint: "<<*v;
209 throw std::runtime_error(s.str());
210 }
211 }
213 ofstream f(LOGFILE,ios::app);
214 f<<" finished cleanup.\n";
215 printBlocks();
216 }
217}
220 ofstream f(LOGFILE,ios::app);
221 f<<"moveBlocks()...\n";
222 }
223 for(Block *b : bs) {
224 b->wposn = b->desiredWeightedPosition();
225 b->posn = b->wposn / b->weight;
226 }
228 ofstream f(LOGFILE,ios::app);
229 f<<" moved blocks.\n";
230 }
231}
233 moveBlocks();
234 splitCnt=0;
235 // Split each block if necessary on min LM
236 for(Block *b : bs) {
237 Constraint* v=b->findMinLM();
238 if(v!=nullptr && v->lm < -0.0000001) {
240 ofstream f(LOGFILE,ios::app);
241 f<<" found split point: "<<*v<<" lm="<<v->lm<<"\n";
242 }
243 splitCnt++;
244 Block *b2 = v->left->block, *l=nullptr, *r=nullptr;
245 assert(v->left->block == v->right->block);
246 double pos = b2->posn;
247 b2->split(l,r,v);
248 l->posn=r->posn=pos;
249 l->wposn = l->posn * l->weight;
250 r->wposn = r->posn * r->weight;
251 bs.insert(l);
252 bs.insert(r);
253 b2->deleted=true;
254 inactive.push_back(v);
256 ofstream f(LOGFILE,ios::app);
257 f<<" new blocks: "<<*l<<" and "<<*r<<"\n";
258 }
259 }
260 }
262 ofstream f(LOGFILE,ios::app);
263 f<<" finished splits.\n";
264 }
265 bs.cleanup();
266}
267
272double IncVPSC::mostViolated(ConstraintList &l, Constraint* &v) {
273 double minSlack = DBL_MAX;
275 ofstream f(LOGFILE,ios::app);
276 f<<"Looking for most violated...\n";
277 }
278 ConstraintList::iterator end = l.end();
279 ConstraintList::iterator deletePoint = end;
280 for(ConstraintList::iterator i=l.begin();i!=end;i++) {
281 Constraint *c=*i;
282 double slack = c->slack();
283 if (slack < minSlack) {
284 minSlack=slack;
285 v=c;
286 deletePoint=i;
287 }
288 }
289 // Because the constraint list is not order dependent we just
290 // move the last element over the deletePoint and resize
291 // downwards. There is always at least 1 element in the
292 // vector because of search.
293 if(deletePoint != end && minSlack<-0.0000001) {
294 *deletePoint = l.back();
295 l.pop_back();
296 }
298 ofstream f(LOGFILE,ios::app);
299 f<<" most violated is: "<<*v<<"\n";
300 }
301 return minSlack;
302}
303
304#include <map>
305using std::map;
306using std::vector;
307struct node {
308 set<node*> in;
309 set<node*> out;
310};
311// useful in debugging - cycles would be BAD
312bool VPSC::constraintGraphIsCyclic(const unsigned n, Variable *vs[]) {
313 map<Variable*, node*> varmap;
314 vector<std::unique_ptr<node>> graph;
315 for(unsigned i=0;i<n;i++) {
316 graph.emplace_back(new node);
317 varmap[vs[i]]=graph.back().get();
318 }
319 for(unsigned i=0;i<n;i++) {
320 for(Constraint *c : vs[i]->in) {
321 Variable *l=c->left;
322 varmap[vs[i]]->in.insert(varmap[l]);
323 }
324
325 for(Constraint *c : vs[i]->out) {
326 Variable *r=c->right;
327 varmap[vs[i]]->out.insert(varmap[r]);
328 }
329 }
330 while(!graph.empty()) {
331 node *u=nullptr;
332 vector<std::unique_ptr<node>>::iterator i=graph.begin();
333 for(;i!=graph.end();i++) {
334 u=(*i).get();
335 if(u->in.empty()) {
336 break;
337 }
338 }
339 if(i==graph.end()) {
340 //cycle found!
341 return true;
342 } else {
343 graph.erase(i);
344 for(node *v : u->out) {
345 v->in.erase(u);
346 }
347 }
348 }
349 return false;
350}
351
352// useful in debugging - cycles would be BAD
353bool VPSC::blockGraphIsCyclic() {
354 map<Block*, node*> bmap;
355 vector<std::unique_ptr<node>> graph;
356 for(Block *b : bs) {
357 graph.emplace_back(new node);
358 bmap[b]=graph.back().get();
359 }
360 for(Block *b : bs) {
361 b->setUpInConstraints();
362 Constraint *c=b->findMinInConstraint();
363 while(c!=nullptr) {
364 Block *l=c->left->block;
365 bmap[b]->in.insert(bmap[l]);
366 b->deleteMinInConstraint();
367 c=b->findMinInConstraint();
368 }
369
370 b->setUpOutConstraints();
371 c=b->findMinOutConstraint();
372 while(c!=nullptr) {
373 Block *r=c->right->block;
374 bmap[b]->out.insert(bmap[r]);
375 b->deleteMinOutConstraint();
376 c=b->findMinOutConstraint();
377 }
378 }
379 while(!graph.empty()) {
380 node *u=nullptr;
381 vector<std::unique_ptr<node>>::iterator i=graph.begin();
382 for(;i!=graph.end();i++) {
383 u=(*i).get();
384 if(u->in.empty()) {
385 break;
386 }
387 }
388 if(i==graph.end()) {
389 //cycle found!
390 return true;
391 }
392 graph.erase(i);
393 for(node *v : u->out) {
394 v->in.erase(u);
395 }
396 }
397 return false;
398}
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:86
#define RECTANGLE_OVERLAP_LOGGING
Definition block.cpp:35
#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:398
double posn
Definition block.h:32
Constraint * splitBetween(Variable *vl, Variable *vr, Block *&lb, Block *&rb)
Definition block.cpp:379
std::vector< Constraint * > in
Definition block.h:55
void merge(Block *b, Constraint *c, double dist)
Definition block.cpp:148
void cleanup()
Definition blocks.cpp:158
double cost()
Definition blocks.cpp:197
void split(Block *b, Block *&l, Block *&r, Constraint *c)
Definition blocks.cpp:173
std::list< Variable * > totalOrder()
Definition blocks.cpp:57
void mergeLeft(Block *r)
Definition blocks.cpp:88
static int in(Extype_t lhs, Exid_t *rhs, Exdisc_t *disc)
Definition compile.c:1632
Agraph_t * graph(char *name)
Definition gv.cpp:34
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:90