Restore the "GPL licensing not permitted" in GLUT license headers.
[haiku.git] / src / libs / linprog / Constraint.cpp
blob9d0596b5df3322e1c905ff165beba5ff7adaede8
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 */
9 #include "Constraint.h"
11 #include <new>
12 #include <stdio.h>
14 #include "LinearSpec.h"
15 #include "Variable.h"
18 // Toggle debug output
19 //#define DEBUG_CONSTRAINT
21 #ifdef DEBUG_CONSTRAINT
22 # define STRACE(x) debug_printf x
23 #else
24 # define STRACE(x) ;
25 #endif
28 Constraint::Constraint()
30 fLS(NULL),
31 fLeftSide(new SummandList),
32 fOp(kEQ),
33 fRightSide(0),
34 fPenaltyNeg(-1),
35 fPenaltyPos(-1)
40 Constraint::Constraint(Constraint* constraint)
42 fLS(NULL),
43 fLeftSide(new SummandList),
44 fOp(constraint->Op()),
45 fRightSide(constraint->RightSide()),
46 fPenaltyNeg(constraint->PenaltyNeg()),
47 fPenaltyPos(constraint->PenaltyPos()),
48 fLabel(constraint->Label())
50 SummandList* orgSummands = constraint->LeftSide();
51 for (int32 i = 0; i < orgSummands->CountItems(); i++) {
52 Summand* summand = orgSummands->ItemAt(i);
53 fLeftSide->AddItem(new Summand(summand));
58 /**
59 * Gets the index of the constraint.
61 * @return the index of the constraint
63 int32
64 Constraint::Index() const
66 if (fLS == NULL)
67 return -1;
68 int32 i = fLS->Constraints().IndexOf(this);
69 if (i == -1)
70 STRACE(("Constraint not part of fLS->Constraints()."));
72 return i;
76 /**
77 * Gets the left side of the constraint.
79 * @return pointer to a BList containing the summands on the left side of the constraint
81 SummandList*
82 Constraint::LeftSide()
84 return fLeftSide;
88 /**
89 * Sets the summands on the left side of the constraint.
90 * The old summands are NOT deleted.
92 * @param summands a BList containing the Summand objects that make up the new left side
94 bool
95 Constraint::SetLeftSide(SummandList* summands, bool deleteOldSummands)
97 if (summands == NULL)
98 debugger("Invalid summands");
100 // check left side
101 for (int32 i = 0; i < summands->CountItems(); i++) {
102 Summand* summand = summands->ItemAt(i);
103 for (int32 a = i + 1; a < summands->CountItems(); a++) {
104 Summand* nextSummand = summands->ItemAt(a);
105 if (summand->Var() == nextSummand->Var()) {
106 summand->SetCoeff(summand->Coeff() + nextSummand->Coeff());
107 summands->RemoveItem(nextSummand);
108 delete nextSummand;
109 a--;
114 if (fLS == NULL) {
115 if (deleteOldSummands)
116 delete fLeftSide;
117 fLeftSide = summands;
118 return true;
121 // notify the solver
122 SummandList oldSummands;
123 if (fLeftSide != NULL)
124 oldSummands = *fLeftSide;
125 if (deleteOldSummands)
126 delete fLeftSide;
127 fLeftSide = summands;
128 if (fLS != NULL)
129 fLS->UpdateLeftSide(this, &oldSummands);
131 if (deleteOldSummands) {
132 for (int32 i = 0; i < oldSummands.CountItems(); i++)
133 delete oldSummands.ItemAt(i);
135 return true;
139 bool
140 Constraint::SetLeftSide(double coeff1, Variable* var1)
142 SummandList* list = new SummandList;
143 list->AddItem(new(std::nothrow) Summand(coeff1, var1));
144 return SetLeftSide(list, true);
148 bool
149 Constraint::SetLeftSide(double coeff1, Variable* var1,
150 double coeff2, Variable* var2)
152 SummandList* list = new SummandList;
153 list->AddItem(new(std::nothrow) Summand(coeff1, var1));
154 list->AddItem(new(std::nothrow) Summand(coeff2, var2));
155 return SetLeftSide(list, true);
159 bool
160 Constraint::SetLeftSide(double coeff1, Variable* var1,
161 double coeff2, Variable* var2,
162 double coeff3, Variable* var3)
164 SummandList* list = new SummandList;
165 list->AddItem(new(std::nothrow) Summand(coeff1, var1));
166 list->AddItem(new(std::nothrow) Summand(coeff2, var2));
167 list->AddItem(new(std::nothrow) Summand(coeff3, var3));
168 return SetLeftSide(list, true);
172 bool
173 Constraint::SetLeftSide(double coeff1, Variable* var1,
174 double coeff2, Variable* var2,
175 double coeff3, Variable* var3,
176 double coeff4, Variable* var4)
178 SummandList* list = new SummandList;
179 list->AddItem(new(std::nothrow) Summand(coeff1, var1));
180 list->AddItem(new(std::nothrow) Summand(coeff2, var2));
181 list->AddItem(new(std::nothrow) Summand(coeff3, var3));
182 list->AddItem(new(std::nothrow) Summand(coeff4, var4));
183 return SetLeftSide(list, true);
188 * Gets the operator used for this constraint.
190 * @return the operator used for this constraint
192 OperatorType
193 Constraint::Op()
195 return fOp;
200 * Sets the operator used for this constraint.
202 * @param value operator
204 void
205 Constraint::SetOp(OperatorType value)
207 fOp = value;
208 if (fLS != NULL)
209 fLS->UpdateOperator(this);
214 * Gets the constant value that is on the right side of the operator.
216 * @return the constant value that is on the right side of the operator
218 double
219 Constraint::RightSide() const
221 return fRightSide;
226 * Sets the constant value that is on the right side of the operator.
228 * @param value constant value that is on the right side of the operator
230 void
231 Constraint::SetRightSide(double value)
233 if (fRightSide == value)
234 return;
236 fRightSide = value;
238 if (fLS != NULL)
239 fLS->UpdateRightSide(this);
244 * Gets the penalty coefficient for negative deviations.
246 * @return the penalty coefficient
248 double
249 Constraint::PenaltyNeg() const
251 return fPenaltyNeg;
256 * The penalty coefficient for negative deviations from the soft constraint's exact solution,&nbsp;
257 * i.e. if the left side is too large.
259 * @param value coefficient of negative penalty <code>double</code>
261 void
262 Constraint::SetPenaltyNeg(double value)
264 fPenaltyNeg = value;
266 if (fLS != NULL)
267 fLS->UpdatePenalties(this);
272 * Gets the penalty coefficient for positive deviations.
274 * @return the penalty coefficient
276 double
277 Constraint::PenaltyPos() const
279 return fPenaltyPos;
284 * The penalty coefficient for negative deviations from the soft constraint's
285 * exact solution, i.e. if the left side is too small.
286 * @param value coefficient of positive penalty <code>double</code>
288 void
289 Constraint::SetPenaltyPos(double value)
291 fPenaltyPos = value;
293 if (fLS != NULL)
294 fLS->UpdatePenalties(this);
298 const char*
299 Constraint::Label()
301 return fLabel.String();
305 void
306 Constraint::SetLabel(const char* label)
308 fLabel = label;
312 bool
313 Constraint::IsValid()
315 return fLS != NULL;
319 void
320 Constraint::Invalidate()
322 STRACE(("Constraint::Invalidate() on %d\n", this));
324 if (fLS == NULL)
325 return;
327 fLS->RemoveConstraint(this, false);
328 fLS = NULL;
332 BString
333 Constraint::ToString() const
335 BString string;
336 string << "Constraint ";
337 string << fLabel;
338 string << "(" << (addr_t)this << "): ";
340 for (int i = 0; i < fLeftSide->CountItems(); i++) {
341 Summand* s = static_cast<Summand*>(fLeftSide->ItemAt(i));
342 if (i != 0 && s->Coeff() >= 0)
343 string << " + ";
344 string << (float)s->Coeff() << "*";
345 string << "x";
346 string << s->Var()->Index();
347 string << " ";
349 string << ((fOp == kEQ) ? "== "
350 : (fOp == kGE) ? ">= "
351 : (fOp == kLE) ? "<= "
352 : "?? ");
353 string << (float)fRightSide;
354 string << " PenaltyPos=" << (float)PenaltyPos();
355 string << " PenaltyNeg=" << (float)PenaltyNeg();
357 return string;
361 void
362 Constraint::PrintToStream()
364 BString string = ToString();
365 printf("%s\n", string.String());
370 * Constructor.
372 Constraint::Constraint(LinearSpec* ls, SummandList* summands, OperatorType op,
373 double rightSide, double penaltyNeg, double penaltyPos)
375 fLS(ls),
376 fLeftSide(NULL),
377 fOp(op),
378 fRightSide(rightSide),
379 fPenaltyNeg(penaltyNeg),
380 fPenaltyPos(penaltyPos)
382 SetLeftSide(summands, false);
387 * Destructor.
388 * Removes the constraint from its specification and deletes all the summands.
390 Constraint::~Constraint()
392 Invalidate();
394 for (int32 i = 0; i < fLeftSide->CountItems(); i++)
395 delete fLeftSide->ItemAt(i);
396 delete fLeftSide;
397 fLeftSide = NULL;