Graphviz 16.1.1~dev.20261013.0011
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 // Split each block if necessary on min LM
235 for(Block *b : bs) {
236 Constraint* v=b->findMinLM();
237 if(v!=nullptr && v->lm < -0.0000001) {
239 ofstream f(LOGFILE,ios::app);
240 f<<" found split point: "<<*v<<" lm="<<v->lm<<"\n";
241 }
242 Block *b2 = v->left->block, *l=nullptr, *r=nullptr;
243 assert(v->left->block == v->right->block);
244 double pos = b2->posn;
245 b2->split(l,r,v);
246 l->posn=r->posn=pos;
247 l->wposn = l->posn * l->weight;
248 r->wposn = r->posn * r->weight;
249 bs.insert(l);
250 bs.insert(r);
251 b2->deleted=true;
252 inactive.push_back(v);
254 ofstream f(LOGFILE,ios::app);
255 f<<" new blocks: "<<*l<<" and "<<*r<<"\n";
256 }
257 }
258 }
260 ofstream f(LOGFILE,ios::app);
261 f<<" finished splits.\n";
262 }
263 bs.cleanup();
264}
265
270double IncVPSC::mostViolated(ConstraintList &l, Constraint* &v) {
271 double minSlack = DBL_MAX;
273 ofstream f(LOGFILE,ios::app);
274 f<<"Looking for most violated...\n";
275 }
276 ConstraintList::iterator end = l.end();
277 ConstraintList::iterator deletePoint = end;
278 for(ConstraintList::iterator i=l.begin();i!=end;i++) {
279 Constraint *c=*i;
280 double slack = c->slack();
281 if (slack < minSlack) {
282 minSlack=slack;
283 v=c;
284 deletePoint=i;
285 }
286 }
287 // Because the constraint list is not order dependent we just
288 // move the last element over the deletePoint and resize
289 // downwards. There is always at least 1 element in the
290 // vector because of search.
291 if(deletePoint != end && minSlack<-0.0000001) {
292 *deletePoint = l.back();
293 l.pop_back();
294 }
296 ofstream f(LOGFILE,ios::app);
297 f<<" most violated is: "<<*v<<"\n";
298 }
299 return minSlack;
300}
301
302#include <map>
303using std::map;
304using std::vector;
305struct node {
306 set<node*> in;
307 set<node*> out;
308};
309// useful in debugging - cycles would be BAD
310bool VPSC::constraintGraphIsCyclic(const unsigned n, Variable *vs[]) {
311 map<Variable*, node*> varmap;
312 vector<std::unique_ptr<node>> graph;
313 for(unsigned i=0;i<n;i++) {
314 graph.emplace_back(new node);
315 varmap[vs[i]]=graph.back().get();
316 }
317 for(unsigned i=0;i<n;i++) {
318 for(Constraint *c : vs[i]->in) {
319 Variable *l=c->left;
320 varmap[vs[i]]->in.insert(varmap[l]);
321 }
322
323 for(Constraint *c : vs[i]->out) {
324 Variable *r=c->right;
325 varmap[vs[i]]->out.insert(varmap[r]);
326 }
327 }
328 while(!graph.empty()) {
329 node *u=nullptr;
330 vector<std::unique_ptr<node>>::iterator i=graph.begin();
331 for(;i!=graph.end();i++) {
332 u=(*i).get();
333 if(u->in.empty()) {
334 break;
335 }
336 }
337 if(i==graph.end()) {
338 //cycle found!
339 return true;
340 } else {
341 graph.erase(i);
342 for(node *v : u->out) {
343 v->in.erase(u);
344 }
345 }
346 }
347 return false;
348}
349
350// useful in debugging - cycles would be BAD
351bool VPSC::blockGraphIsCyclic() {
352 map<Block*, node*> bmap;
353 vector<std::unique_ptr<node>> graph;
354 for(Block *b : bs) {
355 graph.emplace_back(new node);
356 bmap[b]=graph.back().get();
357 }
358 for(Block *b : bs) {
359 b->setUpInConstraints();
360 Constraint *c=b->findMinInConstraint();
361 while(c!=nullptr) {
362 Block *l=c->left->block;
363 bmap[b]->in.insert(bmap[l]);
364 b->deleteMinInConstraint();
365 c=b->findMinInConstraint();
366 }
367
368 b->setUpOutConstraints();
369 c=b->findMinOutConstraint();
370 while(c!=nullptr) {
371 Block *r=c->right->block;
372 bmap[b]->out.insert(bmap[r]);
373 b->deleteMinOutConstraint();
374 c=b->findMinOutConstraint();
375 }
376 }
377 while(!graph.empty()) {
378 node *u=nullptr;
379 vector<std::unique_ptr<node>>::iterator i=graph.begin();
380 for(;i!=graph.end();i++) {
381 u=(*i).get();
382 if(u->in.empty()) {
383 break;
384 }
385 }
386 if(i==graph.end()) {
387 //cycle found!
388 return true;
389 }
390 graph.erase(i);
391 for(node *v : u->out) {
392 v->in.erase(u);
393 }
394 }
395 return false;
396}
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:1646
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()
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