Graphviz 13.0.0~dev.20241222.1117
Loading...
Searching...
No Matches
block.cpp
Go to the documentation of this file.
1
20#include <algorithm>
21#include <cassert>
22#include <ostream>
23#include <vector>
24#include <vpsc/constraint.h>
25#include <vpsc/block.h>
26#include <vpsc/blocks.h>
27#include <fstream>
28using std::ios;
29using std::ofstream;
30using std::vector;
31
32#ifndef RECTANGLE_OVERLAP_LOGGING
33 #define RECTANGLE_OVERLAP_LOGGING 0
34#endif
35
37static bool gt(const Constraint *const lhs, const Constraint *const rhs) {
38 return compareConstraints(rhs, lhs);
39}
40
45static void make_heap(std::vector<Constraint *> &heap) {
46 std::make_heap(heap.begin(), heap.end(), gt);
47}
48
50static void merge_heaps(std::vector<Constraint *> &heap1,
51 const std::vector<Constraint *> &heap2) {
52 heap1.insert(heap1.end(), heap2.begin(), heap2.end());
53 make_heap(heap1);
54}
55
57static Constraint *findMin(std::vector<Constraint *> &heap) {
58 assert(std::is_heap(heap.begin(), heap.end(), gt));
59 return heap.front();
60}
61
63static void deleteMin(std::vector<Constraint *> &heap) {
64 assert(std::is_heap(heap.begin(), heap.end(), gt));
65 std::pop_heap(heap.begin(), heap.end(), gt);
66 heap.pop_back();
67}
68
70static void insert(std::vector<Constraint *> &heap, Constraint *c) {
71 assert(std::is_heap(heap.begin(), heap.end(), gt));
72 heap.push_back(c);
73 std::push_heap(heap.begin(), heap.end(), gt);
74}
75
76void Block::addVariable(Variable *v) {
77 v->block=this;
78 vars.push_back(v);
79 weight+=v->weight;
80 wposn += v->weight * (v->desiredPosition - v->offset);
82}
84 timeStamp=0;
86 deleted=false;
87 if(v!=nullptr) {
88 v->offset=0;
89 addVariable(v);
90 }
91}
92
94 double wp = 0;
95 for (const Variable *v : vars) {
96 wp += (v->desiredPosition - v->offset) * v->weight;
97 }
98 return wp;
99}
101 in = setUpConstraintHeap(true);
102}
104 out = setUpConstraintHeap(false);
105}
106
107std::vector<Constraint *> Block::setUpConstraintHeap(bool use_in) {
108 std::vector<Constraint *> h;
109 for (Variable *v : vars) {
110 vector<Constraint*> *cs= use_in ? &v->in : &v->out;
111 for (Constraint *c : *cs) {
112 c->timeStamp=blockTimeCtr;
113 if ((c->left->block != this && use_in) || (c->right->block != this && !use_in)) {
114 h.push_back(c);
115 }
116 }
117 }
118 make_heap(h);
119 return h;
120}
123 ofstream f(LOGFILE,ios::app);
124 f<<" merging on: "<<*c<<",c->left->offset="<<c->left->offset<<",c->right->offset="<<c->right->offset<<"\n";
125 }
126 const double dist = c->right->offset - c->left->offset - c->gap;
127 Block *l=c->left->block;
128 Block *r=c->right->block;
129 if (vars.size() < b->vars.size()) {
130 r->merge(l,c,dist);
131 } else {
132 l->merge(r,c,-dist);
133 }
135 ofstream f(LOGFILE,ios::app);
136 f<<" merged block="<<(b->deleted?*this:*b)<<"\n";
137 }
138}
146void Block::merge(Block *b, Constraint *c, double dist) {
148 ofstream f(LOGFILE,ios::app);
149 f<<" merging: "<<*b<<"dist="<<dist<<"\n";
150 }
151 c->active=true;
152 wposn+=b->wposn-dist*b->weight;
153 weight+=b->weight;
155 for (Variable *v : b->vars) {
156 v->block=this;
157 v->offset+=dist;
158 vars.push_back(v);
159 }
160 b->deleted=true;
161}
162
165 ofstream f(LOGFILE,ios::app);
166 f<<" merging constraint heaps... \n";
167 }
168 // We check the top of the heaps to remove possible internal constraints
171 merge_heaps(in, b->in);
172}
179 Constraint *v = nullptr;
180 vector<Constraint*> outOfDate;
181 while (!in.empty()) {
182 v = findMin(in);
183 const Block *lb = v->left->block;
184 const Block *rb = v->right->block;
185 // rb may not be this if called between merge and mergeIn
187 ofstream f(LOGFILE,ios::app);
188 f<<" checking constraint ... "<<*v;
189 f<<" timestamps: left="<<lb->timeStamp<<" right="<<rb->timeStamp<<" constraint="<<v->timeStamp<<"\n";
190 }
191 if(lb == rb) {
192 // constraint has been merged into the same block
193 if(RECTANGLE_OVERLAP_LOGGING && v->slack()<0) {
194 ofstream f(LOGFILE,ios::app);
195 f<<" violated internal constraint found! "<<*v<<"\n";
196 f<<" lb="<<*lb<<"\n";
197 f<<" rb="<<*rb<<"\n";
198 }
199 deleteMin(in);
201 ofstream f(LOGFILE,ios::app);
202 f<<" ... skipping internal constraint\n";
203 }
204 } else if(v->timeStamp < lb->timeStamp) {
205 // block at other end of constraint has been moved since this
206 deleteMin(in);
207 outOfDate.push_back(v);
209 ofstream f(LOGFILE,ios::app);
210 f<<" reinserting out of date (reinsert later)\n";
211 }
212 } else {
213 break;
214 }
215 }
216 for (Constraint *c : outOfDate) {
217 c->timeStamp=blockTimeCtr;
218 insert(in, c);
219 }
220 if(in.empty()) {
221 v=nullptr;
222 } else {
223 v = findMin(in);
224 }
225 return v;
226}
228 if(out.empty()) return nullptr;
229 Constraint *v = findMin(out);
230 while (v->left->block == v->right->block) {
231 deleteMin(out);
232 if(out.empty()) return nullptr;
233 v = findMin(out);
234 }
235 return v;
236}
243inline bool Block::canFollowLeft(const Constraint *c, const Variable *last) {
244 return c->left->block==this && c->active && last!=c->left;
245}
246inline bool Block::canFollowRight(const Constraint *c, const Variable *last) {
247 return c->right->block==this && c->active && last!=c->right;
248}
249
250// computes the derivative of v and the lagrange multipliers
251// of v's out constraints (as the recursive sum of those below.
252// Does not backtrack over u.
253// also records the constraint with minimum lagrange multiplier
254// in min_lm
255double Block::compute_dfdv(Variable *v, Variable *u, Constraint *&min_lm) {
256 double dfdv=v->weight*(v->position() - v->desiredPosition);
257 for (Constraint *c : v->out) {
258 if(canFollowRight(c,u)) {
259 dfdv+=c->lm=compute_dfdv(c->right,v,min_lm);
260 if(min_lm==nullptr||c->lm<min_lm->lm) min_lm=c;
261 }
262 }
263 for (Constraint *c : v->in) {
264 if(canFollowLeft(c,u)) {
265 dfdv-=c->lm=-compute_dfdv(c->left,v,min_lm);
266 if(min_lm==nullptr||c->lm<min_lm->lm) min_lm=c;
267 }
268 }
269 return dfdv;
270}
271
272
273// computes dfdv for each variable and uses the sum of dfdv on either side of
274// the constraint c to compute the lagrangian multiplier lm_c.
275// The top level v and r are variables between which we want to find the
276// constraint with the smallest lm.
277// When we find r we pass nullptr to subsequent recursive calls,
278// thus r=nullptr indicates constraints are not on the shortest path.
279// Similarly, m is initially nullptr and is only assigned a value if the next
280// variable to be visited is r or if a possible min constraint is returned from
281// a nested call (rather than nullptr).
282// Then, the search for the m with minimum lm occurs as we return from
283// the recursion (checking only constraints traversed left-to-right
284// in order to avoid creating any new violations).
285Block::Pair Block::compute_dfdv_between(Variable* r, Variable* v, Variable* u,
286 Direction dir = NONE, bool changedDirection = false) {
287 double dfdv=v->weight*(v->position() - v->desiredPosition);
288 Constraint *m=nullptr;
289 for (Constraint *c : v->in) {
290 if(canFollowLeft(c,u)) {
291 if(dir==RIGHT) {
292 changedDirection = true;
293 }
294 if(c->left==r) {
295 r=nullptr; m=c;
296 }
297 Pair p=compute_dfdv_between(r,c->left,v,
298 LEFT,changedDirection);
299 dfdv -= c->lm = -p.first;
300 if(r && p.second)
301 m = p.second;
302 }
303 }
304 for (Constraint *c : v->out) {
305 if(canFollowRight(c,u)) {
306 if(dir==LEFT) {
307 changedDirection = true;
308 }
309 if(c->right==r) {
310 r=nullptr; m=c;
311 }
312 Pair p=compute_dfdv_between(r,c->right,v,
313 RIGHT,changedDirection);
314 dfdv += c->lm = p.first;
315 if(r && p.second)
316 m = changedDirection && c->lm < p.second->lm
317 ? c
318 : p.second;
319 }
320 }
321 return Pair(dfdv,m);
322}
323
324// resets LMs for all active constraints to 0 by
325// traversing active constraint tree starting from v,
326// not back tracking over u
327void Block::reset_active_lm(Variable *v, Variable *u) {
328 for (Constraint *c : v->out) {
329 if(canFollowRight(c,u)) {
330 c->lm=0;
331 reset_active_lm(c->right,v);
332 }
333 }
334 for (Constraint *c : v->in) {
335 if(canFollowLeft(c,u)) {
336 c->lm=0;
337 reset_active_lm(c->left,v);
338 }
339 }
340}
346 Constraint *min_lm=nullptr;
347 reset_active_lm(vars.front(),nullptr);
348 compute_dfdv(vars.front(),nullptr,min_lm);
349 return min_lm;
350}
352 Constraint *min_lm=nullptr;
353 reset_active_lm(vars.front(),nullptr);
354 min_lm=compute_dfdv_between(rv,lv,nullptr).second;
355 return min_lm;
356}
357
358// populates block b by traversing the active constraint tree adding variables as they're
359// visited. Starts from variable v and does not backtrack over variable u.
360void Block::populateSplitBlock(Block *b, Variable *v, Variable *u) {
361 b->addVariable(v);
362 for (Constraint *c : v->in) {
363 if (canFollowLeft(c,u))
364 populateSplitBlock(b, c->left, v);
365 }
366 for (Constraint *c : v->out) {
367 if (canFollowRight(c,u))
368 populateSplitBlock(b, c->right, v);
369 }
370}
379 ofstream f(LOGFILE,ios::app);
380 f<<" need to split between: "<<*vl<<" and "<<*vr<<"\n";
381 }
382 Constraint *c=findMinLMBetween(vl, vr);
384 ofstream f(LOGFILE,ios::app);
385 f<<" going to split on: "<<*c<<"\n";
386 }
387 split(lb,rb,c);
388 deleted = true;
389 return c;
390}
396void Block::split(Block* &l, Block* &r, Constraint* c) {
397 c->active=false;
398 l=new Block();
399 populateSplitBlock(l,c->left,c->right);
400 r=new Block();
401 populateSplitBlock(r,c->right,c->left);
402}
403
408double Block::cost() {
409 double c = 0;
410 for (const Variable *v : vars) {
411 const double diff = v->position() - v->desiredPosition;
412 c += v->weight * diff * diff;
413 }
414 return c;
415}
416
417std::ostream& operator <<(std::ostream &os, const Block &b) {
418 os<<"Block:";
419 for(const Variable *v : b.vars) {
420 os<<" "<<*v;
421 }
422 if(b.deleted) {
423 os<<" Deleted!";
424 }
425 return os;
426}
static agxbuf last
last message
Definition agerror.c:29
std::ostream & operator<<(std::ostream &os, const Block &b)
Definition block.cpp:417
static Constraint * findMin(std::vector< Constraint * > &heap)
get the minimum heap element
Definition block.cpp:57
static void make_heap(std::vector< Constraint * > &heap)
Definition block.cpp:45
#define RECTANGLE_OVERLAP_LOGGING
Definition block.cpp:33
static void insert(std::vector< Constraint * > &heap, Constraint *c)
add an item to a heap
Definition block.cpp:70
static void deleteMin(std::vector< Constraint * > &heap)
remove the minimum heap element
Definition block.cpp:63
static void merge_heaps(std::vector< Constraint * > &heap1, const std::vector< Constraint * > &heap2)
add all elements from heap2 into the heap heap1
Definition block.cpp:50
static bool gt(const Constraint *const lhs, const Constraint *const rhs)
> comparator for constraints
Definition block.cpp:37
long blockTimeCtr
Definition blocks.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
Constraint * findMinInConstraint()
Definition block.cpp:178
std::vector< Variable * > vars
Definition block.h:31
void split(Block *&l, Block *&r, Constraint *c)
Definition block.cpp:396
double posn
Definition block.h:32
Constraint * findMinLM()
Definition block.cpp:345
Constraint * splitBetween(Variable *vl, Variable *vr, Block *&lb, Block *&rb)
Definition block.cpp:377
void deleteMinOutConstraint()
Definition block.cpp:240
Block(Variable *v=nullptr)
Definition block.cpp:83
void mergeIn(Block *b)
Definition block.cpp:163
void mergeOut(Block *b)
Definition block.cpp:173
std::vector< Constraint * > in
Definition block.h:55
void setUpOutConstraints()
Definition block.cpp:103
double wposn
Definition block.h:34
void setUpInConstraints()
Definition block.cpp:100
double cost()
Definition block.cpp:408
double desiredWeightedPosition()
Definition block.cpp:93
double weight
Definition block.h:33
Constraint * findMinOutConstraint()
Definition block.cpp:227
void merge(Block *b, Constraint *c, double dist)
Definition block.cpp:146
void deleteMinInConstraint()
Definition block.cpp:237
Constraint * findMinLMBetween(Variable *lv, Variable *rv)
Definition block.cpp:351
long timeStamp
Definition block.h:54
static void insert(PairHeap *h, Pair edge)
Definition closest.c:145
static void split(void)
Definition ccomps.c:102
#define NONE
Definition const.h:126
static bool compareConstraints(const Constraint *const l, const Constraint *const r)
Definition constraint.h:41
static double dist(int dim, double *x, double *y)
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
long timeStamp
Definition constraint.h:35
double gap
Definition constraint.h:30
Variable * left
Definition constraint.h:28
bool active
Definition constraint.h:36
double slack() const
Definition constraint.h:34
Definition closest.c:29
double desiredPosition
Definition variable.h:30
Constraints out
Definition variable.h:36
const double weight
Definition variable.h:31
Block * block
Definition variable.h:33
double offset
Definition variable.h:32
Constraints in
Definition variable.h:35
double position() const
Definition variable.h:46