Added libalm.so and its dependency liblinprog.so. libalm.so provides a

BLayout implementation (BALMLayout) using the Auckland Layout Model
(ALM). The original ALM was implemented by Christof Lutteroth, the
Haiku/C++ version by James Kim.
The code needs some review, but the test programs seem to work fine.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23889 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2008-02-06 10:51:44 +00:00
parent 38d596cb81
commit a101e99aad
42 changed files with 5554 additions and 1 deletions

View File

@ -65,7 +65,7 @@ BEOS_SYSTEM_LIB = libbe.so $(HAIKU_LIBSTDC++) libmedia.so libtracker.so
libtranslation.so libnetwork.so libdebug.so libbsd.so libmail.so
libtextencoding.so libz.so libfreetype.so libpng.so libmidi.so libmidi2.so
libdevice.so libgame.so libscreensaver.so <revisioned>libroot.so
$(X86_ONLY)libGL.so libfluidsynth.so
$(X86_ONLY)libGL.so libfluidsynth.so liblpsolve55.so liblinprog.so libalm.so
;
BEOS_SYSTEM_SERVERS = registrar debug_server syslog_daemon media_server
net_server media_addon_server input_server app_server fake_app_server

149
headers/libs/alm/Area.h Normal file
View File

@ -0,0 +1,149 @@
#ifndef AREA_H
#define AREA_H
#include "Constraint.h"
#include "SoftConstraint.h"
#include <Alignment.h>
#include <List.h>
#include <Size.h>
#include <SupportDefs.h>
#include <View.h>
namespace BALM {
class Column;
class BALMLayout;
class Row;
class XTab;
class YTab;
/**
* Rectangular area in the GUI, defined by a tab on each side.
*/
class Area {
public:
bool AutoPrefContentSize() const;
void SetAutoPrefContentSize(bool value);
XTab* Left() const;
void SetLeft(XTab* left);
XTab* Right() const;
void SetRight(XTab* right);
YTab* Top() const;
void SetTop(YTab* top);
YTab* Bottom() const;
void SetBottom(YTab* bottom);
Row* GetRow() const;
void SetRow(Row* row);
Column* GetColumn() const;
void SetColumn(Column* column);
BView* Content() const;
void SetContent(BView* content);
XTab* ContentLeft() const;
YTab* ContentTop() const;
XTab* ContentRight() const;
YTab* ContentBottom() const;
BSize MinContentSize() const;
void SetMinContentSize(BSize min);
BSize MaxContentSize() const;
void SetMaxContentSize(BSize max);
BSize PrefContentSize() const;
void SetPrefContentSize(BSize pref);
BSize ShrinkRigidity() const;
void SetShrinkRigidity(BSize shrink);
BSize ExpandRigidity() const;
void SetExpandRigidity(BSize expand);
double ContentAspectRatio() const;
void SetContentAspectRatio(double ratio);
BAlignment Alignment() const;
void SetAlignment(BAlignment alignment);
void SetHAlignment(alignment horizontal);
void SetVAlignment(vertical_alignment vertical);
int32 LeftInset() const;
void SetLeftInset(int32 left);
int32 TopInset() const;
void SetTopInset(int32 top);
int32 RightInset() const;
void SetRightInset(int32 right);
int32 BottomInset() const;
void SetBottomInset(int32 bottom);
void SetDefaultPrefContentSize();
//~ string ToString();
Constraint* HasSameWidthAs(Area* area);
Constraint* HasSameHeightAs(Area* area);
BList* HasSameSizetAs(Area* area);
~Area();
protected:
Area(BALMLayout* ls, XTab* left, YTab* top,
XTab* right, YTab* bottom,
BView* content,
BSize minContentSize);
Area(BALMLayout* ls, Row* row, Column* column,
BView* content,
BSize minContentSize);
void DoLayout();
private:
void InitChildArea();
void UpdateHorizontal();
void UpdateVertical();
void Init(BALMLayout* ls, XTab* left, YTab* top,
XTab* right, YTab* bottom,
BView* content,
BSize minContentSize);
public:
static BSize kMaxSize;
static BSize kMinSize;
static BSize kUndefinedSize;
protected:
BView* fContent;
BList* fConstraints;
private:
BALMLayout* fLS;
XTab* fLeft;
XTab* fRight;
YTab* fTop;
YTab* fBottom;
Row* fRow;
Column* fColumn;
BSize fMinContentSize;
BSize fMaxContentSize;
Constraint* fMinContentWidth;
Constraint* fMaxContentWidth;
Constraint* fMinContentHeight;
Constraint* fMaxContentHeight;
BSize fPrefContentSize;
BSize fShrinkRigidity;
BSize fExpandRigidity;
double fContentAspectRatio;
Constraint* fContentAspectRatioC;
bool fAutoPrefContentSize;
SoftConstraint* fPrefContentWidth;
SoftConstraint* fPrefContentHeight;
Area* fChildArea;
BAlignment fAlignment;
int32 fLeftInset;
int32 fTopInset;
int32 fRightInset;
int32 fBottomInset;
Constraint* fLeftConstraint;
Constraint* fTopConstraint;
Constraint* fRightConstraint;
Constraint* fBottomConstraint;
public:
friend class BALMLayout;
};
} // namespace BALM
using BALM::Area;
#endif // AREA_H

View File

@ -0,0 +1,106 @@
#ifndef BALM_LAYOUT_H
#define BALM_LAYOUT_H
#include <File.h>
#include <Layout.h>
#include <List.h>
#include <Size.h>
#include <SupportDefs.h>
#include <View.h>
#include "LayoutStyleType.h"
#include "LinearSpec.h"
namespace BALM {
class Area;
class Column;
class Row;
class XTab;
class YTab;
/**
* A GUI layout engine using the ALM.
*/
class BALMLayout : public BLayout, public LinearSpec {
public:
BALMLayout();
void SolveLayout();
XTab* AddXTab();
YTab* AddYTab();
Row* AddRow();
Row* AddRow(YTab* top, YTab* bottom);
Column* AddColumn();
Column* AddColumn(XTab* left, XTab* right);
Area* AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
BView* content, BSize minContentSize);
Area* AddArea(Row* row, Column* column, BView* content,
BSize minContentSize);
Area* AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
BView* content);
Area* AddArea(Row* row, Column* column, BView* content);
Area* AreaOf(BView* control);
BList* Areas() const;
void SetAreas(BList* areas);
XTab* Left() const;
void SetLeft(XTab* left);
XTab* Right() const;
void SetRight(XTab* right);
YTab* Top() const;
void SetTop(YTab* top);
YTab* Bottom() const;
void SetBottom(YTab* bottom);
void RecoverLayout(BView* parent);
LayoutStyleType LayoutStyle() const;
void SetLayoutStyle(LayoutStyleType style);
BLayoutItem* AddView(BView* child);
BLayoutItem* AddView(int32 index, BView* child);
bool AddItem(BLayoutItem* item);
bool AddItem(int32 index, BLayoutItem* item);
bool RemoveView(BView* child);
bool RemoveItem(BLayoutItem* item);
BLayoutItem* RemoveItem(int32 index);
BSize MinSize();
BSize MaxSize();
BSize PreferredSize();
BAlignment Alignment();
bool HasHeightForWidth();
void GetHeightForWidth(float width, float* min,
float* max, float* preferred);
void InvalidateLayout();
void LayoutView();
char* PerformancePath() const;
void SetPerformancePath(char* path);
private:
BSize CalculateMinSize();
BSize CalculateMaxSize();
BSize CalculatePreferredSize();
private:
LayoutStyleType fLayoutStyle;
bool fActivated;
BList* fAreas;
XTab* fLeft;
XTab* fRight;
YTab* fTop;
YTab* fBottom;
BSize fMinSize;
BSize fMaxSize;
BSize fPreferredSize;
char* fPerformancePath;
};
} // namespace BALM
using BALM::BALMLayout;
#endif // BALM_LAYOUT_H

58
headers/libs/alm/Column.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef COLUMN_H
#define COLUMN_H
#include "Constraint.h"
#include <List.h>
namespace BALM {
class BALMLayout;
class XTab;
/**
* Represents a column defined by two x-tabs.
*/
class Column {
public:
XTab* Left() const;
XTab* Right() const;
Column* Previous() const;
void SetPrevious(Column* value);
Column* Next() const;
void SetNext(Column* value);
//~ string ToString();
void InsertBefore(Column* column);
void InsertAfter(Column* column);
Constraint* HasSameWidthAs(Column* column);
BList* Constraints() const;
void SetConstraints(BList* constraints);
~Column();
protected:
Column(BALMLayout* ls);
protected:
BALMLayout* fLS;
XTab* fLeft;
XTab* fRight;
private:
Column* fPrevious;
Column* fNext;
Constraint* fPreviousGlue;
Constraint* fNextGlue;
BList* fConstraints;
public:
friend class BALMLayout;
};
} // namespace BALM
using BALM::Column;
#endif // COLUMN_H

View File

@ -0,0 +1,20 @@
#ifndef LAYOUT_STYLE_TYPE_H
#define LAYOUT_STYLE_TYPE_H
namespace BALM {
/**
* The possibilities for adjusting a GUI's layout.
* Either change the child controls so that they fit into their parent control, or adjust
* the size of the parent control so that the children have as much space as they want.
*/
enum LayoutStyleType {
FIT_TO_SIZE, ADJUST_SIZE
};
} // namespace BALM
using BALM::LayoutStyleType;
#endif

58
headers/libs/alm/Row.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef ROW_H
#define ROW_H
#include "Constraint.h"
#include <List.h>
namespace BALM {
class BALMLayout;
class YTab;
/**
* Represents a row defined by two y-tabs.
*/
class Row {
public:
YTab* Top() const;
YTab* Bottom() const;
Row* Previous() const;
void SetPrevious(Row* value);
Row* Next() const;
void SetNext(Row* value);
//~ string ToString();
void InsertBefore(Row* row);
void InsertAfter(Row* row);
Constraint* HasSameHeightAs(Row* row);
BList* Constraints() const;
void SetConstraints(BList* constraints);
~Row();
protected:
Row(BALMLayout* ls);
protected:
BALMLayout* fLS;
YTab* fTop;
YTab* fBottom;
private:
Row* fPrevious;
Row* fNext;
Constraint* fPreviousGlue;
Constraint* fNextGlue;
BList* fConstraints;
public:
friend class BALMLayout;
};
} // namespace BALM
using BALM::Row;
#endif // ROW_H

38
headers/libs/alm/XTab.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef X_TAB_H
#define X_TAB_H
#include "Variable.h"
namespace BALM {
class BALMLayout;
/**
* Vertical grid line (x-tab).
*/
class XTab : public Variable {
protected:
XTab(BALMLayout* ls);
protected:
/**
* Property signifying if there is a constraint which relates
* this tab to a different tab that is further to the left.
* Only used for reverse engineering.
*/
bool fLeftLink;
public:
friend class Area;
friend class Column;
friend class BALMLayout;
};
} // namespace BALM
using BALM::XTab;
#endif // X_TAB_H

37
headers/libs/alm/YTab.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef Y_TAB_H
#define Y_TAB_H
#include "Variable.h"
namespace BALM {
class BALMLayout;
/**
* Horizontal grid line (y-tab).
*/
class YTab : public Variable {
protected:
YTab(BALMLayout* ls);
protected:
/**
* Property signifying if there is a constraint which relates
* this tab to a different tab that is further to the top.
* Only used for reverse engineering.
*/
bool fTopLink;
public:
friend class Area;
friend class Row;
friend class BALMLayout;
};
} // namespace BALM
using BALM::YTab;
#endif // Y_TAB_H

View File

@ -0,0 +1,56 @@
#ifndef CONSTRAINT_H
#define CONSTRAINT_H
#include "OperatorType.h"
#include <List.h>
#include <String.h>
#include <SupportDefs.h>
namespace LinearProgramming {
class LinearSpec;
/**
* Hard linear constraint, i.e.&nbsp;one that must be satisfied.
* May render a specification infeasible.
*/
class Constraint {
public:
int32 Index();
BList* Coeffs();
BList* Vars();
virtual void ChangeLeftSide(BList* coeffs, BList* vars);
virtual OperatorType Op();
virtual void SetOp(OperatorType value);
double RightSide();
void SetRightSide(double value);
BString ToString();
virtual ~Constraint();
protected:
Constraint();
private:
Constraint(LinearSpec* ls, BList* coeffs, BList* vars,
OperatorType op, double rightSide);
protected:
LinearSpec* fLS;
BList* fCoeffs;
BList* fVars;
OperatorType fOp;
double fRightSide;
public:
friend class LinearSpec;
};
} // namespace LinearProgramming
using LinearProgramming::Constraint;
#endif // CONSTRAINT_H

View File

@ -0,0 +1,124 @@
#ifndef LINEAR_SPEC_H
#define LINEAR_SPEC_H
#include "OperatorType.h"
#include "ResultType.h"
#include "OptimizationType.h"
#include "lp_lib.h"
#include <List.h>
#include <OS.h>
#include <SupportDefs.h>
namespace LinearProgramming {
class Constraint;
class ObjFunctionSummand;
class PenaltyFunction;
class SoftConstraint;
class Variable;
/**
* Specification of a linear programming problem.
*/
class LinearSpec {
public:
LinearSpec();
~LinearSpec();
void UpdateObjFunction();
void SetObjFunction(BList* coeffs, BList* vars);
ObjFunctionSummand* AddObjFunctionSummand(double coeff, Variable* var);
Variable* AddVariable();
Constraint* AddConstraint(BList* coeffs, BList* vars,
OperatorType op, double rightSide);
Constraint* AddConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
OperatorType op, double rightSide);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
OperatorType op, double rightSide);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
double coeff4, Variable* var4,
OperatorType op, double rightSide);
SoftConstraint* AddSoftConstraint(BList* coeffs, BList* vars,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
SoftConstraint* AddSoftConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
SoftConstraint* AddSoftConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
SoftConstraint* AddSoftConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
SoftConstraint* AddSoftConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
double coeff4, Variable* var4,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
PenaltyFunction* AddPenaltyFunction(Variable* var, BList* xs, BList* gs);
void RemovePresolved();
ResultType Presolve();
ResultType Solve();
void Save(char* fname);
int32 Columns() const;
void SetColumns(int32 value);
OptimizationType Optimization() const;
void SetOptimization(OptimizationType value);
lprec* LP() const;
void SetLP(lprec* value);
BList* ObjFunctionSummands() const;
void SetObjFunctionSummands(BList* value);
BList* Variables() const;
void SetVariables(BList* value);
BList* Constraints() const;
void SetConstraints(BList* value);
ResultType Result() const;
void SetResult(ResultType value);
double ObjectiveValue() const;
void SetObjectiveValue(double value);
double SolvingTime() const;
void SetSolvingTime(double value);
protected:
int32 fColumns;
private:
lprec* fLpPresolved;
OptimizationType fOptimization;
lprec* fLP;
BList* fObjFunctionSummands;
BList* fVariables;
BList* fConstraints;
ResultType fResult;
double fObjectiveValue;
double fSolvingTime; // = Double.Nan
public:
friend class ObjFunctionSummand;
friend class SoftConstraint;
};
} // namespace LinearProgramming
using LinearProgramming::LinearSpec;
#endif // LINEAR_SPEC_H

View File

@ -0,0 +1,39 @@
#ifndef OBJ_FUNCTION_SUMMAND_H
#define OBJ_FUNCTION_SUMMAND_H
namespace LinearProgramming {
class LinearSpec;
class Variable;
/**
* A summand of the objective function.
*/
class ObjFunctionSummand {
public:
double Coeff();
void SetCoeff(double coeff);
Variable* Var();
void SetVar(Variable* var);
~ObjFunctionSummand();
protected:
ObjFunctionSummand(LinearSpec* ls, double coeff, Variable* var);
private:
LinearSpec* fLS;
double fCoeff;
Variable* fVar;
public:
friend class LinearSpec;
};
} // namespace LinearProgramming
using LinearProgramming::ObjFunctionSummand;
#endif // OBJ_FUNCTION_SUMMAND_H

View File

@ -0,0 +1,18 @@
#ifndef OPERATOR_TYPE_H
#define OPERATOR_TYPE_H
namespace LinearProgramming {
/**
* Possible operators for linear constraints.
*/
enum OperatorType {
EQ, LE, GE
};
} // namespace LinearProgramming
using LinearProgramming::OperatorType;
#endif

View File

@ -0,0 +1,18 @@
#ifndef OPTIMIZATION_TYPE_H
#define OPTIMIZATION_TYPE_H
namespace LinearProgramming {
/**
* The two possibilities for optimizing the objective function.
*/
enum OptimizationType {
MINIMIZE, MAXIMIZE
};
} // namespace LinearProgramming
using LinearProgramming::OptimizationType;
#endif

View File

@ -0,0 +1,43 @@
#ifndef PENALTY_FUNCTION_H
#define PENALTY_FUNCTION_H
#include <List.h>
namespace LinearProgramming {
class LinearSpec;
class Variable;
/**
* Penalty function.
*/
class PenaltyFunction {
protected:
PenaltyFunction(LinearSpec* ls, Variable* var, BList* xs, BList* gs);
public:
~PenaltyFunction();
const Variable* Var() const;
const BList* Xs() const;
const BList* Gs() const;
private:
LinearSpec* fLS;
Variable* fVar;
BList* fXs; // double
BList* fGs; // double
BList* fConstraints;
BList* fObjFunctionSummands;
public:
friend class LinearSpec;
};
} // namespace LinearProgramming
using LinearProgramming::PenaltyFunction;
#endif // PENALTY_FUNCTION_H

View File

@ -0,0 +1,20 @@
#ifndef RESULT_TYPE_H
#define RESULT_TYPE_H
namespace LinearProgramming {
/**
* The possible results of a solving attempt.
*/
enum ResultType {
NOMEMORY = -2, ERROR = -1, OPTIMAL = 0, SUBOPTIMAL = 1, INFEASIBLE = 2, UNBOUNDED = 3,
DEGENERATE = 4, NUMFAILURE = 5, USERABORT = 6, TIMEOUT = 7, PRESOLVED = 9, PROCFAIL = 10,
PROCBREAK = 11, FEASFOUND = 12, NOFEASFOUND = 13
};
} // namespace LinearProgramming
using LinearProgramming::ResultType;
#endif

View File

@ -0,0 +1,54 @@
#ifndef SOFT_CONSTRAINT_H
#define SOFT_CONSTRAINT_H
#include "Constraint.h"
#include <List.h>
namespace LinearProgramming {
class LinearSpec;
class ObjFunctionSummand;
class Variable;
/**
* Soft constraint, i.e.&nbsp;one that does not necessarily have to be satisfied.
* Use this instead of hard constraints to avoid over-constrained specifications.
*/
class SoftConstraint : public Constraint {
public:
void ChangeLeftSide(BList* coeffs, BList* vars);
OperatorType Op();
void SetOp(OperatorType value);
double PenaltyNeg();
void SetPenaltyNeg(double value);
double PenaltyPos();
void SetPenaltyPos(double value);
//~ string ToString();
Variable* DNeg() const;
Variable* DPos() const;
~SoftConstraint();
protected:
SoftConstraint(LinearSpec* ls, BList* coeffs, BList* vars,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
private:
Variable* fDNeg;
Variable* fDPos;
ObjFunctionSummand* fDNegSummand;
ObjFunctionSummand* fDPosSummand;
public:
friend class LinearSpec;
};
} // namespace LinearProgramming
using LinearProgramming::SoftConstraint;
#endif // SOFT_CONSTRAINT_H

View File

@ -0,0 +1,53 @@
#ifndef VARIABLE_H
#define VARIABLE_H
#include <SupportDefs.h>
namespace LinearProgramming {
class Constraint;
class LinearSpec;
/**
* Contains minimum and maximum values.
*/
class Variable {
public:
int32 Index();
LinearSpec* LS() const;
void SetLS(LinearSpec* value);
double Value() const;
void SetValue(double value);
double Min() const;
void SetMin(double min);
double Max() const;
void SetMax(double max);
void SetRange(double min, double max);
//~ string ToString();
Constraint* IsEqual(Variable* var);
Constraint* IsSmallerOrEqual(Variable* var);
Constraint* IsGreaterorEqual(Variable* var);
protected:
Variable(LinearSpec* ls);
~Variable();
private:
LinearSpec* fLS;
double fValue;
double fMin;
double fMax;
public:
friend class LinearSpec;
friend class SoftConstraint;
};
} // namespace LinearProgramming
using LinearProgramming::Variable;
#endif // VARIABLE_H

View File

@ -1,6 +1,7 @@
SubDir HAIKU_TOP src libs ;
SubInclude HAIKU_TOP src libs agg ;
SubInclude HAIKU_TOP src libs alm ;
SubInclude HAIKU_TOP src libs bsd ;
SubInclude HAIKU_TOP src libs compat ;
SubInclude HAIKU_TOP src libs crypt ;
@ -10,6 +11,8 @@ SubInclude HAIKU_TOP src libs fluidsynth ;
SubInclude HAIKU_TOP src libs freetype2 ;
SubInclude HAIKU_TOP src libs icon ;
SubInclude HAIKU_TOP src libs libtelnet ;
SubInclude HAIKU_TOP src libs linprog ;
SubInclude HAIKU_TOP src libs lp_solve ;
SubInclude HAIKU_TOP src libs ncurses ;
SubInclude HAIKU_TOP src libs pdflib ;
SubInclude HAIKU_TOP src libs png ;

1267
src/libs/alm/Area.cpp Normal file

File diff suppressed because it is too large Load Diff

699
src/libs/alm/BALMLayout.cpp Normal file
View File

@ -0,0 +1,699 @@
#include "BALMLayout.h"
#include "Area.h"
#include "Column.h"
#include "ResultType.h"
#include "Row.h"
#include "XTab.h"
#include "YTab.h"
#include <math.h> // for floor
/**
* Constructor.
* Creates new layout engine.
*/
BALMLayout::BALMLayout()
: BLayout(),
LinearSpec()
{
fLayoutStyle = FIT_TO_SIZE;
fActivated = true;
fAreas = new BList(1);
fLeft = new XTab(this);
fRight = new XTab(this);
fTop = new YTab(this);
fBottom = new YTab(this);
// the Left tab is always at x-position 0, and the Top tab is always at y-position 0
fLeft->SetRange(0, 0);
fTop->SetRange(0, 0);
// cached layout values
// need to be invalidated whenever the layout specification is changed
fMinSize = Area::kUndefinedSize;
fMaxSize = Area::kUndefinedSize;
fPreferredSize = Area::kUndefinedSize;
fPerformancePath = NULL;
}
/**
* Solves the layout.
*/
void
BALMLayout::SolveLayout()
{
// if autoPrefContentSize is set on an area, readjust its prefContentSize and
// rigidity settings
int32 sizeAreas = fAreas->CountItems();
Area* currentArea;
for (int32 i = 0; i < sizeAreas; i++) {
currentArea = (Area*)fAreas->ItemAt(i);
if (currentArea->AutoPrefContentSize())
currentArea->SetDefaultPrefContentSize();
}
// try to solve the layout until the result is OPTIMAL or INFEASIBLE, maximally
// 15 tries sometimes the solving algorithm encounters numerical problems
// (NUMFAILURE), and repeating the solving often helps to overcome them
BFile* file = new BFile(fPerformancePath,
B_READ_WRITE | B_CREATE_FILE | B_OPEN_AT_END);
ResultType result;
for (int32 tries = 0; tries < 15; tries++) {
result = Solve();
if (fPerformancePath != NULL) {
char buffer [100];
file->Write(buffer, sprintf(buffer, "%d\t%fms\t#vars=%d\t#constraints=%d\n",
result, SolvingTime(), Variables()->CountItems(),
Constraints()->CountItems()));
}
if (result == OPTIMAL || result == INFEASIBLE) break;
}
delete file;
}
/**
* Adds a new x-tab to the specification.
*
* @return the new x-tab
*/
XTab*
BALMLayout::AddXTab()
{
return new XTab(this);
}
/**
* Adds a new y-tab to the specification.
*
* @return the new y-tab
*/
YTab*
BALMLayout::AddYTab()
{
return new YTab(this);
}
/**
* Adds a new row to the specification.
*
* @return the new row
*/
Row*
BALMLayout::AddRow()
{
return new Row(this);
}
/**
* Adds a new row to the specification that is glued to the given y-tabs.
*
* @param top
* @param bottom
* @return the new row
*/
Row*
BALMLayout::AddRow(YTab* top, YTab* bottom)
{
Row* row = new Row(this);
if (top != NULL) row->Constraints()->AddItem(row->Top()->IsEqual(top));
if (bottom != NULL) row->Constraints()->AddItem(row->Bottom()->IsEqual(bottom));
return row;
}
/**
* Adds a new column to the specification.
*
* @return the new column
*/
Column*
BALMLayout::AddColumn()
{
return new Column(this);
}
/**
* Adds a new column to the specification that is glued to the given x-tabs.
*
* @param left
* @param right
* @return the new column
*/
Column*
BALMLayout::AddColumn(XTab* left, XTab* right)
{
Column* column = new Column(this);
if (left != NULL) column->Constraints()->AddItem(column->Left()->IsEqual(left));
if (right != NULL) column->Constraints()->AddItem(column->Right()->IsEqual(right));
return column;
}
/**
* Adds a new area to the specification, setting only the necessary minimum size constraints.
*
* @param left left border
* @param top top border
* @param right right border
* @param bottom bottom border
* @param content the control which is the area content
* @param minContentSize minimum content size
* @return the new area
*/
Area*
BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
BView* content, BSize minContentSize)
{
InvalidateLayout();
if (content != NULL)
View()->AddChild(content);
Area* area = new Area(this, left, top, right, bottom, content, minContentSize);
fAreas->AddItem(area);
return area;
}
/**
* Adds a new area to the specification, setting only the necessary minimum size constraints.
*
* @param row the row that defines the top and bottom border
* @param column the column that defines the left and right border
* @param content the control which is the area content
* @param minContentSize minimum content size
* @return the new area
*/
Area*
BALMLayout::AddArea(Row* row, Column* column, BView* content,
BSize minContentSize)
{
InvalidateLayout();
if (content != NULL)
View()->AddChild(content);
Area* area = new Area(this, row, column, content, minContentSize);
fAreas->AddItem(area);
return area;
}
/**
* Adds a new area to the specification, automatically setting preferred size constraints.
*
* @param left left border
* @param top top border
* @param right right border
* @param bottom bottom border
* @param content the control which is the area content
* @return the new area
*/
Area*
BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
BView* content)
{
InvalidateLayout();
if (content != NULL)
View()->AddChild(content);
Area* area = new Area(this, left, top, right, bottom, content, BSize(0, 0));
area->SetDefaultPrefContentSize();
area->SetAutoPrefContentSize(true);
fAreas->AddItem(area);
return area;
}
/**
* Adds a new area to the specification, automatically setting preferred size constraints.
*
* @param row the row that defines the top and bottom border
* @param column the column that defines the left and right border
* @param content the control which is the area content
* @return the new area
*/
Area*
BALMLayout::AddArea(Row* row, Column* column, BView* content)
{
InvalidateLayout();
if (content != NULL)
View()->AddChild(content);
Area* area = new Area(this, row, column, content, BSize(0, 0));
area->SetDefaultPrefContentSize();
area->SetAutoPrefContentSize(true);
fAreas->AddItem(area);
return area;
}
/**
* Finds the area that contains the given control.
*
* @param control the control to look for
* @return the area that contains the control
*/
Area*
BALMLayout::AreaOf(BView* control)
{
Area* area;
for (int32 i = 0; i < fAreas->CountItems(); i++) {
area = (Area*)fAreas->ItemAt(i);
if (area->Content() == control)
return area;
}
return NULL;
}
/**
* Gets the ares.
*
* @return the areas
*/
BList*
BALMLayout::Areas() const
{
return fAreas;
}
/**
* Sets the ares.
*
* @param areas the areas
*/
void
BALMLayout::SetAreas(BList* areas)
{
fAreas = areas;
}
/**
* Gets the left variable.
*/
XTab*
BALMLayout::Left() const
{
return fLeft;
}
/**
* Sets the left variable.
*/
void
BALMLayout::SetLeft(XTab* left)
{
fLeft = left;
}
/**
* Gets the right variable.
*/
XTab*
BALMLayout::Right() const
{
return fRight;
}
/**
* Sets the right variable.
*/
void
BALMLayout::SetRight(XTab* right)
{
fRight = right;
}
/**
* Gets the top variable.
*/
YTab*
BALMLayout::Top() const
{
return fTop;
}
/**
* Sets the top variable.
*/
void
BALMLayout::SetTop(YTab* top)
{
fTop = top;
}
/**
* Gets the bottom variable.
*/
YTab*
BALMLayout::Bottom() const
{
return fBottom;
}
/**
* Sets the bottom variable.
*/
void
BALMLayout::SetBottom(YTab* bottom)
{
fBottom = bottom;
}
/**
* Reverse engineers a GUI and recovers an ALM specification.
* @param parent the parent container of the GUI
*/
void
BALMLayout::RecoverLayout(BView* parent) {} // Still working on it.
/**
* Gets the current layout style.
*/
LayoutStyleType
BALMLayout::LayoutStyle() const
{
return fLayoutStyle;
}
/**
* Sets the current layout style.
*/
void
BALMLayout::SetLayoutStyle(LayoutStyleType style)
{
fLayoutStyle = style;
}
/**
* Adds view to layout.
*/
BLayoutItem*
BALMLayout::AddView(BView* child)
{
return NULL;
}
/**
* Adds view to layout.
*/
BLayoutItem*
BALMLayout::AddView(int32 index, BView* child)
{
return NULL;
}
/**
* Adds item to layout.
*/
bool
BALMLayout::AddItem(BLayoutItem* item)
{
return false;
}
/**
* Adds item to layout.
*/
bool
BALMLayout::AddItem(int32 index, BLayoutItem* item)
{
return false;
}
/**
* Removes view from layout.
*/
bool
BALMLayout::RemoveView(BView* child)
{
return false;
}
/**
* Removes item from layout.
*/
bool
BALMLayout::RemoveItem(BLayoutItem* item)
{
return false;
}
/**
* Removes item from layout.
*/
BLayoutItem*
BALMLayout::RemoveItem(int32 index)
{
return NULL;
}
/**
* Sets and gets minimum size.
*/
BSize BALMLayout::MinSize() {
if (fMinSize == Area::kUndefinedSize)
fMinSize = CalculateMinSize();
return fMinSize;
}
/**
* Sets and gets maximum size.
*/
BSize
BALMLayout::MaxSize()
{
if (fMaxSize == Area::kUndefinedSize)
fMaxSize = CalculateMaxSize();
return fMaxSize;
}
/**
* Sets and gets preferred size.
*/
BSize
BALMLayout::PreferredSize()
{
if (fPreferredSize == Area::kUndefinedSize)
fPreferredSize = CalculatePreferredSize();
return fPreferredSize;
}
/**
* Gets the alignment.
*/
BAlignment
BALMLayout::Alignment()
{
BAlignment alignment;
alignment.SetHorizontal(B_ALIGN_HORIZONTAL_CENTER);
alignment.SetVertical(B_ALIGN_VERTICAL_CENTER);
return alignment;
}
/**
* Gets whether the height of the layout depends on its width.
*/
bool
BALMLayout::HasHeightForWidth()
{
return false;
}
/**
* Sets whether the height of the layout depends on its width.
*/
void
BALMLayout::GetHeightForWidth(float width, float* min, float* max, float* preferred) {}
/**
* Invalidates the layout.
* Resets minimum/maximum/preferred size.
*/
void
BALMLayout::InvalidateLayout()
{
fMinSize = Area::kUndefinedSize;
fMaxSize = Area::kUndefinedSize;
fPreferredSize = Area::kUndefinedSize;
}
/**
* Calculate and set the layout.
* If no layout specification is given, a specification is reverse engineered automatically.
*/
void
BALMLayout::LayoutView()
{
// make sure that layout events occuring during layout are ignored
// i.e. activated is set to false during layout caluclation
if (!fActivated)
return;
fActivated = false;
if (View() == NULL)
return;
// reverse engineer a layout specification if none was given
//~ if (this == NULL) RecoverLayout(View());
// if the layout engine is set to fit the GUI to the given size,
// then the given size is enforced by setting absolute positions for Right and Bottom
if (fLayoutStyle == FIT_TO_SIZE) {
Right()->SetRange(View()->Bounds().Width(), View()->Bounds().Width());
Bottom()->SetRange(View()->Bounds().Height(), View()->Bounds().Height());
}
SolveLayout();
// if new layout is infasible, use previous layout
if (Result() == INFEASIBLE) {
fActivated = true; // now layout calculation is allowed to run again
return;
}
if (Result() != OPTIMAL) {
Save("failed-layout.txt");
printf("Could not solve the layout specification (%d). ", Result());
printf("Saved specification in file failed-layout.txt\n");
}
// change the size of the GUI according to the calculated size
// if the layout engine was configured to do so
if (fLayoutStyle == ADJUST_SIZE) {
View()->ResizeTo(floor(Right()->Value() - Left()->Value() + 0.5),
floor(Bottom()->Value() - Top()->Value() + 0.5));
}
// set the calculated positions and sizes for every area
for (int32 i = 0; i < Areas()->CountItems(); i++)
((Area*)Areas()->ItemAt(i))->DoLayout();
fActivated = true;
}
/**
* Gets the path of the performance log file.
*
* @return the path of the performance log file
*/
char*
BALMLayout::PerformancePath() const
{
return fPerformancePath;
}
/**
* Sets the path of the performance log file.
*
* @param path the path of the performance log file
*/
void
BALMLayout::SetPerformancePath(char* path)
{
fPerformancePath = path;
}
/**
* Caculates the miminum size.
*/
BSize
BALMLayout::CalculateMinSize()
{
printf("CalculateMinSize");
BList* buf = ObjFunctionSummands();
SetObjFunctionSummands(new BList(2));
AddObjFunctionSummand(1.0, fRight);
AddObjFunctionSummand(1.0, fBottom);
SolveLayout();
SetObjFunctionSummands(buf);
UpdateObjFunction();
if (Result() == UNBOUNDED)
return Area::kMinSize;
if (Result() != OPTIMAL) {
Save("failed-layout.txt");
printf("Could not solve the layout specification (%d). Saved specification in file failed-layout.txt", Result());
}
return BSize(Right()->Value() - Left()->Value(), Bottom()->Value() - Top()->Value());
}
/**
* Caculates the maximum size.
*/
BSize
BALMLayout::CalculateMaxSize()
{
printf("CalculateMaxSize");
BList* buf = ObjFunctionSummands();
SetObjFunctionSummands(new BList(2));
AddObjFunctionSummand(-1.0, fRight);
AddObjFunctionSummand(-1.0, fBottom);
SolveLayout();
SetObjFunctionSummands(buf);
UpdateObjFunction();
if (Result() == UNBOUNDED)
return Area::kMaxSize;
if (Result() != OPTIMAL) {
Save("failed-layout.txt");
printf("Could not solve the layout specification (%d). Saved specification in file failed-layout.txt", Result());
}
return BSize(Right()->Value() - Left()->Value(), Bottom()->Value() - Top()->Value());
}
/**
* Caculates the preferred size.
*/
BSize
BALMLayout::CalculatePreferredSize()
{
printf("CalculatePreferredSize");
SolveLayout();
if (Result() != OPTIMAL) {
Save("failed-layout.txt");
printf("Could not solve the layout specification (%d). Saved specification in file failed-layout.txt", Result());
}
return BSize(Right()->Value() - Left()->Value(), Bottom()->Value() - Top()->Value());
}

218
src/libs/alm/Column.cpp Normal file
View File

@ -0,0 +1,218 @@
#include "Column.h"
#include "BALMLayout.h"
#include "OperatorType.h"
#include "XTab.h"
#include <SupportDefs.h>
/**
* The left boundary of the column.
*/
XTab*
Column::Left() const
{
return fLeft;
}
/**
* The right boundary of the column.
*/
XTab*
Column::Right() const
{
return fRight;
}
/**
* Gets the column directly to the left of this column.
*/
Column*
Column::Previous() const
{
return fPrevious;
}
/**
* Sets the column directly to the left of this column.
* May be null.
*/
void
Column::SetPrevious(Column* value)
{
// if there should be no column directly left of this column, then we have to
// separate any such column and can remove any constraint that was used
// to glue this column to it
if (value == NULL) {
if (fPrevious == NULL) return;
fPrevious->fNext = NULL;
fPrevious->fNextGlue = NULL;
fPrevious = NULL;
delete fPreviousGlue;
fPreviousGlue = NULL;
return;
}
// otherwise we have to set up the pointers and the glue constraint accordingly
if (value->fNext != NULL)
value->SetNext(NULL);
if (fPrevious != NULL)
SetPrevious(NULL);
fPrevious = value;
fPrevious->fNext = this;
value->fNextGlue = value->fRight->IsEqual(fLeft);
fPreviousGlue = value->fNextGlue;
}
/**
* Gets the column directly to the right of this column.
*/
Column*
Column::Next() const
{
return fNext;
}
/**
* Sets the column directly to the right of this column.
* May be null.
*/
void
Column::SetNext(Column* value)
{
// if there should be no column directly right of this column, then we have to
// separate any such column and can remove any constraint that was used
// to glue this column to it
if (value == NULL) {
if (fNext == NULL) return;
fNext->fPrevious = NULL;
fNext->fPreviousGlue = NULL;
fNext = NULL;
delete fNextGlue;
fNextGlue = NULL;
return;
}
// otherwise we have to set up the pointers and the glue constraint accordingly
if (value->fPrevious != NULL)
value->SetPrevious(NULL);
if (fNext != NULL)
SetNext(NULL);
fNext = value;
fNext->fPrevious = this;
value->fPreviousGlue = fRight->IsEqual(value->fLeft);
fNextGlue = value->fPreviousGlue;
}
//~ string Column::ToString() {
//~ return "Column(" + fLeft.ToString() + ", " + fRight.ToString() + ")";
//~ }
/**
* Inserts the given column directly to the left of this column.
*
* @param column the column to insert
*/
void
Column::InsertBefore(Column* column)
{
SetPrevious(column->fPrevious);
SetNext(column);
}
/**
* Inserts the given column directly to the right of this column.
*
* @param column the column to insert
*/
void
Column::InsertAfter(Column* column)
{
SetNext(column->fNext);
SetPrevious(column);
}
/**
* Constrains this column to have the same width as the given column.
*
* @param column the column that should have the same width
* @return the resulting same-width constraint
*/
Constraint*
Column::HasSameWidthAs(Column* column)
{
BList* coeffs = new BList(4);
coeffs->AddItem(new double(-1.0));
coeffs->AddItem(new double(1.0));
coeffs->AddItem(new double(1.0));
coeffs->AddItem(new double(-1.0));
BList* vars = new BList(4);
vars->AddItem(fLeft);
vars->AddItem(fRight);
vars->AddItem(column->fLeft);
vars->AddItem(column->fRight);
Constraint* constraint = fLS->AddConstraint(coeffs, vars, OperatorType(EQ), 0.0);
fConstraints->AddItem(constraint);
return constraint;
}
/**
* Gets the constraints.
*/
BList*
Column::Constraints() const
{
return fConstraints;
}
/**
* Sets the constraints.
*/
void
Column::SetConstraints(BList* constraints)
{
fConstraints = constraints;
}
/**
* Destructor.
* Removes the column from the specification.
*/
Column::~Column()
{
if (fPrevious != NULL)
fPrevious->SetNext(fNext);
for (int32 i = 0; i < fConstraints->CountItems(); i++)
delete (Constraint*)fConstraints->ItemAt(i);
delete fLeft;
delete fRight;
}
/**
* Constructor.
*/
Column::Column(BALMLayout* ls)
{
fLS = ls;
fLeft = new XTab(ls);
fRight = new XTab(ls);
fConstraints = new BList(1);
}

17
src/libs/alm/Jamfile Normal file
View File

@ -0,0 +1,17 @@
SubDir HAIKU_TOP src libs alm ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UseLibraryHeaders lp_solve linprog alm ;
SharedLibrary libalm.so :
Area.cpp
Column.cpp
BALMLayout.cpp
Row.cpp
XTab.cpp
YTab.cpp
:
be liblpsolve55.so liblinprog.so
;

220
src/libs/alm/Row.cpp Normal file
View File

@ -0,0 +1,220 @@
#include "Row.h"
#include "BALMLayout.h"
#include "OperatorType.h"
#include "YTab.h"
#include <SupportDefs.h>
/**
* The top boundary of the row.
*/
YTab*
Row::Top() const
{
return fTop;
}
/**
* The bottom boundary of the row.
*/
YTab*
Row::Bottom() const
{
return fBottom;
}
/**
* Gets the row directly above this row.
*/
Row*
Row::Previous() const
{
return fPrevious;
}
/**
* Sets the row directly above this row.
* May be null.
*/
void
Row::SetPrevious(Row* value)
{
// if there should be no row directly above this row, then we have to
// separate any such row and can remove any constraint that was used
// to glue this row to it
if (value == NULL) {
if (fPrevious == NULL)
return;
fPrevious->fNext = NULL;
fPrevious->fNextGlue = NULL;
fPrevious = NULL;
delete fPreviousGlue;
fPreviousGlue = NULL;
return;
}
// otherwise we have to set up the pointers and the glue constraint accordingly
if (value->fNext != NULL)
value->SetNext(NULL);
if (fPrevious != NULL)
SetPrevious(NULL);
fPrevious = value;
fPrevious->fNext = this;
value->fNextGlue = value->fBottom->IsEqual(fTop);
fPreviousGlue = value->fNextGlue;
}
/**
* Gets the row directly below this row.
*/
Row*
Row::Next() const
{
return fNext;
}
/**
* Sets the row directly below this row.
* May be null.
*/
void
Row::SetNext(Row* value)
{
// if there should be no row directly below this row, then we have to
// separate any such row and can remove any constraint that was used
// to glue this row to it
if (value == NULL) {
if (fNext == NULL)
return;
fNext->fPrevious = NULL;
fNext->fPreviousGlue = NULL;
fNext = NULL;
delete fNextGlue;
fNextGlue = NULL;
return;
}
// otherwise we have to set up the pointers and the glue constraint accordingly
if (value->fPrevious != NULL)
value->SetPrevious(NULL);
if (fNext != NULL)
SetNext(NULL);
fNext = value;
fNext->fPrevious = this;
value->fPreviousGlue = fBottom->IsEqual(value->fTop);
fNextGlue = value->fPreviousGlue;
}
//~ string Row::ToString() {
//~ return "Row(" + fTop.ToString() + ", " + fBottom.ToString() + ")";
//~ }
/**
* Inserts the given row directly above this row.
*
* @param row the row to insert
*/
void
Row::InsertBefore(Row* row)
{
SetPrevious(row->fPrevious);
SetNext(row);
}
/**
* Inserts the given row directly below this row.
*
* @param row the row to insert
*/
void
Row::InsertAfter(Row* row)
{
SetNext(row->fNext);
SetPrevious(row);
}
/**
* Constrains this row to have the same height as the given row.
*
* @param row the row that should have the same height
* @return the resulting same-height constraint
*/
Constraint*
Row::HasSameHeightAs(Row* row)
{
BList* coeffs = new BList(4);
coeffs->AddItem(new double(-1.0));
coeffs->AddItem(new double(1.0));
coeffs->AddItem(new double(1.0));
coeffs->AddItem(new double(-1.0));
BList* vars = new BList(4);
vars->AddItem(fTop);
vars->AddItem(fBottom);
vars->AddItem(row->fTop);
vars->AddItem(row->fBottom);
Constraint* constraint = fLS->AddConstraint(coeffs, vars, OperatorType(EQ), 0.0);
fConstraints->AddItem(constraint);
return constraint;
}
/**
* Gets the constraints.
*/
BList*
Row::Constraints() const
{
return fConstraints;
}
/**
* Sets the constraints.
*/
void
Row::SetConstraints(BList* constraints)
{
fConstraints = constraints;
}
/**
* Destructor.
* Removes the row from the specification.
*/
Row::~Row()
{
if (fPrevious != NULL)
fPrevious->SetNext(fNext);
for (int32 i = 0; i < fConstraints->CountItems(); i++)
delete (Constraint*)fConstraints->ItemAt(i);
delete fTop;
delete fBottom;
}
/**
* Constructor.
*/
Row::Row(BALMLayout* ls)
{
fLS = ls;
fTop = new YTab(ls);
fBottom = new YTab(ls);
fConstraints = new BList(1);
}

13
src/libs/alm/XTab.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "XTab.h"
#include "BALMLayout.h"
/**
* Constructor.
*/
XTab::XTab(BALMLayout* ls)
: Variable(ls)
{
fLeftLink = false;
}

13
src/libs/alm/YTab.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "YTab.h"
#include "BALMLayout.h"
/**
* Constructor.
*/
YTab::YTab(BALMLayout* ls)
: Variable(ls)
{
fTopLink = false;
}

View File

@ -0,0 +1,206 @@
#include "Constraint.h"
#include "LinearSpec.h"
#include "Variable.h"
#include "lp_lib.h"
/**
* Gets the index of the constraint.
*
* @return the index of the constraint
*/
int32
Constraint::Index()
{
int32 i = fLS->Constraints()->IndexOf(this);
if (i == -1)
printf("Constraint not part of fLS->Constraints().");
return i + 1;
}
/**
* Gets the coefficients of the constraint.
*
* @return the coefficients of the constraint
*/
BList*
Constraint::Coeffs()
{
return fCoeffs;
}
/**
* Gets the variables of the constraint.
*
* @return the variables of the constraint
*/
BList*
Constraint::Vars()
{
return fVars;
}
/**
* Changes the left side of the constraint, i.e.&nbsp;its coefficients and variables.
* There must be exactly one coefficient for each variable.
*
* @param coeffs the new coefficients
* @param vars the new variables
*/
void
Constraint::ChangeLeftSide(BList* coeffs, BList* vars)
{
int32 sizeCoeffs = coeffs->CountItems();
int32 sizeVars = vars->CountItems();
if (sizeCoeffs != sizeVars)
printf("Number of coefficients and number of variables in a constraint must be equal.");
fCoeffs = coeffs;
fVars = vars;
double coeffsArray[sizeCoeffs];
for (int32 i = 0; i < sizeCoeffs; i++)
coeffsArray[i] = *(double*)coeffs->ItemAt(i);
int vIndexes[sizeCoeffs];
for (int32 i = 0; i < sizeVars; i++)
vIndexes[i] = ((Variable*)vars->ItemAt(i))->Index();
if (!set_rowex(fLS->LP(), this->Index(), sizeCoeffs, &coeffsArray[0], &vIndexes[0]))
printf("Error in set_rowex.");
fLS->RemovePresolved();
}
/**
* Gets the operator used for this constraint.
*
* @return the operator used for this constraint
*/
OperatorType
Constraint::Op()
{
return fOp;
}
/**
* Sets the operator used for this constraint.
*
* @param value operator
*/
void
Constraint::SetOp(OperatorType value)
{
fOp = value;
if (!set_constr_type(fLS->LP(), this->Index(),
((fOp == OperatorType(EQ)) ? EQ
: (fOp == OperatorType(GE)) ? GE
: LE)))
printf("Error in set_constr_type.");
fLS->RemovePresolved();
}
/**
* Gets 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
Constraint::RightSide()
{
return fRightSide;
}
/**
* Sets the constant value that is on the right side of the operator.
*
* @param value constant value that is on the right side of the operator
*/
void
Constraint::SetRightSide(double value)
{
fRightSide = value;
if (!set_rh(fLS->LP(), Index(), fRightSide))
printf("Error in set_rh.");
fLS->RemovePresolved();
}
// Needs to be fixed. Use BString. Substring?
//~ string Constraint::ToString() {
//~ string s = "";
//~ for (int32 i = 0; i < fVars->CountItems(); i++)
//~ s += (double)fCoeffs->ItemAt(i) + "*" + (Variable*)fVars->ItemAt(i).ToString() + " + ";
//~ s = s.Substring(0, s.Length - 2);
//~ if (Op == OperatorType.EQ) s += "= ";
//~ else if (Op == OperatorType.GE) s += ">= ";
//~ else s += "<= ";
//~ s += rightSide.ToString();
//~ return s;
//~ }
/**
* Destructor.
* Removes the constraint from its specification.
*/
Constraint::~Constraint()
{
del_constraint(fLS->LP(), Index());
delete fCoeffs;
delete fVars;
fLS->Constraints()->RemoveItem(this);
}
/**
* Default constructor.
*/
Constraint::Constraint() {}
/**
* Constructor.
*/
Constraint::Constraint(LinearSpec* ls, BList* coeffs, BList* vars, OperatorType op,
double rightSide)
{
int32 sizeCoeffs = coeffs->CountItems();
int32 sizeVars = vars->CountItems();
if (sizeCoeffs != sizeVars)
printf("Number of coefficients and number of variables in a constraint must be equal.");
fLS = ls;
fCoeffs = coeffs;
fVars = vars;
fOp = op;
fRightSide = rightSide;
double coeffsArray[sizeCoeffs];
for (int32 i = 0; i < sizeCoeffs; i++)
coeffsArray[i] = *(double*)coeffs->ItemAt(i);
int vIndexes[sizeCoeffs];
for (int32 i = 0; i < sizeVars; i++)
vIndexes[i] = ((Variable*)vars->ItemAt(i))->Index();
if (!add_constraintex(ls->LP(), sizeCoeffs, &coeffsArray[0], &vIndexes[0],
((op == OperatorType(EQ)) ? EQ
: (op == OperatorType(GE)) ? GE
: LE), rightSide))
printf("Error in add_constraintex.");
ls->Constraints()->AddItem(this);
}

17
src/libs/linprog/Jamfile Normal file
View File

@ -0,0 +1,17 @@
SubDir HAIKU_TOP src libs linprog ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UseLibraryHeaders lp_solve linprog ;
SharedLibrary liblinprog.so :
Constraint.cpp
LinearSpec.cpp
ObjFunctionSummand.cpp
PenaltyFunction.cpp
SoftConstraint.cpp
Variable.cpp
:
be liblpsolve55.so
;

View File

@ -0,0 +1,736 @@
#include "LinearSpec.h"
#include "Constraint.h"
#include "ObjFunctionSummand.h"
#include "PenaltyFunction.h"
#include "SoftConstraint.h"
#include "Variable.h"
#include "lp_lib.h"
/**
* Constructor.
* Creates a new specification for a linear programming problem.
*/
LinearSpec::LinearSpec()
{
fLP = make_lp(0, 0);
if (fLP == NULL)
printf("Couldn't construct a new model.");
set_verbose(fLP, 1);
fObjFunctionSummands = new BList(1);
fVariables = new BList(1);
fConstraints = new BList(1);
fColumns = 0;
fLpPresolved = NULL;
fOptimization = MINIMIZE;
fResult = ERROR;
fObjectiveValue = NULL;
}
/**
* Destructor.
* Removes the specification.
*/
LinearSpec::~LinearSpec()
{
delete_lp(fLP);
}
/**
* Updates the objective function.
*/
void
LinearSpec::UpdateObjFunction()
{
int32 size = fObjFunctionSummands->CountItems();;
double coeffs[size];
int vIndexes[size];
ObjFunctionSummand* current;
for (int32 i = 0; i < size; i++) {
current = (ObjFunctionSummand*)fObjFunctionSummands->ItemAt(i);
coeffs[i] = current->Coeff();
vIndexes[i] = current->Var()->Index();
}
if (!set_obj_fnex(fLP, size, &coeffs[0], &vIndexes[0]))
printf("Error in set_obj_fnex.");
RemovePresolved();
}
/**
* Sets the objective function.
*
* @param coeffs the objective function's coefficients
* @param vars the objective function's variables
*/
void
LinearSpec::SetObjFunction(BList* coeffs, BList* vars)
{
int32 sizeCoeffs = coeffs->CountItems();
int32 sizeVars = vars->CountItems();
if (sizeCoeffs != sizeVars)
printf("Number of coefficients and number of fVariables in objective function must be equal.");
fObjFunctionSummands = new BList(1);
for (int32 i = 0; i < sizeCoeffs; i++)
fObjFunctionSummands->AddItem(new ObjFunctionSummand(this,
*(double*)coeffs->ItemAt(i), (Variable*)vars->ItemAt(i)));
UpdateObjFunction();
}
/**
* Adds a new summand to the objective function.
*
* @param coeff the summand's coefficient
* @param var the summand's variable
* @return the new summand
*/
ObjFunctionSummand*
LinearSpec::AddObjFunctionSummand(double coeff, Variable* var)
{
ObjFunctionSummand* s = new ObjFunctionSummand(this, coeff, var);
fObjFunctionSummands->AddItem(s);
UpdateObjFunction();
return s;
}
/**
* Adds a new variable to the specification.
*
* @return the new variable
*/
Variable*
LinearSpec::AddVariable()
{
return new Variable(this);
}
/**
* Adds a new hard linear constraint to the specification.
*
* @param coeffs the constraint's coefficients
* @param vars the constraint's variables
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(BList* coeffs, BList* vars, OperatorType op,
double rightSide)
{
Constraint* c = new Constraint(this, coeffs, vars, op, rightSide);
RemovePresolved();
return c;
}
/**
* Adds a new hard linear constraint to the specification with a single summand.
*
* @param coeff1 the constraint's first coefficient
* @param var1 the constraint's first variable
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide)
{
BList* coeffs = new BList(1);
coeffs->AddItem(new double(coeff1));
BList* vars = new BList(1);
vars->AddItem(var1);
Constraint* c = AddConstraint(coeffs, vars, op, rightSide);
return c;
}
/**
* Adds a new hard linear constraint to the specification with two summands.
*
* @param coeff1 the constraint's first coefficient
* @param var1 the constraint's first variable
* @param coeff2 the constraint's second coefficient
* @param var2 the constraint's second variable
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, OperatorType op, double rightSide)
{
BList* coeffs = new BList(2);
coeffs->AddItem(new double(coeff1));
coeffs->AddItem(new double(coeff2));
BList* vars = new BList(2);
vars->AddItem(var1);
vars->AddItem(var2);
Constraint* c = AddConstraint(coeffs, vars, op, rightSide);
return c;
}
/**
* Adds a new hard linear constraint to the specification with three summands.
*
* @param coeff1 the constraint's first coefficient
* @param var1 the constraint's first variable
* @param coeff2 the constraint's second coefficient
* @param var2 the constraint's second variable
* @param coeff3 the constraint's third coefficient
* @param var3 the constraint's third variable
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
OperatorType op, double rightSide)
{
BList* coeffs = new BList(3);
coeffs->AddItem(new double(coeff1));
coeffs->AddItem(new double(coeff2));
coeffs->AddItem(new double(coeff3));
BList* vars = new BList(3);
vars->AddItem(var1);
vars->AddItem(var2);
vars->AddItem(var3);
Constraint* c = AddConstraint(coeffs, vars, op, rightSide);
return c;
}
/**
* Adds a new hard linear constraint to the specification with four summands.
*
* @param coeff1 the constraint's first coefficient
* @param var1 the constraint's first variable
* @param coeff2 the constraint's second coefficient
* @param var2 the constraint's second variable
* @param coeff3 the constraint's third coefficient
* @param var3 the constraint's third variable
* @param coeff4 the constraint's fourth coefficient
* @param var4 the constraint's fourth variable
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
double coeff4, Variable* var4, OperatorType op, double rightSide)
{
BList* coeffs = new BList(4);
coeffs->AddItem(new double(coeff1));
coeffs->AddItem(new double(coeff2));
coeffs->AddItem(new double(coeff3));
coeffs->AddItem(new double(coeff4));
BList* vars = new BList(4);
vars->AddItem(var1);
vars->AddItem(var2);
vars->AddItem(var3);
vars->AddItem(var4);
Constraint* c = AddConstraint(coeffs, vars, op, rightSide);
return c;
}
/**
* Adds a new soft linear constraint to the specification.
* i.e. a constraint that does not always have to be satisfied.
*
* @param coeffs the constraint's coefficients
* @param vars the constraint's variables
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @param penaltyNeg the coefficient penalizing negative deviations from the exact solution
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
SoftConstraint*
LinearSpec::AddSoftConstraint(BList* coeffs, BList* vars, OperatorType op,
double rightSide, double penaltyNeg, double penaltyPos)
{
SoftConstraint* c = new SoftConstraint(this, coeffs, vars, op, rightSide,
penaltyNeg, penaltyPos);
RemovePresolved();
return c;
}
/**
* Adds a new soft linear constraint to the specification with a single summand.
*
* @param coeff1 the constraint's first coefficient
* @param var1 the constraint's first variable
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @param penaltyNeg the coefficient penalizing negative deviations from the exact solution
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
SoftConstraint*
LinearSpec::AddSoftConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide, double penaltyNeg, double penaltyPos)
{
BList* coeffs = new BList(1);
coeffs->AddItem(new double(coeff1));
BList* vars = new BList(1);
vars->AddItem(var1);
SoftConstraint* c = AddSoftConstraint(coeffs, vars, op, rightSide,
penaltyNeg, penaltyPos);
return c;
}
/**
* Adds a new soft linear constraint to the specification with two summands.
*
* @param coeff1 the constraint's first coefficient
* @param var1 the constraint's first variable
* @param coeff2 the constraint's second coefficient
* @param var2 the constraint's second variable
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @param penaltyNeg the coefficient penalizing negative deviations from the exact solution
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
SoftConstraint*
LinearSpec::AddSoftConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos)
{
BList* coeffs = new BList(2);
coeffs->AddItem(new double(coeff1));
coeffs->AddItem(new double(coeff2));
BList* vars = new BList(2);
vars->AddItem(var1);
vars->AddItem(var2);
SoftConstraint* c = AddSoftConstraint(coeffs, vars, op, rightSide,
penaltyNeg, penaltyPos);
return c;
}
/**
* Adds a new soft linear constraint to the specification with three summands.
*
* @param coeff1 the constraint's first coefficient
* @param var1 the constraint's first variable
* @param coeff2 the constraint's second coefficient
* @param var2 the constraint's second variable
* @param coeff3 the constraint's third coefficient
* @param var3 the constraint's third variable
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @param penaltyNeg the coefficient penalizing negative deviations from the exact solution
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
SoftConstraint*
LinearSpec::AddSoftConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
OperatorType op, double rightSide, double penaltyNeg, double penaltyPos)
{
BList* coeffs = new BList(3);
coeffs->AddItem(new double(coeff1));
coeffs->AddItem(new double(coeff2));
coeffs->AddItem(new double(coeff3));
BList* vars = new BList(3);
vars->AddItem(var1);
vars->AddItem(var2);
vars->AddItem(var3);
SoftConstraint* c = AddSoftConstraint(coeffs, vars, op, rightSide,
penaltyNeg, penaltyPos);
return c;
}
/**
* Adds a new soft linear constraint to the specification with four summands.
*
* @param coeff1 the constraint's first coefficient
* @param var1 the constraint's first variable
* @param coeff2 the constraint's second coefficient
* @param var2 the constraint's second variable
* @param coeff3 the constraint's third coefficient
* @param var3 the constraint's third variable
* @param coeff4 the constraint's fourth coefficient
* @param var4 the constraint's fourth variable
* @param op the constraint's operand
* @param rightSide the constant value on the constraint's right side
* @param penaltyNeg the coefficient penalizing negative deviations from the exact solution
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
SoftConstraint*
LinearSpec::AddSoftConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
double coeff4, Variable* var4, OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos)
{
BList* coeffs = new BList(4);
coeffs->AddItem(new double(coeff1));
coeffs->AddItem(new double(coeff2));
coeffs->AddItem(new double(coeff3));
coeffs->AddItem(new double(coeff4));
BList* vars = new BList(4);
vars->AddItem(var1);
vars->AddItem(var2);
vars->AddItem(var3);
vars->AddItem(var4);
SoftConstraint* c = AddSoftConstraint(coeffs, vars, op, rightSide,
penaltyNeg, penaltyPos);
return c;
}
/**
* Adds a new penalty function to the specification.
*
* @param var the penalty function's variable
* @param xs the penalty function's sampling points
* @param gs the penalty function's gradients
* @return the new penalty function
*/
PenaltyFunction*
LinearSpec::AddPenaltyFunction(Variable* var, BList* xs, BList* gs)
{
return new PenaltyFunction(this, var, xs, gs);
}
/**
* 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
LinearSpec::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
LinearSpec::Presolve()
{
bigtime_t start, end;
start = system_time();
if (fLpPresolved == NULL) {
fLpPresolved = copy_lp(fLP);
set_presolve(fLpPresolved, PRESOLVE_ROWS | PRESOLVE_COLS | PRESOLVE_LINDEP,
get_presolveloops(fLpPresolved));
}
fResult = (ResultType)solve(fLpPresolved);
fObjectiveValue = get_objective(fLpPresolved);
if (fResult == OPTIMAL) {
int32 size = fVariables->CountItems();
for (int32 i = 0; i < size; i++) {
Variable* current = (Variable*)fVariables->ItemAt(i);
current->SetValue(get_var_primalresult(fLpPresolved,
get_Norig_rows(fLpPresolved) + current->Index()));
}
}
end = system_time();
fSolvingTime = (end - start) / 1000.0;
return fResult;
}
/**
* Tries to solve the linear programming problem.
* If a cached simplified version of the problem exists, it is used instead.
*
* @return the result of the solving attempt
*/
ResultType
LinearSpec::Solve()
{
if (fLpPresolved != NULL)
return Presolve();
bigtime_t start, end;
start = system_time();
fResult = (ResultType)solve(fLP);
fObjectiveValue = get_objective(fLP);
if (fResult == OPTIMAL) {
int32 size = fVariables->CountItems();
double x[size];
if (!get_variables(fLP, &x[0]))
printf("Error in get_variables.");
int32 i = 0;
while (i < size) {
((Variable*)fVariables->ItemAt(i))->SetValue(x[i]);
i++;
}
}
end = system_time();
fSolvingTime = (end - start) / 1000.0;
return fResult;
}
/**
* Writes the specification into a text file.
* The file will be overwritten if it exists.
*
* @param fname the file name
*/
void
LinearSpec::Save(char* fname)
{
write_lp(fLP, fname);
}
/**
* Gets the number of columns.
*
* @return the number of columns
*/
int32
LinearSpec::Columns() const
{
return fColumns;
}
/**
* Sets the number of columns.
*
* @param value the number of columns
*/
void
LinearSpec::SetColumns(int32 value)
{
fColumns = value;
}
/**
* Gets the current optimization.
* The default is minimization.
*
* @return the current optimization
*/
OptimizationType
LinearSpec::Optimization() const
{
return fOptimization;
}
/**
* Sets whether the solver should minimize or maximize the objective function.
* The default is minimization.
*
* @param optimization the optimization type
*/
void
LinearSpec::SetOptimization(OptimizationType value)
{
fOptimization = value;
if (fOptimization == MINIMIZE)
set_minim(fLP);
else
set_maxim(fLP);
}
/**
* Gets the lpsolve variable.
*
* @return the lpsolve variable
*/
lprec*
LinearSpec::LP() const
{
return fLP;
}
/**
* Sets the lpsolve variable.
*
* @param value the lpsolve variable
*/
void
LinearSpec::SetLP(lprec* value)
{
fLP = value;
}
/**
* Gets the objective function summand.
*
* @return the objective function summand
*/
BList*
LinearSpec::ObjFunctionSummands() const
{
return fObjFunctionSummands;
}
/**
* Sets the objective function summand.
*
* @param value the objective function summand
*/
void
LinearSpec::SetObjFunctionSummands(BList* value)
{
fObjFunctionSummands = value;
}
/**
* Gets the the variables.
*
* @return the variables
*/
BList*
LinearSpec::Variables() const
{
return fVariables;
}
/**
* Sets the the variables.
*
* @param value the variables
*/
void
LinearSpec::SetVariables(BList* value)
{
fVariables = value;
}
/**
* Gets the constraints.
*
* @return the constraints
*/
BList*
LinearSpec::Constraints() const
{
return fConstraints;
}
/**
* Sets the constraints.
*
* @param value the constraints
*/
void LinearSpec::SetConstraints(BList* value) {
fConstraints = value;
}
/**
* Gets the result type.
*
* @return the result type
*/
ResultType
LinearSpec::Result() const
{
return fResult;
}
/**
* Sets the result type.
*
* @param value the result type
*/
void
LinearSpec::SetResult(ResultType value)
{
fResult = value;
}
/**
* Gets the objective value.
*
* @return the objective value
*/
double
LinearSpec::ObjectiveValue() const
{
return fObjectiveValue;
}
/**
* Sets the objective value.
*
* @param value the objective value
*/
void
LinearSpec::SetObjectiveValue(double value)
{
fObjectiveValue = value;
}
/**
* Gets the solving time.
*
* @return the solving time
*/
double
LinearSpec::SolvingTime() const
{
return fSolvingTime;
}
/**
* Sets the solving time.
*
* @param value the solving time
*/
void
LinearSpec::SetSolvingTime(double value)
{
fSolvingTime = value;
}

View File

@ -0,0 +1,76 @@
#include "ObjFunctionSummand.h"
#include "Variable.h"
#include "LinearSpec.h"
/**
* Gets the summmand's coefficient.
*
* @return the summand's coefficient
*/
double
ObjFunctionSummand::Coeff()
{
return fCoeff;
}
/**
* Sets the summmand's coefficient.
*
* @param coeff coefficient
*/
void
ObjFunctionSummand::SetCoeff(double coeff)
{
fCoeff = coeff;
fLS->UpdateObjFunction();
}
/**
* Gets the summand's variable.
*
* @return the summand's variable
*/
Variable*
ObjFunctionSummand::Var()
{
return fVar;
}
/**
* Sets the summand's variable.
*
* @param var variable
*/
void
ObjFunctionSummand::SetVar(Variable* var)
{
fVar = var;
fLS->UpdateObjFunction();
}
/**
* Destructor.
* Removes the summand from the objective function.
*/
ObjFunctionSummand::~ObjFunctionSummand()
{
fLS->ObjFunctionSummands()->RemoveItem(this);
fLS->UpdateObjFunction();
}
/**
* Constructor.
*/
ObjFunctionSummand::ObjFunctionSummand(LinearSpec* ls, double coeff, Variable* var)
{
fLS = ls;
fCoeff = coeff;
fVar = var;
}

View File

@ -0,0 +1,116 @@
#include "PenaltyFunction.h"
#include "Constraint.h"
#include "ObjFunctionSummand.h"
#include "OperatorType.h"
#include "Variable.h"
#include "LinearSpec.h"
/**
* Constructor.
*/
PenaltyFunction::PenaltyFunction(LinearSpec* ls, Variable* var, BList* xs, BList* gs)
{
int32 sizeXs = xs->CountItems();
int32 sizeGs = gs->CountItems();
if (var->LS() != ls)
printf("The variable must belong to the same linear specification as the penalty function.");
if (sizeXs + 1 != sizeGs)
printf("The number of sampling points must be exactly one less than the number of gradients.");
for (int32 i = 1; i < sizeGs; i++) {
if (*(double*)(gs->ItemAt(i - 1)) > *(double*)(gs->ItemAt(i)))
printf("Penalty function must be concave.");
}
fVar = var;
fXs = xs;
fGs = gs;
fConstraints = new BList(1);
fObjFunctionSummands = new BList(1);
BList* coeffs = new BList(1);
coeffs->AddItem(new double(1.0));
BList* vars = new BList(1);
vars->AddItem(var);
fConstraints->AddItem(ls->AddSoftConstraint(coeffs, vars, OperatorType(EQ),
*(double*)(xs->ItemAt(0)), -*(double*)(gs->ItemAt(0)),
*(double*)(gs->ItemAt(1))));
for (int32 i = 1; i < sizeGs; i++) {
Variable* dPos = ls->AddVariable();
BList* coeffs = new BList(2);
coeffs->AddItem(new double(1.0));
coeffs->AddItem(new double(-1.0));
BList* vars = new BList(2);
vars->AddItem(var);
vars->AddItem(dPos);
fConstraints->AddItem(ls->AddConstraint(coeffs, vars, OperatorType(LE),
*(double*)(xs->ItemAt(i))));
fObjFunctionSummands->AddItem(ls->AddObjFunctionSummand(
*(double*)(gs->ItemAt(i + 1)) - *(double*)(gs->ItemAt(i)), dPos));
}
}
/**
* Destructor.
* Removes all constraints and summands from the penalty function.
*/
PenaltyFunction::~PenaltyFunction()
{
int32 sizeConstraints = fConstraints->CountItems();
for (int32 i = 0; i < sizeConstraints; i++) {
Constraint* currentConstraint = (Constraint*)fConstraints->ItemAt(i);
delete currentConstraint;
}
int32 sizeObjFunctionSummands = fObjFunctionSummands->CountItems();
for (int32 i = 0; i < sizeObjFunctionSummands; i++) {
ObjFunctionSummand* currentObjFunctionSummand =
(ObjFunctionSummand*)fObjFunctionSummands->ItemAt(i);
delete currentObjFunctionSummand;
}
}
/**
* Gets the variable.
*
* @return the variable
*/
const Variable*
PenaltyFunction::Var() const
{
return fVar;
}
/**
* Gets the sampling points.
*
* @return the sampling points
*/
const BList*
PenaltyFunction::Xs() const
{
return fXs;
}
/**
* Gets the sampling gradients.
*
* @return the sampling gradients
*/
const
BList* PenaltyFunction::Gs() const
{
return fGs;
}

View File

@ -0,0 +1,235 @@
#include "SoftConstraint.h"
#include "ObjFunctionSummand.h"
#include "Variable.h"
#include "LinearSpec.h"
#include "lp_lib.h"
/**
* Changes the left side of the soft constraint,&nbsp;i.e. its coefficients and variables.
* There must be exactly one coefficient for each variable.
*
* @param coeffs the constraint's coefficients
* @param vars the constraint's variables
*/
void
SoftConstraint::ChangeLeftSide(BList* coeffs, BList* vars)
{
int32 sizeCoeffs = coeffs->CountItems();
int32 sizeVars = vars->CountItems();
if (sizeCoeffs != sizeVars)
printf("Number of coefficients and number of variables in a constraint must be equal.");
fCoeffs = coeffs;
fVars = vars;
int vIndexes[sizeCoeffs + 2];
double coeffs2[sizeCoeffs + 2];
int32 i;
for (i = 0; i < sizeVars; i++) {
vIndexes[i] = ((Variable*)vars->ItemAt(i))->Index();
coeffs2[i] = *(double*)coeffs->ItemAt(i);
}
if (fOp != OperatorType(LE)) {
vIndexes[i] = fDNegSummand->Var()->Index();
coeffs2[i] = 1.0;
i++;
}
if (fOp != OperatorType(GE)) {
vIndexes[i] = fDPosSummand->Var()->Index();
coeffs2[i] = -1.0;
i++;
}
if (!set_rowex(fLS->LP(), this->Index(), i, &coeffs2[0], &vIndexes[0]))
printf("Error in set_rowex.");
fLS->RemovePresolved();
}
/**
* Gets the operator used for this constraint.
*
* @return the operator used for this constraint
*/
OperatorType
SoftConstraint::Op()
{
return fOp;
}
/**
* Sets the operator used for this constraint.
*
* @param value operator type
*/
void
SoftConstraint::SetOp(OperatorType value)
{
fOp = value;
ChangeLeftSide(fCoeffs, fVars);
}
/**
* Gets the coefficient of negative summand.
*
* @return the coefficient of negative summand.
*/
double
SoftConstraint::PenaltyNeg()
{
return fDNegSummand->Coeff();
}
/**
* The penalty coefficient for positive deviations from the soft constraint's exact solution,&nbsp;
* i.e. if the left side is too large.
*
* @param value coefficient of negative penalty <code>double</code>
*/
void
SoftConstraint::SetPenaltyNeg(double value)
{
if (value == fDNegSummand->Coeff())
return;
fDNegSummand->SetCoeff(value);
fLS->UpdateObjFunction();
}
/**
* Gets the coefficient of positive summand.
*
* @return the coefficient of positive summand.
*/
double
SoftConstraint::PenaltyPos()
{
return fDPosSummand->Coeff();
}
/**
* The penalty coefficient for negative deviations from the soft constraint's exact solution,
* i.e. if the left side is too small.
*
* @param value coefficient of positive penalty <code>double</code>
*/
void
SoftConstraint::SetPenaltyPos(double value)
{
if (value == fDPosSummand->Coeff())
return;
fDPosSummand->SetCoeff(value);
fLS->UpdateObjFunction();
}
/**
* Returns positive and negative penalty coefficient as string.
*/
// Needs to be fixed.
//~ string SoftConstraint::ToString() {
//~ return base.ToString()
//~ + "; PenaltyNeg=" + PenaltyNeg()
//~ + "; PenaltyPos=" + PenaltyPos();
//~ }
/**
* Gets the slack variable for the negative variations.
*
* @return the slack variable for the negative variations
*/
Variable*
SoftConstraint::DNeg() const
{
return fDNeg;
}
/**
* Gets the slack variable for the positive variations.
*
* @return the slack variable for the positive variations
*/
Variable*
SoftConstraint::DPos() const
{
return fDPos;
}
/**
* Destructor.
* Removes the soft constraint from its specification.
*/
SoftConstraint::~SoftConstraint()
{
delete fDNegSummand->Var();
delete fDPosSummand->Var();
delete fDNegSummand;
delete fDPosSummand;
}
/**
* Constructor.
*/
SoftConstraint::SoftConstraint(LinearSpec* ls, BList* coeffs, BList* vars, OperatorType op,
double rightSide, double penaltyNeg, double penaltyPos)
{
int32 sizeCoeffs = coeffs->CountItems();
int32 sizeVars = vars->CountItems();
if (sizeCoeffs != sizeVars)
printf("Number of coefficients and number of variables in a constraint must be equal.");
fLS = ls;
fCoeffs = coeffs;
fVars = vars;
fOp = op;
fRightSide = rightSide;
fDNeg = new Variable(ls);
fDPos = new Variable(ls);
fDNegSummand = ls->AddObjFunctionSummand(penaltyNeg, DNeg());
fDPosSummand = ls->AddObjFunctionSummand(penaltyPos, DPos());
int vIndexes[sizeCoeffs + 2];
double coeffs2[sizeCoeffs + 2];
int32 i;
for (i=0; i < sizeVars; i++) {
vIndexes[i] = ((Variable*)vars->ItemAt(i))->Index();
coeffs2[i] = *(double*)coeffs->ItemAt(i);
}
if (fOp != OperatorType(LE)) {
vIndexes[i] = fDNegSummand->Var()->Index();
coeffs2[i] = 1.0;
i++;
}
if (fOp != OperatorType(GE)) {
vIndexes[i] = fDPosSummand->Var()->Index();
coeffs2[i] = -1.0;
i++;
}
if (!add_constraintex(ls->LP(), i, &coeffs2[0], &vIndexes[0],
((fOp == OperatorType(EQ)) ? EQ
: (fOp == OperatorType(GE)) ? GE
: LE), rightSide))
printf("Error in add_constraintex.");
ls->Constraints()->AddItem(this);
}

View File

@ -0,0 +1,244 @@
#include "Variable.h"
#include "Constraint.h"
#include "LinearSpec.h"
#include "OperatorType.h"
#include "lp_lib.h"
#include <float.h> // for DBL_MAX
/**
* Gets index of the variable.
*
* @return the index of the variable
*/
int32
Variable::Index()
{
int32 i = fLS->Variables()->IndexOf(this);
if (i == -1)
printf("Variable not part of fLS->Variables().");
return i + 1;
}
/**
* Gets the current linear specification.
*
* @return the current linear specification
*/
LinearSpec*
Variable::LS() const
{
return fLS;
}
/**
* Sets the current linear specification.
*
* @param value the current linear specification
*/
void
Variable::SetLS(LinearSpec* value)
{
fLS = value;
}
/**
* Gets the value.
*
* @return the value
*/
double
Variable::Value() const
{
return fValue;
}
/**
* Sets the value.
*
* @param value the value
*/
void
Variable::SetValue(double value)
{
fValue = value;
}
/**
* Gets the minimum value of the variable.
*
* @return the minimum value of variable
*/
double
Variable::Min() const
{
return fMin;
}
/**
* Sets the minimum value of the variable.
*
* @param min minimum value
*/
void
Variable::SetMin(double min)
{
fMin = min;
set_bounds(fLS->LP(), this->Index(), fMin, fMax);
}
/**
* Gets the maximum value of the variable.
*
* @return the maximum value of variable
*/
double
Variable::Max() const
{
return fMax;
}
/**
* Sets the maximum value of the variable.
*
* @param max maximum value
*/
void
Variable::SetMax(double max)
{
fMax = max;
set_bounds(fLS->LP(), this->Index(), fMin, fMax);
}
/**
* Sets the minimum and maximum values of the variable.
*
* @param min minimum value
* @param max maximum value
*/
void
Variable::SetRange(double min, double max)
{
fMin = min;
fMax = max;
set_bounds(fLS->LP(), this->Index(), fMin, fMax);
}
/**
* 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();
//~ }
/**
* Adds a constraint that sets this variable equal to the given one.
*
* @param var variable that should have the same value
* @return the new equality constraint
*/
Constraint*
Variable::IsEqual(Variable* var)
{
BList* coeffs = new BList(2);
coeffs->AddItem(new double(1.0));
coeffs->AddItem(new double(-1.0));
BList* vars = new BList(2);
vars->AddItem(this);
vars->AddItem(var);
return fLS->AddConstraint(coeffs, vars, OperatorType(EQ), 0.0);
}
/**
* Adds a constraint that sets this variable smaller or equal to the given one.
*
* @param var variable that should have a larger or equal value
* @return the new constraint
*/
Constraint*
Variable::IsSmallerOrEqual(Variable* var)
{
BList* coeffs = new BList(2);
coeffs->AddItem(new double(1.0));
coeffs->AddItem(new double(-1.0));
BList* vars = new BList(2);
vars->AddItem(this);
vars->AddItem(var);
return fLS->AddConstraint(coeffs, vars, OperatorType(LE), 0.0);
}
/**
* Adds a constraint that sets this variable greater or equal to the given one.
*
* @param var variable that should have a smaller or equal value
* @return the new constraint
*/
Constraint*
Variable::IsGreaterorEqual(Variable* var)
{
BList* coeffs = new BList(2);
coeffs->AddItem(new double(-1.0));
coeffs->AddItem(new double(1.0));
BList* vars = new BList(2);
vars->AddItem(var);
vars->AddItem(this);
return fLS->AddConstraint(coeffs, vars, OperatorType(GE), 0.0);
}
/**
* Constructor.
*/
Variable::Variable(LinearSpec* ls)
{
fMin = 0;
fMax = DBL_MAX;
fValue = NULL;
fLS = ls;
ls->Variables()->AddItem(this);
int32 size = ls->Variables()->CountItems();
if (size > ls->Columns()) {
double d = 0;
int i = 0;
if (!add_columnex(ls->LP(), 0, &d, &i))
printf("Error in add_columnex.");
}
}
/**
* Destructor.
* Removes the variable from its specification.
*/
Variable::~Variable()
{
del_column(fLS->LP(), this->Index());
fLS->Variables()->RemoveItem(this);
}

View File

@ -29,5 +29,6 @@ SubInclude HAIKU_TOP src tests apps ;
SubInclude HAIKU_TOP src tests bin ;
SubInclude HAIKU_TOP src tests system ;
SubInclude HAIKU_TOP src tests kits ;
SubInclude HAIKU_TOP src tests libs ;
SubInclude HAIKU_TOP src tests misc ;
SubInclude HAIKU_TOP src tests servers ;

6
src/tests/libs/Jamfile Normal file
View File

@ -0,0 +1,6 @@
SubDir HAIKU_TOP src tests libs ;
SubInclude HAIKU_TOP src tests libs lp_solve ;
SubInclude HAIKU_TOP src tests libs linprog ;
SubInclude HAIKU_TOP src tests libs alm ;

View File

@ -0,0 +1,24 @@
SubDir HAIKU_TOP src tests libs alm ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UseLibraryHeaders lp_solve linprog alm ;
Application table_test :
TableTest.cpp
:
be liblpsolve55.so liblinprog.so libalm.so
;
Application test1 :
Test1.cpp
:
be liblpsolve55.so be liblinprog.so libalm.so
;
Application test2 :
Test2.cpp
:
be liblpsolve55.so be liblinprog.so libalm.so
;

View File

@ -0,0 +1,70 @@
#include <Application.h>
#include <File.h>
#include <Button.h>
#include <Window.h>
#include "Area.h"
#include "Column.h"
#include "BALMLayout.h"
#include "Row.h"
using namespace BALM;
class TableTestWindow : public BWindow {
public:
TableTestWindow(BRect frame) : BWindow(frame, "TableTest", B_TITLED_WINDOW,
B_QUIT_ON_WINDOW_CLOSE) {
BALMLayout* fLS = new BALMLayout();
SetLayout(fLS);
fLS->SetPerformancePath("/boot/home/Desktop/table_test_performance.txt");
Column* c1 = fLS->AddColumn(fLS->Left(), fLS->Right());
Row* r1 = fLS->AddRow(fLS->Top(), NULL);
Row* r3 = fLS->AddRow(NULL, fLS->Bottom());
r1->SetNext(r3);
Row* r2 = fLS->AddRow();
r2->InsertAfter(r1);
BButton* b1 = new BButton("A1");
Area* a1 = fLS->AddArea(r1, c1, b1);
a1->SetHAlignment(B_ALIGN_LEFT);
a1->SetVAlignment(B_ALIGN_TOP);
BButton* b2 = new BButton("A2");
Area* a2 = fLS->AddArea(r2, c1, b2);
a2->SetHAlignment(B_ALIGN_HORIZONTAL_CENTER);
a2->SetVAlignment(B_ALIGN_VERTICAL_CENTER);
BButton* b3 = new BButton("A3");
Area* a3 = fLS->AddArea(r3, c1, b3);
a3->SetHAlignment(B_ALIGN_RIGHT);
a3->SetVAlignment(B_ALIGN_BOTTOM);
r2->HasSameHeightAs(r1);
r3->HasSameHeightAs(r1);
Show();
}
};
class TableTest : public BApplication {
public:
TableTest() : BApplication("application/x-vnd.haiku.table-test") {
BRect frameRect;
frameRect.Set(100, 100, 400, 400);
TableTestWindow* theWindow = new TableTestWindow(frameRect);
}
};
int main() {
TableTest test;
test.Run();
return 0;
}

View File

@ -0,0 +1,83 @@
#include <Application.h>
#include <Button.h>
#include <List.h>
#include <Window.h>
#include "Area.h"
#include "BALMLayout.h"
#include "OperatorType.h"
#include "XTab.h"
#include "YTab.h"
using namespace BALM;
class Test1Window : public BWindow {
public:
Test1Window(BRect frame) : BWindow(frame, "Test1", B_TITLED_WINDOW,
B_QUIT_ON_WINDOW_CLOSE) {
fLS = new BALMLayout();
SetLayout(fLS);
button1 = new BButton("button1");
button2 = new BButton("button2");
button3 = new BButton("button3");
fLS->SetPerformancePath("/boot/home/Desktop/test1_performance.txt");
SetBALMLayout();
Show();
}
void SetBALMLayout() {
XTab* x1 = fLS->AddXTab();
YTab* y1 = fLS->AddYTab();
fLS->AddArea(fLS->Left(), fLS->Top(), x1, y1, button1);
fLS->AddArea(x1, fLS->Top(), fLS->Right(), y1, button2);
fLS->AddArea(fLS->Left(), y1, fLS->Right(), fLS->Bottom(), button3);
//~ BList* coeffs1 = new BList(2);
//~ coeffs1->AddItem(new double(2.0));
//~ coeffs1->AddItem(new double(-1.0));
//~ BList* vars1 = new BList(2);
//~ vars1->AddItem(x1);
//~ vars1->AddItem(fLS->Right());
fLS->AddConstraint(2.0, x1, -1.0, fLS->Right(), OperatorType(EQ), 0.0);
//~ BList* coeffs2 = new BList(2);
//~ coeffs2->AddItem(new double(2.0));
//~ coeffs2->AddItem(new double(-1.0));
//~ BList* vars2 = new BList(2);
//~ vars2->AddItem(y1);
//~ vars2->AddItem(fLS->Bottom());
fLS->AddConstraint(2.0, y1, -1.0, fLS->Bottom(), OperatorType(EQ), 0.0);
}
private:
BALMLayout* fLS;
BButton* button1;
BButton* button2;
BButton* button3;
};
class Test1 : public BApplication {
public:
Test1() : BApplication("application/x-vnd.haiku.test1") {
BRect frameRect;
frameRect.Set(100, 100, 392, 366);
Test1Window* theWindow = new Test1Window(frameRect);
}
};
int main() {
Test1 test;
test.Run();
return 0;
}

View File

@ -0,0 +1,162 @@
#include <Application.h>
#include <Button.h>
#include <List.h>
#include <StringView.h>
#include <TextControl.h>
#include <TextView.h>
#include <Window.h>
#include "Area.h"
#include "BALMLayout.h"
#include "OperatorType.h"
#include "XTab.h"
#include "YTab.h"
using namespace BALM;
class Test2Window : public BWindow {
public:
Test2Window(BRect frame) : BWindow(frame, "Test2", B_TITLED_WINDOW,
B_QUIT_ON_WINDOW_CLOSE) {
fLS = new BALMLayout();
SetLayout(fLS);
button1 = new BButton("button1");
button2 = new BButton("button2");
button3 = new BButton("button3");
button4 = new BButton("button4");
button5 = new BButton("button5");
button6 = new BButton("button6");
checkedListBox1 = new BButton("checkedListBox1");
textBox1 = new BButton("textBox1");
textBox2 = new BButton("textBox2");
richTextBox1 = new BButton("richTextBox1");
//~ textBox1 = new BTextView(frame, "textBox1", NULL, NULL);
//~ textBox2 = new BTextView(frame, "textBox2", NULL, NULL);
//~ richTextBox1 = new BTextControl(NULL, "richTextBox1", NULL);
listView1 = new BButton("listView1");
label1 = new BStringView(frame, "label1", "label1");
label2 = new BStringView(frame, "label2", "label2");
label3 = new BStringView(frame, "label3", "label3");
fLS->SetPerformancePath("/boot/home/Desktop/test2_performance.txt");
SetBALMLayout();
Show();
}
void SetBALMLayout() {
XTab* x1 = fLS->AddXTab();
XTab* x2 = fLS->AddXTab();
XTab* x3 = fLS->AddXTab();
YTab* y1 = fLS->AddYTab();
YTab* y2 = fLS->AddYTab();
YTab* y3 = fLS->AddYTab();
YTab* y4 = fLS->AddYTab();
YTab* y5 = fLS->AddYTab();
fLS->AddArea(fLS->Left(), fLS->Top(), x1, y1, button1);
fLS->AddArea(x1, fLS->Top(), x2, y1, button2);
fLS->AddArea(fLS->Left(), y1, x1, y2, button3);
fLS->AddArea(x1, y1, x2, y2, button4);
fLS->AddArea(fLS->Left(), y2, x1, y3, button5);
fLS->AddArea(x1, y2, x2, y3, button6);
//~ BList* coeffs1 = new BList(2);
//~ coeffs1->AddItem(new double(2.0));
//~ coeffs1->AddItem(new double(-1.0));
//~ BList* vars1 = new BList(2);
//~ vars1->AddItem(x1);
//~ vars1->AddItem(x2);
//~ fLS->AddConstraint(coeffs1, vars1, OperatorType(EQ), 0.0);
fLS->AddConstraint(2.0, x1, -1.0, x2, OperatorType(EQ), 0.0);
//~ BList* coeffs2 = new BList(2);
//~ coeffs2->AddItem(new double(2.0));
//~ coeffs2->AddItem(new double(-1.0));
//~ BList* vars2 = new BList(2);
//~ vars2->AddItem(y1);
//~ vars2->AddItem(y2);
fLS->AddConstraint(2.0, y1, -1.0, y2, OperatorType(EQ), 0.0);
//~ BList* coeffs3 = new BList(3);
//~ coeffs3->AddItem(new double(1.0));
//~ coeffs3->AddItem(new double(1.0));
//~ coeffs3->AddItem(new double(-1.0));
//~ BList* vars3 = new BList(3);
//~ vars3->AddItem(y1);
//~ vars3->AddItem(y2);
//~ vars3->AddItem(y3);
fLS->AddConstraint(1.0, y1, 1.0, y2, -1.0, y3, OperatorType(EQ), 0.0);
fLS->AddArea(fLS->Left(), y3, x2, y4, checkedListBox1);
fLS->AddArea(x2, fLS->Top(), fLS->Right(), y2, textBox1);
fLS->AddArea(fLS->Left(), y4, x3, y5, listView1);
fLS->AddArea(x3, y2, fLS->Right(), y5, textBox2);
Area* richTextBox1Area = fLS->AddArea(x2, y2, x3, y4, richTextBox1);
richTextBox1Area->SetLeftInset(10);
richTextBox1Area->SetTopInset(10);
richTextBox1Area->SetRightInset(10);
richTextBox1Area->SetBottomInset(10);
Area* label1Area = fLS->AddArea(fLS->Left(), y5, x2, fLS->Bottom(), label1);
label1Area->SetHAlignment(B_ALIGN_LEFT);
label1Area->SetTopInset(4);
label1Area->SetBottomInset(4);
Area* label2Area = fLS->AddArea(x2, y5, x3, fLS->Bottom(), label2);
label2Area->SetHAlignment(B_ALIGN_HORIZONTAL_CENTER);
label2Area->SetTopInset(4);
label2Area->SetBottomInset(4);
Area* label3Area = fLS->AddArea(x3, y5, fLS->Right(), fLS->Bottom(), label3);
label3Area->SetHAlignment(B_ALIGN_RIGHT);
label3Area->SetTopInset(4);
label3Area->SetBottomInset(4);
}
private:
BALMLayout* fLS;
BButton* button1;
BButton* button2;
BButton* button3;
BButton* button4;
BButton* button5;
BButton* button6;
BButton* checkedListBox1;
BButton* textBox1;
BButton* textBox2;
BButton* richTextBox1;
//~ BTextView* textBox1;
//~ BTextView* textBox2;
//~ BTextControl* richTextBox1;
BButton* listView1;
BStringView* label1;
BStringView* label2;
BStringView* label3;
};
class Test2 : public BApplication {
public:
Test2() : BApplication("application/x-vnd.haiku.test2") {
BRect frameRect;
frameRect.Set(100, 100, 610, 456);
Test2Window* theWindow = new Test2Window(frameRect);
}
};
int main() {
Test2 test;
test.Run();
return 0;
}

View File

@ -0,0 +1,11 @@
SubDir HAIKU_TOP src tests libs linprog ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UseLibraryHeaders lp_solve linprog ;
SimpleTest linprog :
Program.cpp
:
be liblpsolve55.so liblinprog.so
;

View File

@ -0,0 +1,67 @@
#include <List.h>
#include <SupportDefs.h>
#include "Constraint.h"
#include "LinearSpec.h"
#include "OperatorType.h"
#include "Variable.h"
#include <stdio.h>
void PrintVars(LinearSpec* ls) {
int32 size = ls->Variables()->CountItems();
Variable* variable;
for (int i = 0; i < size; i++) {
variable = (Variable*)ls->Variables()->ItemAt(i);
printf("%f ", variable->Value());
}
printf("%d\n", ls->Result());
}
void Test1() {
LinearSpec* ls = new LinearSpec();
Variable* x1 = ls->AddVariable();
Variable* x2 = ls->AddVariable();
BList* coeffs1 = new BList(1);
coeffs1->AddItem(new double(1.0));
BList* vars1 = new BList(1);
vars1->AddItem(x1);
Constraint* c1 = ls->AddConstraint(coeffs1, vars1, OperatorType(LE), 108);
BList* coeffs2 = new BList(1);
coeffs2->AddItem(new double(1.0));
BList* vars2 = new BList(1);
vars2->AddItem(x2);
Constraint* c2 = ls->AddConstraint(coeffs2, vars2, OperatorType(GE), 113);
BList* coeffs3 = new BList(2);
coeffs3->AddItem(new double(1.0));
coeffs3->AddItem(new double(1.0));
BList* vars3 = new BList(2);
vars3->AddItem(x1);
vars3->AddItem(x2);
ls->SetObjFunction(coeffs3, vars3);
ls->Solve();
PrintVars(ls);
delete c2;
ls->Solve();
PrintVars(ls);
BList* coeffs4 = new BList(1);
coeffs4->AddItem(new double(1.0));
BList* vars4 = new BList(1);
vars4->AddItem(x2);
c2 = ls->AddConstraint(coeffs4, vars4, OperatorType(GE), 113);
ls->Solve();
PrintVars(ls);
}
int main() {
Test1();
}

View File

@ -0,0 +1,12 @@
SubDir HAIKU_TOP src tests libs lp_solve ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UseLibraryHeaders lp_solve ;
SimpleTest lp_solve :
demo.c
:
liblpsolve55.so
;

View File

@ -0,0 +1,146 @@
/* demo.c */
#include "lp_lib.h"
int demo()
{
lprec *lp;
int Ncol, *colno = NULL, j, ret = 0;
REAL *row = NULL;
/* We will build the model row by row
So we start with creating a model with 0 rows and 2 columns */
Ncol = 2; /* there are two variables in the model */
lp = make_lp(0, Ncol);
if(lp == NULL)
ret = 1; /* couldn't construct a new model... */
if(ret == 0) {
/* let us name our variables. Not required, but can be useful for debugging */
set_col_name(lp, 1, "x");
set_col_name(lp, 2, "y");
/* create space large enough for one row */
colno = (int *) malloc(Ncol * sizeof(*colno));
row = (REAL *) malloc(Ncol * sizeof(*row));
if((colno == NULL) || (row == NULL))
ret = 2;
}
if(ret == 0) {
set_add_rowmode(lp, TRUE); /* makes building the model faster if it is done rows by row */
/* construct first row (120 x + 210 y <= 15000) */
j = 0;
colno[j] = 1; /* first column */
row[j++] = 120;
colno[j] = 2; /* second column */
row[j++] = 210;
/* add the row to lpsolve */
if(!add_constraintex(lp, j, row, colno, LE, 15000))
ret = 3;
}
if(ret == 0) {
/* construct second row (110 x + 30 y <= 4000) */
j = 0;
colno[j] = 1; /* first column */
row[j++] = 110;
colno[j] = 2; /* second column */
row[j++] = 30;
/* add the row to lpsolve */
if(!add_constraintex(lp, j, row, colno, LE, 4000))
ret = 3;
}
if(ret == 0) {
/* construct third row (x + y <= 75) */
j = 0;
colno[j] = 1; /* first column */
row[j++] = 1;
colno[j] = 2; /* second column */
row[j++] = 1;
/* add the row to lpsolve */
if(!add_constraintex(lp, j, row, colno, LE, 75))
ret = 3;
}
if(ret == 0) {
set_add_rowmode(lp, FALSE); /* rowmode should be turned off again when done building the model */
/* set the objective function (143 x + 60 y) */
j = 0;
colno[j] = 1; /* first column */
row[j++] = 143;
colno[j] = 2; /* second column */
row[j++] = 60;
/* set the objective in lpsolve */
if(!set_obj_fnex(lp, j, row, colno))
ret = 4;
}
if(ret == 0) {
/* set the object direction to maximize */
set_maxim(lp);
/* just out of curioucity, now show the model in lp format on screen */
/* this only works if this is a console application. If not, use write_lp and a filename */
write_LP(lp, stdout);
/* write_lp(lp, "model.lp"); */
/* I only want to see important messages on screen while solving */
set_verbose(lp, IMPORTANT);
/* Now let lpsolve calculate a solution */
ret = solve(lp);
if(ret == OPTIMAL)
ret = 0;
else
ret = 5;
}
if(ret == 0) {
/* a solution is calculated, now lets get some results */
/* objective value */
printf("Objective value: %f\n", get_objective(lp));
/* variable values */
get_variables(lp, row);
for(j = 0; j < Ncol; j++)
printf("%s: %f\n", get_col_name(lp, j + 1), row[j]);
/* we are done now */
}
/* free allocated memory */
if(row != NULL)
free(row);
if(colno != NULL)
free(colno);
if(lp != NULL) {
/* clean up such that all used memory by lpsolve is freed */
delete_lp(lp);
}
return(ret);
}
int main()
{
demo();
}