xref: /haiku/src/libs/linprog/Constraint.cpp (revision 89755088d790ff4fe36f8aa77dacb2bd15507108)
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 "Constraint.h"
8 #include "LinearSpec.h"
9 #include "Variable.h"
10 
11 #include "lp_lib.h"
12 
13 
14 /**
15  * Gets the index of the constraint.
16  *
17  * @return the index of the constraint
18  */
19 int32
20 Constraint::Index()
21 {
22 	int32 i = fLS->Constraints()->IndexOf(this);
23 	if (i == -1)
24 		printf("Constraint not part of fLS->Constraints().");
25 	return i + 1;
26 }
27 
28 
29 /**
30  * Gets the left side of the constraint.
31  *
32  * @return pointer to a BList containing the summands on the left side of the constraint
33  */
34 BList*
35 Constraint::LeftSide()
36 {
37 	return fLeftSide;
38 }
39 
40 
41 /**
42  * Sets the summands on the left side of the constraint.
43  * The old summands are NOT deleted.
44  *
45  * @param summands	a BList containing the Summand objects that make up the new left side
46  */
47 void
48 Constraint::SetLeftSide(BList* summands)
49 {
50 	fLeftSide = summands;
51 	UpdateLeftSide();
52 }
53 
54 
55 void
56 Constraint::UpdateLeftSide()
57 {
58 	double coeffs[fLeftSide->CountItems() + 2];
59 	int varIndexes[fLeftSide->CountItems() + 2];
60 	int32 i;
61 	for (i = 0; i < fLeftSide->CountItems(); i++) {
62 		Summand* s = (Summand*)fLeftSide->ItemAt(i);
63 		coeffs[i] = s->Coeff();
64 		varIndexes[i] = s->Var()->Index();
65 	}
66 
67 	if (fDNegObjSummand != NULL && fOp != OperatorType(LE)) {
68 		varIndexes[i] = fDNegObjSummand->Var()->Index();
69 		coeffs[i] = 1.0;
70 		i++;
71 	}
72 
73 	if (fDPosObjSummand != NULL && fOp != OperatorType(GE)) {
74 		varIndexes[i] = fDPosObjSummand->Var()->Index();
75 		coeffs[i] = -1.0;
76 		i++;
77 	}
78 
79 	if (!set_rowex(fLS->fLP, this->Index(), i, &coeffs[0], &varIndexes[0]))
80 		printf("Error in set_rowex.");
81 
82 	fLS->UpdateObjFunction();
83 	fLS->RemovePresolved();
84 }
85 
86 
87 void
88 Constraint::SetLeftSide(double coeff1, Variable* var1)
89 {
90 	for (int i=0; i<fLeftSide->CountItems(); i++)
91 		delete (Summand*)fLeftSide->ItemAt(i);
92 	fLeftSide->MakeEmpty();
93 	fLeftSide->AddItem(new Summand(coeff1, var1));
94 	UpdateLeftSide();
95 }
96 
97 
98 void
99 Constraint::SetLeftSide(double coeff1, Variable* var1,
100 	double coeff2, Variable* var2)
101 {
102 	for (int i=0; i<fLeftSide->CountItems(); i++)
103 		delete (Summand*)fLeftSide->ItemAt(i);
104 	fLeftSide->MakeEmpty();
105 	fLeftSide->AddItem(new Summand(coeff1, var1));
106 	fLeftSide->AddItem(new Summand(coeff2, var2));
107 	UpdateLeftSide();
108 }
109 
110 
111 void
112 Constraint::SetLeftSide(double coeff1, Variable* var1,
113 	double coeff2, Variable* var2,
114 	double coeff3, Variable* var3)
115 {
116 	for (int i=0; i<fLeftSide->CountItems(); i++)
117 		delete (Summand*)fLeftSide->ItemAt(i);
118 	fLeftSide->MakeEmpty();
119 	fLeftSide->AddItem(new Summand(coeff1, var1));
120 	fLeftSide->AddItem(new Summand(coeff2, var2));
121 	fLeftSide->AddItem(new Summand(coeff3, var3));
122 	UpdateLeftSide();
123 }
124 
125 
126 void
127 Constraint::SetLeftSide(double coeff1, Variable* var1,
128 	double coeff2, Variable* var2,
129 	double coeff3, Variable* var3,
130 	double coeff4, Variable* var4)
131 {
132 	for (int i=0; i<fLeftSide->CountItems(); i++)
133 		delete (Summand*)fLeftSide->ItemAt(i);
134 	fLeftSide->MakeEmpty();
135 	fLeftSide->AddItem(new Summand(coeff1, var1));
136 	fLeftSide->AddItem(new Summand(coeff2, var2));
137 	fLeftSide->AddItem(new Summand(coeff3, var3));
138 	fLeftSide->AddItem(new Summand(coeff4, var4));
139 	UpdateLeftSide();
140 }
141 
142 
143 /**
144  * Gets the operator used for this constraint.
145  *
146  * @return the operator used for this constraint
147  */
148 OperatorType
149 Constraint::Op()
150 {
151 	return fOp;
152 }
153 
154 
155 /**
156  * Sets the operator used for this constraint.
157  *
158  * @param value	operator
159  */
160 void
161 Constraint::SetOp(OperatorType value)
162 {
163 	fOp = value;
164 	if (!set_constr_type(fLS->fLP, this->Index(),
165 			((fOp == OperatorType(EQ)) ? EQ
166 			: (fOp == OperatorType(GE)) ? GE
167 			: LE)))
168 		printf("Error in set_constr_type.");
169 
170 	fLS->RemovePresolved();
171 }
172 
173 
174 /**
175  * Gets the constant value that is on the right side of the operator.
176  *
177  * @return the constant value that is on the right side of the operator
178  */
179 double
180 Constraint::RightSide()
181 {
182 	return fRightSide;
183 }
184 
185 
186 /**
187  * Sets the constant value that is on the right side of the operator.
188  *
189  * @param value	constant value that is on the right side of the operator
190  */
191 void
192 Constraint::SetRightSide(double value)
193 {
194 	fRightSide = value;
195 	if (!set_rh(fLS->fLP, Index(), fRightSide))
196 		printf("Error in set_rh.");
197 
198 	fLS->RemovePresolved();
199 }
200 
201 
202 /**
203  * Gets the penalty coefficient for negative deviations.
204  *
205  * @return the penalty coefficient
206  */
207 double
208 Constraint::PenaltyNeg()
209 {
210 	if (fDNegObjSummand == NULL)
211 		return INFINITY;
212 	return fDNegObjSummand->Coeff();
213 }
214 
215 
216 /**
217  * The penalty coefficient for negative deviations from the soft constraint's exact solution,&nbsp;
218  * i.e. if the left side is too large.
219  *
220  * @param value	coefficient of negative penalty <code>double</code>
221  */
222 void
223 Constraint::SetPenaltyNeg(double value)
224 {
225 	if (fDNegObjSummand == NULL) {
226 		fDNegObjSummand = new Summand(value, new Variable(fLS));
227 		fLS->ObjFunction()->AddItem(fDNegObjSummand);
228 		UpdateLeftSide();
229 		fLS->UpdateObjFunction();
230 		return;
231 	}
232 
233 	if (value == fDNegObjSummand->Coeff())
234 		return;
235 
236 	fDNegObjSummand->SetCoeff(value);
237 	fLS->UpdateObjFunction();
238 }
239 
240 
241 /**
242  * Gets the penalty coefficient for positive deviations.
243  *
244  * @return the penalty coefficient
245  */
246 double
247 Constraint::PenaltyPos()
248 {
249 	if (fDPosObjSummand == NULL)
250 		return INFINITY;
251 	return fDPosObjSummand->Coeff();
252 }
253 
254 
255 /**
256  * The penalty coefficient for negative deviations from the soft constraint's exact solution,
257  * i.e. if the left side is too small.
258  *
259  * @param value	coefficient of positive penalty <code>double</code>
260  */
261 void
262 Constraint::SetPenaltyPos(double value)
263 {
264 	if (fDPosObjSummand == NULL) {
265 		fDPosObjSummand = new Summand(value, new Variable(fLS));
266 		fLS->ObjFunction()->AddItem(fDPosObjSummand);
267 		UpdateLeftSide();
268 		fLS->UpdateObjFunction();
269 		return;
270 	}
271 
272 	if (value == fDPosObjSummand->Coeff())
273 		return;
274 
275 	fDPosObjSummand->SetCoeff(value);
276 	fLS->UpdateObjFunction();
277 }
278 
279 
280 /**
281  * Gets the slack variable for the negative variations.
282  *
283  * @return the slack variable for the negative variations
284  */
285 Variable*
286 Constraint::DNeg() const
287 {
288 	if (fDNegObjSummand == NULL)
289 		return NULL;
290 	return fDNegObjSummand->Var();
291 }
292 
293 
294 /**
295  * Gets the slack variable for the positive variations.
296  *
297  * @return the slack variable for the positive variations
298  */
299 Variable*
300 Constraint::DPos() const
301 {
302 	if (fDPosObjSummand == NULL)
303 		return NULL;
304 	return fDPosObjSummand->Var();
305 }
306 
307 
308 /**
309  * Constructor.
310  */
311 Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
312 	double rightSide, double penaltyNeg, double penaltyPos)
313 {
314 	fLS = ls;
315 	fLeftSide = summands;
316 	fOp = op;
317 	fRightSide = rightSide;
318 
319 	double coeffs[summands->CountItems() + 2];
320 	int varIndexes[summands->CountItems() + 2];
321 	int32 i;
322 	for (i = 0; i < summands->CountItems(); i++) {
323 		Summand* s = (Summand*)summands->ItemAt(i);
324 		coeffs[i] = s->Coeff();
325 		varIndexes[i] = s->Var()->Index();
326 	}
327 
328 	if (penaltyNeg != INFINITY
329 		&& fOp != OperatorType(LE)) {
330 		fDNegObjSummand = new Summand(penaltyNeg, new Variable(ls));
331 		ls->fObjFunction->AddItem(fDNegObjSummand);
332 		varIndexes[i] = fDNegObjSummand->Var()->Index();
333 		coeffs[i] = 1.0;
334 		i++;
335 	}
336 	else
337 		fDNegObjSummand = NULL;
338 
339 	if (penaltyPos != INFINITY
340 		&& fOp != OperatorType(GE)) {
341 		fDPosObjSummand = new Summand(penaltyPos, new Variable(ls));
342 		ls->fObjFunction->AddItem(fDPosObjSummand);
343 		varIndexes[i] = fDPosObjSummand->Var()->Index();
344 		coeffs[i] = -1.0;
345 		i++;
346 	}
347 	else
348 		fDPosObjSummand = NULL;
349 
350 	if (!add_constraintex(ls->fLP, i, &coeffs[0], &varIndexes[0],
351 			((fOp == OperatorType(EQ)) ? EQ
352 			: (fOp == OperatorType(GE)) ? GE
353 			: LE), rightSide))
354 		printf("Error in add_constraintex.");
355 
356 	fLS->UpdateObjFunction();
357 	ls->Constraints()->AddItem(this);
358 }
359 
360 
361 /**
362  * Destructor.
363  * Removes the constraint from its specification and deletes all the summands.
364  */
365 Constraint::~Constraint()
366 {
367 	for (int i=0; i<fLeftSide->CountItems(); i++)
368 		delete (Summand*)fLeftSide->ItemAt(i);
369 	delete fLeftSide;
370 
371 	if (fDNegObjSummand != NULL) {
372 		delete fDNegObjSummand->Var();
373 		delete fDNegObjSummand;
374 	}
375 	if (fDPosObjSummand != NULL) {
376 		delete fDPosObjSummand->Var();
377 		delete fDPosObjSummand;
378 	}
379 
380 	del_constraint(fLS->fLP, Index());
381 	fLS->Constraints()->RemoveItem(this);
382 }
383 
384