1/*
2 * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz
3 * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz
4 * Copyright 2010, Clemens Zeidler <haiku@clemens-zeidler.de>
5 * Distributed under the terms of the MIT License.
6 */
7
8
9#include "Variable.h"
10
11#include <math.h>
12
13#include "Constraint.h"
14#include "LinearSpec.h"
15
16// Toggle debug output
17//#define DEBUG_VARIABLE
18
19#ifdef DEBUG_VARIABLE
20#	define STRACE(x) debug_printf x
21#else
22#	define STRACE(x) ;
23#endif
24
25
26/**
27 * Gets index of the variable.
28 *
29 * @return the index of the variable
30 */
31int32
32Variable::Index() const
33{
34	return fLS->IndexOf(this);
35}
36
37
38int32
39Variable::GlobalIndex() const
40{
41	return fLS->GlobalIndexOf(this);
42}
43
44
45/**
46 * Gets the current linear specification.
47 *
48 * @return the current linear specification
49 */
50LinearSpec*
51Variable::LS() const
52{
53	return fLS;
54}
55
56
57/**
58 * Gets the value.
59 *
60 * @return the value
61 */
62double
63Variable::Value() const
64{
65	return fValue;
66}
67
68
69/**
70 * Sets the value.
71 *
72 * @param value	the value
73 */
74void
75Variable::SetValue(double value)
76{
77	fValue = value;
78}
79
80
81/**
82 * Gets the minimum value of the variable.
83 *
84 * @return the minimum value of variable
85 */
86double
87Variable::Min() const
88{
89	return fMin;
90}
91
92
93/**
94 * Sets the minimum value of the variable.
95 *
96 * @param min	minimum value
97 */
98void
99Variable::SetMin(double min)
100{
101	SetRange(min, fMax);
102}
103
104
105/**
106 * Gets the maximum value of the variable.
107 *
108 * @return the maximum value of variable
109 */
110double
111Variable::Max() const
112{
113	return fMax;
114}
115
116
117/**
118 * Sets the maximum value of the variable.
119 *
120 * @param max	maximum value
121 */
122void
123Variable::SetMax(double max)
124{
125	SetRange(fMin, max);
126}
127
128
129/**
130 * Sets the minimum and maximum values of the variable.
131 *
132 * @param min	minimum value
133 * @param max	maximum value
134 */
135void
136Variable::SetRange(double min, double max)
137{
138	fMin = min;
139	fMax = max;
140	if (fIsValid)
141		fLS->UpdateRange(this);
142}
143
144
145const char*
146Variable::Label()
147{
148	return fLabel.String();
149}
150
151
152void
153Variable::SetLabel(const char* label)
154{
155	fLabel = label;
156}
157
158
159/**
160 * Returns index of the variable as String.
161 * E.g. "Var2"
162 *
163 * @return the <code>String</code> index of the variable
164 */
165BString
166Variable::ToString() const
167{
168	BString string = "x";
169	string << Index() << " ";
170	if (fLabel) {
171		string << fLabel << ": ";
172		if (!fIsValid)
173			string << "(invalid)";
174	} else {
175		if (!fIsValid)
176			string << "(invalid," << (addr_t)this << ")";
177		else
178			string << Index() << ": ";
179	}
180	string << Value();
181	BString pointerString;
182	pointerString.SetToFormat("%p", this);
183	string << " (" << pointerString << ")";
184	return string;
185}
186
187
188/**
189 * Adds a constraint that sets this variable equal to the given one.
190 *
191 * @param var	variable that should have the same value
192 * @return the new equality constraint
193 */
194Constraint*
195Variable::IsEqual(Variable* var)
196{
197	if (!fIsValid)
198		return NULL;
199
200	return fLS->AddConstraint(1.0, this, -1.0, var, kEQ, 0.0);
201}
202
203
204/**
205 * Adds a constraint that sets this variable smaller or equal to the given one.
206 *
207 * @param var	variable that should have a larger or equal value
208 * @return the new constraint
209 */
210Constraint*
211Variable::IsSmallerOrEqual(Variable* var)
212{
213	if (!fIsValid)
214		return NULL;
215
216	return fLS->AddConstraint(1.0, this, -1.0, var, kLE, 0.0);
217}
218
219
220/**
221 * Adds a constraint that sets this variable greater or equal to the given one.
222 *
223 * @param var	variable that should have a smaller or equal value
224 * @return the new constraint
225 */
226Constraint*
227Variable::IsGreaterOrEqual(Variable* var)
228{
229	if (!fIsValid)
230		return NULL;
231
232	return fLS->AddConstraint(-1.0, var, 1.0, this, kGE, 0.0);
233}
234
235
236Constraint*
237Variable::IsEqual(Variable* var, double penaltyNeg, double penaltyPos)
238{
239	if (!fIsValid)
240		return NULL;
241
242	return fLS->AddConstraint(1.0, this, -1.0, var, kEQ, 0.0,
243		penaltyNeg, penaltyPos);
244}
245
246
247Constraint*
248Variable::IsSmallerOrEqual(Variable* var, double penaltyNeg, double penaltyPos)
249{
250	if (!fIsValid)
251		return NULL;
252
253	return fLS->AddConstraint(1.0, this, -1.0, var, kLE, 0.0, penaltyNeg,
254		penaltyPos);
255}
256
257
258Constraint*
259Variable::IsGreaterOrEqual(Variable* var, double penaltyNeg, double penaltyPos)
260{
261	if (!fIsValid)
262		return NULL;
263
264	return fLS->AddConstraint(-1.0, var, 1.0, this, kGE, 0.0, penaltyNeg,
265		penaltyPos);
266}
267
268
269bool
270Variable::IsValid()
271{
272	return fIsValid;
273}
274
275
276void
277Variable::Invalidate()
278{
279	STRACE(("Variable::Invalidate() on %s\n", BString(*this).String()));
280
281	if (!fIsValid)
282		return;
283
284	fIsValid = false;
285	fLS->RemoveVariable(this, false);
286}
287
288
289/**
290 * Constructor.
291 */
292Variable::Variable(LinearSpec* ls)
293	:
294	fLS(ls),
295	fValue(NAN),
296	fMin(-20000),
297	fMax(20000),
298	fLabel(NULL),
299	fIsValid(false),
300	fReferenceCount(0)
301{
302
303}
304
305
306int32
307Variable::AddReference()
308{
309	fReferenceCount++;
310	return fReferenceCount;
311}
312
313
314int32
315Variable::RemoveReference()
316{
317	fReferenceCount--;
318	return fReferenceCount;
319}
320
321
322/**
323 * Destructor.
324 * Removes the variable from its specification.
325 */
326Variable::~Variable()
327{
328	if (fLS)
329		fLS->RemoveVariable(this, false);
330}
331
332