diff --git a/headers/libs/alm/Column.h b/headers/libs/alm/Column.h index e5f3290040..1dd930c69c 100644 --- a/headers/libs/alm/Column.h +++ b/headers/libs/alm/Column.h @@ -8,12 +8,12 @@ #include "Constraint.h" #include "LinearSpec.h" +#include "Tab.h" namespace BALM { class BALMLayout; -class XTab; /** * Represents a column defined by two x-tabs. @@ -36,7 +36,7 @@ public: ConstraintList* Constraints() const; protected: - Column(LinearSpec* ls); + Column(BALMLayout* layout); protected: LinearSpec* fLS; diff --git a/headers/libs/alm/Row.h b/headers/libs/alm/Row.h index 44a004bae8..df21d1a858 100644 --- a/headers/libs/alm/Row.h +++ b/headers/libs/alm/Row.h @@ -8,13 +8,13 @@ #include "Constraint.h" #include "LinearSpec.h" +#include "Tab.h" namespace BALM { class BALMLayout; -class YTab; - + /** * Represents a row defined by two y-tabs. */ @@ -34,7 +34,7 @@ public: ConstraintList* Constraints() const; protected: - Row(LinearSpec* ls); + Row(BALMLayout* layout); protected: LinearSpec* fLS; diff --git a/headers/libs/alm/Tab.h b/headers/libs/alm/Tab.h index 3c79cb1be1..cf31ec3f09 100644 --- a/headers/libs/alm/Tab.h +++ b/headers/libs/alm/Tab.h @@ -27,7 +27,6 @@ protected: public: friend class BALMLayout; - friend class Column; }; @@ -42,7 +41,6 @@ protected: public: friend class BALMLayout; - friend class Row; }; diff --git a/headers/libs/linprog/LinearSpec.h b/headers/libs/linprog/LinearSpec.h index 2616cd445a..43ca89cb98 100644 --- a/headers/libs/linprog/LinearSpec.h +++ b/headers/libs/linprog/LinearSpec.h @@ -36,6 +36,12 @@ public: virtual ~LinearSpec(); Variable* AddVariable(); + bool AddVariable(Variable* variable); + bool RemoveVariable(Variable* variable, + bool deleteVariable = true); + int32 IndexOf(const Variable* variable) const; + bool SetRange(Variable* variable, double min, + double max); Constraint* AddConstraint(SummandList* summands, OperatorType op, double rightSide); @@ -86,8 +92,6 @@ public: void SetObjectiveFunction(SummandList* objFunction); void UpdateObjectiveFunction(); - ResultType Presolve(); - void RemovePresolved(); ResultType Solve(); void Save(const char* fileName); @@ -102,13 +106,12 @@ public: operator BString() const; void GetString(BString& string) const; -protected: - VariableList* Variables() const; - ConstraintList* Constraints() const; - - int32 fCountColumns; + const ConstraintList& Constraints() const; private: + ResultType Presolve(); + void RemovePresolved(); + lprec* fLpPresolved; OptimizationType fOptimization; lprec* fLP; @@ -121,7 +124,6 @@ private: public: friend class Constraint; - friend class Variable; }; diff --git a/headers/libs/linprog/Variable.h b/headers/libs/linprog/Variable.h index d5e19f6eff..d790b334a3 100644 --- a/headers/libs/linprog/Variable.h +++ b/headers/libs/linprog/Variable.h @@ -6,11 +6,9 @@ #ifndef VARIABLE_H #define VARIABLE_H -#include + #include #include -#include - namespace LinearProgramming { @@ -51,15 +49,18 @@ public: double penaltyNeg, double penaltyPos); bool IsValid(); + //! Dangerous the variable don't belong to the LinearSpec anymore, + //! delete it yourself! void Invalidate(); - virtual ~Variable(); + ~Variable(); protected: Variable(LinearSpec* ls); private: LinearSpec* fLS; + BObjectList fUsingSummands; // All Summands that link to this Variable double fValue; @@ -71,9 +72,7 @@ private: public: friend class LinearSpec; - friend class Constraint; friend class Summand; - }; diff --git a/src/libs/alm/ALMLayout.cpp b/src/libs/alm/ALMLayout.cpp index d7d3966862..7e5186a95c 100644 --- a/src/libs/alm/ALMLayout.cpp +++ b/src/libs/alm/ALMLayout.cpp @@ -10,6 +10,7 @@ #include // for floor #include +#include #include "ViewLayoutItem.h" @@ -31,10 +32,10 @@ BALMLayout::BALMLayout(float spacing) fSpacing(spacing), fCurrentArea(NULL) { - fLeft = new XTab(&fSolver); - fRight = new XTab(&fSolver); - fTop = new YTab(&fSolver); - fBottom = new YTab(&fSolver); + fLeft = AddXTab(); + fRight = AddXTab(); + fTop = AddYTab(); + fBottom = AddYTab(); // the Left tab is always at x-position 0, and the Top tab is always at y-position 0 fLeft->SetRange(0, 0); @@ -64,7 +65,15 @@ BALMLayout::~BALMLayout() XTab* BALMLayout::AddXTab() { - return new XTab(&fSolver); + XTab* tab = new XTab(&fSolver); + if (!tab) + return NULL; + if (!fSolver.AddVariable(tab)) { + delete tab; + return NULL; + } + + return tab; } @@ -76,7 +85,15 @@ BALMLayout::AddXTab() YTab* BALMLayout::AddYTab() { - return new YTab(&fSolver); + YTab* tab = new YTab(&fSolver); + if (!tab) + return NULL; + if (!fSolver.AddVariable(tab)) { + delete tab; + return NULL; + } + + return tab; } @@ -88,7 +105,7 @@ BALMLayout::AddYTab() Row* BALMLayout::AddRow() { - return new Row(&fSolver); + return new Row(this); } @@ -102,7 +119,7 @@ BALMLayout::AddRow() Row* BALMLayout::AddRow(YTab* top, YTab* bottom) { - Row* row = new Row(&fSolver); + Row* row = new Row(this); if (top != NULL) row->Constraints()->AddItem(row->Top()->IsEqual(top)); if (bottom != NULL) @@ -119,7 +136,7 @@ BALMLayout::AddRow(YTab* top, YTab* bottom) Column* BALMLayout::AddColumn() { - return new Column(&fSolver); + return new Column(this); } @@ -133,7 +150,7 @@ BALMLayout::AddColumn() Column* BALMLayout::AddColumn(XTab* left, XTab* right) { - Column* column = new Column(&fSolver); + Column* column = new Column(this); if (left != NULL) column->Constraints()->AddItem(column->Left()->IsEqual(left)); if (right != NULL) @@ -677,7 +694,7 @@ BALMLayout::DerivedLayoutItems() _SolveLayout(); - // if new layout is infasible, use previous layout + // if new layout is infeasible, use previous layout if (fSolver.Result() == INFEASIBLE) return; diff --git a/src/libs/alm/Area.cpp b/src/libs/alm/Area.cpp index e8770c0b14..d23eff31ca 100644 --- a/src/libs/alm/Area.cpp +++ b/src/libs/alm/Area.cpp @@ -1,6 +1,7 @@ /* * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz + * Copyright 2010, Clemens Zeidler * Distributed under the terms of the MIT License. */ diff --git a/src/libs/alm/Column.cpp b/src/libs/alm/Column.cpp index 83481b56c3..98f203c188 100644 --- a/src/libs/alm/Column.cpp +++ b/src/libs/alm/Column.cpp @@ -1,6 +1,7 @@ /* * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz + * Copyright 2010, Clemens Zeidler * Distributed under the terms of the MIT License. */ @@ -11,8 +12,6 @@ #include "OperatorType.h" #include "Tab.h" -#include - /** * The left boundary of the column. @@ -72,7 +71,7 @@ Column::SetPrevious(Column* value) fPrevious = value; fPrevious->fNext = this; - value->fNextGlue = value->fRight->IsEqual(fLeft); + value->fNextGlue = value->Right()->IsEqual(Left()); fPreviousGlue = value->fNextGlue; } @@ -115,7 +114,7 @@ Column::SetNext(Column* value) fNext = value; fNext->fPrevious = this; - value->fPreviousGlue = fRight->IsEqual(value->fLeft); + value->fPreviousGlue = Right()->IsEqual(value->Left()); fNextGlue = value->fPreviousGlue; } @@ -156,7 +155,7 @@ Constraint* Column::HasSameWidthAs(Column* column) { Constraint* constraint = fLS->AddConstraint( - -1.0, fLeft, 1.0, fRight, 1.0, column->fLeft, -1.0, column->fRight, + -1.0, Left(), 1.0, Right(), 1.0, column->Left(), -1.0, column->Right(), OperatorType(EQ), 0.0); fConstraints.AddItem(constraint); return constraint; @@ -188,10 +187,10 @@ Column::~Column() /** * Constructor. */ -Column::Column(LinearSpec* ls) +Column::Column(BALMLayout* layout) { - fLS = ls; - fLeft = new XTab(ls); - fRight = new XTab(ls); + fLS = layout->Solver(); + fLeft = layout->AddXTab(); + fRight = layout->AddXTab(); } diff --git a/src/libs/alm/Row.cpp b/src/libs/alm/Row.cpp index 7ed517568e..9d90e75322 100644 --- a/src/libs/alm/Row.cpp +++ b/src/libs/alm/Row.cpp @@ -1,6 +1,7 @@ /* * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz + * Copyright 2010, Clemens Zeidler * Distributed under the terms of the MIT License. */ @@ -73,7 +74,7 @@ Row::SetPrevious(Row* value) fPrevious = value; fPrevious->fNext = this; - value->fNextGlue = value->fBottom->IsEqual(fTop); + value->fNextGlue = value->Bottom()->IsEqual(Top()); fPreviousGlue = value->fNextGlue; } @@ -117,7 +118,7 @@ Row::SetNext(Row* value) fNext = value; fNext->fPrevious = this; - value->fPreviousGlue = fBottom->IsEqual(value->fTop); + value->fPreviousGlue = Bottom()->IsEqual(value->Top()); fNextGlue = value->fPreviousGlue; } @@ -158,7 +159,7 @@ Constraint* Row::HasSameHeightAs(Row* row) { Constraint* constraint = fLS->AddConstraint( - -1.0, fTop, 1.0, fBottom, 1.0, row->fTop, -1.0, row->fBottom, + -1.0, Top(), 1.0, Bottom(), 1.0, row->Top(), -1.0, row->Bottom(), OperatorType(EQ), 0.0); fConstraints.AddItem(constraint); return constraint; @@ -193,10 +194,10 @@ Row::~Row() /** * Constructor. */ -Row::Row(LinearSpec* ls) +Row::Row(BALMLayout* layout) { - fLS = ls; - fTop = new YTab(ls); - fBottom = new YTab(ls); + fLS = layout->Solver(); + fTop = layout->AddYTab(); + fBottom = layout->AddYTab(); } diff --git a/src/libs/linprog/Constraint.cpp b/src/libs/linprog/Constraint.cpp index 680ebbfb7b..f2b8119651 100644 --- a/src/libs/linprog/Constraint.cpp +++ b/src/libs/linprog/Constraint.cpp @@ -8,8 +8,6 @@ #include "LinearSpec.h" #include "Variable.h" -#include "lp_lib.h" - // Toggle debug output //#define DEBUG_CONSTRAINT @@ -29,7 +27,7 @@ int32 Constraint::Index() const { - int32 i = fLS->Constraints()->IndexOf(this); + int32 i = fLS->Constraints().IndexOf(this); if (i == -1) { STRACE(("Constraint not part of fLS->Constraints().")); return -1; @@ -265,7 +263,7 @@ Constraint::SetPenaltyNeg(double value) return; if (fDNegObjSummand == NULL) { - fDNegObjSummand = new Summand(value, new Variable(fLS)); + fDNegObjSummand = new Summand(value, fLS->AddVariable()); fLS->ObjectiveFunction()->AddItem(fDNegObjSummand); UpdateLeftSide(); fLS->UpdateObjectiveFunction(); @@ -307,7 +305,7 @@ Constraint::SetPenaltyPos(double value) return; if (fDPosObjSummand == NULL) { - fDPosObjSummand = new Summand(value, new Variable(fLS)); + fDPosObjSummand = new Summand(value, fLS->AddVariable()); fLS->ObjectiveFunction()->AddItem(fDPosObjSummand); UpdateLeftSide(); fLS->UpdateObjectiveFunction(); @@ -441,7 +439,7 @@ Constraint::Invalidate() } del_constraint(fLS->fLP, this->Index()); - fLS->Constraints()->RemoveItem(this); + const_cast(fLS->Constraints()).RemoveItem(this); } @@ -502,7 +500,7 @@ Constraint::Constraint(LinearSpec* ls, SummandList* summands, OperatorType op, if (penaltyNeg != INFINITY && fOp != OperatorType(LE)) { - fDNegObjSummand = new Summand(penaltyNeg, new Variable(fLS)); + fDNegObjSummand = new Summand(penaltyNeg, ls->AddVariable()); fLS->fObjFunction->AddItem(fDNegObjSummand); varIndexes[i] = fDNegObjSummand->Var()->Index(); coeffs[i] = 1.0; @@ -513,7 +511,7 @@ Constraint::Constraint(LinearSpec* ls, SummandList* summands, OperatorType op, if (penaltyPos != INFINITY && fOp != OperatorType(GE)) { - fDPosObjSummand = new Summand(penaltyPos, new Variable(fLS)); + fDPosObjSummand = new Summand(penaltyPos, ls->AddVariable()); fLS->fObjFunction->AddItem(fDPosObjSummand); varIndexes[i] = fDPosObjSummand->Var()->Index(); coeffs[i] = -1.0; @@ -529,7 +527,7 @@ Constraint::Constraint(LinearSpec* ls, SummandList* summands, OperatorType op, STRACE(("Error in add_constraintex.")); fLS->UpdateObjectiveFunction(); - fLS->Constraints()->AddItem(this); + const_cast(fLS->Constraints()).AddItem(this); } diff --git a/src/libs/linprog/LinearSpec.cpp b/src/libs/linprog/LinearSpec.cpp index 83bfacf24a..15e6a48970 100644 --- a/src/libs/linprog/LinearSpec.cpp +++ b/src/libs/linprog/LinearSpec.cpp @@ -1,9 +1,11 @@ /* * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz + * Copyright 2010, Clemens Zeidler * Distributed under the terms of the MIT License. */ + #include "LinearSpec.h" @@ -13,7 +15,6 @@ */ LinearSpec::LinearSpec() : - fCountColumns(0), fLpPresolved(NULL), fOptimization(MINIMIZE), fObjFunction(new SummandList()), @@ -40,8 +41,9 @@ LinearSpec::~LinearSpec() delete (Constraint*)fConstraints.ItemAt(i); for (int32 i = 0; i < fObjFunction->CountItems(); i++) delete (Summand*)fObjFunction->ItemAt(i); - for (int32 i = 0; i < fVariables.CountItems(); i++) - delete (Variable*)fVariables.ItemAt(i); + while (fVariables.CountItems() > 0) + RemoveVariable(fVariables.ItemAt(0)); + delete_lp(fLP); delete fObjFunction; @@ -56,7 +58,75 @@ LinearSpec::~LinearSpec() Variable* LinearSpec::AddVariable() { - return new Variable(this); + Variable* variable = new Variable(this); + if (!variable) + return NULL; + if (!AddVariable(variable)) { + delete variable; + return NULL; + } + + return variable; +} + + +bool +LinearSpec::AddVariable(Variable* variable) +{ + double d = 0; + int i = 0; + + if (!fVariables.AddItem(variable)) + return false; + if (add_columnex(fLP, 0, &d, &i) == 0) { + fVariables.RemoveItem(variable); + return false; + } + + if (!SetRange(variable, -20000, 20000)) { + RemoveVariable(variable, false); + return false; + } + + variable->fIsValid = true; + return true; +} + + +bool +LinearSpec::RemoveVariable(Variable* variable, bool deleteVariable) +{ + int32 index = IndexOf(variable); + if (index < 0) + return false; + + if (!del_column(fLP, index)) + return false; + fVariables.RemoveItemAt(index - 1); + variable->Invalidate(); + + if (deleteVariable) + delete variable; + return true; +} + + +int32 +LinearSpec::IndexOf(const Variable* variable) const +{ + int32 i = fVariables.IndexOf(variable); + if (i == -1) { + printf("Variable 0x%p not part of fLS->Variables().\n", variable); + return -1; + } + return i + 1; +} + + +bool +LinearSpec::SetRange(Variable* variable, double min, double max) +{ + return set_bounds(fLP, IndexOf(variable), min, max); } @@ -396,7 +466,7 @@ LinearSpec::UpdateObjectiveFunction() } if (!set_obj_fnex(fLP, size, &coeffs[0], &varIndexes[0])) - printf("Error in set_obj_fnex."); + printf("Error in set_obj_fnex.\n"); RemovePresolved(); } @@ -433,8 +503,8 @@ LinearSpec::Presolve() if (fLpPresolved == NULL) { fLpPresolved = copy_lp(fLP); - set_presolve(fLpPresolved, PRESOLVE_ROWS | PRESOLVE_COLS | PRESOLVE_LINDEP, - get_presolveloops(fLpPresolved)); + set_presolve(fLpPresolved, PRESOLVE_ROWS | PRESOLVE_COLS + | PRESOLVE_LINDEP, get_presolveloops(fLpPresolved)); } fResult = (ResultType)solve(fLpPresolved); @@ -478,7 +548,7 @@ LinearSpec::Solve() int32 size = fVariables.CountItems(); double x[size]; if (!get_variables(fLP, &x[0])) - printf("Error in get_variables."); + printf("Error in get_variables.\n"); int32 i = 0; while (i < size) { @@ -508,18 +578,6 @@ LinearSpec::Save(const char* fileName) } -/** - * Gets the number of columns. - * - * @return the number of columns - */ -int32 -LinearSpec::CountColumns() const -{ - return fCountColumns; -} - - /** * Gets the current optimization. * The default is minimization. @@ -550,27 +608,15 @@ LinearSpec::SetOptimization(OptimizationType value) } -/** - * Gets the the variables. - * - * @return the variables - */ -VariableList* -LinearSpec::Variables() const -{ - return const_cast(&fVariables); -} - - /** * Gets the constraints. * * @return the constraints */ -ConstraintList* +const ConstraintList& LinearSpec::Constraints() const { - return const_cast(&fConstraints); + return fConstraints; } diff --git a/src/libs/linprog/Variable.cpp b/src/libs/linprog/Variable.cpp index f7ae3b34c1..5e083342e6 100644 --- a/src/libs/linprog/Variable.cpp +++ b/src/libs/linprog/Variable.cpp @@ -1,18 +1,19 @@ /* * Copyright 2007-2008, Christof Lutteroth, lutteroth@cs.auckland.ac.nz * Copyright 2007-2008, James Kim, jkim202@ec.auckland.ac.nz + * Copyright 2010, Clemens Zeidler * Distributed under the terms of the MIT License. */ -#include "Variable.h" -#include "Constraint.h" -#include "LinearSpec.h" -#include "OperatorType.h" -#include "lp_lib.h" +#include "Variable.h" #include // for DBL_MAX +#include + +#include "Constraint.h" +#include "LinearSpec.h" // Toggle debug output //#define DEBUG_VARIABLE @@ -32,12 +33,7 @@ int32 Variable::Index() const { - int32 i = fLS->Variables()->IndexOf(this); - if (i == -1) { - printf("Variable not part of fLS->Variables()."); - return -1; - } - return i + 1; + return fLS->IndexOf(this); } @@ -139,7 +135,7 @@ Variable::SetRange(double min, double max) fMin = min; fMax = max; - set_bounds(fLS->fLP, this->Index(), fMin, fMax); + fLS->SetRange(this, fMin, fMax); } @@ -279,20 +275,20 @@ Variable::IsValid() void Variable::Invalidate() { - STRACE(("Variable::Invalidate() on %s\n", ToString())); + STRACE(("Variable::Invalidate() on %s\n", BString(*this).String())); if (!fIsValid) return; fIsValid = false; - del_column(fLS->fLP, Index()); - fLS->Variables()->RemoveItem(this); + + fLS->RemoveVariable(this, false); // invalidate all constraints that use this variable ConstraintList markedForInvalidation; - ConstraintList* constraints = fLS->Constraints(); - for (int i = 0; i < constraints->CountItems(); i++) { - Constraint* constraint = constraints->ItemAt(i); + const ConstraintList& constraints = fLS->Constraints(); + for (int i = 0; i < constraints.CountItems(); i++) { + Constraint* constraint = constraints.ItemAt(i); if (!constraint->IsValid()) continue; @@ -321,18 +317,9 @@ Variable::Variable(LinearSpec* ls) fMin(0), fMax(DBL_MAX), fLabel(NULL), - fIsValid(true) + fIsValid(false) { - fLS->Variables()->AddItem(this); - if (fLS->Variables()->CountItems() > fLS->CountColumns()) { - double d = 0; - int i = 0; - if (!add_columnex(fLS->fLP, 0, &d, &i)) - printf("Error in add_columnex."); - } - - SetRange(-20000, 20000); } @@ -342,6 +329,6 @@ Variable::Variable(LinearSpec* ls) */ Variable::~Variable() { - Invalidate(); + fLS->RemoveVariable(this, false); }