summaryrefslogtreecommitdiff
path: root/libs/cassowary/cassowary/ClSimplexSolver.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cassowary/cassowary/ClSimplexSolver.h')
-rw-r--r--libs/cassowary/cassowary/ClSimplexSolver.h588
1 files changed, 0 insertions, 588 deletions
diff --git a/libs/cassowary/cassowary/ClSimplexSolver.h b/libs/cassowary/cassowary/ClSimplexSolver.h
deleted file mode 100644
index c187992728..0000000000
--- a/libs/cassowary/cassowary/ClSimplexSolver.h
+++ /dev/null
@@ -1,588 +0,0 @@
-// $Id$
-//
-// Cassowary Incremental Constraint Solver
-// Original Smalltalk Implementation by Alan Borning
-// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
-// http://www.cs.washington.edu/homes/gjb
-// (C) 1998, 1999 Greg J. Badros and Alan Borning
-// See ../LICENSE for legal details regarding this software
-//
-// ClSimplexSolver.h
-
-#ifndef ClSimplexSolver_H
-#define ClSimplexSolver_H
-
-#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
-#include <cassowary/config-inline.h>
-#define CONFIG_INLINE_H_INCLUDED
-#endif
-
-#include <stack>
-#include <list>
-#include <iostream>
-#include "Cassowary.h"
-#include "ClSolver.h"
-#include "ClTableau.h"
-#include "ClLinearInequality.h"
-#include "ClStrength.h"
-#include "ClStayConstraint.h"
-#include "ClEditConstraint.h"
-#include "ClSlackVariable.h"
-#include "ClObjectiveVariable.h"
-#include "ClErrors.h"
-#include "ClTypedefs.h"
-
-using std::list;
-using std::stack;
-using std::ostream;
-
-class ClVariable;
-class ClPoint;
-class ExCLRequiredFailureWithExplanation;
-
-
-// ClSimplexSolver encapsulates the solving behaviour
-// of the cassowary algorithm
-class ClSimplexSolver : public ClSolver, public ClTableau {
- protected:
- class ClEditInfo;
- typedef list<ClEditInfo *> ClEditInfoList;
-
- ClEditInfo *PEditInfoFromClv(ClVariable clv) {
- ClEditInfoList::iterator it = _editInfoList.begin();
- for (; it != _editInfoList.end(); ++it) {
- ClEditInfo *pei = (*it);
- if (pei->_clv == clv)
- return pei;
- }
- return 0;
- }
-
- public:
-
- // Constructor
- ClSimplexSolver() :
- ClSolver(),
- _objective(ClVariable(new ClObjectiveVariable("Z"))),
- _slackCounter(0),
- _artificialCounter(0),
-#ifdef CL_FIND_LEAK
- _cArtificialVarsDeleted(0),
-#endif
- _dummyCounter(0),
- _epsilon(1e-8),
- _fResetStayConstantsAutomatically(true),
- _fNeedsSolving(false),
- _fExplainFailure(false),
- _pfnResolveCallback(0),
- _pfnCnSatCallback(0)
- {
- _rows[_objective] = new ClLinearExpression();
- // start out with no edit variables
- _stkCedcns.push(0);
-#ifdef CL_TRACE
- std::cerr << "objective row new@ " << _rows[_objective] << std::endl;
-#endif
- }
-
- virtual ~ClSimplexSolver();
-
- // Add constraints so that lower<=var<=upper. (nil means no bound.)
- ClSimplexSolver &AddLowerBound(ClVariable v, Number lower)
- {
- ClLinearInequality *pcn = new ClLinearInequality(ClLinearExpression(v - lower));
- return AddConstraint(pcn);
- }
- ClSimplexSolver &AddUpperBound(ClVariable v, Number upper)
- {
- ClLinearInequality *pcn = new ClLinearInequality(ClLinearExpression(upper - v));
- return AddConstraint(pcn);
- }
- ClSimplexSolver &AddBounds(ClVariable v, Number lower, Number upper)
- { AddLowerBound(v,lower); AddUpperBound(v,upper); return *this; }
-
- // Add the constraint cn to the tableau
- ClSimplexSolver &AddConstraint(ClConstraint *const pcn);
-
-#ifndef CL_NO_DEPRECATED
- // Deprecated! --02/19/99 gjb
- ClSimplexSolver &AddConstraint(ClConstraint &cn)
- { return AddConstraint(&cn); }
-#endif
-
- // Add an edit constraint for "v" with given strength
- ClSimplexSolver &AddEditVar(const ClVariable v, const ClStrength &strength = ClsStrong(),
- double weight = 1.0 )
- {
- ClEditConstraint *pedit = new ClEditConstraint(v, strength, weight);
- return AddConstraint(pedit);
- }
-
- ClSimplexSolver &RemoveEditVar(ClVariable v)
- {
- ClEditInfo *pcei = PEditInfoFromClv(v);
- if (!pcei) {
- throw ExCLEditMisuse("Removing edit variable that was not found");
- }
- ClConstraint *pcnEdit = pcei->_pconstraint;
- RemoveConstraint(pcnEdit);
- delete pcnEdit;
- return *this;
- }
-
- // BeginEdit() should be called before sending
- // Resolve() messages, after adding the appropriate edit variables
- ClSimplexSolver &BeginEdit()
- {
- if (_editInfoList.size() == 0) {
- throw ExCLEditMisuse("BeginEdit called, but no edit variable");
- }
- // may later want to do more in here
- _infeasibleRows.clear();
- ResetStayConstants();
- _stkCedcns.push(_editInfoList.size());
- return *this;
- }
-
- // EndEdit should be called after editing has finished
- // for now, it just removes edit variables added from before the last BeginEdit
- ClSimplexSolver &EndEdit()
- {
- if (_editInfoList.size() == 0)
- throw ExCLEditMisuse("EndEdit called but no edit variables");
- Resolve();
- _stkCedcns.pop();
- RemoveEditVarsTo(_stkCedcns.top());
- // may later want to do more in here
- return *this;
- }
-
- // RemoveAllEditVars() just eliminates all the edit constraints
- // that were added
- ClSimplexSolver &RemoveAllEditVars() { RemoveEditVarsTo(0); return *this; }
-
- // remove the last added edit vars to leave only n edit vars left
- ClSimplexSolver &RemoveEditVarsTo(unsigned int n);
-
- int numEditVars() const
- { return _editInfoList.size(); }
-
- // Add weak stays to the x and y parts of each point. These have
- // increasing weights so that the solver will try to satisfy the x
- // and y stays on the same point, rather than the x stay on one and
- // the y stay on another.
- ClSimplexSolver &AddPointStays(const vector<const ClPoint *> &listOfPoints,
- const ClStrength &strength = ClsWeak());
-
- ClSimplexSolver &AddPointStay(const ClVariable vx, const ClVariable vy,
- const ClStrength &strength = ClsWeak(),
- double weight = 1.0)
- { AddStay(vx,strength,weight); AddStay(vy,strength,weight); return *this; }
-
- ClSimplexSolver &AddPointStay(const ClPoint &clp,
- const ClStrength &strength = ClsWeak(),
- double weight = 1.0);
-
-
- // Add a stay of the given strength (default to weak) of v to the tableau
- ClSimplexSolver &AddStay(const ClVariable v,
- const ClStrength &strength = ClsWeak(), double weight = 1.0 )
- {
- ClStayConstraint *pcn = new ClStayConstraint(v,strength,weight);
- return AddConstraint(pcn);
- }
-
- // Remove the constraint cn from the tableau
- // Also remove any error variable associated with cn
- ClSimplexSolver &RemoveConstraint(ClConstraint *const pcn)
- { RemoveConstraintInternal(pcn); pcn->removedFrom(*this); return *this; }
-
-#ifndef CL_NO_DEPRECATED
- // Deprecated! --02/19/99 gjb
- ClSimplexSolver &RemoveConstraint(ClConstraint &cn)
- { return RemoveConstraint(&cn); }
-#endif
-
-
- // Re-initialize this solver from the original constraints, thus
- // getting rid of any accumulated numerical problems. (Actually, we
- // haven't definitely observed any such problems yet)
- void Reset();
-
- // Re-solve the current collection of constraints, given the new
- // values for the edit variables that have already been
- // suggested (see SuggestValue() method)
- // This is not guaranteed to work if you remove an edit constraint
- // from the middle of the edit constraints you added
- // (e.g., edit A, edit B, edit C, remove B -> this will fail!)
- // DEPRECATED
- void Resolve();
-
- // Re-solve the current collection of constraints for new values for
- // the constants of the edit variables.
- // This is implemented in terms of SuggestValue-s, and is
- // less efficient than that more natural interface
- void Resolve(const vector<Number> &newEditConstants);
-
- // Convenience function for Resolve-s of two variables
- void Resolve(Number x, Number y)
- {
- vector<Number> vals;
- vals.push_back(x);
- vals.push_back(y);
- Resolve(vals);
- }
-
- // Suggest a new value for an edit variable
- // the variable needs to be added as an edit variable
- // and BeginEdit() needs to be called before this is called.
- // The tableau will not be solved completely until
- // after Resolve() has been called
- ClSimplexSolver &SuggestValue(ClVariable v, Number x);
-
- // Set and check whether or not the solver will attempt to compile
- // an explanation of failure when a required constraint conflicts
- // with another required constraint
- ClSimplexSolver &SetExplaining(bool f)
- { _fExplainFailure = f; return *this; }
-
- bool FIsExplaining() const
- { return _fExplainFailure; }
-
- // If autosolving has been turned off, client code needs
- // to explicitly call solve() before accessing variables
- // values
- ClSimplexSolver &Solve()
- {
-#ifdef CL_SOLVER_CHECK_INTEGRITY
- AssertValid();
-#endif
- if (_fNeedsSolving)
- {
- Optimize(_objective);
- SetExternalVariables();
-#ifdef CL_TRACE_VERBOSE
- std::cerr << "Manual solve actually solving." << std::endl;
-#endif
- }
- return *this;
- }
-
- ClSimplexSolver &SetEditedValue(ClVariable v, double n)
- {
- if (!FContainsVariable(v))
- {
- ChangeClv(v,n);
- return *this;
- }
-
- if (!ClApprox(n, v.Value()))
- {
- AddEditVar(v);
- BeginEdit();
- SuggestValue(v,n);
- EndEdit();
- }
- return *this;
- }
-
- // Solver contains the variable if it's in either the columns
- // list or the rows list
- bool FContainsVariable(const ClVariable v)
- { return ColumnsHasKey(v) || RowExpression(v); }
-
- ClSimplexSolver &AddVar(const ClVariable v)
- { if (!FContainsVariable(v))
- {
- AddStay(v);
-#ifdef CL_TRACE
- std::cerr << "added initial stay on " << v << std::endl;
-#endif
- }
- return *this; }
-
- typedef void (*PfnResolveCallback)(ClSimplexSolver *psolver);
-
- void SetResolveCallback(PfnResolveCallback pfn)
- { _pfnResolveCallback = pfn; }
-
- typedef void (*PfnCnSatCallback)(ClSimplexSolver *psolver,
- ClConstraint *pcn, bool fSatisfied);
-
- void SetCnSatCallback(PfnCnSatCallback pfn)
- { _pfnCnSatCallback = pfn; }
-
-#ifndef CL_NO_IO
- friend ostream &operator<<(ostream &xo, const ClSimplexSolver &tableau);
-
- ostream &PrintOn(ostream &xo) const;
-
- ostream &PrintInternalInfo(ostream &xo) const;
-
- ostream &PrintOnVerbose(ostream &xo) const
- { PrintOn(xo); PrintInternalInfo(xo); xo << std::endl; return xo; }
-
-#endif
-
- const ClConstraintToVarMap &ConstraintMap() const
- { return _markerVars; }
-
- const ClVarToConstraintMap &MarkerMap() const
- { return _constraintsMarked; }
-
- bool FIsConstraintSatisfied(const ClConstraint *const pcn) const;
-
- // DEPRECATED
- bool FIsConstraintSatisfied(const ClConstraint &pcn) const
- { return FIsConstraintSatisfied(&pcn); }
-
- // re-set all the external variables to their current values
- // most importantly, this re-calls all the ChangeClv callbacks
- // (which might be used to copy the ClVariable's value to another
- // variable)
- void UpdateExternalVariables()
- { SetExternalVariables(); }
-
- // A. Beurive' Tue Jul 6 17:05:39 CEST 1999
- void ChangeStrengthAndWeight(ClConstraint *pcn, const ClStrength &strength, double weight);
- void ChangeStrength(ClConstraint *pcn, const ClStrength &strength);
- void ChangeWeight(ClConstraint *pcn, double weight);
- // void DisplayObjective();
-
- // Each of the non-required stays will be represented by an equation
- // of the form
- // v = c + eplus - eminus
- // where v is the variable with the stay, c is the previous value of
- // v, and eplus and eminus are slack variables that hold the error
- // in satisfying the stay constraint. We are about to change
- // something, and we want to fix the constants in the equations
- // representing the stays. If both eplus and eminus are nonbasic
- // they have value 0 in the current solution, meaning the previous
- // stay was exactly satisfied. In this case nothing needs to be
- // changed. Otherwise one of them is basic, and the other must
- // occur only in the Expression for that basic error variable.
- // Reset the Constant in this Expression to 0.
- void ResetStayConstants();
-
- ClSimplexSolver &SetAutoResetStayConstants(bool f)
- { _fResetStayConstantsAutomatically = f; if (f) ResetStayConstants(); return *this; }
-
- bool FIsAutoResetStayConstants() const
- { return _fResetStayConstantsAutomatically; }
-
- protected:
-
- // ClEditInfo is a privately-used class
- // that just wraps a constraint, its positive and negative
- // error variables, and its prior edit Constant.
- // It is used as values in _editInfoList, and replaces
- // the parallel vectors of error variables and previous edit
- // constants from the smalltalk version of the code.
- class ClEditInfo {
- friend class ClSimplexSolver;
- public:
-
- // These instances own none of the pointers;
- // the tableau row (the Expression) owns the peplus, peminus,
- // and AddEditVar/RemoveEditVar pair or the client code owns
- // the constraint object
- ClEditInfo(ClVariable clv,
- ClEditConstraint *pconstraint,
- ClVariable eplus, ClVariable eminus,
- Number prevEditConstant)
- :_clv(clv),
- _pconstraint(pconstraint),
- _clvEditPlus(eplus), _clvEditMinus(eminus),
- _prevEditConstant(prevEditConstant)
- { }
-
- ~ClEditInfo()
- { }
-
- ostream &PrintOn(ostream &xo) const
- { xo << _clv << " -> [" << _clvEditPlus << ", " << _clvEditMinus << "]("
- << _prevEditConstant << ")@" << " -- "
- << *_pconstraint;
- return xo; }
-
- friend ostream &operator<<(ostream &xo, const ClEditInfo &cei)
- { return cei.PrintOn(xo); }
-
- private:
- ClVariable _clv;
- ClConstraint *_pconstraint;
- ClVariable _clvEditPlus;
- ClVariable _clvEditMinus;
- Number _prevEditConstant;
- };
-
- // Add the constraint expr=0 to the inequality tableau using an
- // artificial variable. To do this, create an artificial variable
- // av and Add av=expr to the inequality tableau, then make av be 0.
- // (Raise an exception if we can't attain av=0.)
- // (Raise an exception if we can't attain av=0.) If the Add fails,
- // prepare an explanation in e that describes why it failed (note
- // that an empty explanation is considered to mean the explanation
- // encompasses all active constraints.
- bool AddWithArtificialVariable(ClLinearExpression &pexpr,
- ExCLRequiredFailureWithExplanation &e);
-
- // Using the given equation (av = cle) build an explanation which
- // implicates all constraints used to construct the equation. That
- // is, everything for which the variables in the equation are markers.
- // Thanks to Steve Wolfman for the implementation of the explanation feature
- void BuildExplanation(ExCLRequiredFailureWithExplanation & e,
- ClVariable av,
- const ClLinearExpression * pcle);
-
- // We are trying to Add the constraint expr=0 to the appropriate
- // tableau. Try to Add expr directly to the tableax without
- // creating an artificial variable. Return true if successful and
- // false if not.
- bool TryAddingDirectly(ClLinearExpression &pexpr);
-
- // We are trying to Add the constraint expr=0 to the tableaux. Try
- // to choose a subject (a variable to become basic) from among the
- // current variables in expr. If expr contains any unrestricted
- // variables, then we must choose an unrestricted variable as the
- // subject. Also, if the subject is new to the solver we won't have
- // to do any substitutions, so we prefer new variables to ones that
- // are currently noted as parametric. If expr contains only
- // restricted variables, if there is a restricted variable with a
- // negative coefficient that is new to the solver we can make that
- // the subject. Otherwise we can't find a subject, so return nil.
- // (In this last case we have to Add an artificial variable and use
- // that variable as the subject -- this is done outside this method
- // though.)
- //
- // Note: in checking for variables that are new to the solver, we
- // ignore whether a variable occurs in the objective function, since
- // new slack variables are added to the objective function by
- // 'NewExpression:', which is called before this method.
- ClVariable ChooseSubject(ClLinearExpression &pexpr);
-
- // Each of the non-required edits will be represented by an equation
- // of the form
- // v = c + eplus - eminus
- // where v is the variable with the edit, c is the previous edit
- // value, and eplus and eminus are slack variables that hold the
- // error in satisfying the edit constraint. We are about to change
- // something, and we want to fix the constants in the equations
- // representing the edit constraints. If one of eplus and eminus is
- // basic, the other must occur only in the Expression for that basic
- // error variable. (They can't both be basic.) Fix the Constant in
- // this Expression. Otherwise they are both nonbasic. Find all of
- // the expressions in which they occur, and fix the constants in
- // those. See the UIST paper for details.
- // (This comment was for resetEditConstants(), but that is now
- // gone since it was part of the screwey vector-based interface
- // to resolveing. --02/15/99 gjb)
- void DeltaEditConstant(Number delta, ClVariable pv1, ClVariable pv2);
-
- // We have set new values for the constants in the edit constraints.
- // Re-Optimize using the dual simplex algorithm.
- void DualOptimize();
-
- // Make a new linear Expression representing the constraint cn,
- // replacing any basic variables with their defining expressions.
- // Normalize if necessary so that the Constant is non-negative. If
- // the constraint is non-required give its error variables an
- // appropriate weight in the objective function.
- ClLinearExpression *NewExpression(const ClConstraint *pcn,
- /* output to */
- ClVariable &clvEplus,
- ClVariable &clvEminus,
- Number &prevEConstant);
-
- // Minimize the value of the objective. (The tableau should already
- // be feasible.)
- void Optimize(ClVariable zVar);
-
- // Do a Pivot. Move entryVar into the basis (i.e. make it a basic variable),
- // and move exitVar out of the basis (i.e., make it a parametric variable)
- void Pivot(ClVariable entryVar, ClVariable exitVar);
-
- // Set the external variables known to this solver to their appropriate values.
- // Set each external basic variable to its value, and set each
- // external parametric variable to 0. (It isn't clear that we will
- // ever have external parametric variables -- every external
- // variable should either have a stay on it, or have an equation
- // that defines it in terms of other external variables that do have
- // stays. For the moment I'll put this in though.) Variables that
- // are internal to the solver don't actually store values -- their
- // values are just implicit in the tableu -- so we don't need to set
- // them.
- void SetExternalVariables();
-
- // this gets called by RemoveConstraint and by AddConstraint when the
- // contraint we're trying to Add is inconsistent
- ClSimplexSolver &RemoveConstraintInternal(const ClConstraint *const pcn);
-
- void ChangeClv(ClVariable clv, Number n) {
- clv.ChangeValue(n);
- if (_pfnChangeClvCallback)
- _pfnChangeClvCallback(&clv,this);
- }
-
- /// instance variables
-
- // the arrays of positive and negative error vars for the stay constraints
- // (need both positive and negative since they have only non-negative values)
- ClVarVector _stayMinusErrorVars;
- ClVarVector _stayPlusErrorVars;
-
- // give error variables for a non required constraint,
- // maps to ClSlackVariable-s
- ClConstraintToVarSetMap _errorVars;
-
- // Return a lookup table giving the marker variable for each
- // constraint (used when deleting a constraint).
- ClConstraintToVarMap _markerVars;
-
- // Reverse of the above-- a lookup table giving the constraint
- // for each marker variable (used when building failure explanations)
- ClVarToConstraintMap _constraintsMarked;
-
- ClVariable _objective;
-
- // Map edit variables to their constraints, errors, and prior
- // values
- ClEditInfoList _editInfoList;
-
- int _slackCounter;
- int _artificialCounter;
-#ifdef CL_FIND_LEAK
- int _cArtificialVarsDeleted;
-#endif
- int _dummyCounter;
- const double _epsilon;
-
- bool _fResetStayConstantsAutomatically;
- bool _fNeedsSolving;
- bool _fExplainFailure;
-
- PfnResolveCallback _pfnResolveCallback;
- PfnCnSatCallback _pfnCnSatCallback;
-
- // C-style extension mechanism so I
- // don't have to wrap ScwmClSolver separately
- void *_pv;
-
- // a stack of the number of edit constraints
- // that existed at the prior BeginEdit.
- // an EndEdit needs to pop off the top value,
- // then remove constraints to get down
- // to the # of constraints as in _stkCedcns.top()
- stack<int> _stkCedcns;
-
-
-#ifndef CL_NO_IO
-
-friend ostream &PrintTo(ostream &xo, const ClSimplexSolver::ClEditInfoList &listPEditInfo);
-friend ostream &operator<<(ostream &xo, const ClSimplexSolver::ClEditInfoList &listPEditInfo);
-
-#endif
-
-};
-
-#endif // ClSimplexSolver_H