summaryrefslogtreecommitdiff
path: root/libs/cassowary/cassowary/ClLinearExpression.h
blob: 0a1df9c2431b83c930c6fc0104d9c0722c99787f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClLinearExpression.h

#ifndef ClLinearExpression_H
#define ClLinearExpression_H

#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif

#include "Cassowary.h"
#include "debug.h"
#include "ClVariable.h"
#include "ClLinearExpression_fwd.h"

class ClSimplexSolver;
class ClTableau;
class ClSymbolicWeight;

ClLinearExpression &cleNil();

template <class T>
class ClGenericLinearExpression  {
 public:
  typedef std::map<ClVariable,T> ClVarToCoeffMap;

  // convert Number-s into ClLinearExpression-s
  ClGenericLinearExpression(T num = 0.0);

  // Convert from ClVariable to a ClLinearExpression
  // this replaces ClVariable::asLinearExpression
  ClGenericLinearExpression(ClVariable clv, T value = 1.0, T constant = 0.0);

  // copy ctr
  ClGenericLinearExpression(const ClGenericLinearExpression<T> &expr) :
    _constant(expr._constant),
    _terms(expr._terms)
    { }

  virtual ~ClGenericLinearExpression();

  // Return a new linear expression formed by multiplying self by x.
  // (Note that this result must be linear.)
  ClGenericLinearExpression<T> Times(Number x) const;

  // Return a new linear expression formed by multiplying self by x.
  // (Note that this result must be linear.)
  ClGenericLinearExpression<T> Times(const ClGenericLinearExpression<T> &expr) const;

  // Return a new linear expression formed by adding x to self.
  ClGenericLinearExpression<T> Plus(const ClGenericLinearExpression<T> &expr) const;

  // Return a new linear expression formed by subtracting x from self.
  ClGenericLinearExpression<T> Minus(const ClGenericLinearExpression<T> &expr) const;

  // Return a new linear expression formed by dividing self by x.
  // (Note that this result must be linear.)
  ClGenericLinearExpression<T> Divide(Number x) const;



  // Return a new linear expression formed by multiplying self by x.
  // (Note that this result must be linear.)
  ClGenericLinearExpression<T> *P_times(Number x) const
    { return new ClGenericLinearExpression<T>(Times(x)); }

  // Return a new linear expression formed by adding x to self.
  ClGenericLinearExpression<T> *P_plus(const ClGenericLinearExpression<T> &expr) const
    { return new ClGenericLinearExpression<T>(Plus(expr)); }

  // Return a new linear expression formed by subtracting x from self.
  ClGenericLinearExpression<T> *P_minus(const ClGenericLinearExpression<T> &expr) const
    { return new ClGenericLinearExpression<T>(Minus(expr)); }

  // Return a new linear expression formed by dividing self by x.
  // (Note that this result must be linear.)
  ClGenericLinearExpression<T> *P_divide(Number x) const
    { return new ClGenericLinearExpression<T>(Divide(x)); }

  // Return a new linear expression formed by dividing self by x.
  // (Note that this result must be linear.)
  ClGenericLinearExpression<T> Divide(const ClGenericLinearExpression<T> &expr) const;

  // Return a new linear expression (aNumber/this).  Since the result
  // must be linear, this is permissible only if 'this' is a constant.
  ClGenericLinearExpression<T> DivFrom(const ClGenericLinearExpression<T> &expr) const;

  // Return a new linear expression (aNumber-this).
  ClGenericLinearExpression<T> SubtractFrom(const ClGenericLinearExpression<T> &expr) const
  { return expr.Minus(*this); }

  // Add n*expr to this expression from another expression expr.
  ClGenericLinearExpression<T> &AddExpression(const ClGenericLinearExpression<T> &expr, 
				    Number n = 1.0);

  // Add n*expr to this expression from another expression expr.
  // Notify the solver if a variable is added or deleted from this
  // expression.
  ClGenericLinearExpression<T> &AddExpression(const ClGenericLinearExpression<T> &expr, Number n,
				    ClVariable subject,
				    ClTableau &solver);

  // Add a term c*v to this expression.  If the expression already
  // contains a term involving v, Add c to the existing coefficient.
  // If the new coefficient is approximately 0, delete v.
  ClGenericLinearExpression<T> &AddVariable(ClVariable v, T c = 1.0);

  // Add a term c*v to this expression.  If the expression already
  // contains a term involving v, Add c to the existing coefficient.
  // If the new coefficient is approximately 0, delete v.
  ClGenericLinearExpression<T> &setVariable(ClVariable v, T c)
    {assert(c != 0.0);  _terms[v] = c; return *this; }

  // Add a term c*v to this expression.  If the expression already
  // contains a term involving v, Add c to the existing coefficient.
  // If the new coefficient is approximately 0, delete v.  Notify the
  // solver if v appears or disappears from this expression.
  ClGenericLinearExpression<T> &AddVariable(ClVariable v, T c,
				  ClVariable subject,
				  ClTableau &solver);

  // Return a pivotable variable in this expression.  (It is an error
  // if this expression is constant -- signal ExCLInternalError in
  // that case).  Return NULL if no pivotable variables
  ClVariable AnyPivotableVariable() const;

  // Replace var with a symbolic expression expr that is equal to it.
  // If a variable has been added to this expression that wasn't there
  // before, or if a variable has been dropped from this expression
  // because it now has a coefficient of 0, inform the solver.
  // PRECONDITIONS:
  //   var occurs with a non-Zero coefficient in this expression.
  void SubstituteOut(ClVariable v, 
		     const ClGenericLinearExpression<T> &expr,
		     ClVariable subject,
		     ClTableau &solver);

  // This linear expression currently represents the equation
  // oldSubject=self.  Destructively modify it so that it represents
  // the equation NewSubject=self.
  //
  // Precondition: NewSubject currently has a nonzero coefficient in
  // this expression.
  //
  // NOTES
  //   Suppose this expression is c + a*NewSubject + a1*v1 + ... + an*vn.
  //
  //   Then the current equation is 
  //       oldSubject = c + a*NewSubject + a1*v1 + ... + an*vn.
  //   The new equation will be
  //        NewSubject = -c/a + oldSubject/a - (a1/a)*v1 - ... - (an/a)*vn.
  //   Note that the term involving NewSubject has been dropped.
  void ChangeSubject(ClVariable old_subject,
		     ClVariable new_subject);

  // This linear expression currently represents the equation self=0.  Destructively modify it so 
  // that subject=self represents an equivalent equation.  
  //
  // Precondition: subject must be one of the variables in this expression.
  // NOTES
  //   Suppose this expression is
  //     c + a*subject + a1*v1 + ... + an*vn
  //   representing 
  //     c + a*subject + a1*v1 + ... + an*vn = 0
  // The modified expression will be
  //    subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
  //   representing
  //    subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
  //
  // Note that the term involving subject has been dropped.
  // Returns the reciprocal, so ChangeSubject can use it, too
  T NewSubject(ClVariable subject);

  // Return the value of the linear expression
  // given the current assignments of values to contained variables
  T Evaluate() const;

  // Return the coefficient corresponding to variable var, i.e.,
  // the 'ci' corresponding to the 'vi' that var is:
  //     v1*c1 + v2*c2 + .. + vn*cn + c
  T CoefficientFor(ClVariable var) const
    { 
    typename ClVarToCoeffMap::const_iterator it = _terms.find(var);
    if (it != _terms.end())
      return (*it).second;
    return 0.0;
    }

  T Constant() const
    { return _constant; }

  void Set_constant(T c)
    { _constant = c; }

  const ClVarToCoeffMap &Terms() const
    { return _terms; }

  ClVarToCoeffMap &Terms() 
    { return _terms; }

  void IncrementConstant(T c)
    { _constant += c; }

  bool IsConstant() const
    { return _terms.size() == 0; }

#ifndef CL_NO_IO
  virtual ostream &PrintOn(ostream &xo) const;

  friend ostream &operator<<(ostream &xo,const ClGenericLinearExpression<T> &cle)
    { return cle.PrintOn(xo); }
#endif

  friend ClGenericLinearExpression<T> operator+(const ClGenericLinearExpression<T> &e1,
				      const ClGenericLinearExpression<T> &e2)
    { return e1.Plus(e2); }

  friend ClGenericLinearExpression<T> operator-(const ClGenericLinearExpression<T> &e1,
				      const ClGenericLinearExpression<T> &e2)
    { return e1.Minus(e2); }

  friend ClGenericLinearExpression<T> operator*(const ClGenericLinearExpression<T> &e1,
				      const ClGenericLinearExpression<T> &e2)
    { return e1.Times(e2); }


  friend ClGenericLinearExpression<T> operator/(const ClGenericLinearExpression<T> &e1,
				      const ClGenericLinearExpression<T> &e2)
    { return e1.Divide(e2); }

  // FIXGJB -- this may be wrong -- should test underlying expression for equality
  friend bool operator==(const ClGenericLinearExpression<T> &e1,
			 const ClGenericLinearExpression<T> &e2)
    { return &e1 == &e2; }

  /// Named versions of the operator functions for ease of
  /// wrapping, or expressing using prefix notation

  friend ClGenericLinearExpression<T> Plus(const ClGenericLinearExpression<T> &e1,
				 const ClGenericLinearExpression<T> &e2)
    { return e1.Plus(e2); }

  friend ClGenericLinearExpression<T> Minus(const ClGenericLinearExpression<T> &e1,
				  const ClGenericLinearExpression<T> &e2)
    { return e1.Minus(e2); }

  friend ClGenericLinearExpression<T> Times(const ClGenericLinearExpression<T> &e1,
				  const ClGenericLinearExpression<T> &e2)
    { return e1.Times(e2); }


  friend ClGenericLinearExpression<T> *Divide(const ClGenericLinearExpression<T> &e1,
				   const ClGenericLinearExpression<T> &e2)
    { return new ClGenericLinearExpression<T>(e1.Divide(e2)); }

  friend ClGenericLinearExpression<T> *p_Plus(const ClGenericLinearExpression<T> &e1,
				   const ClGenericLinearExpression<T> &e2)
    { return new ClGenericLinearExpression<T>(e1.Plus(e2)); }

  friend ClGenericLinearExpression<T> *p_Minus(const ClGenericLinearExpression<T> &e1,
				    const ClGenericLinearExpression<T> &e2)
    { return new ClGenericLinearExpression<T>(e1.Minus(e2)); }

  friend ClGenericLinearExpression<T> *p_Times(const ClGenericLinearExpression<T> &e1,
				    const ClGenericLinearExpression<T> &e2)
    { return new ClGenericLinearExpression<T>(e1.Times(e2)); }

  friend ClGenericLinearExpression<T> *p_Divide(const ClGenericLinearExpression<T> &e1,
				     const ClGenericLinearExpression<T> &e2)
    { return new ClGenericLinearExpression<T>(e1.Divide(e2)); }


  // FIXGJB -- this may be wrong -- should test underlying expression for equality
  friend bool FEquals(const ClGenericLinearExpression<T> &e1,
		      const ClGenericLinearExpression<T> &e2)
    { return &e1 == &e2; }

  ClGenericLinearExpression<T> &MultiplyMe(T x);

 private:

  T _constant;
  ClVarToCoeffMap _terms;

};

typedef ClGenericLinearExpression<Number>::ClVarToCoeffMap ClVarToNumberMap;

#endif