Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
block.cpp
Go to the documentation of this file.
1
19#include <cassert>
20#include <memory>
22#include <vpsc/constraint.h>
23#include <vpsc/block.h>
24#include <vpsc/blocks.h>
25#include <fstream>
26using std::ios;
27using std::ofstream;
28using std::vector;
29
30#ifndef RECTANGLE_OVERLAP_LOGGING
31 #define RECTANGLE_OVERLAP_LOGGING 0
32#endif
33
34void Block::addVariable(Variable *v) {
35 v->block=this;
36 vars.push_back(v);
37 weight+=v->weight;
38 wposn += v->weight * (v->desiredPosition - v->offset);
40}
42 timeStamp=0;
44 deleted=false;
45 if(v!=nullptr) {
46 v->offset=0;
47 addVariable(v);
48 }
49}
50
52 double wp = 0;
53 for (const Variable *v : vars) {
54 wp += (v->desiredPosition - v->offset) * v->weight;
55 }
56 return wp;
57}
59 setUpConstraintHeap(in,true);
60}
62 setUpConstraintHeap(out,false);
63}
64void Block::setUpConstraintHeap(std::unique_ptr<PairingHeap<Constraint*>> &h,
65 bool use_in) {
66 h = std::make_unique<PairingHeap<Constraint*>>(&compareConstraints);
67 for (Variable *v : vars) {
68 vector<Constraint*> *cs= use_in ? &v->in : &v->out;
69 for (Constraint *c : *cs) {
70 c->timeStamp=blockTimeCtr;
71 if ((c->left->block != this && use_in) || (c->right->block != this && !use_in)) {
72 h->insert(c);
73 }
74 }
75 }
76}
79 ofstream f(LOGFILE,ios::app);
80 f<<" merging on: "<<*c<<",c->left->offset="<<c->left->offset<<",c->right->offset="<<c->right->offset<<"\n";
81 }
82 const double dist = c->right->offset - c->left->offset - c->gap;
83 Block *l=c->left->block;
84 Block *r=c->right->block;
85 if (vars.size() < b->vars.size()) {
86 r->merge(l,c,dist);
87 } else {
88 l->merge(r,c,-dist);
89 }
91 ofstream f(LOGFILE,ios::app);
92 f<<" merged block="<<(b->deleted?*this:*b)<<"\n";
93 }
94}
102void Block::merge(Block *b, Constraint *c, double dist) {
104 ofstream f(LOGFILE,ios::app);
105 f<<" merging: "<<*b<<"dist="<<dist<<"\n";
106 }
107 c->active=true;
108 wposn+=b->wposn-dist*b->weight;
109 weight+=b->weight;
111 for (Variable *v : b->vars) {
112 v->block=this;
113 v->offset+=dist;
114 vars.push_back(v);
115 }
116 b->deleted=true;
117}
118
121 ofstream f(LOGFILE,ios::app);
122 f<<" merging constraint heaps... \n";
123 }
124 // We check the top of the heaps to remove possible internal constraints
127 in->merge(b->in.get());
129 ofstream f(LOGFILE,ios::app);
130 f<<" merged heap: "<<*in<<"\n";
131 }
132}
136 out->merge(b->out.get());
137}
139 Constraint *v = nullptr;
140 vector<Constraint*> outOfDate;
141 while (!in->isEmpty()) {
142 v = in->findMin();
143 const Block *lb = v->left->block;
144 const Block *rb = v->right->block;
145 // rb may not be this if called between merge and mergeIn
147 ofstream f(LOGFILE,ios::app);
148 f<<" checking constraint ... "<<*v;
149 f<<" timestamps: left="<<lb->timeStamp<<" right="<<rb->timeStamp<<" constraint="<<v->timeStamp<<"\n";
150 }
151 if(lb == rb) {
152 // constraint has been merged into the same block
153 if(RECTANGLE_OVERLAP_LOGGING && v->slack()<0) {
154 ofstream f(LOGFILE,ios::app);
155 f<<" violated internal constraint found! "<<*v<<"\n";
156 f<<" lb="<<*lb<<"\n";
157 f<<" rb="<<*rb<<"\n";
158 }
159 in->deleteMin();
161 ofstream f(LOGFILE,ios::app);
162 f<<" ... skipping internal constraint\n";
163 }
164 } else if(v->timeStamp < lb->timeStamp) {
165 // block at other end of constraint has been moved since this
166 in->deleteMin();
167 outOfDate.push_back(v);
169 ofstream f(LOGFILE,ios::app);
170 f<<" reinserting out of date (reinsert later)\n";
171 }
172 } else {
173 break;
174 }
175 }
176 for (Constraint *c : outOfDate) {
177 c->timeStamp=blockTimeCtr;
178 in->insert(c);
179 }
180 if(in->isEmpty()) {
181 v=nullptr;
182 } else {
183 v=in->findMin();
184 }
185 return v;
186}
188 if(out->isEmpty()) return nullptr;
189 Constraint *v = out->findMin();
190 while (v->left->block == v->right->block) {
191 out->deleteMin();
192 if(out->isEmpty()) return nullptr;
193 v = out->findMin();
194 }
195 return v;
196}
198 in->deleteMin();
200 ofstream f(LOGFILE,ios::app);
201 f<<"deleteMinInConstraint... \n";
202 f<<" result: "<<*in<<"\n";
203 }
204}
206 out->deleteMin();
207}
208inline bool Block::canFollowLeft(const Constraint *c, const Variable *last) {
209 return c->left->block==this && c->active && last!=c->left;
210}
211inline bool Block::canFollowRight(const Constraint *c, const Variable *last) {
212 return c->right->block==this && c->active && last!=c->right;
213}
214
215// computes the derivative of v and the lagrange multipliers
216// of v's out constraints (as the recursive sum of those below.
217// Does not backtrack over u.
218// also records the constraint with minimum lagrange multiplier
219// in min_lm
220double Block::compute_dfdv(Variable *v, Variable *u, Constraint *&min_lm) {
221 double dfdv=v->weight*(v->position() - v->desiredPosition);
222 for (Constraint *c : v->out) {
223 if(canFollowRight(c,u)) {
224 dfdv+=c->lm=compute_dfdv(c->right,v,min_lm);
225 if(min_lm==nullptr||c->lm<min_lm->lm) min_lm=c;
226 }
227 }
228 for (Constraint *c : v->in) {
229 if(canFollowLeft(c,u)) {
230 dfdv-=c->lm=-compute_dfdv(c->left,v,min_lm);
231 if(min_lm==nullptr||c->lm<min_lm->lm) min_lm=c;
232 }
233 }
234 return dfdv;
235}
236
237
238// computes dfdv for each variable and uses the sum of dfdv on either side of
239// the constraint c to compute the lagrangian multiplier lm_c.
240// The top level v and r are variables between which we want to find the
241// constraint with the smallest lm.
242// When we find r we pass nullptr to subsequent recursive calls,
243// thus r=nullptr indicates constraints are not on the shortest path.
244// Similarly, m is initially nullptr and is only assigned a value if the next
245// variable to be visited is r or if a possible min constraint is returned from
246// a nested call (rather than nullptr).
247// Then, the search for the m with minimum lm occurs as we return from
248// the recursion (checking only constraints traversed left-to-right
249// in order to avoid creating any new violations).
250Block::Pair Block::compute_dfdv_between(Variable* r, Variable* v, Variable* u,
251 Direction dir = NONE, bool changedDirection = false) {
252 double dfdv=v->weight*(v->position() - v->desiredPosition);
253 Constraint *m=nullptr;
254 for (Constraint *c : v->in) {
255 if(canFollowLeft(c,u)) {
256 if(dir==RIGHT) {
257 changedDirection = true;
258 }
259 if(c->left==r) {
260 r=nullptr; m=c;
261 }
262 Pair p=compute_dfdv_between(r,c->left,v,
263 LEFT,changedDirection);
264 dfdv -= c->lm = -p.first;
265 if(r && p.second)
266 m = p.second;
267 }
268 }
269 for (Constraint *c : v->out) {
270 if(canFollowRight(c,u)) {
271 if(dir==LEFT) {
272 changedDirection = true;
273 }
274 if(c->right==r) {
275 r=nullptr; m=c;
276 }
277 Pair p=compute_dfdv_between(r,c->right,v,
278 RIGHT,changedDirection);
279 dfdv += c->lm = p.first;
280 if(r && p.second)
281 m = changedDirection && c->lm < p.second->lm
282 ? c
283 : p.second;
284 }
285 }
286 return Pair(dfdv,m);
287}
288
289// resets LMs for all active constraints to 0 by
290// traversing active constraint tree starting from v,
291// not back tracking over u
292void Block::reset_active_lm(Variable *v, Variable *u) {
293 for (Constraint *c : v->out) {
294 if(canFollowRight(c,u)) {
295 c->lm=0;
296 reset_active_lm(c->right,v);
297 }
298 }
299 for (Constraint *c : v->in) {
300 if(canFollowLeft(c,u)) {
301 c->lm=0;
302 reset_active_lm(c->left,v);
303 }
304 }
305}
311 Constraint *min_lm=nullptr;
312 reset_active_lm(vars.front(),nullptr);
313 compute_dfdv(vars.front(),nullptr,min_lm);
314 return min_lm;
315}
317 Constraint *min_lm=nullptr;
318 reset_active_lm(vars.front(),nullptr);
319 min_lm=compute_dfdv_between(rv,lv,nullptr).second;
320 return min_lm;
321}
322
323// populates block b by traversing the active constraint tree adding variables as they're
324// visited. Starts from variable v and does not backtrack over variable u.
325void Block::populateSplitBlock(Block *b, Variable *v, Variable *u) {
326 b->addVariable(v);
327 for (Constraint *c : v->in) {
328 if (canFollowLeft(c,u))
329 populateSplitBlock(b, c->left, v);
330 }
331 for (Constraint *c : v->out) {
332 if (canFollowRight(c,u))
333 populateSplitBlock(b, c->right, v);
334 }
335}
344 ofstream f(LOGFILE,ios::app);
345 f<<" need to split between: "<<*vl<<" and "<<*vr<<"\n";
346 }
347 Constraint *c=findMinLMBetween(vl, vr);
349 ofstream f(LOGFILE,ios::app);
350 f<<" going to split on: "<<*c<<"\n";
351 }
352 split(lb,rb,c);
353 deleted = true;
354 return c;
355}
361void Block::split(Block* &l, Block* &r, Constraint* c) {
362 c->active=false;
363 l=new Block();
364 populateSplitBlock(l,c->left,c->right);
365 r=new Block();
366 populateSplitBlock(r,c->right,c->left);
367}
368
373double Block::cost() {
374 double c = 0;
375 for (const Variable *v : vars) {
376 const double diff = v->position() - v->desiredPosition;
377 c += v->weight * diff * diff;
378 }
379 return c;
380}
381ostream& operator <<(ostream &os, const Block &b)
382{
383 os<<"Block:";
384 for(const Variable *v : b.vars) {
385 os<<" "<<*v;
386 }
387 if(b.deleted) {
388 os<<" Deleted!";
389 }
390 return os;
391}
static agxbuf last
last message
Definition agerror.c:29
#define RECTANGLE_OVERLAP_LOGGING
Definition block.cpp:31
ostream & operator<<(ostream &os, const Block &b)
Definition block.cpp:381
long blockTimeCtr
Definition blocks.cpp:35
#define LOGFILE
A block structure defined over the variables.
Definition blocks.h:24
Definition block.h:30
bool deleted
Definition block.h:55
Constraint * findMinInConstraint()
Definition block.cpp:138
std::vector< Variable * > vars
Definition block.h:33
void split(Block *&l, Block *&r, Constraint *c)
Definition block.cpp:361
double posn
Definition block.h:34
Constraint * findMinLM()
Definition block.cpp:310
Constraint * splitBetween(Variable *vl, Variable *vr, Block *&lb, Block *&rb)
Definition block.cpp:342
void deleteMinOutConstraint()
Definition block.cpp:205
Block(Variable *v=nullptr)
Definition block.cpp:41
void mergeIn(Block *b)
Definition block.cpp:119
void mergeOut(Block *b)
Definition block.cpp:133
void setUpOutConstraints()
Definition block.cpp:61
double wposn
Definition block.h:36
void setUpInConstraints()
Definition block.cpp:58
double cost()
Definition block.cpp:373
std::unique_ptr< PairingHeap< Constraint * > > out
Definition block.h:58
double desiredWeightedPosition()
Definition block.cpp:51
double weight
Definition block.h:35
Constraint * findMinOutConstraint()
Definition block.cpp:187
void merge(Block *b, Constraint *c, double dist)
Definition block.cpp:102
void deleteMinInConstraint()
Definition block.cpp:197
Constraint * findMinLMBetween(Variable *lv, Variable *rv)
Definition block.cpp:316
long timeStamp
Definition block.h:56
std::unique_ptr< PairingHeap< Constraint * > > in
Definition block.h:57
Pairing heap datastructure implementation.
Definition PairingHeap.h:68
static void split(void)
Definition ccomps.c:108
#define NONE
Definition const.h:126
static bool compareConstraints(Constraint *const &l, 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
const double weight
Definition variable.h:31
Block * block
Definition variable.h:33
double offset
Definition variable.h:32
double position() const
Definition variable.h:46