Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
blocks.cpp
Go to the documentation of this file.
1/*
2 * vim: ts=4 sw=4 et tw=0 wm=0
3 *
4 * libvpsc - A solver for the problem of Variable Placement with
5 * Separation Constraints.
6 *
7 * Copyright (C) 2005-2012 Monash University
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 * See the file LICENSE.LGPL distributed with the library.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * Author(s): Tim Dwyer
20 * Michael Wybrow
21*/
22
23/*
24 * @brief A block structure defined over the variables
25 *
26 * A block structure defined over the variables such that each block contains
27 * 1 or more variables, with the invariant that all constraints inside a block
28 * are satisfied by keeping the variables fixed relative to one another
29 */
30
31#include "libvpsc/blocks.h"
32#include "libvpsc/block.h"
33#include "libvpsc/constraint.h"
34#include "libvpsc/variable.h"
35#include "libvpsc/assertions.h"
36
37#ifdef LIBVPSC_LOGGING
38#include <fstream>
39using std::ios;
40using std::ofstream;
41using std::endl;
42#endif
43using std::vector;
44using std::iterator;
45using std::list;
46using std::copy;
47#define __NOTNAN(p) (p)==(p)
48
49namespace vpsc {
50
51
52Blocks::Blocks(vector<Variable*> const &vs) : vs(vs),nvs(vs.size()) {
54 m_blocks.resize(nvs);
55 for(size_t i=0;i<nvs;i++) {
56 m_blocks[i] = new Block(this, vs[i]);
57 }
58}
60{
62 size_t length = m_blocks.size();
63 for (size_t i = 0; i < length; ++i)
64 {
65 delete m_blocks[i];
66 }
67 m_blocks.clear();
68}
69
70/*
71 * returns a list of variables with total ordering determined by the constraint
72 * DAG
73 */
74list<Variable*> *Blocks::totalOrder() {
75 list<Variable*> *order = new list<Variable*>;
76 for(size_t i=0;i<nvs;i++) {
77 vs[i]->visited=false;
78 }
79 for(size_t i=0;i<nvs;i++) {
80 if(vs[i]->in.size()==0) {
81 dfsVisit(vs[i],order);
82 }
83 }
84 return order;
85}
86// Recursive depth first search giving total order by pushing nodes in the DAG
87// onto the front of the list when we finish searching them
88void Blocks::dfsVisit(Variable *v, list<Variable*> *order) {
89 v->visited=true;
90 vector<Constraint*>::iterator it=v->out.begin();
91 for(;it!=v->out.end();++it) {
92 Constraint *c=*it;
93 if(!c->right->visited) {
94 dfsVisit(c->right, order);
95 }
96 }
97#ifdef LIBVPSC_LOGGING
98 ofstream f(LOGFILE,ios::app);
99 f<<" order="<<*v<<endl;
100#endif
101 order->push_front(v);
102}
103/*
104 * Processes incoming constraints, most violated to least, merging with the
105 * neighbouring (left) block until no more violated constraints are found
106 */
108#ifdef LIBVPSC_LOGGING
109 ofstream f(LOGFILE,ios::app);
110 f<<"mergeLeft called on "<<*r<<endl;
111#endif
115 while (c != nullptr && c->slack()<0) {
116#ifdef LIBVPSC_LOGGING
117 f<<"mergeLeft on constraint: "<<*c<<endl;
118#endif
120 Block *l = c->left->block;
121 if (l->in==nullptr) l->setUpInConstraints();
122 double dist = c->right->offset - c->left->offset - c->gap;
123 if (r->vars->size() < l->vars->size()) {
124 dist=-dist;
125 std::swap(l, r);
126 }
127 blockTimeCtr++;
128 r->merge(l, c, dist);
129 r->mergeIn(l);
131 removeBlock(l);
133 }
134#ifdef LIBVPSC_LOGGING
135 f<<"merged "<<*r<<endl;
136#endif
137}
138/*
139 * Symmetrical to mergeLeft
140 */
142#ifdef LIBVPSC_LOGGING
143 ofstream f(LOGFILE,ios::app);
144 f<<"mergeRight called on "<<*l<<endl;
145#endif
148 while (c != nullptr && c->slack()<0) {
149#ifdef LIBVPSC_LOGGING
150 f<<"mergeRight on constraint: "<<*c<<endl;
151#endif
153 Block *r = c->right->block;
155 double dist = c->left->offset + c->gap - c->right->offset;
156 if (l->vars->size() > r->vars->size()) {
157 dist=-dist;
158 std::swap(l, r);
159 }
160 l->merge(r, c, dist);
161 l->mergeOut(r);
162 removeBlock(r);
164 }
165#ifdef LIBVPSC_LOGGING
166 f<<"merged "<<*l<<endl;
167#endif
168}
170 doomed->deleted=true;
171 //erase(doomed);
172}
173
174// Clears up deleted blocks from the blocks list.
176{
177 // We handle removal of items in-place by doing a single linear pass over
178 // the vector. We use two indexes, j to refer to elements we've checked
179 // from the original list and i to refer to the current position we are
180 // writing in the updated list.
181 size_t i = 0;
182
183 // For all items in the current blocks list...
184 size_t length = m_blocks.size();
185 for (size_t j = 0; j < length; )
186 {
187 if (m_blocks[j]->deleted)
188 {
189 // The element is deleted, so free it and increment j.
190 delete m_blocks[j];
191 ++j;
192 }
193 else
194 {
195 // The current element is still valid.
196 if (j > i)
197 {
198 // If we've not looking at same element, then copy from j to i.
199 m_blocks[i] = m_blocks[j];
200 }
201 // Increment both indexes.
202 ++i;
203 ++j;
204 }
205 }
206 m_blocks.resize(i);
207}
208/*
209 * Splits block b across constraint c into two new blocks, l and r (c's left
210 * and right sides respectively)
211 */
213 b->split(l,r,c);
214 m_blocks.push_back(l);
215 m_blocks.push_back(r);
216#ifdef LIBVPSC_LOGGING
217 ofstream f(LOGFILE,ios::app);
218 f<<"Split left: "<<*l<<endl;
219 f<<"Split right: "<<*r<<endl;
220#endif
221 r->posn = b->posn;
222 //COLA_ASSERT(r->weight!=0);
223 //r->wposn = r->posn * r->weight;
224 mergeLeft(l);
225 // r may have been merged!
226 r = c->right->block;
228 //r->posn = r->wposn / r->weight;
229 mergeRight(r);
230 removeBlock(b);
231
232 COLA_ASSERT(__NOTNAN(l->posn));
233 COLA_ASSERT(__NOTNAN(r->posn));
234}
235/*
236 * returns the cost total squared distance of variables from their desired
237 * positions
238 */
239double Blocks::cost() {
240 double c = 0;
241 size_t length = m_blocks.size();
242 for (size_t i = 0; i < length; ++i)
243 {
244 c += m_blocks[i]->cost();
245 }
246 return c;
247}
248
249}
void mergeOut(Block *b)
Definition block.cpp:210
PairingHeap< Constraint *, CompareConstraints > * in
Definition block.h:86
void merge(Block *b, Constraint *c, double dist)
Definition block.cpp:166
void mergeIn(Block *b)
Definition block.cpp:197
void setUpOutConstraints()
Definition block.cpp:120
long timeStamp
Definition block.h:85
bool deleted
Definition block.h:84
void deleteMinInConstraint()
Definition block.cpp:274
void split(Block *&l, Block *&r, Constraint *c)
Definition block.cpp:612
Constraint * findMinOutConstraint()
Definition block.cpp:264
void updateWeightedPosition()
Definition block.cpp:97
Constraint * findMinInConstraint()
Definition block.cpp:215
void deleteMinOutConstraint()
Definition block.cpp:282
double posn
Definition block.h:62
Variables * vars
Definition block.h:61
void setUpInConstraints()
Definition block.cpp:117
void split(Block *b, Block *&l, Block *&r, Constraint *c)
Definition blocks.cpp:212
std::vector< Block * > m_blocks
Definition blocks.h:75
size_t nvs
Definition blocks.h:77
void removeBlock(Block *doomed)
Definition blocks.cpp:169
long blockTimeCtr
Definition blocks.h:70
void mergeLeft(Block *r)
Definition blocks.cpp:107
double cost()
Definition blocks.cpp:239
std::list< Variable * > * totalOrder()
Definition blocks.cpp:74
void cleanup()
Definition blocks.cpp:175
~Blocks(void)
Definition blocks.cpp:59
Blocks(std::vector< Variable * > const &vs)
Definition blocks.cpp:52
std::vector< Variable * > const & vs
Definition blocks.h:76
void dfsVisit(Variable *v, std::list< Variable * > *order)
Definition blocks.cpp:88
void mergeRight(Block *l)
Definition blocks.cpp:141
A constraint determines a minimum or exact spacing required between two Variable objects.
Definition constraint.h:45
A variable is comprised of an ideal position, final position and a weight.
Definition variable.h:45
Geom::IntPoint size
double c[8][4]
const unsigned order
libvpsc: Variable Placement with Separation Constraints quadratic program solver library.