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.
9 #include "Constraint.h"
14 #include "LinearSpec.h"
18 // Toggle debug output
19 //#define DEBUG_CONSTRAINT
21 #ifdef DEBUG_CONSTRAINT
22 # define STRACE(x) debug_printf x
28 Constraint::Constraint()
31 fLeftSide(new SummandList
),
40 Constraint::Constraint(Constraint
* constraint
)
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
));
59 * Gets the index of the constraint.
61 * @return the index of the constraint
64 Constraint::Index() const
68 int32 i
= fLS
->Constraints().IndexOf(this);
70 STRACE(("Constraint not part of fLS->Constraints()."));
77 * Gets the left side of the constraint.
79 * @return pointer to a BList containing the summands on the left side of the constraint
82 Constraint::LeftSide()
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
95 Constraint::SetLeftSide(SummandList
* summands
, bool deleteOldSummands
)
98 debugger("Invalid summands");
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
);
115 if (deleteOldSummands
)
117 fLeftSide
= summands
;
122 SummandList oldSummands
;
123 if (fLeftSide
!= NULL
)
124 oldSummands
= *fLeftSide
;
125 if (deleteOldSummands
)
127 fLeftSide
= summands
;
129 fLS
->UpdateLeftSide(this, &oldSummands
);
131 if (deleteOldSummands
) {
132 for (int32 i
= 0; i
< oldSummands
.CountItems(); i
++)
133 delete oldSummands
.ItemAt(i
);
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);
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);
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);
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
200 * Sets the operator used for this constraint.
202 * @param value operator
205 Constraint::SetOp(OperatorType value
)
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
219 Constraint::RightSide() const
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
231 Constraint::SetRightSide(double value
)
233 if (fRightSide
== value
)
239 fLS
->UpdateRightSide(this);
244 * Gets the penalty coefficient for negative deviations.
246 * @return the penalty coefficient
249 Constraint::PenaltyNeg() const
256 * The penalty coefficient for negative deviations from the soft constraint's exact solution,
257 * i.e. if the left side is too large.
259 * @param value coefficient of negative penalty <code>double</code>
262 Constraint::SetPenaltyNeg(double value
)
267 fLS
->UpdatePenalties(this);
272 * Gets the penalty coefficient for positive deviations.
274 * @return the penalty coefficient
277 Constraint::PenaltyPos() const
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>
289 Constraint::SetPenaltyPos(double value
)
294 fLS
->UpdatePenalties(this);
301 return fLabel
.String();
306 Constraint::SetLabel(const char* label
)
313 Constraint::IsValid()
320 Constraint::Invalidate()
322 STRACE(("Constraint::Invalidate() on %d\n", this));
327 fLS
->RemoveConstraint(this, false);
333 Constraint::ToString() const
336 string
<< "Constraint ";
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)
344 string
<< (float)s
->Coeff() << "*";
346 string
<< s
->Var()->Index();
349 string
<< ((fOp
== kEQ
) ? "== "
350 : (fOp
== kGE
) ? ">= "
351 : (fOp
== kLE
) ? "<= "
353 string
<< (float)fRightSide
;
354 string
<< " PenaltyPos=" << (float)PenaltyPos();
355 string
<< " PenaltyNeg=" << (float)PenaltyNeg();
362 Constraint::PrintToStream()
364 BString string
= ToString();
365 printf("%s\n", string
.String());
372 Constraint::Constraint(LinearSpec
* ls
, SummandList
* summands
, OperatorType op
,
373 double rightSide
, double penaltyNeg
, double penaltyPos
)
378 fRightSide(rightSide
),
379 fPenaltyNeg(penaltyNeg
),
380 fPenaltyPos(penaltyPos
)
382 SetLeftSide(summands
, false);
388 * Removes the constraint from its specification and deletes all the summands.
390 Constraint::~Constraint()
394 for (int32 i
= 0; i
< fLeftSide
->CountItems(); i
++)
395 delete fLeftSide
->ItemAt(i
);