* Simplified and optimized a lot the "ToString()" debugging facilities.

* *::Index() is now const, thanks to the BList improvements.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34521 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2009-12-06 13:14:45 +00:00
parent b0850e9ba1
commit b8ec67f491
9 changed files with 404 additions and 423 deletions

View File

@ -29,7 +29,7 @@ class BALMLayout;
* Rectangular area in the GUI, defined by a tab on each side.
*/
class Area {
public:
XTab* Left() const;
void SetLeft(XTab* left);
@ -83,32 +83,32 @@ public:
bool AutoPreferredContentSize() const;
void SetAutoPreferredContentSize(bool value);
BString* ToBString();
const char* ToString();
operator BString() const;
void GetString(BString& string) const;
Constraint* HasSameWidthAs(Area* area);
Constraint* HasSameHeightAs(Area* area);
BList* HasSameSizeAs(Area* area);
~Area();
protected:
Area(BALMLayout* ls, XTab* left, YTab* top,
XTab* right, YTab* bottom,
BView* content,
XTab* right, YTab* bottom,
BView* content,
BSize minContentSize);
Area(BALMLayout* ls, Row* row, Column* column,
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,
void Init(BALMLayout* ls, XTab* left, YTab* top,
XTab* right, YTab* bottom,
BView* content,
BSize minContentSize);
public:
@ -152,7 +152,7 @@ private:
Constraint* fTopConstraint;
Constraint* fRightConstraint;
Constraint* fBottomConstraint;
public:
friend class BALMLayout;

View File

@ -19,28 +19,28 @@
namespace LinearProgramming {
class LinearSpec;
/**
* Hard linear constraint, i.e. one that must be satisfied.
* Hard linear constraint, i.e. one that must be satisfied.
* May render a specification infeasible.
*/
class Constraint {
public:
int32 Index();
int32 Index() const;
BList* LeftSide();
void SetLeftSide(BList* summands);
void UpdateLeftSide();
void SetLeftSide(double coeff1, Variable* var1);
void SetLeftSide(double coeff1, Variable* var1,
void SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2);
void SetLeftSide(double coeff1, Variable* var1,
void SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3);
void SetLeftSide(double coeff1, Variable* var1,
void SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
double coeff4, Variable* var4);
@ -68,8 +68,8 @@ public:
bool IsValid();
void Invalidate();
BString* ToBString();
const char* ToString();
operator BString() const;
void GetString(BString& string) const;
~Constraint();

View File

@ -25,7 +25,7 @@
namespace LinearProgramming {
class Constraint;
class ObjFunctionSummand;
class PenaltyFunction;
@ -35,52 +35,52 @@ class Variable;
* Specification of a linear programming problem.
*/
class LinearSpec {
public:
LinearSpec();
virtual ~LinearSpec();
Variable* AddVariable();
Constraint* AddConstraint(BList* summands,
OperatorType op, double rightSide);
Constraint* AddConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
Constraint* AddConstraint(BList* summands,
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,
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);
Constraint* AddConstraint(BList* summands,
OperatorType op, double rightSide,
Constraint* AddConstraint(BList* summands,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
Constraint* AddConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
OperatorType op, double rightSide,
double coeff2, Variable* var2,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
OperatorType op, double rightSide,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos);
Constraint* AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3,
double coeff4, Variable* var4,
OperatorType op, double rightSide,
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);
BList* ObjFunction();
@ -90,7 +90,7 @@ public:
ResultType Presolve();
void RemovePresolved();
ResultType Solve();
void Save(char* fname);
void Save(const char* fileName);
int32 CountColumns() const;
OptimizationType Optimization() const;
@ -101,8 +101,8 @@ public:
double ObjectiveValue() const;
double SolvingTime() const;
BString* ToBString();
const char* ToString();
operator BString() const;
void GetString(BString& string) const;
protected:
int32 fCountColumns;

View File

@ -24,7 +24,7 @@ class Summand;
class Variable {
public:
int32 Index();
int32 Index() const;
LinearSpec* LS() const;
double Value() const;
void SetValue(double value);
@ -36,9 +36,9 @@ public:
const char* Label();
void SetLabel(const char* label);
BString* ToBString();
const char* ToString();
operator BString() const;
void GetString(BString& string) const;
Constraint* IsEqual(Variable* var);
Constraint* IsSmallerOrEqual(Variable* var);

View File

@ -73,12 +73,12 @@ void
Area::SetLeft(XTab* left)
{
fLeft = left;
fColumn = NULL;
if (fChildArea == NULL) {
fMinContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
if (fMaxContentWidth != NULL)
fMaxContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
} else
@ -108,12 +108,12 @@ void
Area::SetRight(XTab* right)
{
fRight = right;
fColumn = NULL;
if (fChildArea == NULL) {
fMinContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
if (fMaxContentWidth != NULL)
fMaxContentWidth->SetLeftSide(-1.0, fLeft, 1.0, fRight);
} else
@ -139,12 +139,12 @@ void
Area::SetTop(YTab* top)
{
fTop = top;
fRow = NULL;
if (fChildArea == NULL) {
fMinContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
if (fMaxContentHeight != NULL)
fMaxContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
} else
@ -170,12 +170,12 @@ void
Area::SetBottom(YTab* bottom)
{
fBottom = bottom;
fRow = NULL;
if (fChildArea == NULL) {
fMinContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
if (fMaxContentHeight != NULL)
fMaxContentHeight->SetLeftSide(-1.0, fTop, 1.0, fBottom);
} else
@ -315,7 +315,7 @@ Area::SetMinContentSize(BSize min)
fMinContentSize = min;
fMinContentWidth->SetRightSide(fMinContentSize.Width());
fMinContentHeight->SetRightSide(fMinContentSize.Height());
} else
} else
fChildArea->SetMinContentSize(min);
fLS->InvalidateLayout();
}
@ -342,7 +342,7 @@ Area::SetMaxContentSize(BSize max)
fMaxContentWidth = fLS->AddConstraint(-1.0, fLeft, 1.0, fRight, OperatorType(LE),
fMaxContentSize.Width());
fConstraints->AddItem(fMaxContentWidth);
fMaxContentHeight = fLS->AddConstraint(-1.0, fTop, 1.0, fBottom, OperatorType(LE),
fMaxContentSize.Height());
fConstraints->AddItem(fMaxContentHeight);
@ -370,7 +370,7 @@ Area::PreferredContentSize() const
/**
* Sets Preferred size of the area's content.
* May be different from the preferred size of the area.
* Manual changes of PreferredContentSize are ignored unless
* Manual changes of PreferredContentSize are ignored unless
* autoPreferredContentSize is set to false.
*/
void
@ -384,7 +384,7 @@ Area::SetPreferredContentSize(BSize preferred)
fPreferredContentSize.Width(), fShrinkPenalties.Width(),
fGrowPenalties.Width());
fConstraints->AddItem(fPreferredContentWidth);
fPreferredContentHeight = fLS->AddConstraint(
-1.0, fTop, 1.0, fBottom, OperatorType(EQ),
fPreferredContentSize.Height(), fShrinkPenalties.Height(),
@ -418,7 +418,7 @@ void Area::SetShrinkPenalties(BSize shrink) {
fPreferredContentWidth->SetPenaltyNeg(shrink.Width());
fPreferredContentHeight->SetPenaltyNeg(shrink.Height());
}
} else
} else
fChildArea->SetShrinkPenalties(shrink);
fLS->InvalidateLayout();
}
@ -444,7 +444,7 @@ Area::SetGrowPenalties(BSize grow)
fPreferredContentWidth->SetPenaltyPos(grow.Width());
fPreferredContentHeight->SetPenaltyPos(grow.Height());
}
} else
} else
fChildArea->SetGrowPenalties(grow);
fLS->InvalidateLayout();
}
@ -616,7 +616,7 @@ Area::SetBottomInset(int32 bottom)
/**
* Sets the preferred size according to the content's PreferredSize method,
* Sets the preferred size according to the content's PreferredSize method,
* and the penalties according to heuristics.
*/
void
@ -628,12 +628,12 @@ Area::SetDefaultBehavior()
SetGrowPenalties(BSize(0, 0));
return;
}
if (PreferredContentSize() != Content()->PreferredSize()){
SetPreferredContentSize(Content()->PreferredSize());
fLS->InvalidateLayout();
}
if (dynamic_cast<BButton*>(Content()) != NULL
|| dynamic_cast<BRadioButton*>(Content()) != NULL
|| dynamic_cast<BCheckBox*>(Content()) != NULL
@ -649,40 +649,32 @@ Area::SetDefaultBehavior()
}
BString*
Area::ToBString()
{
BString* str = new BString();
BString* leftStr = fLeft->ToBString();
BString* topStr = fTop->ToBString();
BString* rightStr = fRight->ToBString();
BString* bottomStr = fBottom->ToBString();
*str << "Area(" << *leftStr << ", "
<< *topStr << ", "
<< *rightStr << ", "
<< *bottomStr << ")";
delete leftStr;
delete topStr;
delete rightStr;
delete bottomStr;
return str;
}
const char*
Area::ToString()
{
BString* str = new BString();
char* result = (char*) malloc(str->Length() + 1);
str->CopyInto(result, 0, str->Length());
delete str;
return result;
Area::operator BString() const
{
BString string;
GetString(string);
return string;
}
void
Area::GetString(BString& string) const
{
string << "Area(";
fLeft->GetString(string);
string << ", ";
fTop->GetString(string);
string << ", ";
fRight->GetString(string);
string << ", ";
fBottom->GetString(string);
string << ")";
}
/**
* Sets the width of the area to be the same as the width of the given area.
*
*
* @param area the area that should have the same width
* @return the same-width constraint
*/
@ -690,14 +682,14 @@ Constraint*
Area::HasSameWidthAs(Area* area)
{
return fLS->AddConstraint(
-1.0, fLeft, 1.0, fRight, 1.0, area->fLeft, -1.0, area->fRight,
-1.0, fLeft, 1.0, fRight, 1.0, area->fLeft, -1.0, area->fRight,
OperatorType(EQ), 0.0);
}
/**
* Sets the height of the area to be the same as the height of the given area.
*
*
* @param area the area that should have the same height
* @return the same-height constraint
*/
@ -705,14 +697,14 @@ Constraint*
Area::HasSameHeightAs(Area* area)
{
return fLS->AddConstraint(
-1.0, fTop, 1.0, fBottom, 1.0, area->fTop, -1.0, area->fBottom,
-1.0, fTop, 1.0, fBottom, 1.0, area->fTop, -1.0, area->fBottom,
OperatorType(EQ), 0.0);
}
/**
* Sets the size of the area to be the same as the size of the given area.
*
*
* @param area the area that should have the same size
* @return a list containing a same-width and same-height constraint
*/
@ -743,9 +735,9 @@ Area::~Area()
* Constructor.
* Uses XTabs and YTabs.
*/
Area::Area(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
Area::Area(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
BView* content, BSize minContentSize)
{
{
Init(ls, left, top, right, bottom, content, minContentSize);
}
@ -757,8 +749,8 @@ Area::Area(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
Area::Area(BALMLayout* ls, Row* row, Column* column, BView* content,
BSize minContentSize)
{
Init(ls, column->Left(), row->Top(), column->Right(), row->Bottom(),
Init(ls, column->Left(), row->Top(), column->Right(), row->Bottom(),
content, minContentSize);
fRow = row;
fColumn = column;
@ -769,40 +761,40 @@ Area::Area(BALMLayout* ls, Row* row, Column* column, BView* content,
* Initialize variables.
*/
void
Area::Init(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
Area::Init(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
BView* content, BSize minContentSize)
{
fConstraints = new BList(2);
fMaxContentSize = kMaxSize;
fMaxContentWidth = NULL;
fMaxContentHeight = NULL;
fPreferredContentSize = kUndefinedSize;
fShrinkPenalties = BSize(2, 2);
fGrowPenalties = BSize(1, 1);
fContentAspectRatio = 0;
fContentAspectRatioC = NULL;
fAutoPreferredContentSize = false;
fPreferredContentWidth = NULL;
fPreferredContentHeight = NULL;
fChildArea = NULL;
fAlignment = BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
fLeftInset = 0;
fTopInset = 0;
fRightInset = 0;
fBottomInset = 0;
fLeftConstraint = NULL;
fTopConstraint = NULL;
fRightConstraint = NULL;
fBottomConstraint = NULL;
fLS = ls;
fLeft = left;
fRight = right;
@ -810,13 +802,13 @@ Area::Init(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
fBottom = bottom;
SetContent(content);
fMinContentSize = minContentSize;
// adds the two essential constraints of the area that make sure that the left x-tab is
// adds the two essential constraints of the area that make sure that the left x-tab is
// really to the left of the right x-tab, and the top y-tab really above the bottom y-tab
fMinContentWidth = ls->AddConstraint(-1.0, left, 1.0, right, OperatorType(GE),
minContentSize.Width());
fConstraints->AddItem(fMinContentWidth);
fMinContentHeight = ls->AddConstraint(-1.0, top, 1.0, bottom, OperatorType(GE),
minContentSize.Height());
fConstraints->AddItem(fMinContentHeight);
@ -828,14 +820,14 @@ Area::Init(BALMLayout* ls, XTab* left, YTab* top, XTab* right, YTab* bottom,
*/
void Area::DoLayout()
{
if (Content() == NULL)
if (Content() == NULL)
return; // empty areas need no layout
// if there is a childArea, then it is the childArea that actually contains the content
Area* area = (fChildArea != NULL) ? fChildArea : this;
// set content location and size
area->Content()->MoveTo(floor(area->Left()->Value() + 0.5),
area->Content()->MoveTo(floor(area->Left()->Value() + 0.5),
floor(area->Top()->Value() + 0.5));
int32 width = (int32)floor(area->Right()->Value() - area->Left()->Value() + 0.5);
int32 height = (int32)floor(area->Bottom()->Value() - area->Top()->Value() + 0.5);
@ -844,15 +836,15 @@ void Area::DoLayout()
/**
* Adds a childArea to this area, together with constraints that specify the relative location
* of the childArea within this area. It is called when such a childArea becomes necessary,
* Adds a childArea to this area, together with constraints that specify the relative location
* of the childArea within this area. It is called when such a childArea becomes necessary,
* i.e. when the user requests insets or special alignment.
*/
void
Area::InitChildArea()
{
// add a child area with new tabs,
// and add constraints that set its tabs to be equal to the
// and add constraints that set its tabs to be equal to the
// coresponding tabs of this area (for a start)
fChildArea = new Area(fLS, new XTab(fLS), new YTab(fLS), new XTab(fLS),
new YTab(fLS), fContent, BSize(0, 0));
@ -864,7 +856,7 @@ Area::InitChildArea()
fConstraints->AddItem(fRightConstraint);
fBottomConstraint = fBottom->IsEqual(fChildArea->Bottom());
fConstraints->AddItem(fBottomConstraint);
// remove the minimum content size constraints from this area
// and copy the minimum content size setting to the childArea
fConstraints->RemoveItem(fMinContentWidth);
@ -875,33 +867,33 @@ Area::InitChildArea()
fMinContentHeight = fChildArea->fMinContentHeight;
fChildArea->SetMinContentSize(fMinContentSize);
// if there are maximum content size constraints on this area,
// change them so that they refer to the tabs of the childArea
// if there are maximum content size constraints on this area,
// change them so that they refer to the tabs of the childArea
// and copy the minimum content size settings to the childArea
if (fMaxContentWidth != NULL) {
fChildArea->fMaxContentSize = fMaxContentSize;
fChildArea->fMaxContentWidth = fMaxContentWidth;
fMaxContentWidth->SetLeftSide(
-1.0, fChildArea->Left(), 1.0, fChildArea->Right());
fChildArea->fMaxContentHeight = fMaxContentHeight;
fMaxContentHeight->SetLeftSide(
-1.0, fChildArea->Top(), 1.0, fChildArea->Bottom());
}
// if there are preferred content size constraints on this area,
// change them so that they refer to the tabs of the childArea
// if there are preferred content size constraints on this area,
// change them so that they refer to the tabs of the childArea
// and copy the preferred content size settings to the childArea
if (fPreferredContentHeight != NULL) {
fChildArea->fPreferredContentSize = fPreferredContentSize;
fChildArea->fShrinkPenalties = fShrinkPenalties;
fChildArea->fGrowPenalties = fGrowPenalties;
fChildArea->fPreferredContentWidth = fPreferredContentWidth;
fPreferredContentWidth->SetLeftSide(
-1.0, fChildArea->Left(), 1.0, fChildArea->Right());
fChildArea->fPreferredContentHeight = fPreferredContentHeight;
fPreferredContentHeight->SetLeftSide(
-1.0, fChildArea->Top(), 1.0, fChildArea->Bottom());
@ -919,13 +911,13 @@ Area::UpdateHorizontal()
if (fChildArea == NULL)
InitChildArea();
// change the constraints leftConstraint and rightConstraint so that the horizontal
// change the constraints leftConstraint and rightConstraint so that the horizontal
// alignment and insets of the childArea within this area are as specified by the user
if (fAlignment.Horizontal() == B_ALIGN_LEFT) {
fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
fLeftConstraint->SetOp(OperatorType(EQ));
fLeftConstraint->SetRightSide(fLeftInset);
fRightConstraint->SetLeftSide(-1.0, fChildArea->Right(), 1.0, fRight);
fRightConstraint->SetOp(OperatorType(GE));
fRightConstraint->SetRightSide(fRightInset);
@ -933,7 +925,7 @@ Area::UpdateHorizontal()
fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
fLeftConstraint->SetOp(OperatorType(GE));
fLeftConstraint->SetRightSide(fLeftInset);
fRightConstraint->SetLeftSide(-1.0, fChildArea->Right(), 1.0, fRight);
fRightConstraint->SetOp(OperatorType(EQ));
fRightConstraint->SetRightSide(fRightInset);
@ -941,7 +933,7 @@ Area::UpdateHorizontal()
fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
fLeftConstraint->SetOp(OperatorType(GE));
fLeftConstraint->SetRightSide(max(fLeftInset, fRightInset));
fRightConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left(), 1.0, fChildArea->Right(), -1.0, fRight);
fRightConstraint->SetOp(OperatorType(EQ));
fRightConstraint->SetRightSide(0);
@ -949,7 +941,7 @@ Area::UpdateHorizontal()
fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
fLeftConstraint->SetOp(OperatorType(EQ));
fLeftConstraint->SetRightSide(fLeftInset);
fRightConstraint->SetLeftSide(-1.0, fChildArea->Right(), 1.0, fRight);
fRightConstraint->SetOp(OperatorType(EQ));
fRightConstraint->SetRightSide(fRightInset);
@ -957,7 +949,7 @@ Area::UpdateHorizontal()
fLeftConstraint->SetLeftSide(-1.0, fLeft, 1.0, fChildArea->Left());
fLeftConstraint->SetOp(OperatorType(GE));
fLeftConstraint->SetRightSide(fLeftInset);
fRightConstraint->SetLeftSide(-1.0, fChildArea->Right(), 1.0, fRight);
fRightConstraint->SetOp(OperatorType(GE));
fRightConstraint->SetRightSide(fRightInset);
@ -970,16 +962,16 @@ Area::UpdateHorizontal()
*/
void Area::UpdateVertical() {
// if the area does not have a childAdrea yet, this is the time to add it
if (fChildArea == NULL)
if (fChildArea == NULL)
InitChildArea();
// change the constraints topConstraint and bottomConstraint so that the vertical
// change the constraints topConstraint and bottomConstraint so that the vertical
// alignment and insets of the childArea within this area are as specified by the user
if (fAlignment.Vertical() == B_ALIGN_TOP) {
fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
fTopConstraint->SetOp(OperatorType(EQ));
fTopConstraint->SetRightSide(fTopInset);
fBottomConstraint->SetLeftSide(-1.0, fChildArea->Bottom(), 1.0, fBottom);
fBottomConstraint->SetOp(OperatorType(GE));
fBottomConstraint->SetRightSide(fBottomInset);
@ -987,7 +979,7 @@ void Area::UpdateVertical() {
fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
fTopConstraint->SetOp(OperatorType(GE));
fTopConstraint->SetRightSide(fTopInset);
fBottomConstraint->SetLeftSide(-1.0, fChildArea->Bottom(), 1.0, fBottom);
fBottomConstraint->SetOp(OperatorType(EQ));
fBottomConstraint->SetRightSide(fBottomInset);
@ -995,7 +987,7 @@ void Area::UpdateVertical() {
fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
fTopConstraint->SetOp(OperatorType(GE));
fTopConstraint->SetRightSide(max(fTopInset, fBottomInset));
fBottomConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top(), 1.0, fChildArea->Bottom(), -1.0, fBottom);
fBottomConstraint->SetOp(OperatorType(EQ));
fBottomConstraint->SetRightSide(0);
@ -1003,7 +995,7 @@ void Area::UpdateVertical() {
fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
fTopConstraint->SetOp(OperatorType(EQ));
fTopConstraint->SetRightSide(fTopInset);
fBottomConstraint->SetLeftSide(-1.0, fChildArea->Bottom(), 1.0, fBottom);
fBottomConstraint->SetOp(OperatorType(EQ));
fBottomConstraint->SetRightSide(fBottomInset);
@ -1011,7 +1003,7 @@ void Area::UpdateVertical() {
fTopConstraint->SetLeftSide(-1.0, fTop, 1.0, fChildArea->Top());
fTopConstraint->SetOp(OperatorType(GE));
fTopConstraint->SetRightSide(fTopInset);
fBottomConstraint->SetLeftSide(-1.0, fChildArea->Bottom(), 1.0, fBottom);
fBottomConstraint->SetOp(OperatorType(GE));
fBottomConstraint->SetRightSide(fBottomInset);

View File

@ -19,29 +19,29 @@
* Constructor.
* Creates new layout engine.
*/
BALMLayout::BALMLayout()
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;
}
@ -61,23 +61,28 @@ BALMLayout::SolveLayout()
if (currentArea->AutoPreferredContentSize())
currentArea->SetDefaultBehavior();
}
// 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);
// 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 = NULL;
if (fPerformancePath != NULL) {
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=%ld\t#constraints=%ld\n",
result, SolvingTime(), Variables()->CountItems(),
Constraints()->CountItems()));
file->Write(buffer, sprintf(buffer, "%d\t%fms\t#vars=%ld\t"
"#constraints=%ld\n", result, SolvingTime(),
Variables()->CountItems(), Constraints()->CountItems()));
}
if (result == OPTIMAL || result == INFEASIBLE) break;
if (result == OPTIMAL || result == INFEASIBLE)
break;
}
delete file;
}
@ -85,7 +90,7 @@ BALMLayout::SolveLayout()
/**
* Adds a new x-tab to the specification.
*
*
* @return the new x-tab
*/
XTab*
@ -93,11 +98,11 @@ BALMLayout::AddXTab()
{
return new XTab(this);
}
/**
* Adds a new y-tab to the specification.
*
*
* @return the new y-tab
*/
YTab*
@ -109,7 +114,7 @@ BALMLayout::AddYTab()
/**
* Adds a new row to the specification.
*
*
* @return the new row
*/
Row*
@ -121,7 +126,7 @@ BALMLayout::AddRow()
/**
* Adds a new row to the specification that is glued to the given y-tabs.
*
*
* @param top
* @param bottom
* @return the new row
@ -130,15 +135,17 @@ 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));
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*
@ -150,7 +157,7 @@ BALMLayout::AddColumn()
/**
* Adds a new column to the specification that is glued to the given x-tabs.
*
*
* @param left
* @param right
* @return the new column
@ -167,7 +174,7 @@ BALMLayout::AddColumn(XTab* left, XTab* right)
/**
* 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
@ -179,7 +186,7 @@ BALMLayout::AddColumn(XTab* left, XTab* right)
Area*
BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
BView* content, BSize minContentSize)
{
{
InvalidateLayout();
if (content != NULL)
View()->AddChild(content);
@ -191,7 +198,7 @@ BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
/**
* 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
@ -201,7 +208,7 @@ BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
Area*
BALMLayout::AddArea(Row* row, Column* column, BView* content,
BSize minContentSize)
{
{
InvalidateLayout();
if (content != NULL)
View()->AddChild(content);
@ -213,7 +220,7 @@ BALMLayout::AddArea(Row* row, Column* column, BView* content,
/**
* Adds a new area to the specification, automatically setting preferred size constraints.
*
*
* @param left left border
* @param top top border
* @param right right border
@ -224,7 +231,7 @@ BALMLayout::AddArea(Row* row, Column* column, BView* content,
Area*
BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
BView* content)
{
{
InvalidateLayout();
if (content != NULL)
View()->AddChild(content);
@ -238,11 +245,11 @@ BALMLayout::AddArea(XTab* left, YTab* top, XTab* right, YTab* bottom,
/**
* 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
* @return the new area
*/
Area*
BALMLayout::AddArea(Row* row, Column* column, BView* content)
@ -260,7 +267,7 @@ BALMLayout::AddArea(Row* row, Column* column, BView* content)
/**
* Finds the area that contains the given control.
*
*
* @param control the control to look for
* @return the area that contains the control
*/
@ -270,7 +277,7 @@ BALMLayout::AreaOf(BView* control)
Area* area;
for (int32 i = 0; i < fAreas->CountItems(); i++) {
area = (Area*)fAreas->ItemAt(i);
if (area->Content() == control)
if (area->Content() == control)
return area;
}
return NULL;
@ -516,45 +523,45 @@ BALMLayout::LayoutView()
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
// 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;
}
@ -600,14 +607,14 @@ BALMLayout::CalculateMinSize()
delete (Summand*)newObjFunction->ItemAt(0);
delete (Summand*)newObjFunction->ItemAt(1);
delete newObjFunction;
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());
}
@ -629,14 +636,14 @@ BALMLayout::CalculateMaxSize()
delete (Summand*)newObjFunction->ItemAt(0);
delete (Summand*)newObjFunction->ItemAt(1);
delete newObjFunction;
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());
}
@ -652,7 +659,7 @@ BALMLayout::CalculatePreferredSize()
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());
}

View File

@ -23,11 +23,11 @@
/**
* Gets the index of the constraint.
*
*
* @return the index of the constraint
*/
int32
Constraint::Index()
Constraint::Index() const
{
int32 i = fLS->Constraints()->IndexOf(this);
if (i == -1) {
@ -40,7 +40,7 @@ Constraint::Index()
/**
* Gets the left side of the constraint.
*
*
* @return pointer to a BList containing the summands on the left side of the constraint
*/
BList*
@ -53,7 +53,7 @@ Constraint::LeftSide()
/**
* Sets the summands on the left side of the constraint.
* The old summands are NOT deleted.
*
*
* @param summands a BList containing the Summand objects that make up the new left side
*/
void
@ -81,22 +81,22 @@ Constraint::UpdateLeftSide()
coeffs[i] = s->Coeff();
varIndexes[i] = s->Var()->Index();
}
if (fDNegObjSummand != NULL && fOp != OperatorType(LE)) {
varIndexes[i] = fDNegObjSummand->Var()->Index();
coeffs[i] = 1.0;
i++;
}
if (fDPosObjSummand != NULL && fOp != OperatorType(GE)) {
varIndexes[i] = fDPosObjSummand->Var()->Index();
coeffs[i] = -1.0;
i++;
}
if (!set_rowex(fLS->fLP, this->Index(), i, &coeffs[0], &varIndexes[0]))
STRACE(("Error in set_rowex."));
fLS->UpdateObjFunction();
fLS->RemovePresolved();
}
@ -117,7 +117,7 @@ Constraint::SetLeftSide(double coeff1, Variable* var1)
void
Constraint::SetLeftSide(double coeff1, Variable* var1,
Constraint::SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2)
{
if (!fIsValid)
@ -131,9 +131,9 @@ Constraint::SetLeftSide(double coeff1, Variable* var1,
UpdateLeftSide();
}
void
Constraint::SetLeftSide(double coeff1, Variable* var1,
Constraint::SetLeftSide(double coeff1, Variable* var1,
double coeff2, Variable* var2,
double coeff3, Variable* var3)
{
@ -172,7 +172,7 @@ Constraint::SetLeftSide(double coeff1, Variable* var1,
/**
* Gets the operator used for this constraint.
*
*
* @return the operator used for this constraint
*/
OperatorType
@ -184,7 +184,7 @@ Constraint::Op()
/**
* Sets the operator used for this constraint.
*
*
* @param value operator
*/
void
@ -199,14 +199,14 @@ Constraint::SetOp(OperatorType value)
: (fOp == OperatorType(GE)) ? GE
: LE)))
STRACE(("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
@ -215,10 +215,10 @@ Constraint::RightSide() const
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
@ -230,14 +230,14 @@ Constraint::SetRightSide(double value)
fRightSide = value;
if (!set_rh(fLS->fLP, Index(), fRightSide))
STRACE(("Error in set_rh."));
fLS->RemovePresolved();
}
/**
* Gets the penalty coefficient for negative deviations.
*
*
* @return the penalty coefficient
*/
double
@ -252,7 +252,7 @@ Constraint::PenaltyNeg() const
/**
* The penalty coefficient for negative 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
@ -268,7 +268,7 @@ Constraint::SetPenaltyNeg(double value)
fLS->UpdateObjFunction();
return;
}
if (value == fDNegObjSummand->Coeff())
return;
@ -279,7 +279,7 @@ Constraint::SetPenaltyNeg(double value)
/**
* Gets the penalty coefficient for positive deviations.
*
*
* @return the penalty coefficient
*/
double
@ -294,7 +294,7 @@ Constraint::PenaltyPos() const
/**
* 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
@ -339,33 +339,32 @@ Constraint::WriteXML(BFile* file)
{
if (file->IsWritable() && fOwner == NULL) {
char buffer[200];
file->Write(buffer, sprintf(buffer, "\t<constraint>\n"));
file->Write(buffer, sprintf(buffer, "\t\t<leftside>\n"));
Summand* summand;
for (int32 i = 0; i < fLeftSide->CountItems(); i++) {
summand = (Summand*)fLeftSide->ItemAt(i);
file->Write(buffer, sprintf(buffer, "\t\t\t<summand>\n"));
file->Write(buffer, sprintf(buffer, "\t\t\t\t<coeff>%f</coeff>\n",
file->Write(buffer, sprintf(buffer, "\t\t\t\t<coeff>%f</coeff>\n",
summand->Coeff()));
BString* varStr = summand->Var()->ToBString();
file->Write(buffer, sprintf(buffer, "\t\t\t\t<var>%s</var>\n",
varStr->String()));
delete varStr;
BString varStr = *(summand->Var());
file->Write(buffer, sprintf(buffer, "\t\t\t\t<var>%s</var>\n",
varStr.String()));
file->Write(buffer, sprintf(buffer, "\t\t\t</summand>\n"));
}
file->Write(buffer, sprintf(buffer, "\t\t</leftside>\n"));
char* op;
const char* op = "??";
if (fOp == OperatorType(EQ))
op = "EQ";
else if (fOp == OperatorType(LE))
op = "LE";
else if (fOp == OperatorType(GE))
op = "GE";
file->Write(buffer, sprintf(buffer, "\t\t<op>%s</op>\n", op));
file->Write(buffer, sprintf(buffer, "\t\t<rightside>%f</rightside>\n", fRightSide));
//~ file->Write(buffer, sprintf(buffer, "\t\t<penaltyneg>%s</penaltyneg>\n", PenaltyNeg()));
@ -377,7 +376,7 @@ Constraint::WriteXML(BFile* file)
/**
* Gets the slack variable for the negative variations.
*
*
* @return the slack variable for the negative variations
*/
Variable*
@ -391,7 +390,7 @@ Constraint::DNeg() const
/**
* Gets the slack variable for the positive variations.
*
*
* @return the slack variable for the positive variations
*/
Variable*
@ -452,56 +451,50 @@ Constraint::Invalidate()
fDPosObjSummand = NULL;
}
del_constraint(fLS->fLP, this->Index());
del_constraint(fLS->fLP, this->Index());
fLS->Constraints()->RemoveItem(this);
}
BString*
Constraint::ToBString()
Constraint::operator BString() const
{
BString* str = new BString();
*str << "Constraint ";
BString string;
GetString(string);
return string;
}
void
Constraint::GetString(BString& string) const
{
string << "Constraint ";
if (fLabel)
*str << fLabel;
*str << "(" << (int32)this << "): ";
string << fLabel;
string << "(" << (int32)this << "): ";
if (fIsValid) {
for (int i = 0; i < fLeftSide->CountItems(); i++) {
Summand* s = static_cast<Summand*>(fLeftSide->ItemAt(i));
*str << (float)s->Coeff() << "*";
BString* varString = s->Var()->ToBString();
*str << *varString << " ";
delete varString;
string << (float)s->Coeff() << "*";
s->Var()->GetString(string);
string << " ";
}
*str << ((fOp == OperatorType(EQ)) ? "== "
string << ((fOp == OperatorType(EQ)) ? "== "
: (fOp == OperatorType(GE)) ? ">= "
: (fOp == OperatorType(LE)) ? "<= "
: "?? ");
*str << (float)fRightSide;
*str << " PenaltyPos=" << (float)PenaltyPos();
*str << " PenaltyNeg=" << (float)PenaltyNeg();
string << (float)fRightSide;
string << " PenaltyPos=" << (float)PenaltyPos();
string << " PenaltyNeg=" << (float)PenaltyNeg();
} else
*str << "invalid";
return str;
}
const char*
Constraint::ToString()
{
BString* str = ToBString();
char* result = (char*) malloc(str->Length() + 1);
str->CopyInto(result, 0, str->Length());
delete str;
return result;
string << "invalid";
}
/**
* Constructor.
*/
Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
double rightSide, double penaltyNeg, double penaltyPos)
: fLS(ls),
fLeftSide(summands),
@ -519,7 +512,7 @@ Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
coeffs[i] = s->Coeff();
varIndexes[i] = s->Var()->Index();
}
if (penaltyNeg != INFINITY
&& fOp != OperatorType(LE)) {
fDNegObjSummand = new Summand(penaltyNeg, new Variable(fLS));
@ -530,7 +523,7 @@ Constraint::Constraint(LinearSpec* ls, BList* summands, OperatorType op,
}
else
fDNegObjSummand = NULL;
if (penaltyPos != INFINITY
&& fOp != OperatorType(GE)) {
fDPosObjSummand = new Summand(penaltyPos, new Variable(fLS));

View File

@ -31,7 +31,7 @@ LinearSpec::LinearSpec()
/**
* Destructor.
* Removes the specification and deletes all constraints,
* Removes the specification and deletes all constraints,
* objective function summands and variables.
*/
LinearSpec::~LinearSpec()
@ -49,7 +49,7 @@ LinearSpec::~LinearSpec()
/**
* Adds a new variable to the specification.
*
*
* @return the new variable
*/
Variable*
@ -61,7 +61,7 @@ LinearSpec::AddVariable()
/**
* 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
@ -70,7 +70,7 @@ LinearSpec::AddVariable()
*/
Constraint*
LinearSpec::AddConstraint(BList* summands, OperatorType op, double rightSide)
{
{
Constraint* c = new Constraint(this, summands, op, rightSide,
INFINITY, INFINITY);
RemovePresolved();
@ -80,7 +80,7 @@ LinearSpec::AddConstraint(BList* summands, OperatorType op, double rightSide)
/**
* 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
@ -88,9 +88,9 @@ LinearSpec::AddConstraint(BList* summands, OperatorType op, double rightSide)
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
LinearSpec::AddConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide)
{
{
BList* summands = new BList(1);
summands->AddItem(new Summand(coeff1, var1));
Constraint* c = new Constraint(this, summands, op, rightSide,
@ -102,7 +102,7 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
/**
* 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
@ -112,22 +112,22 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, OperatorType op, double rightSide)
{
{
BList* summands = new BList(2);
summands->AddItem(new Summand(coeff1, var1));
summands->AddItem(new Summand(coeff2, var2));
Constraint* c = new Constraint(this, summands, op, rightSide,
INFINITY, INFINITY);
RemovePresolved();
return c;
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
@ -139,10 +139,10 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
OperatorType op, double rightSide)
{
{
BList* summands = new BList(3);
summands->AddItem(new Summand(coeff1, var1));
summands->AddItem(new Summand(coeff2, var2));
@ -150,13 +150,13 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
Constraint* c = new Constraint(this, summands, op, rightSide,
INFINITY, INFINITY);
RemovePresolved();
return c;
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
@ -170,10 +170,10 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
* @return the new constraint
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
double coeff4, Variable* var4, OperatorType op, double rightSide)
{
{
BList* summands = new BList(3);
summands->AddItem(new Summand(coeff1, var1));
summands->AddItem(new Summand(coeff2, var2));
@ -182,14 +182,14 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
Constraint* c = new Constraint(this, summands, op, rightSide,
INFINITY, INFINITY);
RemovePresolved();
return c;
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
@ -198,10 +198,10 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
Constraint*
LinearSpec::AddConstraint(BList* summands, OperatorType op,
LinearSpec::AddConstraint(BList* summands, OperatorType op,
double rightSide, double penaltyNeg, double penaltyPos)
{
Constraint* c = new Constraint(this, summands, op, rightSide,
{
Constraint* c = new Constraint(this, summands, op, rightSide,
penaltyNeg, penaltyPos);
RemovePresolved();
return c;
@ -210,7 +210,7 @@ LinearSpec::AddConstraint(BList* summands, OperatorType op,
/**
* 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
@ -219,9 +219,9 @@ LinearSpec::AddConstraint(BList* summands, OperatorType op,
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
LinearSpec::AddConstraint(double coeff1, Variable* var1,
OperatorType op, double rightSide, double penaltyNeg, double penaltyPos)
{
{
BList* summands = new BList(1);
summands->AddItem(new Summand(coeff1, var1));
Constraint* c = new Constraint(this, summands, op, rightSide,
@ -233,7 +233,7 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
/**
* 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
@ -244,10 +244,10 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, OperatorType op, double rightSide,
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, OperatorType op, double rightSide,
double penaltyNeg, double penaltyPos)
{
{
BList* summands = new BList(2);
summands->AddItem(new Summand(coeff1, var1));
summands->AddItem(new Summand(coeff2, var2));
@ -260,7 +260,7 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
/**
* 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
@ -273,8 +273,8 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
OperatorType op, double rightSide, double penaltyNeg, double penaltyPos)
{
BList* summands = new BList(2);
@ -290,7 +290,7 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
/**
* 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
@ -305,11 +305,11 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
* @param penaltyPos the coefficient penalizing positive deviations from the exact solution
*/
Constraint*
LinearSpec::AddConstraint(double coeff1, Variable* var1,
double coeff2, Variable* var2, double coeff3, Variable* var3,
double coeff4, Variable* var4, OperatorType op, double rightSide,
LinearSpec::AddConstraint(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* summands = new BList(2);
summands->AddItem(new Summand(coeff1, var1));
summands->AddItem(new Summand(coeff2, var2));
@ -324,7 +324,7 @@ LinearSpec::AddConstraint(double coeff1, Variable* var1,
/**
* 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
@ -339,7 +339,7 @@ LinearSpec::AddPenaltyFunction(Variable* var, BList* xs, BList* gs)
/**
* Gets the objective function.
*
*
* @return BList containing the objective function's summands
*/
BList*
@ -352,7 +352,7 @@ LinearSpec::ObjFunction()
/**
* Sets a new objective function.
* The old objective function summands are NOT deleted.
*
*
* @param summands BList containing the objective function's summands
*/
void
@ -379,17 +379,17 @@ LinearSpec::UpdateObjFunction()
coeffs[i] = current->Coeff();
varIndexes[i] = current->Var()->Index();
}
if (!set_obj_fnex(fLP, size, &coeffs[0], &varIndexes[0]))
printf("Error in set_obj_fnex.");
RemovePresolved();
}
/**
* Remove a cached presolved model, if existent.
* This is automatically done each time after the model has been changed,
* This is automatically done each time after the model has been changed,
* to avoid an old cached presolved model getting out of sync.
*/
void
@ -403,11 +403,11 @@ LinearSpec::RemovePresolved()
/**
* Creates and caches a simplified version of the linear programming problem,
* where redundant rows, columns and constraints are removed,
* 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
@ -415,28 +415,28 @@ 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,
current->SetValue(get_var_primalresult(fLpPresolved,
get_Norig_rows(fLpPresolved) + current->Index()));
}
}
end = system_time();
fSolvingTime = (end - start) / 1000.0;
return fResult;
}
@ -444,7 +444,7 @@ LinearSpec::Presolve()
/**
* 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
@ -452,29 +452,29 @@ 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;
}
@ -482,13 +482,14 @@ LinearSpec::Solve()
/**
* 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)
LinearSpec::Save(const char* fileName)
{
write_lp(fLP, fname);
// TODO: Constness should be fixed in liblpsolve API.
write_lp(fLP, const_cast<char*>(fileName));
}
@ -507,7 +508,7 @@ LinearSpec::CountColumns() const
/**
* Gets the current optimization.
* The default is minimization.
*
*
* @return the current optimization
*/
OptimizationType
@ -520,7 +521,7 @@ LinearSpec::Optimization() const
/**
* Sets whether the solver should minimize or maximize the objective function.
* The default is minimization.
*
*
* @param optimization the optimization type
*/
void
@ -536,7 +537,7 @@ LinearSpec::SetOptimization(OptimizationType value)
/**
* Gets the the variables.
*
*
* @return the variables
*/
BList*
@ -548,7 +549,7 @@ LinearSpec::Variables() const
/**
* Gets the constraints.
*
*
* @return the constraints
*/
BList*
@ -560,7 +561,7 @@ LinearSpec::Constraints() const
/**
* Gets the result type.
*
*
* @return the result type
*/
ResultType
@ -572,7 +573,7 @@ LinearSpec::Result() const
/**
* Gets the objective value.
*
*
* @return the objective value
*/
double
@ -584,7 +585,7 @@ LinearSpec::ObjectiveValue() const
/**
* Gets the solving time.
*
*
* @return the solving time
*/
double
@ -594,54 +595,47 @@ LinearSpec::SolvingTime() const
}
BString*
LinearSpec::ToBString()
LinearSpec::operator BString() const
{
BString* str = new BString();
*str << "LinearSpec " << (int32)this << ":\n";
BString string;
GetString(string);
return string;
}
void
LinearSpec::GetString(BString& string) const
{
string << "LinearSpec " << (int32)this << ":\n";
for (int i = 0; i < fVariables->CountItems(); i++) {
Variable* variable = static_cast<Variable*>(fVariables->ItemAt(i));
BString* vStr = variable->ToBString();
*str << *vStr << "=" << (float)variable->Value() << " ";
delete vStr;
variable->GetString(string);
string << "=" << (float)variable->Value() << " ";
}
*str << "\n";
string << "\n";
for (int i = 0; i < fConstraints->CountItems(); i++) {
Constraint* c = static_cast<Constraint*>(fConstraints->ItemAt(i));
BString* cStr = c->ToBString();
*str << i << ": " << *cStr;
delete cStr;
*str << "\n";
Constraint* c = static_cast<Constraint*>(fConstraints->ItemAt(i));
string << i << ": ";
c->GetString(string);
string << "\n";
}
*str << "Result=";
string << "Result=";
if (fResult==-1)
*str << "ERROR";
string << "ERROR";
else if (fResult==0)
*str << "OPTIMAL";
string << "OPTIMAL";
else if (fResult==1)
*str << "SUBOPTIMAL";
string << "SUBOPTIMAL";
else if (fResult==2)
*str << "INFEASIBLE";
string << "INFEASIBLE";
else if (fResult==3)
*str << "UNBOUNDED";
string << "UNBOUNDED";
else if (fResult==4)
*str << "DEGENERATE";
string << "DEGENERATE";
else if (fResult==5)
*str << "NUMFAILURE";
string << "NUMFAILURE";
else
*str << fResult;
*str << " SolvingTime=" << (float)fSolvingTime << "ms";
return str;
}
const char*
LinearSpec::ToString()
{
BString* str = ToBString();
char* result = (char*) malloc(str->Length() + 1);
str->CopyInto(result, 0, str->Length());
delete str;
return result;
string << fResult;
string << " SolvingTime=" << (float)fSolvingTime << "ms";
}

View File

@ -26,11 +26,11 @@
/**
* Gets index of the variable.
*
*
* @return the index of the variable
*/
int32
Variable::Index()
Variable::Index() const
{
int32 i = fLS->Variables()->IndexOf(this);
if (i == -1) {
@ -43,7 +43,7 @@ Variable::Index()
/**
* Gets the current linear specification.
*
*
* @return the current linear specification
*/
LinearSpec*
@ -55,7 +55,7 @@ Variable::LS() const
/**
* Gets the value.
*
*
* @return the value
*/
double
@ -67,7 +67,7 @@ Variable::Value() const
/**
* Sets the value.
*
*
* @param value the value
*/
void
@ -79,7 +79,7 @@ Variable::SetValue(double value)
/**
* Gets the minimum value of the variable.
*
*
* @return the minimum value of variable
*/
double
@ -91,7 +91,7 @@ Variable::Min() const
/**
* Sets the minimum value of the variable.
*
*
* @param min minimum value
*/
void
@ -107,7 +107,7 @@ Variable::SetMin(double min)
/**
* Gets the maximum value of the variable.
*
*
* @return the maximum value of variable
*/
double
@ -119,7 +119,7 @@ Variable::Max() const
/**
* Sets the maximum value of the variable.
*
*
* @param max maximum value
*/
void
@ -135,7 +135,7 @@ Variable::SetMax(double max)
/**
* Sets the minimum and maximum values of the variable.
*
*
* @param min minimum value
* @param max maximum value
*/
@ -166,45 +166,40 @@ Variable::SetLabel(const char* label)
}
/**
* Returns index of the variable as String.
* E.g. "Var2"
*
* @return the <code>String</code> index of the variable
*/
BString*
Variable::ToBString()
Variable::operator BString() const
{
BString* str = new BString();
if (fLabel) {
*str << fLabel;
if (!fIsValid)
*str << "(invalid)";
} else {
*str << "Var";
if (!fIsValid)
*str << "(invalid," << (int32)this << ")";
else
*str << Index();
}
return str;
BString string;
GetString(string);
return string;
}
const char*
Variable::ToString()
/**
* Returns index of the variable as String.
* E.g. "Var2"
*
* @return the <code>String</code> index of the variable
*/
void
Variable::GetString(BString& string) const
{
BString* str = ToBString();
char* result = (char*) malloc(str->Length() + 1);
str->CopyInto(result, 0, str->Length());
delete str;
return result;
if (fLabel) {
string << fLabel;
if (!fIsValid)
string << "(invalid)";
} else {
string << "Var";
if (!fIsValid)
string << "(invalid," << (int32)this << ")";
else
string << 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
*/
@ -220,7 +215,7 @@ Variable::IsEqual(Variable* var)
/**
* 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
*/
@ -236,7 +231,7 @@ Variable::IsSmallerOrEqual(Variable* var)
/**
* 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
*/
@ -341,7 +336,7 @@ Variable::Variable(LinearSpec* ls)
fIsValid(true)
{
fLS->Variables()->AddItem(this);
if (fLS->Variables()->CountItems() > fLS->CountColumns()) {
double d = 0;
int i = 0;