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