xref: /haiku/src/libs/linprog/Variable.cpp (revision c9ad965c81b08802fed0827fd1dd16f45297928a)
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()
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 /**
170  * Returns index of the variable as String.
171  * E.g. "Var2"
172  *
173  * @return the <code>String</code> index of the variable
174  */
175 BString*
176 Variable::ToBString()
177 {
178 	BString* str = new BString();
179 	if (fLabel) {
180 		*str << fLabel;
181 		if (!fIsValid)
182 			*str << "(invalid)";
183 	} else {
184 		*str << "Var";
185 		if (!fIsValid)
186 			*str << "(invalid," << (int32)this << ")";
187 		else
188 			*str << Index();
189 	}
190 	return str;
191 }
192 
193 
194 const char*
195 Variable::ToString()
196 {
197 	BString* str = ToBString();
198 	char* result = (char*) malloc(str->Length() + 1);
199 	str->CopyInto(result, 0, str->Length());
200 	delete str;
201 	return result;
202 }
203 
204 
205 /**
206  * Adds a constraint that sets this variable equal to the given one.
207  *
208  * @param var	variable that should have the same value
209  * @return the new equality constraint
210  */
211 Constraint*
212 Variable::IsEqual(Variable* var)
213 {
214 	if (!fIsValid)
215 		return NULL;
216 
217 	return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0);
218 }
219 
220 
221 /**
222  * Adds a constraint that sets this variable smaller or equal to the given one.
223  *
224  * @param var	variable that should have a larger or equal value
225  * @return the new constraint
226  */
227 Constraint*
228 Variable::IsSmallerOrEqual(Variable* var)
229 {
230 	if (!fIsValid)
231 		return NULL;
232 
233 	return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0);
234 }
235 
236 
237 /**
238  * Adds a constraint that sets this variable greater or equal to the given one.
239  *
240  * @param var	variable that should have a smaller or equal value
241  * @return the new constraint
242  */
243 Constraint*
244 Variable::IsGreaterOrEqual(Variable* var)
245 {
246 	if (!fIsValid)
247 		return NULL;
248 
249 	return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0);
250 }
251 
252 
253 Constraint*
254 Variable::IsEqual(Variable* var, double penaltyNeg, double penaltyPos)
255 {
256 	if (!fIsValid)
257 		return NULL;
258 
259 	return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0,
260 		penaltyNeg, penaltyPos);
261 }
262 
263 
264 Constraint*
265 Variable::IsSmallerOrEqual(Variable* var, double penaltyNeg, double penaltyPos)
266 {
267 	if (!fIsValid)
268 		return NULL;
269 
270 	return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0,
271 		penaltyNeg, penaltyPos);
272 }
273 
274 
275 Constraint*
276 Variable::IsGreaterOrEqual(Variable* var, double penaltyNeg, double penaltyPos)
277 {
278 	if (!fIsValid)
279 		return NULL;
280 
281 	return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0,
282 		penaltyNeg, penaltyPos);
283 }
284 
285 
286 bool
287 Variable::IsValid()
288 {
289 	return fIsValid;
290 }
291 
292 
293 void
294 Variable::Invalidate()
295 {
296 	STRACE(("Variable::Invalidate() on %s\n", ToString()));
297 
298 	if (!fIsValid)
299 		return;
300 
301 	fIsValid = false;
302 	del_column(fLS->fLP, Index());
303 	fLS->Variables()->RemoveItem(this);
304 
305 	// invalidate all constraints that use this variable
306 	BList* markedForInvalidation = new BList();
307 	BList* constraints = fLS->Constraints();
308 	for (int i = 0; i < constraints->CountItems(); i++) {
309 		Constraint* constraint = static_cast<Constraint*>(
310 			constraints->ItemAt(i));
311 
312 		if (!constraint->IsValid())
313 			continue;
314 
315 		BList* summands = constraint->LeftSide();
316 		for (int j = 0; j < summands->CountItems(); j++) {
317 			Summand* summand = static_cast<Summand*>(summands->ItemAt(j));
318 			if (summand->Var() == this) {
319 				markedForInvalidation->AddItem(constraint);
320 				break;
321 			}
322 		}
323 	}
324 	for (int i = 0; i < markedForInvalidation->CountItems(); i++)
325 		static_cast<Constraint*>(markedForInvalidation->ItemAt(i))
326 			->Invalidate();
327 	delete markedForInvalidation;
328 }
329 
330 
331 /**
332  * Constructor.
333  */
334 Variable::Variable(LinearSpec* ls)
335 	: fLS(ls),
336 	fUsingSummands(new BList()),
337 	fValue(NAN),
338 	fMin(0),
339 	fMax(DBL_MAX),
340 	fLabel(NULL),
341 	fIsValid(true)
342 {
343 	fLS->Variables()->AddItem(this);
344 
345 	if (fLS->Variables()->CountItems() > fLS->CountColumns()) {
346 		double d = 0;
347 		int i = 0;
348 		if (!add_columnex(fLS->fLP, 0, &d, &i))
349 			printf("Error in add_columnex.");
350 	}
351 }
352 
353 
354 /**
355  * Destructor.
356  * Removes the variable from its specification.
357  */
358 Variable::~Variable()
359 {
360 	Invalidate();
361 	free(fLabel);
362 	delete fUsingSummands;
363 }
364 
365