Move lp_solve dependency completely into LinearSpec. Clean up and some more memory allocation checks.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39681 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -33,7 +33,7 @@ public:
|
|||||||
|
|
||||||
SummandList* LeftSide();
|
SummandList* LeftSide();
|
||||||
void SetLeftSide(SummandList* summands);
|
void SetLeftSide(SummandList* summands);
|
||||||
void UpdateLeftSide();
|
|
||||||
void SetLeftSide(double coeff1, Variable* var1);
|
void SetLeftSide(double coeff1, Variable* var1);
|
||||||
void SetLeftSide(double coeff1, Variable* var1,
|
void SetLeftSide(double coeff1, Variable* var1,
|
||||||
double coeff2, Variable* var2);
|
double coeff2, Variable* var2);
|
||||||
@@ -73,14 +73,18 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
Constraint(LinearSpec* ls,
|
Constraint(LinearSpec* ls,
|
||||||
SummandList* summands, OperatorType op,
|
SummandList* summands, OperatorType op,
|
||||||
double rightSide, double penaltyNeg,
|
double rightSide,
|
||||||
double penaltyPos);
|
double penaltyNeg = INFINITY,
|
||||||
|
double penaltyPos = INFINITY);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LinearSpec* fLS;
|
LinearSpec* fLS;
|
||||||
SummandList* fLeftSide;
|
SummandList* fLeftSide;
|
||||||
OperatorType fOp;
|
OperatorType fOp;
|
||||||
double fRightSide;
|
double fRightSide;
|
||||||
|
|
||||||
|
double fPenaltyNeg;
|
||||||
|
double fPenaltyPos;
|
||||||
Summand* fDNegObjSummand;
|
Summand* fDNegObjSummand;
|
||||||
Summand* fDPosObjSummand;
|
Summand* fDPosObjSummand;
|
||||||
BString fLabel;
|
BString fLabel;
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ public:
|
|||||||
bool SetRange(Variable* variable, double min,
|
bool SetRange(Variable* variable, double min,
|
||||||
double max);
|
double max);
|
||||||
|
|
||||||
|
bool AddConstraint(Constraint* constraint);
|
||||||
|
bool RemoveConstraint(Constraint* constraint,
|
||||||
|
bool deleteConstraint = true);
|
||||||
|
|
||||||
Constraint* AddConstraint(SummandList* summands,
|
Constraint* AddConstraint(SummandList* summands,
|
||||||
OperatorType op, double rightSide);
|
OperatorType op, double rightSide);
|
||||||
Constraint* AddConstraint(double coeff1, Variable* var1,
|
Constraint* AddConstraint(double coeff1, Variable* var1,
|
||||||
@@ -108,9 +112,21 @@ public:
|
|||||||
|
|
||||||
const ConstraintList& Constraints() const;
|
const ConstraintList& Constraints() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class Constraint;
|
||||||
|
bool UpdateLeftSide(Constraint* constraint);
|
||||||
|
bool UpdateRightSide(Constraint* constraint);
|
||||||
|
bool UpdateOperator(Constraint* constraint);
|
||||||
private:
|
private:
|
||||||
ResultType Presolve();
|
/*! Check if all entries != NULL otherwise delete the list and its
|
||||||
void RemovePresolved();
|
entries. */
|
||||||
|
bool _CheckSummandList(SummandList* list);
|
||||||
|
Constraint* _AddConstraint(SummandList* leftSide,
|
||||||
|
OperatorType op, double rightSide,
|
||||||
|
double penaltyNeg, double penaltyPos);
|
||||||
|
|
||||||
|
ResultType _Presolve();
|
||||||
|
void _RemovePresolved();
|
||||||
|
|
||||||
lprec* fLpPresolved;
|
lprec* fLpPresolved;
|
||||||
OptimizationType fOptimization;
|
OptimizationType fOptimization;
|
||||||
@@ -122,9 +138,6 @@ private:
|
|||||||
double fObjectiveValue;
|
double fObjectiveValue;
|
||||||
double fSolvingTime;
|
double fSolvingTime;
|
||||||
|
|
||||||
public:
|
|
||||||
friend class Constraint;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace LinearProgramming
|
} // namespace LinearProgramming
|
||||||
|
|||||||
+27
-119
@@ -66,42 +66,7 @@ Constraint::SetLeftSide(SummandList* summands)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fLeftSide = summands;
|
fLeftSide = summands;
|
||||||
UpdateLeftSide();
|
fLS->UpdateLeftSide(this);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Constraint::UpdateLeftSide()
|
|
||||||
{
|
|
||||||
if (!fIsValid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
double coeffs[fLeftSide->CountItems() + 2];
|
|
||||||
int varIndexes[fLeftSide->CountItems() + 2];
|
|
||||||
int32 i;
|
|
||||||
for (i = 0; i < fLeftSide->CountItems(); i++) {
|
|
||||||
Summand* s = fLeftSide->ItemAt(i);
|
|
||||||
coeffs[i] = s->Coeff();
|
|
||||||
varIndexes[i] = s->Var()->Index();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fDNegObjSummand != NULL && fOp != OperatorType(LE)) {
|
|
||||||
varIndexes[i] = fDNegObjSummand->Var()->Index();
|
|
||||||
coeffs[i] = 1.0;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fDPosObjSummand != NULL && fOp != OperatorType(GE)) {
|
|
||||||
varIndexes[i] = fDPosObjSummand->Var()->Index();
|
|
||||||
coeffs[i] = -1.0;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!set_rowex(fLS->fLP, this->Index(), i, &coeffs[0], &varIndexes[0]))
|
|
||||||
STRACE(("Error in set_rowex."));
|
|
||||||
|
|
||||||
fLS->UpdateObjectiveFunction();
|
|
||||||
fLS->RemovePresolved();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -115,7 +80,7 @@ Constraint::SetLeftSide(double coeff1, Variable* var1)
|
|||||||
delete fLeftSide->ItemAt(i);
|
delete fLeftSide->ItemAt(i);
|
||||||
fLeftSide->MakeEmpty();
|
fLeftSide->MakeEmpty();
|
||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
||||||
UpdateLeftSide();
|
fLS->UpdateLeftSide(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -131,7 +96,7 @@ Constraint::SetLeftSide(double coeff1, Variable* var1,
|
|||||||
fLeftSide->MakeEmpty();
|
fLeftSide->MakeEmpty();
|
||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
||||||
UpdateLeftSide();
|
fLS->UpdateLeftSide(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -149,7 +114,7 @@ Constraint::SetLeftSide(double coeff1, Variable* var1,
|
|||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
||||||
UpdateLeftSide();
|
fLS->UpdateLeftSide(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -169,7 +134,7 @@ Constraint::SetLeftSide(double coeff1, Variable* var1,
|
|||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
||||||
fLeftSide->AddItem(new(std::nothrow) Summand(coeff4, var4));
|
fLeftSide->AddItem(new(std::nothrow) Summand(coeff4, var4));
|
||||||
UpdateLeftSide();
|
fLS->UpdateLeftSide(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -197,13 +162,7 @@ Constraint::SetOp(OperatorType value)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fOp = value;
|
fOp = value;
|
||||||
if (!set_constr_type(fLS->fLP, this->Index(),
|
fLS->UpdateOperator(this);
|
||||||
((fOp == OperatorType(EQ)) ? EQ
|
|
||||||
: (fOp == OperatorType(GE)) ? GE
|
|
||||||
: LE)))
|
|
||||||
STRACE(("Error in set_constr_type."));
|
|
||||||
|
|
||||||
fLS->RemovePresolved();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -234,10 +193,8 @@ Constraint::SetRightSide(double value)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fRightSide = value;
|
fRightSide = value;
|
||||||
if (!set_rh(fLS->fLP, Index(), fRightSide))
|
|
||||||
STRACE(("Error in set_rh."));
|
|
||||||
|
|
||||||
fLS->RemovePresolved();
|
fLS->UpdateRightSide(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -249,9 +206,7 @@ Constraint::SetRightSide(double value)
|
|||||||
double
|
double
|
||||||
Constraint::PenaltyNeg() const
|
Constraint::PenaltyNeg() const
|
||||||
{
|
{
|
||||||
if (fDNegObjSummand == NULL)
|
return fPenaltyNeg;
|
||||||
return INFINITY;
|
|
||||||
return fDNegObjSummand->Coeff();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -264,13 +219,15 @@ Constraint::PenaltyNeg() const
|
|||||||
void
|
void
|
||||||
Constraint::SetPenaltyNeg(double value)
|
Constraint::SetPenaltyNeg(double value)
|
||||||
{
|
{
|
||||||
|
fPenaltyNeg = value;
|
||||||
|
|
||||||
if (!fIsValid)
|
if (!fIsValid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fDNegObjSummand == NULL) {
|
if (fDNegObjSummand == NULL) {
|
||||||
fDNegObjSummand = new(std::nothrow) Summand(value, fLS->AddVariable());
|
fDNegObjSummand = new(std::nothrow) Summand(value, fLS->AddVariable());
|
||||||
fLS->ObjectiveFunction()->AddItem(fDNegObjSummand);
|
fLS->ObjectiveFunction()->AddItem(fDNegObjSummand);
|
||||||
UpdateLeftSide();
|
fLS->UpdateLeftSide(this);
|
||||||
fLS->UpdateObjectiveFunction();
|
fLS->UpdateObjectiveFunction();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -291,28 +248,27 @@ Constraint::SetPenaltyNeg(double value)
|
|||||||
double
|
double
|
||||||
Constraint::PenaltyPos() const
|
Constraint::PenaltyPos() const
|
||||||
{
|
{
|
||||||
if (fDPosObjSummand == NULL)
|
return fPenaltyPos;
|
||||||
return INFINITY;
|
|
||||||
return fDPosObjSummand->Coeff();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The penalty coefficient for negative deviations from the soft constraint's exact solution,
|
* The penalty coefficient for negative deviations from the soft constraint's
|
||||||
* i.e. if the left side is too small.
|
* exact solution, i.e. if the left side is too small.
|
||||||
*
|
|
||||||
* @param value coefficient of positive penalty <code>double</code>
|
* @param value coefficient of positive penalty <code>double</code>
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Constraint::SetPenaltyPos(double value)
|
Constraint::SetPenaltyPos(double value)
|
||||||
{
|
{
|
||||||
|
fPenaltyPos = value;
|
||||||
|
|
||||||
if (!fIsValid)
|
if (!fIsValid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fDPosObjSummand == NULL) {
|
if (fDPosObjSummand == NULL) {
|
||||||
fDPosObjSummand = new(std::nothrow) Summand(value, fLS->AddVariable());
|
fDPosObjSummand = new(std::nothrow) Summand(value, fLS->AddVariable());
|
||||||
fLS->ObjectiveFunction()->AddItem(fDPosObjSummand);
|
fLS->ObjectiveFunction()->AddItem(fDPosObjSummand);
|
||||||
UpdateLeftSide();
|
fLS->UpdateLeftSide(this);
|
||||||
fLS->UpdateObjectiveFunction();
|
fLS->UpdateObjectiveFunction();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -424,27 +380,7 @@ Constraint::Invalidate()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fIsValid = false;
|
fIsValid = false;
|
||||||
|
fLS->RemoveConstraint(this, false);
|
||||||
for (int32 i = 0; i < fLeftSide->CountItems(); i++)
|
|
||||||
delete (Summand*)fLeftSide->ItemAt(i);
|
|
||||||
delete fLeftSide;
|
|
||||||
fLeftSide = NULL;
|
|
||||||
|
|
||||||
if (fDNegObjSummand) {
|
|
||||||
fLS->ObjectiveFunction()->RemoveItem(fDNegObjSummand);
|
|
||||||
delete fDNegObjSummand->Var();
|
|
||||||
delete fDNegObjSummand;
|
|
||||||
fDNegObjSummand = NULL;
|
|
||||||
}
|
|
||||||
if (fDPosObjSummand) {
|
|
||||||
fLS->ObjectiveFunction()->RemoveItem(fDPosObjSummand);
|
|
||||||
delete fDPosObjSummand->Var();
|
|
||||||
delete fDPosObjSummand;
|
|
||||||
fDPosObjSummand = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
del_constraint(fLS->fLP, this->Index());
|
|
||||||
const_cast<ConstraintList&>(fLS->Constraints()).RemoveItem(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -492,46 +428,13 @@ Constraint::Constraint(LinearSpec* ls, SummandList* summands, OperatorType op,
|
|||||||
fLeftSide(summands),
|
fLeftSide(summands),
|
||||||
fOp(op),
|
fOp(op),
|
||||||
fRightSide(rightSide),
|
fRightSide(rightSide),
|
||||||
|
fPenaltyNeg(penaltyNeg),
|
||||||
|
fPenaltyPos(penaltyPos),
|
||||||
|
fDNegObjSummand(NULL),
|
||||||
|
fDPosObjSummand(NULL),
|
||||||
fIsValid(true)
|
fIsValid(true)
|
||||||
{
|
{
|
||||||
double coeffs[summands->CountItems() + 2];
|
|
||||||
int varIndexes[summands->CountItems() + 2];
|
|
||||||
int32 nCoefficient = 0;
|
|
||||||
for (; nCoefficient < summands->CountItems(); nCoefficient++) {
|
|
||||||
Summand* s = summands->ItemAt(nCoefficient);
|
|
||||||
coeffs[nCoefficient] = s->Coeff();
|
|
||||||
varIndexes[nCoefficient] = s->Var()->Index();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (penaltyNeg != INFINITY && penaltyNeg != 0. && fOp != OperatorType(LE)) {
|
|
||||||
fDNegObjSummand = new(std::nothrow) Summand(penaltyNeg,
|
|
||||||
ls->AddVariable());
|
|
||||||
fLS->fObjFunction->AddItem(fDNegObjSummand);
|
|
||||||
varIndexes[nCoefficient] = fDNegObjSummand->Var()->Index();
|
|
||||||
coeffs[nCoefficient] = 1.0;
|
|
||||||
nCoefficient++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fDNegObjSummand = NULL;
|
|
||||||
|
|
||||||
if (penaltyPos != INFINITY && penaltyPos != 0. && fOp != OperatorType(GE)) {
|
|
||||||
fDPosObjSummand = new(std::nothrow) Summand(penaltyPos,
|
|
||||||
ls->AddVariable());
|
|
||||||
fLS->fObjFunction->AddItem(fDPosObjSummand);
|
|
||||||
varIndexes[nCoefficient] = fDPosObjSummand->Var()->Index();
|
|
||||||
coeffs[nCoefficient] = -1.0;
|
|
||||||
nCoefficient++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fDPosObjSummand = NULL;
|
|
||||||
|
|
||||||
if (!add_constraintex(fLS->fLP, nCoefficient, &coeffs[0], &varIndexes[0],
|
|
||||||
(fOp == OperatorType(EQ) ? EQ : (fOp == OperatorType(GE)) ? GE
|
|
||||||
: LE), rightSide))
|
|
||||||
STRACE(("Error in add_constraintex."));
|
|
||||||
|
|
||||||
fLS->UpdateObjectiveFunction();
|
|
||||||
const_cast<ConstraintList&>(fLS->Constraints()).AddItem(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -542,5 +445,10 @@ Constraint::Constraint(LinearSpec* ls, SummandList* summands, OperatorType op,
|
|||||||
Constraint::~Constraint()
|
Constraint::~Constraint()
|
||||||
{
|
{
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fLeftSide->CountItems(); i++)
|
||||||
|
delete (Summand*)fLeftSide->ItemAt(i);
|
||||||
|
delete fLeftSide;
|
||||||
|
fLeftSide = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+239
-61
@@ -43,7 +43,7 @@ LinearSpec::LinearSpec()
|
|||||||
*/
|
*/
|
||||||
LinearSpec::~LinearSpec()
|
LinearSpec::~LinearSpec()
|
||||||
{
|
{
|
||||||
RemovePresolved();
|
_RemovePresolved();
|
||||||
for (int32 i = 0; i < fConstraints.CountItems(); i++)
|
for (int32 i = 0; i < fConstraints.CountItems(); i++)
|
||||||
delete (Constraint*)fConstraints.ItemAt(i);
|
delete (Constraint*)fConstraints.ItemAt(i);
|
||||||
for (int32 i = 0; i < fObjFunction->CountItems(); i++)
|
for (int32 i = 0; i < fObjFunction->CountItems(); i++)
|
||||||
@@ -80,6 +80,9 @@ LinearSpec::AddVariable()
|
|||||||
bool
|
bool
|
||||||
LinearSpec::AddVariable(Variable* variable)
|
LinearSpec::AddVariable(Variable* variable)
|
||||||
{
|
{
|
||||||
|
if (variable->IsValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
double d = 0;
|
double d = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
@@ -90,7 +93,7 @@ LinearSpec::AddVariable(Variable* variable)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetRange(variable, -20000, 20000)) {
|
if (!SetRange(variable, variable->Min(), variable->Max())) {
|
||||||
RemoveVariable(variable, false);
|
RemoveVariable(variable, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -110,7 +113,29 @@ LinearSpec::RemoveVariable(Variable* variable, bool deleteVariable)
|
|||||||
if (!del_column(fLP, index))
|
if (!del_column(fLP, index))
|
||||||
return false;
|
return false;
|
||||||
fVariables.RemoveItemAt(index - 1);
|
fVariables.RemoveItemAt(index - 1);
|
||||||
variable->Invalidate();
|
variable->fIsValid = false;
|
||||||
|
|
||||||
|
// invalidate all constraints that use this variable
|
||||||
|
ConstraintList markedForInvalidation;
|
||||||
|
const ConstraintList& constraints = Constraints();
|
||||||
|
for (int i = 0; i < constraints.CountItems(); i++) {
|
||||||
|
Constraint* constraint = constraints.ItemAt(i);
|
||||||
|
|
||||||
|
if (!constraint->IsValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SummandList* summands = constraint->LeftSide();
|
||||||
|
for (int j = 0; j < summands->CountItems(); j++) {
|
||||||
|
Summand* summand = summands->ItemAt(j);
|
||||||
|
if (summand->Var() == variable) {
|
||||||
|
markedForInvalidation.AddItem(constraint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < markedForInvalidation.CountItems(); i++)
|
||||||
|
markedForInvalidation.ItemAt(i)->Invalidate();
|
||||||
|
|
||||||
|
|
||||||
if (deleteVariable)
|
if (deleteVariable)
|
||||||
delete variable;
|
delete variable;
|
||||||
@@ -137,6 +162,147 @@ LinearSpec::SetRange(Variable* variable, double min, double max)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
LinearSpec::AddConstraint(Constraint* constraint)
|
||||||
|
{
|
||||||
|
SummandList* summands = constraint->LeftSide();
|
||||||
|
OperatorType op = constraint->Op();
|
||||||
|
double rightSide = constraint->RightSide();
|
||||||
|
double penaltyNeg = constraint->PenaltyNeg();
|
||||||
|
double penaltyPos = constraint->PenaltyPos();
|
||||||
|
|
||||||
|
double coeffs[summands->CountItems() + 2];
|
||||||
|
int varIndexes[summands->CountItems() + 2];
|
||||||
|
int32 nCoefficient = 0;
|
||||||
|
for (; nCoefficient < summands->CountItems(); nCoefficient++) {
|
||||||
|
Summand* s = summands->ItemAt(nCoefficient);
|
||||||
|
coeffs[nCoefficient] = s->Coeff();
|
||||||
|
varIndexes[nCoefficient] = s->Var()->Index();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (penaltyNeg != INFINITY && penaltyNeg != 0. && op != OperatorType(LE)) {
|
||||||
|
constraint->fDNegObjSummand
|
||||||
|
= new(std::nothrow) Summand(constraint->PenaltyNeg(),
|
||||||
|
AddVariable());
|
||||||
|
fObjFunction->AddItem(constraint->fDNegObjSummand);
|
||||||
|
varIndexes[nCoefficient] = constraint->fDNegObjSummand->Var()->Index();
|
||||||
|
coeffs[nCoefficient] = 1.0;
|
||||||
|
nCoefficient++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (penaltyPos != INFINITY && penaltyPos != 0. && op != OperatorType(GE)) {
|
||||||
|
constraint->fDPosObjSummand
|
||||||
|
= new(std::nothrow) Summand(constraint->PenaltyPos(),
|
||||||
|
AddVariable());
|
||||||
|
fObjFunction->AddItem(constraint->fDPosObjSummand);
|
||||||
|
varIndexes[nCoefficient] = constraint->fDPosObjSummand->Var()->Index();
|
||||||
|
coeffs[nCoefficient] = -1.0;
|
||||||
|
nCoefficient++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!add_constraintex(fLP, nCoefficient, &coeffs[0], &varIndexes[0],
|
||||||
|
(op == OperatorType(EQ) ? EQ : (op == OperatorType(GE)) ? GE
|
||||||
|
: LE), rightSide))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UpdateObjectiveFunction();
|
||||||
|
fConstraints.AddItem(constraint);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
LinearSpec::RemoveConstraint(Constraint* constraint, bool deleteConstraint)
|
||||||
|
{
|
||||||
|
if (constraint->fDNegObjSummand) {
|
||||||
|
fObjFunction->RemoveItem(constraint->fDNegObjSummand);
|
||||||
|
delete constraint->fDNegObjSummand->Var();
|
||||||
|
delete constraint->fDNegObjSummand;
|
||||||
|
constraint->fDNegObjSummand = NULL;
|
||||||
|
}
|
||||||
|
if (constraint->fDPosObjSummand) {
|
||||||
|
fObjFunction->RemoveItem(constraint->fDPosObjSummand);
|
||||||
|
delete constraint->fDPosObjSummand->Var();
|
||||||
|
delete constraint->fDPosObjSummand;
|
||||||
|
constraint->fDPosObjSummand = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
del_constraint(fLP, constraint->Index());
|
||||||
|
fConstraints.RemoveItem(constraint);
|
||||||
|
constraint->fIsValid = false;
|
||||||
|
|
||||||
|
if (deleteConstraint)
|
||||||
|
delete constraint;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
LinearSpec::UpdateLeftSide(Constraint* constraint)
|
||||||
|
{
|
||||||
|
if (!constraint->IsValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SummandList* leftSide = constraint->LeftSide();
|
||||||
|
OperatorType op = constraint->Op();
|
||||||
|
|
||||||
|
double coeffs[leftSide->CountItems() + 2];
|
||||||
|
int varIndexes[leftSide->CountItems() + 2];
|
||||||
|
int32 i;
|
||||||
|
for (i = 0; i < leftSide->CountItems(); i++) {
|
||||||
|
Summand* s = leftSide->ItemAt(i);
|
||||||
|
coeffs[i] = s->Coeff();
|
||||||
|
varIndexes[i] = s->Var()->Index();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraint->fDNegObjSummand != NULL && op != OperatorType(LE)) {
|
||||||
|
varIndexes[i] = constraint->fDNegObjSummand->Var()->Index();
|
||||||
|
coeffs[i] = 1.0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constraint->fDPosObjSummand != NULL && op != OperatorType(GE)) {
|
||||||
|
varIndexes[i] = constraint->fDPosObjSummand->Var()->Index();
|
||||||
|
coeffs[i] = -1.0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!set_rowex(fLP, constraint->Index(), i, &coeffs[0],
|
||||||
|
&varIndexes[0]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UpdateObjectiveFunction();
|
||||||
|
_RemovePresolved();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
LinearSpec::UpdateRightSide(Constraint* constraint)
|
||||||
|
{
|
||||||
|
if (!set_rh(fLP, constraint->Index(), constraint->RightSide()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_RemovePresolved();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
LinearSpec::UpdateOperator(Constraint* constraint)
|
||||||
|
{
|
||||||
|
OperatorType op = constraint->Op();
|
||||||
|
if (!set_constr_type(fLP, constraint->Index(),
|
||||||
|
(op == OperatorType(EQ)) ? EQ : (op == OperatorType(GE)) ? GE
|
||||||
|
: LE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_RemovePresolved();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new hard linear constraint to the specification.
|
* Adds a new hard linear constraint to the specification.
|
||||||
*
|
*
|
||||||
@@ -150,10 +316,7 @@ Constraint*
|
|||||||
LinearSpec::AddConstraint(SummandList* summands, OperatorType op,
|
LinearSpec::AddConstraint(SummandList* summands, OperatorType op,
|
||||||
double rightSide)
|
double rightSide)
|
||||||
{
|
{
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
return AddConstraint(summands, op, rightSide, INFINITY, INFINITY);
|
||||||
INFINITY, INFINITY);
|
|
||||||
RemovePresolved();
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -170,12 +333,7 @@ Constraint*
|
|||||||
LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
||||||
OperatorType op, double rightSide)
|
OperatorType op, double rightSide)
|
||||||
{
|
{
|
||||||
SummandList* summands = new(std::nothrow) SummandList(1);
|
return AddConstraint(coeff1, var1, op, rightSide, INFINITY, INFINITY);
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
|
||||||
INFINITY, INFINITY);
|
|
||||||
RemovePresolved();
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -194,13 +352,8 @@ Constraint*
|
|||||||
LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
||||||
double coeff2, Variable* var2, OperatorType op, double rightSide)
|
double coeff2, Variable* var2, OperatorType op, double rightSide)
|
||||||
{
|
{
|
||||||
SummandList* summands = new(std::nothrow) SummandList(2);
|
return AddConstraint(coeff1, var1, coeff2, var2, op, rightSide, INFINITY,
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
INFINITY);
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
|
||||||
INFINITY, INFINITY);
|
|
||||||
RemovePresolved();
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -222,14 +375,8 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
|||||||
double coeff2, Variable* var2, double coeff3, Variable* var3,
|
double coeff2, Variable* var2, double coeff3, Variable* var3,
|
||||||
OperatorType op, double rightSide)
|
OperatorType op, double rightSide)
|
||||||
{
|
{
|
||||||
SummandList* summands = new(std::nothrow) SummandList(3);
|
return AddConstraint(coeff1, var1, coeff2, var2, coeff3, var3, op,
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
rightSide, INFINITY, INFINITY);
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
|
||||||
INFINITY, INFINITY);
|
|
||||||
RemovePresolved();
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -253,15 +400,8 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
|||||||
double coeff2, Variable* var2, double coeff3, Variable* var3,
|
double coeff2, Variable* var2, double coeff3, Variable* var3,
|
||||||
double coeff4, Variable* var4, OperatorType op, double rightSide)
|
double coeff4, Variable* var4, OperatorType op, double rightSide)
|
||||||
{
|
{
|
||||||
SummandList* summands = new(std::nothrow) SummandList(3);
|
return AddConstraint(coeff1, var1, coeff2, var2, coeff3, var3, coeff4, var4,
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
op, rightSide, INFINITY, INFINITY);
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff4, var4));
|
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
|
||||||
INFINITY, INFINITY);
|
|
||||||
RemovePresolved();
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -280,10 +420,7 @@ Constraint*
|
|||||||
LinearSpec::AddConstraint(SummandList* summands, OperatorType op,
|
LinearSpec::AddConstraint(SummandList* summands, OperatorType op,
|
||||||
double rightSide, double penaltyNeg, double penaltyPos)
|
double rightSide, double penaltyNeg, double penaltyPos)
|
||||||
{
|
{
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
return _AddConstraint(summands, op, rightSide, penaltyNeg, penaltyPos);
|
||||||
penaltyNeg, penaltyPos);
|
|
||||||
RemovePresolved();
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -302,11 +439,12 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
|||||||
OperatorType op, double rightSide, double penaltyNeg, double penaltyPos)
|
OperatorType op, double rightSide, double penaltyNeg, double penaltyPos)
|
||||||
{
|
{
|
||||||
SummandList* summands = new(std::nothrow) SummandList(1);
|
SummandList* summands = new(std::nothrow) SummandList(1);
|
||||||
|
if (!summands)
|
||||||
|
return NULL;
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
if (!_CheckSummandList(summands))
|
||||||
penaltyNeg, penaltyPos);
|
return NULL;
|
||||||
RemovePresolved();
|
return _AddConstraint(summands, op, rightSide, penaltyNeg, penaltyPos);
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -328,12 +466,13 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
|||||||
double penaltyNeg, double penaltyPos)
|
double penaltyNeg, double penaltyPos)
|
||||||
{
|
{
|
||||||
SummandList* summands = new(std::nothrow) SummandList(2);
|
SummandList* summands = new(std::nothrow) SummandList(2);
|
||||||
|
if (!summands)
|
||||||
|
return NULL;
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
if (!_CheckSummandList(summands))
|
||||||
penaltyNeg, penaltyPos);
|
return NULL;
|
||||||
RemovePresolved();
|
return _AddConstraint(summands, op, rightSide, penaltyNeg, penaltyPos);
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -357,13 +496,14 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
|||||||
OperatorType op, double rightSide, double penaltyNeg, double penaltyPos)
|
OperatorType op, double rightSide, double penaltyNeg, double penaltyPos)
|
||||||
{
|
{
|
||||||
SummandList* summands = new(std::nothrow) SummandList(2);
|
SummandList* summands = new(std::nothrow) SummandList(2);
|
||||||
|
if (!summands)
|
||||||
|
return NULL;
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
summands->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
if (!_CheckSummandList(summands))
|
||||||
penaltyNeg, penaltyPos);
|
return NULL;
|
||||||
RemovePresolved();
|
return _AddConstraint(summands, op, rightSide, penaltyNeg, penaltyPos);
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -390,14 +530,15 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
|
|||||||
double penaltyNeg, double penaltyPos)
|
double penaltyNeg, double penaltyPos)
|
||||||
{
|
{
|
||||||
SummandList* summands = new(std::nothrow) SummandList(2);
|
SummandList* summands = new(std::nothrow) SummandList(2);
|
||||||
|
if (!summands)
|
||||||
|
return NULL;
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
summands->AddItem(new(std::nothrow) Summand(coeff1, var1));
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
summands->AddItem(new(std::nothrow) Summand(coeff2, var2));
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
summands->AddItem(new(std::nothrow) Summand(coeff3, var3));
|
||||||
summands->AddItem(new(std::nothrow) Summand(coeff4, var4));
|
summands->AddItem(new(std::nothrow) Summand(coeff4, var4));
|
||||||
Constraint* c = new(std::nothrow) Constraint(this, summands, op, rightSide,
|
if (!_CheckSummandList(summands))
|
||||||
penaltyNeg, penaltyPos);
|
return NULL;
|
||||||
RemovePresolved();
|
return _AddConstraint(summands, op, rightSide, penaltyNeg, penaltyPos);
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -475,7 +616,44 @@ LinearSpec::UpdateObjectiveFunction()
|
|||||||
if (!set_obj_fnex(fLP, size, &coeffs[0], &varIndexes[0]))
|
if (!set_obj_fnex(fLP, size, &coeffs[0], &varIndexes[0]))
|
||||||
printf("Error in set_obj_fnex.\n");
|
printf("Error in set_obj_fnex.\n");
|
||||||
|
|
||||||
RemovePresolved();
|
_RemovePresolved();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
LinearSpec::_CheckSummandList(SummandList* list)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
for (int i = 0; i < list->CountItems(); i++) {
|
||||||
|
if (list->ItemAt(i) == NULL) {
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (int i = 0; i < list->CountItems(); i++)
|
||||||
|
delete list->ItemAt(i);
|
||||||
|
delete list;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Constraint*
|
||||||
|
LinearSpec::_AddConstraint(SummandList* leftSide, OperatorType op,
|
||||||
|
double rightSide, double penaltyNeg, double penaltyPos)
|
||||||
|
{
|
||||||
|
Constraint* constraint = new(std::nothrow) Constraint(this, leftSide,
|
||||||
|
op, rightSide, penaltyNeg, penaltyPos);
|
||||||
|
if (constraint == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (!AddConstraint(constraint)) {
|
||||||
|
delete constraint;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
_RemovePresolved();
|
||||||
|
return constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -485,7 +663,7 @@ LinearSpec::UpdateObjectiveFunction()
|
|||||||
* to avoid an old cached presolved model getting out of sync.
|
* to avoid an old cached presolved model getting out of sync.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
LinearSpec::RemovePresolved()
|
LinearSpec::_RemovePresolved()
|
||||||
{
|
{
|
||||||
if (fLpPresolved == NULL)
|
if (fLpPresolved == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -503,7 +681,7 @@ LinearSpec::RemovePresolved()
|
|||||||
* @return the result of the solving attempt
|
* @return the result of the solving attempt
|
||||||
*/
|
*/
|
||||||
ResultType
|
ResultType
|
||||||
LinearSpec::Presolve()
|
LinearSpec::_Presolve()
|
||||||
{
|
{
|
||||||
bigtime_t start, end;
|
bigtime_t start, end;
|
||||||
start = system_time();
|
start = system_time();
|
||||||
@@ -543,7 +721,7 @@ ResultType
|
|||||||
LinearSpec::Solve()
|
LinearSpec::Solve()
|
||||||
{
|
{
|
||||||
if (fLpPresolved != NULL)
|
if (fLpPresolved != NULL)
|
||||||
return Presolve();
|
return _Presolve();
|
||||||
|
|
||||||
bigtime_t start, end;
|
bigtime_t start, end;
|
||||||
start = system_time();
|
start = system_time();
|
||||||
|
|||||||
@@ -281,29 +281,7 @@ Variable::Invalidate()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fIsValid = false;
|
fIsValid = false;
|
||||||
|
|
||||||
fLS->RemoveVariable(this, false);
|
fLS->RemoveVariable(this, false);
|
||||||
|
|
||||||
// invalidate all constraints that use this variable
|
|
||||||
ConstraintList markedForInvalidation;
|
|
||||||
const ConstraintList& constraints = fLS->Constraints();
|
|
||||||
for (int i = 0; i < constraints.CountItems(); i++) {
|
|
||||||
Constraint* constraint = constraints.ItemAt(i);
|
|
||||||
|
|
||||||
if (!constraint->IsValid())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SummandList* summands = constraint->LeftSide();
|
|
||||||
for (int j = 0; j < summands->CountItems(); j++) {
|
|
||||||
Summand* summand = summands->ItemAt(j);
|
|
||||||
if (summand->Var() == this) {
|
|
||||||
markedForInvalidation.AddItem(constraint);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < markedForInvalidation.CountItems(); i++)
|
|
||||||
markedForInvalidation.ItemAt(i)->Invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -314,8 +292,8 @@ Variable::Variable(LinearSpec* ls)
|
|||||||
:
|
:
|
||||||
fLS(ls),
|
fLS(ls),
|
||||||
fValue(NAN),
|
fValue(NAN),
|
||||||
fMin(0),
|
fMin(-20000),
|
||||||
fMax(DBL_MAX),
|
fMax(20000),
|
||||||
fLabel(NULL),
|
fLabel(NULL),
|
||||||
fIsValid(false)
|
fIsValid(false)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user