Remove lp_solve as a dependency of the linprog lib.

Really, it hasn't depended on lp_solve for a while, but it was still
linked in in some places.
This commit is contained in:
Alex Wilson
2012-05-03 08:44:48 +12:00
parent 03adc8c767
commit 51b5b66b01
7 changed files with 4 additions and 555 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ Application MusicCollection :
NodeMonitorHandler.cpp
:
be liblpsolve55.so libalm.so $(HAIKU_LOCALE_LIBS) $(TARGET_LIBSUPC++)
be libalm.so $(HAIKU_LOCALE_LIBS) $(TARGET_LIBSUPC++)
$(TARGET_LIBSTDC++) libshared.a
:
MusicCollection.rdef
+1 -1
View File
@@ -1,7 +1,7 @@
SubDir HAIKU_TOP src libs alm ;
UseLibraryHeaders lp_solve linprog alm ;
UseLibraryHeaders linprog alm ;
UsePrivateHeaders shared ;
UseHeaders [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) kits interface ] ;
-1
View File
@@ -11,7 +11,6 @@ StaticLibrary liblinprog.a :
Constraint.cpp
LayoutOptimizer.cpp
LinearSpec.cpp
# LPSolveInterface.cpp
QPSolverInterface.cpp
Summand.cpp
Variable.cpp
-481
View File
@@ -1,481 +0,0 @@
/*
* Copyright 2007-2008, Christof Lutteroth, [email protected]
* Copyright 2007-2008, James Kim, [email protected]
* Copyright 2010, Clemens Zeidler <[email protected]>
* Distributed under the terms of the MIT License.
*/
#include "LPSolveInterface.h"
#include <new>
using namespace LinearProgramming;
LPSolveInterface::LPSolveInterface(LinearSpec* linearSpec)
:
SolverInterface(linearSpec),
fLpPresolved(NULL),
fLP(NULL),
fOptimization(kMinimize),
fObjFunction(new(std::nothrow) SummandList())
{
fLP = make_lp(0, 0);
if (fLP == NULL)
printf("Couldn't construct a new model.");
// minimize the objective functions, this is the default of lp_solve so we
// don't have to do it here:
// set_minim(fLP);
set_verbose(fLP, 1);
}
LPSolveInterface::~LPSolveInterface()
{
_RemovePresolved();
delete_lp(fLP);
for (int32 i = 0; i < fObjFunction->CountItems(); i++)
delete (Summand*)fObjFunction->ItemAt(i);
delete fObjFunction;
}
ResultType
LPSolveInterface::Solve()
{
const VariableList& variables = fLinearSpec->AllVariables();
if (fLpPresolved != NULL)
return _Presolve(variables);
// Try to solve the layout until the result is kOptimal or kInfeasible,
// maximally 15 tries sometimes the solving algorithm encounters numerical
// problems (NUMFAILURE), and repeating the solving often helps to overcome
// them.
ResultType result = kInfeasible;
for (int32 tries = 0; tries < 15; tries++) {
result = (ResultType)solve(fLP);
if (result == OPTIMAL) {
int32 size = variables.CountItems();
double x[size];
if (!get_variables(fLP, &x[0]))
printf("Error in get_variables.\n");
for (int32 i = 0; i < size; i++)
variables.ItemAt(i)->SetValue(x[i]);
break;
} else if (result == kInfeasible)
break;
}
return result;
}
bool
LPSolveInterface::VariableAdded(Variable* variable)
{
double d = 0;
int i = 0;
if (!add_columnex(fLP, 0, &d, &i))
return false;
_RemovePresolved();
return true;
}
bool
LPSolveInterface::VariableRemoved(Variable* variable)
{
if (!del_column(fLP, variable->GlobalIndex() + 1))
return false;
_RemovePresolved();
return true;
}
bool
LPSolveInterface::VariableRangeChanged(Variable* variable)
{
double min = variable->Min();
double max = variable->Max();
if (!set_bounds(fLP, variable->GlobalIndex() + 1, min, max))
return false;
_RemovePresolved();
return true;
}
bool
LPSolveInterface::ConstraintAdded(Constraint* constraint)
{
OperatorType op = constraint->Op();
SummandList* summands = constraint->LeftSide();
double coeffs[summands->CountItems() + 2];
int variableIndices[summands->CountItems() + 2];
int32 nCoefficient = 0;
for (; nCoefficient < summands->CountItems(); nCoefficient++) {
Summand* s = summands->ItemAt(nCoefficient);
coeffs[nCoefficient] = s->Coeff();
variableIndices[nCoefficient] = s->Var()->GlobalIndex() + 1;
}
double penaltyNeg = constraint->PenaltyNeg();
if (penaltyNeg > 0. && op != kLE) {
constraint->fDNegObjSummand = new(std::nothrow) Summand(
constraint->PenaltyNeg(), fLinearSpec->AddVariable());
fObjFunction->AddItem(constraint->fDNegObjSummand);
variableIndices[nCoefficient]
= constraint->fDNegObjSummand->Var()->GlobalIndex() + 1;
coeffs[nCoefficient] = 1.0;
nCoefficient++;
}
double penaltyPos = constraint->PenaltyPos();
if (penaltyPos > 0. && op != kGE) {
constraint->fDPosObjSummand = new(std::nothrow) Summand(
constraint->PenaltyPos(), fLinearSpec->AddVariable());
fObjFunction->AddItem(constraint->fDPosObjSummand);
variableIndices[nCoefficient]
= constraint->fDPosObjSummand->Var()->GlobalIndex() + 1;
coeffs[nCoefficient] = -1.0;
nCoefficient++;
}
double rightSide = constraint->RightSide();
if (!add_constraintex(fLP, nCoefficient, coeffs, variableIndices,
(op == kEQ ? EQ : (op == kGE) ? GE : LE), rightSide)) {
return false;
}
_UpdateObjectiveFunction();
_RemovePresolved();
return true;
}
bool
LPSolveInterface::ConstraintRemoved(Constraint* constraint)
{
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;
}
if (!del_constraint(fLP, constraint->Index() + 1))
return false;
_UpdateObjectiveFunction();
_RemovePresolved();
return true;
}
bool
LPSolveInterface::LeftSideChanged(Constraint* constraint)
{
if (!constraint->IsValid())
return false;
int32 index = constraint->Index() + 1;
if (index <= 0)
return false;
SummandList* leftSide = constraint->LeftSide();
OperatorType op = constraint->Op();
double coeffs[leftSide->CountItems() + 2];
int variableIndices[leftSide->CountItems() + 2];
int32 i;
for (i = 0; i < leftSide->CountItems(); i++) {
Summand* s = leftSide->ItemAt(i);
coeffs[i] = s->Coeff();
variableIndices[i] = s->Var()->GlobalIndex() + 1;
}
double penaltyNeg = constraint->PenaltyNeg();
if (penaltyNeg > 0. && op != kLE) {
if (!constraint->fDNegObjSummand) {
constraint->fDNegObjSummand = new(std::nothrow) Summand(
constraint->PenaltyNeg(), fLinearSpec->AddVariable());
fObjFunction->AddItem(constraint->fDNegObjSummand);
}
variableIndices[i] = constraint->fDNegObjSummand->Var()->GlobalIndex() + 1;
coeffs[i] = 1.0;
i++;
} else {
fObjFunction->RemoveItem(constraint->fDNegObjSummand);
delete constraint->fDNegObjSummand;
constraint->fDNegObjSummand = NULL;
}
double penaltyPos = constraint->PenaltyPos();
if (penaltyPos > 0. && op != kGE) {
if (constraint->fDPosObjSummand == NULL) {
constraint->fDPosObjSummand = new(std::nothrow) Summand(penaltyPos,
fLinearSpec->AddVariable());
fObjFunction->AddItem(constraint->fDPosObjSummand);
}
variableIndices[i] = constraint->fDPosObjSummand->Var()->GlobalIndex() + 1;
coeffs[i] = -1.0;
i++;
} else {
fObjFunction->RemoveItem(constraint->fDPosObjSummand);
delete constraint->fDPosObjSummand;
constraint->fDPosObjSummand = NULL;
}
if (!set_rowex(fLP, index, i, coeffs, variableIndices))
return false;
_UpdateObjectiveFunction();
_RemovePresolved();
return true;
}
bool
LPSolveInterface::RightSideChanged(Constraint* constraint)
{
if (!set_rh(fLP, constraint->Index() + 1, constraint->RightSide()))
return false;
_RemovePresolved();
return true;
}
bool
LPSolveInterface::OperatorChanged(Constraint* constraint)
{
int32 index = constraint->Index() + 1;
if (index <= 0)
return false;
OperatorType op = constraint->Op();
if (!set_constr_type(fLP, index, op == kEQ) ? EQ : (op == kGE) ? GE : LE) {
return false;
}
_RemovePresolved();
return true;
}
bool
LPSolveInterface::SetObjectiveFunction(int nElements, double* coefficients,
int* variableIndices)
{
if (!set_obj_fnex(fLP, nElements, coefficients, variableIndices))
return false;
_RemovePresolved();
return true;
}
bool
LPSolveInterface::SetOptimization(OptimizationType value)
{
fOptimization = value;
if (fOptimization == kMinimize)
set_minim(fLP);
else
set_maxim(fLP);
return true;
}
/**
* Gets the current optimization.
* The default is minimization.
*
* @return the current optimization
*/
OptimizationType
LPSolveInterface::Optimization() const
{
return fOptimization;
}
bool
LPSolveInterface::SaveModel(const char* fileName)
{
// TODO: Constness should be fixed in liblpsolve API.
if (!write_lp(fLP, const_cast<char*>(fileName)))
return false;
return true;
}
BSize
LPSolveInterface::MinSize(Variable* width, Variable* height)
{
SummandList* newObjFunction = new(std::nothrow) SummandList(2);
newObjFunction->AddItem(new(std::nothrow) Summand(1.0, width));
newObjFunction->AddItem(new(std::nothrow) Summand(1.0, height));
SummandList* oldObjFunction = SwapObjectiveFunction(newObjFunction);
ResultType result = Solve();
SetObjectiveFunction(oldObjFunction);
if (result == kUnbounded)
return kMinSize;
if (result != kOptimal)
printf("Could not solve the layout specification (%d). ", result);
return BSize(width->Value(), height->Value());
}
BSize
LPSolveInterface::MaxSize(Variable* width, Variable* height)
{
SummandList* newObjFunction = new(std::nothrow) SummandList(2);
newObjFunction->AddItem(new(std::nothrow) Summand(-1.0, width));
newObjFunction->AddItem(new(std::nothrow) Summand(-1.0, height));
SummandList* oldObjFunction = SwapObjectiveFunction(
newObjFunction);
ResultType result = Solve();
SetObjectiveFunction(oldObjFunction);
if (result == kUnbounded)
return kMinSize;
if (result != kOptimal)
printf("Could not solve the layout specification (%d). ", result);
return BSize(width->Value(), height->Value());
}
SummandList*
LPSolveInterface::SwapObjectiveFunction(SummandList* objFunction)
{
SummandList* list = fObjFunction;
fObjFunction = objFunction;
_UpdateObjectiveFunction();
return list;
}
/**
* Sets a new objective function.
*
* @param summands SummandList containing the objective function's summands
*/
void
LPSolveInterface::SetObjectiveFunction(SummandList* objFunction)
{
for (int32 i = 0; i < fObjFunction->CountItems(); i++)
delete (Summand*)fObjFunction->ItemAt(i);
delete fObjFunction;
fObjFunction = objFunction;
_UpdateObjectiveFunction();
}
/**
* Gets the objective function.
*
* @return SummandList containing the objective function's summands
*/
SummandList*
LPSolveInterface::ObjectiveFunction()
{
return fObjFunction;
}
double
LPSolveInterface::GetObjectiveValue()
{
if (fLpPresolved)
return get_objective(fLpPresolved);
return get_objective(fLP);
}
/**
* Updates the internal representation of the objective function.
* Must be called whenever the summands of the objective function are changed.
*/
void
LPSolveInterface::_UpdateObjectiveFunction()
{
int32 size = fObjFunction->CountItems();
double coeffs[size];
int varIndexes[size];
Summand* current;
for (int32 i = 0; i < size; i++) {
current = (Summand*)fObjFunction->ItemAt(i);
coeffs[i] = current->Coeff();
varIndexes[i] = current->Var()->GlobalIndex() + 1;
}
if (!SetObjectiveFunction(size, &coeffs[0], &varIndexes[0]))
printf("Error in set_obj_fnex.\n");
}
/**
* Remove a cached presolved model, if existent.
* This is automatically done each time after the model has been changed,
* to avoid an old cached presolved model getting out of sync.
*/
void
LPSolveInterface::_RemovePresolved()
{
if (fLpPresolved == NULL)
return;
delete_lp(fLpPresolved);
fLpPresolved = NULL;
}
/**
* Creates and caches a simplified version of the linear programming problem,
* where redundant rows, columns and constraints are removed,
* if it has not been created before.
* Then, the simplified problem is solved.
*
* @return the result of the solving attempt
*/
ResultType
LPSolveInterface::_Presolve(const VariableList& variables)
{
if (fLpPresolved == NULL) {
fLpPresolved = copy_lp(fLP);
set_presolve(fLpPresolved, PRESOLVE_ROWS | PRESOLVE_COLS
| PRESOLVE_LINDEP, get_presolveloops(fLpPresolved));
}
ResultType result = (ResultType)solve(fLpPresolved);
if (result == OPTIMAL) {
int32 size = variables.CountItems();
for (int32 i = 0; i < size; i++) {
Variable* current = variables.ItemAt(i);
current->SetValue(get_var_primalresult(fLpPresolved,
get_Norig_rows(fLpPresolved) + current->GlobalIndex() + 1));
}
}
return result;
}
-67
View File
@@ -1,67 +0,0 @@
/*
* Copyright 2010, Clemens Zeidler <[email protected]>
* Distributed under the terms of the MIT License.
*/
#ifndef LP_SOLVE_INTERFACE_H
#define LP_SOLVE_INTERFACE_H
#include "LinearSpec.h"
#include "lp_lib.h"
namespace LinearProgramming {
class LPSolveInterface : public SolverInterface {
public:
LPSolveInterface(LinearSpec* linearSpec);
~LPSolveInterface();
ResultType Solve();
bool VariableAdded(Variable* variable);
bool VariableRemoved(Variable* variable);
bool VariableRangeChanged(Variable* variable);
bool ConstraintAdded(Constraint* constraint);
bool ConstraintRemoved(Constraint* constraint);
bool LeftSideChanged(Constraint* constraint);
bool RightSideChanged(Constraint* constraint);
bool OperatorChanged(Constraint* constraint);
bool SaveModel(const char* fileName);
BSize MinSize(Variable* width, Variable* height);
BSize MaxSize(Variable* width, Variable* height);
bool SetOptimization(OptimizationType value);
OptimizationType Optimization() const;
bool SetObjectiveFunction(int nElements,
double* coefficients,
int* variableIndices);
SummandList* ObjectiveFunction();
double GetObjectiveValue();
//! Caller takes ownership of the Summand's and the SummandList.
SummandList* SwapObjectiveFunction(
SummandList* objFunction);
void SetObjectiveFunction(SummandList* objFunction);
private:
void _UpdateObjectiveFunction();
ResultType _Presolve(const VariableList& variables);
void _RemovePresolved();
lprec* fLpPresolved;
lprec* fLP;
OptimizationType fOptimization;
SummandList* fObjFunction;
};
} // namespace LinearProgramming
#endif // LP_SOLVE_INTERFACE_H
-2
View File
@@ -11,7 +11,6 @@
#include <new>
#include <stdio.h>
//#include "LPSolveInterface.h"
#include "ActiveSetSolver.h"
@@ -45,7 +44,6 @@ LinearSpec::LinearSpec()
fResult(kError),
fSolvingTime(0)
{
//fSolver = new LPSolveInterface(this);
fSolver = new ActiveSetSolver(this);
}
+2 -2
View File
@@ -1,6 +1,6 @@
SubDir HAIKU_TOP src tests libs alm ;
UseLibraryHeaders lp_solve linprog alm ;
UseLibraryHeaders linprog alm ;
UsePrivateHeaders shared ;
@@ -56,5 +56,5 @@ Application ALMComplexButtons :
Application ALMBadLayout :
BadLayout.cpp
:
be liblpsolve55.so libalm.so $(TARGET_LIBSTDC++)
be libalm.so $(TARGET_LIBSTDC++)
;