Author: axeld Date: 2009-10-16 14:13:07 +0200 (Fri, 16 Oct 2009) New Revision: 33609 Changeset: http://dev.haiku-os.org/changeset/33609/haiku Modified: haiku/trunk/headers/libs/linprog/Constraint.h haiku/trunk/headers/libs/linprog/LinearSpec.h haiku/trunk/headers/libs/linprog/Summand.h haiku/trunk/headers/libs/linprog/Variable.h haiku/trunk/src/libs/linprog/Constraint.cpp haiku/trunk/src/libs/linprog/LinearSpec.cpp haiku/trunk/src/libs/linprog/Summand.cpp haiku/trunk/src/libs/linprog/Variable.cpp Log: * Applied patch by Hong Yul Yang to update linprog. Modified: haiku/trunk/headers/libs/linprog/Constraint.h =================================================================== --- haiku/trunk/headers/libs/linprog/Constraint.h 2009-10-16 09:16:17 UTC (rev 33608) +++ haiku/trunk/headers/libs/linprog/Constraint.h 2009-10-16 12:13:07 UTC (rev 33609) @@ -11,6 +11,7 @@ #include "Variable.h" #include "Summand.h" +#include <File.h> #include <List.h> #include <String.h> #include <SupportDefs.h> @@ -29,7 +30,7 @@ public: int32 Index(); - + BList* LeftSide(); void SetLeftSide(BList* summands); void UpdateLeftSide(); @@ -46,17 +47,30 @@ OperatorType Op(); void SetOp(OperatorType value); - double RightSide(); + double RightSide() const; void SetRightSide(double value); - double PenaltyNeg(); + double PenaltyNeg() const; void SetPenaltyNeg(double value); - double PenaltyPos(); + double PenaltyPos() const; void SetPenaltyPos(double value); + const char* Label(); + void SetLabel(const char* label); + + void WriteXML(BFile* file); + Variable* DNeg() const; Variable* DPos() const; - - BString ToString(); + + void SetOwner(void* owner); + void* Owner() const; + + bool IsValid(); + void Invalidate(); + + BString* ToBString(); + const char* ToString(); + ~Constraint(); protected: @@ -71,7 +85,11 @@ double fRightSide; Summand* fDNegObjSummand; Summand* fDPosObjSummand; + void* fOwner; + char* fLabel; + bool fIsValid; + public: friend class LinearSpec; Modified: haiku/trunk/headers/libs/linprog/LinearSpec.h =================================================================== --- haiku/trunk/headers/libs/linprog/LinearSpec.h 2009-10-16 09:16:17 UTC (rev 33608) +++ haiku/trunk/headers/libs/linprog/LinearSpec.h 2009-10-16 12:13:07 UTC (rev 33609) @@ -18,6 +18,7 @@ #include "lp_lib.h" #include <List.h> +#include <String.h> #include <OS.h> #include <SupportDefs.h> #include <math.h> @@ -37,7 +38,7 @@ public: LinearSpec(); - ~LinearSpec(); + virtual ~LinearSpec(); Variable* AddVariable(); @@ -100,6 +101,9 @@ double ObjectiveValue() const; double SolvingTime() const; + BString* ToBString(); + const char* ToString(); + protected: int32 fCountColumns; Modified: haiku/trunk/headers/libs/linprog/Summand.h =================================================================== --- haiku/trunk/headers/libs/linprog/Summand.h 2009-10-16 09:16:17 UTC (rev 33608) +++ haiku/trunk/headers/libs/linprog/Summand.h 2009-10-16 12:13:07 UTC (rev 33609) @@ -29,6 +29,7 @@ private: double fCoeff; Variable* fVar; + bool fUsedInPenaltyFunction; //not set yet }; Modified: haiku/trunk/headers/libs/linprog/Variable.h =================================================================== --- haiku/trunk/headers/libs/linprog/Variable.h 2009-10-16 09:16:17 UTC (rev 33608) +++ haiku/trunk/headers/libs/linprog/Variable.h 2009-10-16 12:13:07 UTC (rev 33609) @@ -7,13 +7,16 @@ #ifndef VARIABLE_H #define VARIABLE_H +#include <File.h> #include <SupportDefs.h> +#include <List.h> namespace LinearProgramming { class Constraint; class LinearSpec; +class Summand; /** * Contains minimum and maximum values. @@ -23,7 +26,6 @@ public: int32 Index(); LinearSpec* LS() const; - void SetLS(LinearSpec* value); double Value() const; void SetValue(double value); double Min() const; @@ -31,24 +33,46 @@ double Max() const; void SetMax(double max); void SetRange(double min, double max); - //~ string ToString(); + + const char* Label(); + void SetLabel(const char* label); + + BString* ToBString(); + const char* ToString(); + Constraint* IsEqual(Variable* var); Constraint* IsSmallerOrEqual(Variable* var); - Constraint* IsGreaterorEqual(Variable* var); + Constraint* IsGreaterOrEqual(Variable* var); + Constraint* IsEqual(Variable* var, + double penaltyNeg, double penaltyPos); + Constraint* IsSmallerOrEqual(Variable* var, + double penaltyNeg, double penaltyPos); + Constraint* IsGreaterOrEqual(Variable* var, + double penaltyNeg, double penaltyPos); + + bool IsValid(); + void Invalidate(); + + virtual ~Variable(); + protected: Variable(LinearSpec* ls); - ~Variable(); private: LinearSpec* fLS; + BList* fUsingSummands; // All Summands that link to this Variable double fValue; double fMin; double fMax; + char* fLabel; + bool fIsValid; + public: - friend class LinearSpec; - friend class Constraint; + friend class LinearSpec; + friend class Constraint; + friend class Summand; }; Modified: haiku/trunk/src/libs/linprog/Constraint.cpp =================================================================== --- haiku/trunk/src/libs/linprog/Constraint.cpp 2009-10-16 09:16:17 UTC (rev 33608) +++ haiku/trunk/src/libs/linprog/Constraint.cpp 2009-10-16 12:13:07 UTC (rev 33609) @@ -11,6 +11,16 @@ #include "lp_lib.h" +// Toggle debug output +//#define DEBUG_CONSTRAINT + +#ifdef DEBUG_CONSTRAINT +# define STRACE(x) debug_printf x +#else +# define STRACE(x) ; +#endif + + /** * Gets the index of the constraint. * @@ -20,8 +30,10 @@ Constraint::Index() { int32 i = fLS->Constraints()->IndexOf(this); - if (i == -1) - printf("Constraint not part of fLS->Constraints()."); + if (i == -1) { + STRACE(("Constraint not part of fLS->Constraints().")); + return -1; + } return i + 1; } @@ -47,6 +59,9 @@ void Constraint::SetLeftSide(BList* summands) { + if (!fIsValid) + return; + fLeftSide = summands; UpdateLeftSide(); } @@ -55,6 +70,9 @@ void Constraint::UpdateLeftSide() { + if (!fIsValid) + return; + double coeffs[fLeftSide->CountItems() + 2]; int varIndexes[fLeftSide->CountItems() + 2]; int32 i; @@ -77,7 +95,7 @@ } if (!set_rowex(fLS->fLP, this->Index(), i, &coeffs[0], &varIndexes[0])) - printf("Error in set_rowex."); + STRACE(("Error in set_rowex.")); fLS->UpdateObjFunction(); fLS->RemovePresolved(); @@ -87,6 +105,9 @@ void Constraint::SetLeftSide(double coeff1, Variable* var1) { + if (!fIsValid) + return; + for (int i=0; i<fLeftSide->CountItems(); i++) delete (Summand*)fLeftSide->ItemAt(i); fLeftSide->MakeEmpty(); @@ -99,6 +120,9 @@ Constraint::SetLeftSide(double coeff1, Variable* var1, double coeff2, Variable* var2) { + if (!fIsValid) + return; + for (int i=0; i<fLeftSide->CountItems(); i++) delete (Summand*)fLeftSide->ItemAt(i); fLeftSide->MakeEmpty(); @@ -113,6 +137,9 @@ double coeff2, Variable* var2, double coeff3, Variable* var3) { + if (!fIsValid) + return; + for (int i=0; i<fLeftSide->CountItems(); i++) delete (Summand*)fLeftSide->ItemAt(i); fLeftSide->MakeEmpty(); @@ -129,6 +156,9 @@ double coeff3, Variable* var3, double coeff4, Variable* var4) { + if (!fIsValid) + return; + for (int i=0; i<fLeftSide->CountItems(); i++) delete (Summand*)fLeftSide->ItemAt(i); fLeftSide->MakeEmpty(); @@ -160,12 +190,15 @@ void Constraint::SetOp(OperatorType value) { + if (!fIsValid) + return; + fOp = value; if (!set_constr_type(fLS->fLP, this->Index(), ((fOp == OperatorType(EQ)) ? EQ : (fOp == OperatorType(GE)) ? GE : LE))) - printf("Error in set_constr_type."); + STRACE(("Error in set_constr_type.")); fLS->RemovePresolved(); } @@ -177,7 +210,7 @@ * @return the constant value that is on the right side of the operator */ double -Constraint::RightSide() +Constraint::RightSide() const { return fRightSide; } @@ -191,9 +224,12 @@ void Constraint::SetRightSide(double value) { + if (!fIsValid) + return; + fRightSide = value; if (!set_rh(fLS->fLP, Index(), fRightSide)) - printf("Error in set_rh."); + STRACE(("Error in set_rh.")); fLS->RemovePresolved(); } @@ -205,7 +241,7 @@ * @return the penalty coefficient */ double -Constraint::PenaltyNeg() +Constraint::PenaltyNeg() const { if (fDNegObjSummand == NULL) return INFINITY; @@ -222,6 +258,9 @@ void Constraint::SetPenaltyNeg(double value) { + if (!fIsValid) + return; + if (fDNegObjSummand == NULL) { fDNegObjSummand = new Summand(value, new Variable(fLS)); fLS->ObjFunction()->AddItem(fDNegObjSummand); @@ -244,7 +283,7 @@ * @return the penalty coefficient */ double -Constraint::PenaltyPos() +Constraint::PenaltyPos() const { if (fDPosObjSummand == NULL) return INFINITY; @@ -261,6 +300,9 @@ void Constraint::SetPenaltyPos(double value) { + if (!fIsValid) + return; + if (fDPosObjSummand == NULL) { fDPosObjSummand = new Summand(value, new Variable(fLS)); fLS->ObjFunction()->AddItem(fDPosObjSummand); @@ -277,6 +319,62 @@ } +const char* +Constraint::Label() +{ + return fLabel; +} + + +void +Constraint::SetLabel(const char* label) +{ + fLabel = (char*) malloc(strlen(label) + 1); + strcpy(fLabel, label); +} + + +void +Constraint::WriteXML(BFile* file) +{ + if (file->IsWritable() && fOwner == NULL) { + char buffer[200]; + + file->Write(buffer, sprintf(buffer, "\t<constraint>\n")); + file->Write(buffer, sprintf(buffer, "\t\t<leftside>\n")); + + Summand* summand; + for (int32 i = 0; i < fLeftSide->CountItems(); i++) { + summand = (Summand*)fLeftSide->ItemAt(i); + file->Write(buffer, sprintf(buffer, "\t\t\t<summand>\n")); + file->Write(buffer, sprintf(buffer, "\t\t\t\t<coeff>%f</coeff>\n", + summand->Coeff())); + BString* varStr = summand->Var()->ToBString(); + file->Write(buffer, sprintf(buffer, "\t\t\t\t<var>%s</var>\n", + varStr->String())); + delete varStr; + file->Write(buffer, sprintf(buffer, "\t\t\t</summand>\n")); + } + + file->Write(buffer, sprintf(buffer, "\t\t</leftside>\n")); + + char* op; + if (fOp == OperatorType(EQ)) + op = "EQ"; + else if (fOp == OperatorType(LE)) + op = "LE"; + else if (fOp == OperatorType(GE)) + op = "GE"; + + file->Write(buffer, sprintf(buffer, "\t\t<op>%s</op>\n", op)); + file->Write(buffer, sprintf(buffer, "\t\t<rightside>%f</rightside>\n", fRightSide)); + //~ file->Write(buffer, sprintf(buffer, "\t\t<penaltyneg>%s</penaltyneg>\n", PenaltyNeg())); + //~ file->Write(buffer, sprintf(buffer, "\t\t<penaltypos>%s</penaltypos>\n", PenaltyPos())); + file->Write(buffer, sprintf(buffer, "\t</constraint>\n")); + } +} + + /** * Gets the slack variable for the negative variations. * @@ -305,17 +403,114 @@ } +void +Constraint::SetOwner(void* owner) +{ + fOwner = owner; +} + + +void* +Constraint::Owner() const +{ + return fOwner; +} + + +bool +Constraint::IsValid() +{ + return fIsValid; +} + + +void +Constraint::Invalidate() +{ + STRACE(("Constraint::Invalidate() on %d\n", this)); + + if (!fIsValid) + return; + + fIsValid = false; + + for (int32 i = 0; i < fLeftSide->CountItems(); i++) + delete (Summand*)fLeftSide->ItemAt(i); + delete fLeftSide; + fLeftSide = NULL; + + if (fDNegObjSummand) { + fLS->ObjFunction()->RemoveItem(fDNegObjSummand); + delete fDNegObjSummand->Var(); + delete fDNegObjSummand; + fDNegObjSummand = NULL; + } + if (fDPosObjSummand) { + fLS->ObjFunction()->RemoveItem(fDPosObjSummand); + delete fDPosObjSummand->Var(); + delete fDPosObjSummand; + fDPosObjSummand = NULL; + } + + del_constraint(fLS->fLP, this->Index()); + fLS->Constraints()->RemoveItem(this); +} + + +BString* +Constraint::ToBString() +{ + BString* str = new BString(); + *str << "Constraint "; + if (fLabel) + *str << fLabel; + *str << "(" << (int32)this << "): "; + + if (fIsValid) { + for (int i = 0; i < fLeftSide->CountItems(); i++) { + Summand* s = static_cast<Summand*>(fLeftSide->ItemAt(i)); + *str << (float)s->Coeff() << "*"; + BString* varString = s->Var()->ToBString(); + *str << *varString << " "; + delete varString; + } + *str << ((fOp == OperatorType(EQ)) ? "== " + : (fOp == OperatorType(GE)) ? ">= " + : (fOp == OperatorType(LE)) ? "<= " + : "?? "); + *str << (float)fRightSide; + *str << " PenaltyPos=" << (float)PenaltyPos(); + *str << " PenaltyNeg=" << (float)PenaltyNeg(); + } else + *str << "invalid"; + return str; +} + + +const char* +Constraint::ToString() +{ + BString* str = ToBString(); + char* result = (char*) malloc(str->Length() + 1); + str->CopyInto(result, 0, str->Length()); + delete str; + return result; +} + + /** * Constructor. */ Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op, double rightSide, double penaltyNeg, double penaltyPos) + : fLS(ls), + fLeftSide(summands), + fOp(op), + fRightSide(rightSide), + fOwner(NULL), + fLabel(NULL), + fIsValid(true) { - fLS = ls; - fLeftSide = summands; - fOp = op; - fRightSide = rightSide; - double coeffs[summands->CountItems() + 2]; int varIndexes[summands->CountItems() + 2]; int32 i; @@ -327,8 +522,8 @@ if (penaltyNeg != INFINITY && fOp != OperatorType(LE)) { - fDNegObjSummand = new Summand(penaltyNeg, new Variable(ls)); - ls->fObjFunction->AddItem(fDNegObjSummand); + fDNegObjSummand = new Summand(penaltyNeg, new Variable(fLS)); + fLS->fObjFunction->AddItem(fDNegObjSummand); varIndexes[i] = fDNegObjSummand->Var()->Index(); coeffs[i] = 1.0; i++; @@ -338,8 +533,8 @@ if (penaltyPos != INFINITY && fOp != OperatorType(GE)) { - fDPosObjSummand = new Summand(penaltyPos, new Variable(ls)); - ls->fObjFunction->AddItem(fDPosObjSummand); + fDPosObjSummand = new Summand(penaltyPos, new Variable(fLS)); + fLS->fObjFunction->AddItem(fDPosObjSummand); varIndexes[i] = fDPosObjSummand->Var()->Index(); coeffs[i] = -1.0; i++; @@ -347,14 +542,14 @@ else fDPosObjSummand = NULL; - if (!add_constraintex(ls->fLP, i, &coeffs[0], &varIndexes[0], + if (!add_constraintex(fLS->fLP, i, &coeffs[0], &varIndexes[0], ((fOp == OperatorType(EQ)) ? EQ : (fOp == OperatorType(GE)) ? GE : LE), rightSide)) - printf("Error in add_constraintex."); + STRACE(("Error in add_constraintex.")); fLS->UpdateObjFunction(); - ls->Constraints()->AddItem(this); + fLS->Constraints()->AddItem(this); } @@ -364,20 +559,6 @@ */ Constraint::~Constraint() { - for (int i=0; i<fLeftSide->CountItems(); i++) - delete (Summand*)fLeftSide->ItemAt(i); - delete fLeftSide; - - if (fDNegObjSummand != NULL) { - delete fDNegObjSummand->Var(); - delete fDNegObjSummand; - } - if (fDPosObjSummand != NULL) { - delete fDPosObjSummand->Var(); - delete fDPosObjSummand; - } - - del_constraint(fLS->fLP, Index()); - fLS->Constraints()->RemoveItem(this); + Invalidate(); } Modified: haiku/trunk/src/libs/linprog/LinearSpec.cpp =================================================================== --- haiku/trunk/src/libs/linprog/LinearSpec.cpp 2009-10-16 09:16:17 UTC (rev 33608) +++ haiku/trunk/src/libs/linprog/LinearSpec.cpp 2009-10-16 12:13:07 UTC (rev 33609) @@ -12,21 +12,20 @@ * Creates a new specification for a linear programming problem. */ LinearSpec::LinearSpec() + : fCountColumns(0), + fLpPresolved(NULL), + fOptimization(MINIMIZE), + fObjFunction(new BList()), + fVariables(new BList()), + fConstraints(new BList()), + fResult(ERROR), + fObjectiveValue(NAN), + fSolvingTime(NAN) { fLP = make_lp(0, 0); if (fLP == NULL) printf("Couldn't construct a new model."); set_verbose(fLP, 1); - - fObjFunction = new BList(); - fVariables = new BList(); - fConstraints = new BList(); - fCountColumns = 0; - fLpPresolved = NULL; - fOptimization = MINIMIZE; - fResult = ERROR; - fObjectiveValue = NAN; - fSolvingTime = NAN; } @@ -38,12 +37,11 @@ LinearSpec::~LinearSpec() { RemovePresolved(); - int i; - for (i=0; i<fConstraints->CountItems(); i++) + for (int32 i=0; i<fConstraints->CountItems(); i++) delete (Constraint*)fConstraints->ItemAt(i); - for (i=0; i<fObjFunction->CountItems(); i++) + for (int32 i=0; i<fObjFunction->CountItems(); i++) delete (Summand*)fObjFunction->ItemAt(i); - for (i=0; i<fVariables->CountItems(); i++) + for (int32 i=0; i<fVariables->CountItems(); i++) delete (Variable*)fVariables->ItemAt(i); delete_lp(fLP); } @@ -496,7 +494,7 @@ /** * Gets the number of columns. - * + * * @return the number of columns */ int32 @@ -595,3 +593,55 @@ return fSolvingTime; } + +BString* +LinearSpec::ToBString() +{ + BString* str = new BString(); + *str << "LinearSpec " << (int32)this << ":\n"; + for (int i = 0; i < fVariables->CountItems(); i++) { + Variable* variable = static_cast<Variable*>(fVariables->ItemAt(i)); + BString* vStr = variable->ToBString(); + *str << *vStr << "=" << (float)variable->Value() << " "; + delete vStr; + } + *str << "\n"; + for (int i = 0; i < fConstraints->CountItems(); i++) { + Constraint* c = static_cast<Constraint*>(fConstraints->ItemAt(i)); + BString* cStr = c->ToBString(); + *str << i << ": " << *cStr; + delete cStr; + *str << "\n"; + } + *str << "Result="; + if (fResult==-1) + *str << "ERROR"; + else if (fResult==0) + *str << "OPTIMAL"; + else if (fResult==1) + *str << "SUBOPTIMAL"; + else if (fResult==2) + *str << "INFEASIBLE"; + else if (fResult==3) + *str << "UNBOUNDED"; + else if (fResult==4) + *str << "DEGENERATE"; + else if (fResult==5) + *str << "NUMFAILURE"; + else + *str << fResult; + *str << " SolvingTime=" << (float)fSolvingTime << "ms"; + return str; +} + + +const char* +LinearSpec::ToString() +{ + BString* str = ToBString(); + char* result = (char*) malloc(str->Length() + 1); + str->CopyInto(result, 0, str->Length()); + delete str; + return result; +} + Modified: haiku/trunk/src/libs/linprog/Summand.cpp =================================================================== --- haiku/trunk/src/libs/linprog/Summand.cpp 2009-10-16 09:16:17 UTC (rev 33608) +++ haiku/trunk/src/libs/linprog/Summand.cpp 2009-10-16 12:13:07 UTC (rev 33609) @@ -62,6 +62,7 @@ */ Summand::~Summand() { + fVar->fUsingSummands->RemoveItem(this); } @@ -72,5 +73,8 @@ { fCoeff = coeff; fVar = var; + fUsedInPenaltyFunction = false; + fVar->fUsingSummands->AddItem(this); + } Modified: haiku/trunk/src/libs/linprog/Variable.cpp =================================================================== --- haiku/trunk/src/libs/linprog/Variable.cpp 2009-10-16 09:16:17 UTC (rev 33608) +++ haiku/trunk/src/libs/linprog/Variable.cpp 2009-10-16 12:13:07 UTC (rev 33609) @@ -14,6 +14,16 @@ #include <float.h> // for DBL_MAX +// Toggle debug output +//#define DEBUG_VARIABLE + +#ifdef DEBUG_VARIABLE +# define STRACE(x) debug_printf x +#else +# define STRACE(x) ; +#endif + + /** * Gets index of the variable. * @@ -23,8 +33,10 @@ Variable::Index() { int32 i = fLS->Variables()->IndexOf(this); - if (i == -1) + if (i == -1) { printf("Variable not part of fLS->Variables()."); + return -1; + } return i + 1; } @@ -42,18 +54,6 @@ /** - * Sets the current linear specification. - * - * @param value the current linear specification - */ -void -Variable::SetLS(LinearSpec* value) -{ - fLS = value; -} - - -/** * Gets the value. * * @return the value @@ -97,6 +97,9 @@ void Variable::SetMin(double min) { + if (!fIsValid) + return; + fMin = min; set_bounds(fLS->fLP, this->Index(), fMin, fMax); } @@ -122,6 +125,9 @@ void Variable::SetMax(double max) { + if (!fIsValid) + return; + fMax = max; set_bounds(fLS->fLP, this->Index(), fMin, fMax); } @@ -136,23 +142,66 @@ void Variable::SetRange(double min, double max) { + if (!fIsValid) + return; + fMin = min; fMax = max; set_bounds(fLS->fLP, this->Index(), fMin, fMax); } +const char* +Variable::Label() +{ + return fLabel; +} + + +void +Variable::SetLabel(const char* label) +{ + fLabel = (char*) malloc(strlen(label) + 1); + strcpy(fLabel, label); +} + + /** * Returns index of the variable as String. * E.g. "Var2" * * @return the <code>String</code> index of the variable */ -//~ string Variable::ToString() { - //~ return "Var" + Index(); -//~ } +BString* +Variable::ToBString() +{ + BString* str = new BString(); + if (fLabel) { + *str << fLabel; + if (!fIsValid) + *str << "(invalid)"; + } else { + *str << "Var"; + if (!fIsValid) + *str << "(invalid," << (int32)this << ")"; + else + *str << Index(); + } + return str; +} +const char* +Variable::ToString() +{ + BString* str = ToBString(); + char* result = (char*) malloc(str->Length() + 1); + str->CopyInto(result, 0, str->Length()); + delete str; + return result; +} + + /** * Adds a constraint that sets this variable equal to the given one. * @@ -162,6 +211,9 @@ Constraint* Variable::IsEqual(Variable* var) { + if (!fIsValid) + return NULL; + return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0); } @@ -175,6 +227,9 @@ Constraint* Variable::IsSmallerOrEqual(Variable* var) { + if (!fIsValid) + return NULL; + return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0); } @@ -186,28 +241,111 @@ * @return the new constraint */ Constraint* -Variable::IsGreaterorEqual(Variable* var) +Variable::IsGreaterOrEqual(Variable* var) { + if (!fIsValid) + return NULL; + return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0); } +Constraint* +Variable::IsEqual(Variable* var, double penaltyNeg, double penaltyPos) +{ + if (!fIsValid) + return NULL; + + return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0, + penaltyNeg, penaltyPos); +} + + +Constraint* +Variable::IsSmallerOrEqual(Variable* var, double penaltyNeg, double penaltyPos) +{ + if (!fIsValid) + return NULL; + + return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0, + penaltyNeg, penaltyPos); +} + + +Constraint* +Variable::IsGreaterOrEqual(Variable* var, double penaltyNeg, double penaltyPos) +{ + if (!fIsValid) + return NULL; + + return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0, + penaltyNeg, penaltyPos); +} + + +bool +Variable::IsValid() +{ + return fIsValid; +} + + +void +Variable::Invalidate() +{ + STRACE(("Variable::Invalidate() on %s\n", ToString())); + + if (!fIsValid) + return; + + fIsValid = false; + del_column(fLS->fLP, Index()); + fLS->Variables()->RemoveItem(this); + + // invalidate all constraints that use this variable + BList* markedForInvalidation = new BList(); + BList* constraints = fLS->Constraints(); + for (int i = 0; i < constraints->CountItems(); i++) { + Constraint* constraint = static_cast<Constraint*>( + constraints->ItemAt(i)); + + if (!constraint->IsValid()) + continue; [... truncated: 58 lines follow ...]