* Applied patch by Hong Yul Yang to update linprog.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33609 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-10-16 12:13:07 +00:00
parent 98b4079944
commit 676ef01ba7
8 changed files with 511 additions and 90 deletions
+24 -6
View File
@@ -11,6 +11,7 @@
#include "Variable.h" #include "Variable.h"
#include "Summand.h" #include "Summand.h"
#include <File.h>
#include <List.h> #include <List.h>
#include <String.h> #include <String.h>
#include <SupportDefs.h> #include <SupportDefs.h>
@@ -29,7 +30,7 @@ class Constraint {
public: public:
int32 Index(); int32 Index();
BList* LeftSide(); BList* LeftSide();
void SetLeftSide(BList* summands); void SetLeftSide(BList* summands);
void UpdateLeftSide(); void UpdateLeftSide();
@@ -46,17 +47,30 @@ public:
OperatorType Op(); OperatorType Op();
void SetOp(OperatorType value); void SetOp(OperatorType value);
double RightSide(); double RightSide() const;
void SetRightSide(double value); void SetRightSide(double value);
double PenaltyNeg(); double PenaltyNeg() const;
void SetPenaltyNeg(double value); void SetPenaltyNeg(double value);
double PenaltyPos(); double PenaltyPos() const;
void SetPenaltyPos(double value); void SetPenaltyPos(double value);
const char* Label();
void SetLabel(const char* label);
void WriteXML(BFile* file);
Variable* DNeg() const; Variable* DNeg() const;
Variable* DPos() const; Variable* DPos() const;
BString ToString(); void SetOwner(void* owner);
void* Owner() const;
bool IsValid();
void Invalidate();
BString* ToBString();
const char* ToString();
~Constraint(); ~Constraint();
protected: protected:
@@ -71,6 +85,10 @@ private:
double fRightSide; double fRightSide;
Summand* fDNegObjSummand; Summand* fDNegObjSummand;
Summand* fDPosObjSummand; Summand* fDPosObjSummand;
void* fOwner;
char* fLabel;
bool fIsValid;
public: public:
friend class LinearSpec; friend class LinearSpec;
+5 -1
View File
@@ -18,6 +18,7 @@
#include "lp_lib.h" #include "lp_lib.h"
#include <List.h> #include <List.h>
#include <String.h>
#include <OS.h> #include <OS.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include <math.h> #include <math.h>
@@ -37,7 +38,7 @@ class LinearSpec {
public: public:
LinearSpec(); LinearSpec();
~LinearSpec(); virtual ~LinearSpec();
Variable* AddVariable(); Variable* AddVariable();
@@ -100,6 +101,9 @@ public:
double ObjectiveValue() const; double ObjectiveValue() const;
double SolvingTime() const; double SolvingTime() const;
BString* ToBString();
const char* ToString();
protected: protected:
int32 fCountColumns; int32 fCountColumns;
+1
View File
@@ -29,6 +29,7 @@ public:
private: private:
double fCoeff; double fCoeff;
Variable* fVar; Variable* fVar;
bool fUsedInPenaltyFunction; //not set yet
}; };
+30 -6
View File
@@ -7,13 +7,16 @@
#ifndef VARIABLE_H #ifndef VARIABLE_H
#define VARIABLE_H #define VARIABLE_H
#include <File.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include <List.h>
namespace LinearProgramming { namespace LinearProgramming {
class Constraint; class Constraint;
class LinearSpec; class LinearSpec;
class Summand;
/** /**
* Contains minimum and maximum values. * Contains minimum and maximum values.
@@ -23,7 +26,6 @@ class Variable {
public: public:
int32 Index(); int32 Index();
LinearSpec* LS() const; LinearSpec* LS() const;
void SetLS(LinearSpec* value);
double Value() const; double Value() const;
void SetValue(double value); void SetValue(double value);
double Min() const; double Min() const;
@@ -31,24 +33,46 @@ public:
double Max() const; double Max() const;
void SetMax(double max); void SetMax(double max);
void SetRange(double min, 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* IsEqual(Variable* var);
Constraint* IsSmallerOrEqual(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: protected:
Variable(LinearSpec* ls); Variable(LinearSpec* ls);
~Variable();
private: private:
LinearSpec* fLS; LinearSpec* fLS;
BList* fUsingSummands; // All Summands that link to this Variable
double fValue; double fValue;
double fMin; double fMin;
double fMax; double fMax;
char* fLabel;
bool fIsValid;
public: public:
friend class LinearSpec; friend class LinearSpec;
friend class Constraint; friend class Constraint;
friend class Summand;
}; };
+216 -35
View File
@@ -11,6 +11,16 @@
#include "lp_lib.h" #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. * Gets the index of the constraint.
* *
@@ -20,8 +30,10 @@ int32
Constraint::Index() Constraint::Index()
{ {
int32 i = fLS->Constraints()->IndexOf(this); int32 i = fLS->Constraints()->IndexOf(this);
if (i == -1) if (i == -1) {
printf("Constraint not part of fLS->Constraints()."); STRACE(("Constraint not part of fLS->Constraints()."));
return -1;
}
return i + 1; return i + 1;
} }
@@ -47,6 +59,9 @@ Constraint::LeftSide()
void void
Constraint::SetLeftSide(BList* summands) Constraint::SetLeftSide(BList* summands)
{ {
if (!fIsValid)
return;
fLeftSide = summands; fLeftSide = summands;
UpdateLeftSide(); UpdateLeftSide();
} }
@@ -55,6 +70,9 @@ Constraint::SetLeftSide(BList* summands)
void void
Constraint::UpdateLeftSide() Constraint::UpdateLeftSide()
{ {
if (!fIsValid)
return;
double coeffs[fLeftSide->CountItems() + 2]; double coeffs[fLeftSide->CountItems() + 2];
int varIndexes[fLeftSide->CountItems() + 2]; int varIndexes[fLeftSide->CountItems() + 2];
int32 i; int32 i;
@@ -77,7 +95,7 @@ Constraint::UpdateLeftSide()
} }
if (!set_rowex(fLS->fLP, this->Index(), i, &coeffs[0], &varIndexes[0])) 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->UpdateObjFunction();
fLS->RemovePresolved(); fLS->RemovePresolved();
@@ -87,6 +105,9 @@ Constraint::UpdateLeftSide()
void void
Constraint::SetLeftSide(double coeff1, Variable* var1) Constraint::SetLeftSide(double coeff1, Variable* var1)
{ {
if (!fIsValid)
return;
for (int i=0; i<fLeftSide->CountItems(); i++) for (int i=0; i<fLeftSide->CountItems(); i++)
delete (Summand*)fLeftSide->ItemAt(i); delete (Summand*)fLeftSide->ItemAt(i);
fLeftSide->MakeEmpty(); fLeftSide->MakeEmpty();
@@ -99,6 +120,9 @@ void
Constraint::SetLeftSide(double coeff1, Variable* var1, Constraint::SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2) double coeff2, Variable* var2)
{ {
if (!fIsValid)
return;
for (int i=0; i<fLeftSide->CountItems(); i++) for (int i=0; i<fLeftSide->CountItems(); i++)
delete (Summand*)fLeftSide->ItemAt(i); delete (Summand*)fLeftSide->ItemAt(i);
fLeftSide->MakeEmpty(); fLeftSide->MakeEmpty();
@@ -113,6 +137,9 @@ Constraint::SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff2, Variable* var2,
double coeff3, Variable* var3) double coeff3, Variable* var3)
{ {
if (!fIsValid)
return;
for (int i=0; i<fLeftSide->CountItems(); i++) for (int i=0; i<fLeftSide->CountItems(); i++)
delete (Summand*)fLeftSide->ItemAt(i); delete (Summand*)fLeftSide->ItemAt(i);
fLeftSide->MakeEmpty(); fLeftSide->MakeEmpty();
@@ -129,6 +156,9 @@ Constraint::SetLeftSide(double coeff1, Variable* var1,
double coeff3, Variable* var3, double coeff3, Variable* var3,
double coeff4, Variable* var4) double coeff4, Variable* var4)
{ {
if (!fIsValid)
return;
for (int i=0; i<fLeftSide->CountItems(); i++) for (int i=0; i<fLeftSide->CountItems(); i++)
delete (Summand*)fLeftSide->ItemAt(i); delete (Summand*)fLeftSide->ItemAt(i);
fLeftSide->MakeEmpty(); fLeftSide->MakeEmpty();
@@ -160,12 +190,15 @@ Constraint::Op()
void void
Constraint::SetOp(OperatorType value) Constraint::SetOp(OperatorType value)
{ {
if (!fIsValid)
return;
fOp = value; fOp = value;
if (!set_constr_type(fLS->fLP, this->Index(), if (!set_constr_type(fLS->fLP, this->Index(),
((fOp == OperatorType(EQ)) ? EQ ((fOp == OperatorType(EQ)) ? EQ
: (fOp == OperatorType(GE)) ? GE : (fOp == OperatorType(GE)) ? GE
: LE))) : LE)))
printf("Error in set_constr_type."); STRACE(("Error in set_constr_type."));
fLS->RemovePresolved(); fLS->RemovePresolved();
} }
@@ -177,7 +210,7 @@ Constraint::SetOp(OperatorType value)
* @return the constant value that is on the right side of the operator * @return the constant value that is on the right side of the operator
*/ */
double double
Constraint::RightSide() Constraint::RightSide() const
{ {
return fRightSide; return fRightSide;
} }
@@ -191,9 +224,12 @@ Constraint::RightSide()
void void
Constraint::SetRightSide(double value) Constraint::SetRightSide(double value)
{ {
if (!fIsValid)
return;
fRightSide = value; fRightSide = value;
if (!set_rh(fLS->fLP, Index(), fRightSide)) if (!set_rh(fLS->fLP, Index(), fRightSide))
printf("Error in set_rh."); STRACE(("Error in set_rh."));
fLS->RemovePresolved(); fLS->RemovePresolved();
} }
@@ -205,7 +241,7 @@ Constraint::SetRightSide(double value)
* @return the penalty coefficient * @return the penalty coefficient
*/ */
double double
Constraint::PenaltyNeg() Constraint::PenaltyNeg() const
{ {
if (fDNegObjSummand == NULL) if (fDNegObjSummand == NULL)
return INFINITY; return INFINITY;
@@ -222,6 +258,9 @@ Constraint::PenaltyNeg()
void void
Constraint::SetPenaltyNeg(double value) Constraint::SetPenaltyNeg(double value)
{ {
if (!fIsValid)
return;
if (fDNegObjSummand == NULL) { if (fDNegObjSummand == NULL) {
fDNegObjSummand = new Summand(value, new Variable(fLS)); fDNegObjSummand = new Summand(value, new Variable(fLS));
fLS->ObjFunction()->AddItem(fDNegObjSummand); fLS->ObjFunction()->AddItem(fDNegObjSummand);
@@ -244,7 +283,7 @@ Constraint::SetPenaltyNeg(double value)
* @return the penalty coefficient * @return the penalty coefficient
*/ */
double double
Constraint::PenaltyPos() Constraint::PenaltyPos() const
{ {
if (fDPosObjSummand == NULL) if (fDPosObjSummand == NULL)
return INFINITY; return INFINITY;
@@ -261,6 +300,9 @@ Constraint::PenaltyPos()
void void
Constraint::SetPenaltyPos(double value) Constraint::SetPenaltyPos(double value)
{ {
if (!fIsValid)
return;
if (fDPosObjSummand == NULL) { if (fDPosObjSummand == NULL) {
fDPosObjSummand = new Summand(value, new Variable(fLS)); fDPosObjSummand = new Summand(value, new Variable(fLS));
fLS->ObjFunction()->AddItem(fDPosObjSummand); fLS->ObjFunction()->AddItem(fDPosObjSummand);
@@ -277,6 +319,62 @@ Constraint::SetPenaltyPos(double value)
} }
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. * Gets the slack variable for the negative variations.
* *
@@ -305,17 +403,114 @@ Constraint::DPos() const
} }
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. * Constructor.
*/ */
Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op, Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
double rightSide, double penaltyNeg, double penaltyPos) 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]; double coeffs[summands->CountItems() + 2];
int varIndexes[summands->CountItems() + 2]; int varIndexes[summands->CountItems() + 2];
int32 i; int32 i;
@@ -327,8 +522,8 @@ Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
if (penaltyNeg != INFINITY if (penaltyNeg != INFINITY
&& fOp != OperatorType(LE)) { && fOp != OperatorType(LE)) {
fDNegObjSummand = new Summand(penaltyNeg, new Variable(ls)); fDNegObjSummand = new Summand(penaltyNeg, new Variable(fLS));
ls->fObjFunction->AddItem(fDNegObjSummand); fLS->fObjFunction->AddItem(fDNegObjSummand);
varIndexes[i] = fDNegObjSummand->Var()->Index(); varIndexes[i] = fDNegObjSummand->Var()->Index();
coeffs[i] = 1.0; coeffs[i] = 1.0;
i++; i++;
@@ -338,8 +533,8 @@ Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
if (penaltyPos != INFINITY if (penaltyPos != INFINITY
&& fOp != OperatorType(GE)) { && fOp != OperatorType(GE)) {
fDPosObjSummand = new Summand(penaltyPos, new Variable(ls)); fDPosObjSummand = new Summand(penaltyPos, new Variable(fLS));
ls->fObjFunction->AddItem(fDPosObjSummand); fLS->fObjFunction->AddItem(fDPosObjSummand);
varIndexes[i] = fDPosObjSummand->Var()->Index(); varIndexes[i] = fDPosObjSummand->Var()->Index();
coeffs[i] = -1.0; coeffs[i] = -1.0;
i++; i++;
@@ -347,14 +542,14 @@ Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
else else
fDPosObjSummand = NULL; 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(EQ)) ? EQ
: (fOp == OperatorType(GE)) ? GE : (fOp == OperatorType(GE)) ? GE
: LE), rightSide)) : LE), rightSide))
printf("Error in add_constraintex."); STRACE(("Error in add_constraintex."));
fLS->UpdateObjFunction(); fLS->UpdateObjFunction();
ls->Constraints()->AddItem(this); fLS->Constraints()->AddItem(this);
} }
@@ -364,20 +559,6 @@ Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
*/ */
Constraint::~Constraint() Constraint::~Constraint()
{ {
for (int i=0; i<fLeftSide->CountItems(); i++) Invalidate();
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);
} }
+65 -15
View File
@@ -12,21 +12,20 @@
* Creates a new specification for a linear programming problem. * Creates a new specification for a linear programming problem.
*/ */
LinearSpec::LinearSpec() 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); fLP = make_lp(0, 0);
if (fLP == NULL) if (fLP == NULL)
printf("Couldn't construct a new model."); printf("Couldn't construct a new model.");
set_verbose(fLP, 1); 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()
LinearSpec::~LinearSpec() LinearSpec::~LinearSpec()
{ {
RemovePresolved(); RemovePresolved();
int i; for (int32 i=0; i<fConstraints->CountItems(); i++)
for (i=0; i<fConstraints->CountItems(); i++)
delete (Constraint*)fConstraints->ItemAt(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); 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 (Variable*)fVariables->ItemAt(i);
delete_lp(fLP); delete_lp(fLP);
} }
@@ -496,7 +494,7 @@ LinearSpec::Save(char* fname)
/** /**
* Gets the number of columns. * Gets the number of columns.
* *
* @return the number of columns * @return the number of columns
*/ */
int32 int32
@@ -595,3 +593,55 @@ LinearSpec::SolvingTime() const
return fSolvingTime; 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;
}
+4
View File
@@ -62,6 +62,7 @@ Summand::SetVar(Variable* var)
*/ */
Summand::~Summand() Summand::~Summand()
{ {
fVar->fUsingSummands->RemoveItem(this);
} }
@@ -72,5 +73,8 @@ Summand::Summand(double coeff, Variable* var)
{ {
fCoeff = coeff; fCoeff = coeff;
fVar = var; fVar = var;
fUsedInPenaltyFunction = false;
fVar->fUsingSummands->AddItem(this);
} }
+166 -27
View File
@@ -14,6 +14,16 @@
#include <float.h> // for DBL_MAX #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. * Gets index of the variable.
* *
@@ -23,8 +33,10 @@ int32
Variable::Index() Variable::Index()
{ {
int32 i = fLS->Variables()->IndexOf(this); int32 i = fLS->Variables()->IndexOf(this);
if (i == -1) if (i == -1) {
printf("Variable not part of fLS->Variables()."); printf("Variable not part of fLS->Variables().");
return -1;
}
return i + 1; return i + 1;
} }
@@ -41,18 +53,6 @@ Variable::LS() const
} }
/**
* Sets the current linear specification.
*
* @param value the current linear specification
*/
void
Variable::SetLS(LinearSpec* value)
{
fLS = value;
}
/** /**
* Gets the value. * Gets the value.
* *
@@ -97,6 +97,9 @@ Variable::Min() const
void void
Variable::SetMin(double min) Variable::SetMin(double min)
{ {
if (!fIsValid)
return;
fMin = min; fMin = min;
set_bounds(fLS->fLP, this->Index(), fMin, fMax); set_bounds(fLS->fLP, this->Index(), fMin, fMax);
} }
@@ -122,6 +125,9 @@ Variable::Max() const
void void
Variable::SetMax(double max) Variable::SetMax(double max)
{ {
if (!fIsValid)
return;
fMax = max; fMax = max;
set_bounds(fLS->fLP, this->Index(), fMin, fMax); set_bounds(fLS->fLP, this->Index(), fMin, fMax);
} }
@@ -136,21 +142,64 @@ Variable::SetMax(double max)
void void
Variable::SetRange(double min, double max) Variable::SetRange(double min, double max)
{ {
if (!fIsValid)
return;
fMin = min; fMin = min;
fMax = max; fMax = max;
set_bounds(fLS->fLP, this->Index(), fMin, fMax); 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. * Returns index of the variable as String.
* E.g. "Var2" * E.g. "Var2"
* *
* @return the <code>String</code> index of the variable * @return the <code>String</code> index of the variable
*/ */
//~ string Variable::ToString() { BString*
//~ return "Var" + Index(); 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;
}
/** /**
@@ -162,6 +211,9 @@ Variable::SetRange(double min, double max)
Constraint* Constraint*
Variable::IsEqual(Variable* var) Variable::IsEqual(Variable* var)
{ {
if (!fIsValid)
return NULL;
return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0); return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0);
} }
@@ -175,6 +227,9 @@ Variable::IsEqual(Variable* var)
Constraint* Constraint*
Variable::IsSmallerOrEqual(Variable* var) Variable::IsSmallerOrEqual(Variable* var)
{ {
if (!fIsValid)
return NULL;
return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0); return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0);
} }
@@ -186,28 +241,111 @@ Variable::IsSmallerOrEqual(Variable* var)
* @return the new constraint * @return the new constraint
*/ */
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); 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;
BList* summands = constraint->LeftSide();
for (int j = 0; j < summands->CountItems(); j++) {
Summand* summand = static_cast<Summand*>(summands->ItemAt(j));
if (summand->Var() == this) {
markedForInvalidation->AddItem(constraint);
break;
}
}
}
for (int i = 0; i < markedForInvalidation->CountItems(); i++)
static_cast<Constraint*>(markedForInvalidation->ItemAt(i))
->Invalidate();
delete markedForInvalidation;
}
/** /**
* Constructor. * Constructor.
*/ */
Variable::Variable(LinearSpec* ls) Variable::Variable(LinearSpec* ls)
: fLS(ls),
fUsingSummands(new BList()),
fValue(NAN),
fMin(0),
fMax(DBL_MAX),
fLabel(NULL),
fIsValid(true)
{ {
fMin = 0; fLS->Variables()->AddItem(this);
fMax = DBL_MAX;
fValue = NULL;
fLS = ls;
ls->Variables()->AddItem(this); if (fLS->Variables()->CountItems() > fLS->CountColumns()) {
if (ls->Variables()->CountItems() > ls->CountColumns()) {
double d = 0; double d = 0;
int i = 0; int i = 0;
if (!add_columnex(ls->fLP, 0, &d, &i)) if (!add_columnex(fLS->fLP, 0, &d, &i))
printf("Error in add_columnex."); printf("Error in add_columnex.");
} }
} }
@@ -219,7 +357,8 @@ Variable::Variable(LinearSpec* ls)
*/ */
Variable::~Variable() Variable::~Variable()
{ {
del_column(fLS->fLP, this->Index()); Invalidate();
fLS->Variables()->RemoveItem(this); free(fLabel);
delete fUsingSummands;
} }