2008-02-25 04:54:05 +03:00
|
|
|
/*
|
|
|
|
* Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz
|
|
|
|
* Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*/
|
|
|
|
|
2008-02-06 13:51:44 +03:00
|
|
|
#include "Variable.h"
|
|
|
|
#include "Constraint.h"
|
|
|
|
#include "LinearSpec.h"
|
|
|
|
#include "OperatorType.h"
|
|
|
|
|
|
|
|
#include "lp_lib.h"
|
|
|
|
|
|
|
|
#include <float.h> // for DBL_MAX
|
|
|
|
|
|
|
|
|
2009-10-16 16:13:07 +04:00
|
|
|
// Toggle debug output
|
|
|
|
//#define DEBUG_VARIABLE
|
|
|
|
|
|
|
|
#ifdef DEBUG_VARIABLE
|
|
|
|
# define STRACE(x) debug_printf x
|
|
|
|
#else
|
|
|
|
# define STRACE(x) ;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2008-02-06 13:51:44 +03:00
|
|
|
/**
|
|
|
|
* Gets index of the variable.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @return the index of the variable
|
|
|
|
*/
|
|
|
|
int32
|
2009-12-06 16:14:45 +03:00
|
|
|
Variable::Index() const
|
2008-02-06 13:51:44 +03:00
|
|
|
{
|
|
|
|
int32 i = fLS->Variables()->IndexOf(this);
|
2009-10-16 16:13:07 +04:00
|
|
|
if (i == -1) {
|
2008-02-06 13:51:44 +03:00
|
|
|
printf("Variable not part of fLS->Variables().");
|
2009-10-16 16:13:07 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2008-02-06 13:51:44 +03:00
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the current linear specification.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @return the current linear specification
|
|
|
|
*/
|
|
|
|
LinearSpec*
|
|
|
|
Variable::LS() const
|
|
|
|
{
|
|
|
|
return fLS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the value.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @return the value
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
Variable::Value() const
|
|
|
|
{
|
|
|
|
return fValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the value.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @param value the value
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Variable::SetValue(double value)
|
|
|
|
{
|
|
|
|
fValue = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the minimum value of the variable.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @return the minimum value of variable
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
Variable::Min() const
|
|
|
|
{
|
|
|
|
return fMin;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the minimum value of the variable.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @param min minimum value
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Variable::SetMin(double min)
|
|
|
|
{
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!fIsValid)
|
|
|
|
return;
|
|
|
|
|
2008-02-06 13:51:44 +03:00
|
|
|
fMin = min;
|
2008-03-11 00:43:32 +03:00
|
|
|
set_bounds(fLS->fLP, this->Index(), fMin, fMax);
|
2008-02-06 13:51:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the maximum value of the variable.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @return the maximum value of variable
|
|
|
|
*/
|
|
|
|
double
|
|
|
|
Variable::Max() const
|
|
|
|
{
|
|
|
|
return fMax;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the maximum value of the variable.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @param max maximum value
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Variable::SetMax(double max)
|
|
|
|
{
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!fIsValid)
|
|
|
|
return;
|
|
|
|
|
2008-02-06 13:51:44 +03:00
|
|
|
fMax = max;
|
2008-03-11 00:43:32 +03:00
|
|
|
set_bounds(fLS->fLP, this->Index(), fMin, fMax);
|
2008-02-06 13:51:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the minimum and maximum values of the variable.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @param min minimum value
|
|
|
|
* @param max maximum value
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Variable::SetRange(double min, double max)
|
|
|
|
{
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!fIsValid)
|
|
|
|
return;
|
|
|
|
|
2008-02-06 13:51:44 +03:00
|
|
|
fMin = min;
|
|
|
|
fMax = max;
|
2008-03-11 00:43:32 +03:00
|
|
|
set_bounds(fLS->fLP, this->Index(), fMin, fMax);
|
2008-02-06 13:51:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-16 16:13:07 +04:00
|
|
|
const char*
|
|
|
|
Variable::Label()
|
|
|
|
{
|
|
|
|
return fLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Variable::SetLabel(const char* label)
|
|
|
|
{
|
|
|
|
fLabel = (char*) malloc(strlen(label) + 1);
|
|
|
|
strcpy(fLabel, label);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-06 16:14:45 +03:00
|
|
|
Variable::operator BString() const
|
|
|
|
{
|
|
|
|
BString string;
|
|
|
|
GetString(string);
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-06 13:51:44 +03:00
|
|
|
/**
|
|
|
|
* Returns index of the variable as String.
|
|
|
|
* E.g. "Var2"
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @return the <code>String</code> index of the variable
|
|
|
|
*/
|
2009-12-06 16:14:45 +03:00
|
|
|
void
|
|
|
|
Variable::GetString(BString& string) const
|
2009-10-16 16:13:07 +04:00
|
|
|
{
|
|
|
|
if (fLabel) {
|
2009-12-06 16:14:45 +03:00
|
|
|
string << fLabel;
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!fIsValid)
|
2009-12-06 16:14:45 +03:00
|
|
|
string << "(invalid)";
|
2009-10-16 16:13:07 +04:00
|
|
|
} else {
|
2009-12-06 16:14:45 +03:00
|
|
|
string << "Var";
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!fIsValid)
|
2009-12-06 16:14:45 +03:00
|
|
|
string << "(invalid," << (int32)this << ")";
|
2009-10-16 16:13:07 +04:00
|
|
|
else
|
2009-12-06 16:14:45 +03:00
|
|
|
string << Index();
|
2009-10-16 16:13:07 +04:00
|
|
|
}
|
|
|
|
}
|
2008-02-06 13:51:44 +03:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a constraint that sets this variable equal to the given one.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @param var variable that should have the same value
|
|
|
|
* @return the new equality constraint
|
|
|
|
*/
|
|
|
|
Constraint*
|
|
|
|
Variable::IsEqual(Variable* var)
|
|
|
|
{
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!fIsValid)
|
|
|
|
return NULL;
|
|
|
|
|
2008-02-25 04:54:05 +03:00
|
|
|
return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(EQ), 0.0);
|
2008-02-06 13:51:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a constraint that sets this variable smaller or equal to the given one.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @param var variable that should have a larger or equal value
|
|
|
|
* @return the new constraint
|
|
|
|
*/
|
|
|
|
Constraint*
|
|
|
|
Variable::IsSmallerOrEqual(Variable* var)
|
|
|
|
{
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!fIsValid)
|
|
|
|
return NULL;
|
|
|
|
|
2008-02-25 04:54:05 +03:00
|
|
|
return fLS->AddConstraint(1.0, this, -1.0, var, OperatorType(LE), 0.0);
|
2008-02-06 13:51:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a constraint that sets this variable greater or equal to the given one.
|
2009-12-06 16:14:45 +03:00
|
|
|
*
|
2008-02-06 13:51:44 +03:00
|
|
|
* @param var variable that should have a smaller or equal value
|
|
|
|
* @return the new constraint
|
|
|
|
*/
|
|
|
|
Constraint*
|
2009-10-16 16:13:07 +04:00
|
|
|
Variable::IsGreaterOrEqual(Variable* var)
|
2008-02-06 13:51:44 +03:00
|
|
|
{
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!fIsValid)
|
|
|
|
return NULL;
|
|
|
|
|
2008-02-25 04:54:05 +03:00
|
|
|
return fLS->AddConstraint(-1.0, var, 1.0, this, OperatorType(GE), 0.0);
|
2008-02-06 13:51:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-16 16:13:07 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-06 13:51:44 +03:00
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
*/
|
|
|
|
Variable::Variable(LinearSpec* ls)
|
2009-10-16 16:13:07 +04:00
|
|
|
: fLS(ls),
|
|
|
|
fUsingSummands(new BList()),
|
|
|
|
fValue(NAN),
|
|
|
|
fMin(0),
|
|
|
|
fMax(DBL_MAX),
|
|
|
|
fLabel(NULL),
|
|
|
|
fIsValid(true)
|
2008-02-06 13:51:44 +03:00
|
|
|
{
|
2009-10-16 16:13:07 +04:00
|
|
|
fLS->Variables()->AddItem(this);
|
2009-12-06 16:14:45 +03:00
|
|
|
|
2009-10-16 16:13:07 +04:00
|
|
|
if (fLS->Variables()->CountItems() > fLS->CountColumns()) {
|
2008-02-06 13:51:44 +03:00
|
|
|
double d = 0;
|
|
|
|
int i = 0;
|
2009-10-16 16:13:07 +04:00
|
|
|
if (!add_columnex(fLS->fLP, 0, &d, &i))
|
2008-02-06 13:51:44 +03:00
|
|
|
printf("Error in add_columnex.");
|
|
|
|
}
|
2010-08-17 09:34:12 +04:00
|
|
|
|
2010-08-23 10:21:55 +04:00
|
|
|
SetRange(-20000, 20000);
|
2008-02-06 13:51:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor.
|
|
|
|
* Removes the variable from its specification.
|
|
|
|
*/
|
|
|
|
Variable::~Variable()
|
|
|
|
{
|
2009-10-16 16:13:07 +04:00
|
|
|
Invalidate();
|
|
|
|
free(fLabel);
|
|
|
|
delete fUsingSummands;
|
2008-02-06 13:51:44 +03:00
|
|
|
}
|
|
|
|
|