Make it possible to create a constraint that is not connected to a solver.

- Clean up.
This commit is contained in:
czeidler
2012-09-01 16:31:13 +12:00
parent 6c4a44e36b
commit 08927d809f
2 changed files with 123 additions and 144 deletions
+13 -21
View File
@@ -6,9 +6,6 @@
#ifndef CONSTRAINT_H #ifndef CONSTRAINT_H
#define CONSTRAINT_H #define CONSTRAINT_H
#include <math.h>
#include <File.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <String.h> #include <String.h>
#include <SupportDefs.h> #include <SupportDefs.h>
@@ -28,20 +25,26 @@ class LinearSpec;
*/ */
class Constraint { class Constraint {
public: public:
Constraint();
/*! Creates a soft copy of the constraint which is not connected
to the solver. Variables are not copied or cloned but the soft copy
has its own summand list with summands. */
Constraint(Constraint* constraint);
int32 Index() const; int32 Index() const;
SummandList* LeftSide(); SummandList* LeftSide();
/*! This just overwrites the current list. The caller has to take
care about the old left side, i.e. delete it. */
void SetLeftSide(SummandList* summands);
void SetLeftSide(double coeff1, Variable* var1); bool SetLeftSide(SummandList* summands,
void SetLeftSide(double coeff1, Variable* var1, bool deleteOldSummands);
bool SetLeftSide(double coeff1, Variable* var1);
bool SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2); double coeff2, Variable* var2);
void SetLeftSide(double coeff1, Variable* var1, bool SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff2, Variable* var2,
double coeff3, Variable* var3); double coeff3, Variable* var3);
void SetLeftSide(double coeff1, Variable* var1, bool SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff2, Variable* var2,
double coeff3, Variable* var3, double coeff3, Variable* var3,
double coeff4, Variable* var4); double coeff4, Variable* var4);
@@ -58,11 +61,6 @@ public:
const char* Label(); const char* Label();
void SetLabel(const char* label); void SetLabel(const char* label);
Variable* DNeg() const;
Variable* DPos() const;
bool IsSoft() const;
bool IsValid(); bool IsValid();
void Invalidate(); void Invalidate();
@@ -86,16 +84,10 @@ private:
double fPenaltyNeg; double fPenaltyNeg;
double fPenaltyPos; double fPenaltyPos;
Summand* fDNegObjSummand;
Summand* fDPosObjSummand;
BString fLabel; BString fLabel;
bool fIsValid;
public: public:
friend class LinearSpec; friend class LinearSpec;
friend class LPSolveInterface;
}; };
+92 -105
View File
@@ -25,6 +25,36 @@
#endif #endif
Constraint::Constraint()
:
fLS(NULL),
fLeftSide(new SummandList),
fOp(kEQ),
fRightSide(0),
fPenaltyNeg(-1),
fPenaltyPos(-1)
{
}
Constraint::Constraint(Constraint* constraint)
:
fLS(NULL),
fLeftSide(new SummandList),
fOp(constraint->Op()),
fRightSide(constraint->RightSide()),
fPenaltyNeg(constraint->PenaltyNeg()),
fPenaltyPos(constraint->PenaltyPos()),
fLabel(constraint->Label())
{
SummandList* orgSummands = constraint->LeftSide();
for (int32 i = 0; i < orgSummands->CountItems(); i++) {
Summand* summand = orgSummands->ItemAt(i);
fLeftSide->AddItem(new Summand(summand));
}
}
/** /**
* Gets the index of the constraint. * Gets the index of the constraint.
* *
@@ -33,6 +63,8 @@
int32 int32
Constraint::Index() const Constraint::Index() const
{ {
if (fLS == NULL)
return -1;
int32 i = fLS->Constraints().IndexOf(this); int32 i = fLS->Constraints().IndexOf(this);
if (i == -1) if (i == -1)
STRACE(("Constraint not part of fLS->Constraints().")); STRACE(("Constraint not part of fLS->Constraints()."));
@@ -59,11 +91,11 @@ Constraint::LeftSide()
* *
* @param summands a BList containing the Summand objects that make up the new left side * @param summands a BList containing the Summand objects that make up the new left side
*/ */
void bool
Constraint::SetLeftSide(SummandList* summands) Constraint::SetLeftSide(SummandList* summands, bool deleteOldSummands)
{ {
if (!fIsValid) if (summands == NULL)
return; debugger("Invalid summands");
// check left side // check left side
for (int32 i = 0; i < summands->CountItems(); i++) { for (int32 i = 0; i < summands->CountItems(); i++) {
@@ -79,76 +111,76 @@ Constraint::SetLeftSide(SummandList* summands)
} }
} }
if (fLS == NULL) {
if (deleteOldSummands)
delete fLeftSide;
fLeftSide = summands; fLeftSide = summands;
fLS->UpdateLeftSide(this); return true;
}
// notify the solver
SummandList oldSummands;
if (fLeftSide != NULL)
oldSummands = *fLeftSide;
if (deleteOldSummands)
delete fLeftSide;
fLeftSide = summands;
if (fLS != NULL)
fLS->UpdateLeftSide(this, &oldSummands);
if (deleteOldSummands) {
for (int32 i = 0; i < oldSummands.CountItems(); i++)
delete oldSummands.ItemAt(i);
}
return true;
} }
void bool
Constraint::SetLeftSide(double coeff1, Variable* var1) Constraint::SetLeftSide(double coeff1, Variable* var1)
{ {
if (!fIsValid) SummandList* list = new SummandList;
return; list->AddItem(new(std::nothrow) Summand(coeff1, var1));
return SetLeftSide(list, true);
for (int i=0; i<fLeftSide->CountItems(); i++)
delete fLeftSide->ItemAt(i);
fLeftSide->MakeEmpty();
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
SetLeftSide(fLeftSide);
} }
void bool
Constraint::SetLeftSide(double coeff1, Variable* var1, Constraint::SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2) double coeff2, Variable* var2)
{ {
if (!fIsValid) SummandList* list = new SummandList;
return; list->AddItem(new(std::nothrow) Summand(coeff1, var1));
list->AddItem(new(std::nothrow) Summand(coeff2, var2));
for (int i=0; i<fLeftSide->CountItems(); i++) return SetLeftSide(list, true);
delete fLeftSide->ItemAt(i);
fLeftSide->MakeEmpty();
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
SetLeftSide(fLeftSide);
} }
void bool
Constraint::SetLeftSide(double coeff1, Variable* var1, Constraint::SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff2, Variable* var2,
double coeff3, Variable* var3) double coeff3, Variable* var3)
{ {
if (!fIsValid) SummandList* list = new SummandList;
return; list->AddItem(new(std::nothrow) Summand(coeff1, var1));
list->AddItem(new(std::nothrow) Summand(coeff2, var2));
for (int i=0; i<fLeftSide->CountItems(); i++) list->AddItem(new(std::nothrow) Summand(coeff3, var3));
delete fLeftSide->ItemAt(i); return SetLeftSide(list, true);
fLeftSide->MakeEmpty();
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
fLeftSide->AddItem(new(std::nothrow) Summand(coeff3, var3));
SetLeftSide(fLeftSide);
} }
void bool
Constraint::SetLeftSide(double coeff1, Variable* var1, Constraint::SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff2, Variable* var2,
double coeff3, Variable* var3, double coeff3, Variable* var3,
double coeff4, Variable* var4) double coeff4, Variable* var4)
{ {
if (!fIsValid) SummandList* list = new SummandList;
return; list->AddItem(new(std::nothrow) Summand(coeff1, var1));
list->AddItem(new(std::nothrow) Summand(coeff2, var2));
for (int i=0; i<fLeftSide->CountItems(); i++) list->AddItem(new(std::nothrow) Summand(coeff3, var3));
delete fLeftSide->ItemAt(i); list->AddItem(new(std::nothrow) Summand(coeff4, var4));
fLeftSide->MakeEmpty(); return SetLeftSide(list, true);
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
fLeftSide->AddItem(new(std::nothrow) Summand(coeff3, var3));
fLeftSide->AddItem(new(std::nothrow) Summand(coeff4, var4));
SetLeftSide(fLeftSide);
} }
@@ -172,10 +204,8 @@ Constraint::Op()
void void
Constraint::SetOp(OperatorType value) Constraint::SetOp(OperatorType value)
{ {
if (!fIsValid)
return;
fOp = value; fOp = value;
if (fLS != NULL)
fLS->UpdateOperator(this); fLS->UpdateOperator(this);
} }
@@ -200,14 +230,12 @@ Constraint::RightSide() const
void void
Constraint::SetRightSide(double value) Constraint::SetRightSide(double value)
{ {
if (!fIsValid)
return;
if (fRightSide == value) if (fRightSide == value)
return; return;
fRightSide = value; fRightSide = value;
if (fLS != NULL)
fLS->UpdateRightSide(this); fLS->UpdateRightSide(this);
} }
@@ -235,7 +263,8 @@ Constraint::SetPenaltyNeg(double value)
{ {
fPenaltyNeg = value; fPenaltyNeg = value;
fLS->UpdateLeftSide(this); if (fLS != NULL)
fLS->UpdatePenalties(this);
} }
@@ -261,7 +290,8 @@ Constraint::SetPenaltyPos(double value)
{ {
fPenaltyPos = value; fPenaltyPos = value;
fLS->UpdateLeftSide(this); if (fLS != NULL)
fLS->UpdatePenalties(this);
} }
@@ -279,49 +309,10 @@ Constraint::SetLabel(const char* label)
} }
/**
* Gets the slack variable for the negative variations.
*
* @return the slack variable for the negative variations
*/
Variable*
Constraint::DNeg() const
{
if (fDNegObjSummand == NULL)
return NULL;
return fDNegObjSummand->Var();
}
/**
* Gets the slack variable for the positive variations.
*
* @return the slack variable for the positive variations
*/
Variable*
Constraint::DPos() const
{
if (fDPosObjSummand == NULL)
return NULL;
return fDPosObjSummand->Var();
}
bool
Constraint::IsSoft() const
{
if (fOp != kEQ)
return false;
if (fPenaltyNeg > 0. || fPenaltyPos > 0.)
return true;
return false;
}
bool bool
Constraint::IsValid() Constraint::IsValid()
{ {
return fIsValid; return fLS != NULL;
} }
@@ -330,11 +321,11 @@ Constraint::Invalidate()
{ {
STRACE(("Constraint::Invalidate() on %d\n", this)); STRACE(("Constraint::Invalidate() on %d\n", this));
if (!fIsValid) if (fLS == NULL)
return; return;
fIsValid = false;
fLS->RemoveConstraint(this, false); fLS->RemoveConstraint(this, false);
fLS = NULL;
} }
@@ -346,7 +337,6 @@ Constraint::ToString() const
string << fLabel; string << fLabel;
string << "(" << (int32)this << "): "; string << "(" << (int32)this << "): ";
if (fIsValid) {
for (int i = 0; i < fLeftSide->CountItems(); i++) { for (int i = 0; i < fLeftSide->CountItems(); i++) {
Summand* s = static_cast<Summand*>(fLeftSide->ItemAt(i)); Summand* s = static_cast<Summand*>(fLeftSide->ItemAt(i));
if (i != 0 && s->Coeff() >= 0) if (i != 0 && s->Coeff() >= 0)
@@ -363,8 +353,7 @@ Constraint::ToString() const
string << (float)fRightSide; string << (float)fRightSide;
string << " PenaltyPos=" << (float)PenaltyPos(); string << " PenaltyPos=" << (float)PenaltyPos();
string << " PenaltyNeg=" << (float)PenaltyNeg(); string << " PenaltyNeg=" << (float)PenaltyNeg();
} else
string << "invalid";
return string; return string;
} }
@@ -384,15 +373,13 @@ Constraint::Constraint(LinearSpec* ls, SummandList* summands, OperatorType op,
double rightSide, double penaltyNeg, double penaltyPos) double rightSide, double penaltyNeg, double penaltyPos)
: :
fLS(ls), fLS(ls),
fLeftSide(NULL),
fOp(op), fOp(op),
fRightSide(rightSide), fRightSide(rightSide),
fPenaltyNeg(penaltyNeg), fPenaltyNeg(penaltyNeg),
fPenaltyPos(penaltyPos), fPenaltyPos(penaltyPos)
fDNegObjSummand(NULL),
fDPosObjSummand(NULL),
fIsValid(true)
{ {
SetLeftSide(summands); SetLeftSide(summands, false);
} }