Adaptagrams
vpsc.h
1 /*
2  * vim: ts=4 sw=4 et tw=0 wm=0
3  *
4  * libavoid - Fast, Incremental, Object-avoiding Line Router
5  *
6  * Copyright (C) 2005-2014 Monash University
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  * See the file LICENSE.LGPL distributed with the library.
13  *
14  * Licensees holding a valid commercial license may use this file in
15  * accordance with the commercial license agreement provided with the
16  * library.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21  *
22  * Author(s): Tim Dwyer
23  * Michael Wybrow
24  *
25  * --------------
26  *
27  * This file contains a slightly modified version of IncSolver() from libvpsc:
28  * A solver for the problem of Variable Placement with Separation Constraints.
29  * It has the following changes from the Adaptagrams VPSC version:
30  * - The required VPSC code has been consolidated into a single file.
31  * - Unnecessary code (like Solver) has been removed.
32  * - The PairingHeap code has been replaced by a STL priority_queue.
33  *
34  * Modifications: Michael Wybrow
35  *
36 */
37 
38 #ifndef LIBAVOID_VPSC_H
39 #define LIBAVOID_VPSC_H
40 
41 
42 #ifdef USELIBVPSC
43 
44 // By default, libavoid will use it's own version of VPSC defined in this file.
45 //
46 // Alternatively, you can directly use IncSolver from libvpsc. This
47 // introduces a dependency on libvpsc but it can be preferable in cases
48 // where you are building all of Adaptagrams together and want to work
49 // with a set of CompoundConstraints or other classes built upon the
50 // base libvpsc Constraint classes.
51 
52 // Include necessary headers from libvpsc.
53 #include "libvpsc/variable.h"
54 #include "libvpsc/constraint.h"
55 #include "libvpsc/rectangle.h"
56 #include "libvpsc/solve_VPSC.h"
57 
58 // Use the libvpsc versions of things needed by libavoid.
59 using vpsc::Variable;
60 using vpsc::Variables;
61 using vpsc::Constraint;
62 using vpsc::Constraints;
63 using vpsc::IncSolver;
64 using vpsc::delete_object;
65 
66 #else
67 
68 #include <vector>
69 #include <list>
70 #include <set>
71 #include <queue>
72 #include <iostream>
73 #include <cfloat>
74 
75 #include "libavoid/assertions.h"
76 
77 namespace Avoid {
78 
79 class Variable;
80 class Constraint;
81 class Blocks;
82 typedef std::vector<Variable*> Variables;
83 typedef std::vector<Constraint*> Constraints;
84 class CompareConstraints {
85 public:
86  bool operator() (Constraint *const &l, Constraint *const &r) const;
87 };
88 struct PositionStats {
89  PositionStats() : scale(0), AB(0), AD(0), A2(0) {}
90  void addVariable(Variable* const v);
91  double scale;
92  double AB;
93  double AD;
94  double A2;
95 };
96 
97 typedef std::priority_queue<Constraint*,std::vector<Constraint*>,
98  CompareConstraints> Heap;
99 
100 class Block
101 {
102  typedef Variables::iterator Vit;
103  typedef Constraints::iterator Cit;
104  typedef Constraints::const_iterator Cit_const;
105 
106  friend std::ostream& operator <<(std::ostream &os,const Block &b);
107 public:
108  Variables *vars;
109  double posn;
110  //double weight;
111  //double wposn;
112  PositionStats ps;
113  Block(Blocks *blocks, Variable* const v=nullptr);
114  ~Block(void);
115  Constraint* findMinLM();
116  Constraint* findMinLMBetween(Variable* const lv, Variable* const rv);
117  Constraint* findMinInConstraint();
118  Constraint* findMinOutConstraint();
119  void deleteMinInConstraint();
120  void deleteMinOutConstraint();
121  void updateWeightedPosition();
122  void merge(Block *b, Constraint *c, double dist);
123  Block* merge(Block *b, Constraint *c);
124  void mergeIn(Block *b);
125  void mergeOut(Block *b);
126  void split(Block *&l, Block *&r, Constraint *c);
127  Constraint* splitBetween(Variable* vl, Variable* vr, Block* &lb, Block* &rb);
128  void setUpInConstraints();
129  void setUpOutConstraints();
130  double cost();
131  bool deleted;
132  long timeStamp;
133  Heap *in;
134  Heap *out;
135  bool getActivePathBetween(Constraints& path, Variable const* u,
136  Variable const* v, Variable const *w) const;
137  bool isActiveDirectedPathBetween(
138  Variable const* u, Variable const* v) const;
139  bool getActiveDirectedPathBetween(Constraints& path, Variable const * u, Variable const * v) const;
140 private:
141  typedef enum {NONE, LEFT, RIGHT} Direction;
142  typedef std::pair<double, Constraint*> Pair;
143  void reset_active_lm(Variable* const v, Variable* const u);
144  void list_active(Variable* const v, Variable* const u);
145  double compute_dfdv(Variable* const v, Variable* const u);
146  double compute_dfdv(Variable* const v, Variable* const u, Constraint *&min_lm);
147  bool split_path(Variable*, Variable* const, Variable* const,
148  Constraint* &min_lm, bool desperation);
149  bool canFollowLeft(Constraint const* c, Variable const* last) const;
150  bool canFollowRight(Constraint const* c, Variable const* last) const;
151  void populateSplitBlock(Block *b, Variable* v, Variable const* u);
152  void addVariable(Variable* v);
153  void setUpConstraintHeap(Heap* &h,bool in);
154 
155  // Parent container, that holds the blockTimeCtr.
156  Blocks *blocks;
157 };
158 
159 
160 class Constraint;
161 typedef std::vector<Constraint*> Constraints;
162 class Variable
163 {
164  friend std::ostream& operator <<(std::ostream &os, const Variable &v);
165  friend class Block;
166  friend class Constraint;
167  friend class IncSolver;
168 public:
169  int id; // useful in log files
170  double desiredPosition;
171  double finalPosition;
172  double weight; // how much the variable wants to
173  // be at it's desired position
174  double scale; // translates variable to another space
175  double offset;
176  Block *block;
177  bool visited;
178  bool fixedDesiredPosition;
179  Constraints in;
180  Constraints out;
181  inline Variable(const int id, const double desiredPos=-1.0,
182  const double weight=1.0, const double scale=1.0)
183  : id(id)
184  , desiredPosition(desiredPos)
185  , weight(weight)
186  , scale(scale)
187  , offset(0)
188  , block(nullptr)
189  , visited(false)
190  , fixedDesiredPosition(false)
191  {
192  }
193  double dfdv(void) const {
194  return 2. * weight * ( position() - desiredPosition );
195  }
196 private:
197  inline double position(void) const {
198  return (block->ps.scale*block->posn+offset)/scale;
199  }
200  inline double unscaledPosition(void) const {
201  COLA_ASSERT(block->ps.scale == 1);
202  COLA_ASSERT(scale == 1);
203  return block->posn + offset;
204  }
205 };
206 
207 
208 class Constraint
209 {
210 public:
211  Constraint(Variable *left, Variable *right, double gap, bool equality=false);
212  ~Constraint();
213  inline double slack(void) const
214  {
215  if (unsatisfiable)
216  {
217  return DBL_MAX;
218  }
219  if (needsScaling)
220  {
221  return right->scale * right->position() - gap -
222  left->scale * left->position();
223  }
224  COLA_ASSERT(left->scale == 1);
225  COLA_ASSERT(right->scale == 1);
226  return right->unscaledPosition() - gap - left->unscaledPosition();
227  }
228  std::string toString(void) const;
229 
230  friend std::ostream& operator <<(std::ostream &os,const Constraint &c);
231  Variable *left;
232  Variable *right;
233  double gap;
234  double lm;
235  long timeStamp;
236  bool active;
237  const bool equality;
238  bool unsatisfiable;
239  bool needsScaling;
240  void *creator;
241 };
242 /*
243  * A block structure defined over the variables such that each block contains
244  * 1 or more variables, with the invariant that all constraints inside a block
245  * are satisfied by keeping the variables fixed relative to one another
246  */
247 class Blocks
248 {
249 public:
250  Blocks(Variables const &vs);
251  ~Blocks(void);
252  void mergeLeft(Block *r);
253  void mergeRight(Block *l);
254  void split(Block *b, Block *&l, Block *&r, Constraint *c);
255  std::list<Variable*> *totalOrder();
256  void cleanup();
257  double cost();
258 
259  size_t size() const;
260  Block *at(size_t index) const;
261  void insert(Block *block);
262 
263  long blockTimeCtr;
264 private:
265  void dfsVisit(Variable *v, std::list<Variable*> *order);
266  void removeBlock(Block *doomed);
267 
268  std::vector<Block *> m_blocks;
269  Variables const &vs;
270  size_t nvs;
271 };
272 
273 inline size_t Blocks::size() const
274 {
275  return m_blocks.size();
276 }
277 
278 inline Block *Blocks::at(size_t index) const
279 {
280  return m_blocks[index];
281 }
282 
283 inline void Blocks::insert(Block *block)
284 {
285  m_blocks.push_back(block);
286 }
287 
288 struct UnsatisfiableException {
289  Constraints path;
290 };
291 struct UnsatisfiedConstraint {
292  UnsatisfiedConstraint(Constraint& c):c(c) {}
293  Constraint& c;
294 };
295 /*
296  * Variable Placement with Separation Constraints problem instance
297  */
298 class IncSolver {
299 public:
300  unsigned splitCnt;
301  bool satisfy();
302  bool solve();
303  void moveBlocks();
304  void splitBlocks();
305  IncSolver(Variables const &vs, Constraints const &cs);
306 
307  ~IncSolver();
308  void addConstraint(Constraint *constraint);
309  Variables const & getVariables() { return vs; }
310 protected:
311  Blocks *bs;
312  size_t m;
313  Constraints const &cs;
314  size_t n;
315  Variables const &vs;
316  bool needsScaling;
317 
318  void printBlocks();
319  void copyResult();
320 private:
321  bool constraintGraphIsCyclic(const unsigned n, Variable* const vs[]);
322  bool blockGraphIsCyclic();
323  Constraints inactive;
324  Constraints violated;
325  Constraint* mostViolated(Constraints &l);
326 };
327 
328 struct delete_object
329 {
330  template <typename T>
331  void operator()(T *ptr){ delete ptr;}
332 };
333 
335  Variables const &vars, Constraints const &constraints);
336 
337 }
338 
339 #endif // ! USELIBVPSC
340 
341 #endif // AVOID_VPSC_H
A variable is comprised of an ideal position, final position and a weight.
Definition: variable.h:44
Incremental solver for Variable Placement with Separation Constraints problem instance.
Definition: solve_VPSC.h:105
ProjectionResult solve(vpsc::Variables &vs, vpsc::Constraints &cs, vpsc::Rectangles &rs, unsigned debugLevel=0)
Constructs a solver and attempts to solve the passed constraints on the passed vars.
std::vector< Variable * > Variables
A vector of pointers to Variable objects.
Definition: constraint.h:38
std::vector< Constraint * > Constraints
A vector of pointers to Constraint objects.
Definition: constraint.h:125
Constraints constraintsRemovingRedundantEqualities(const Variables &vars, const Constraints &constraints)
Given a set of variables and constraints, returns a modified set of constraints with all redundant eq...
Definition: constraint.cpp:188
A constraint determines a minimum or exact spacing required between two Variable objects.
Definition: constraint.h:44
No constraint:
Lateral constraints imply only a separation:
libavoid: Object-avoiding orthogonal and polyline connector routing library.
Definition: actioninfo.cpp:33