summaryrefslogtreecommitdiff
path: root/libs/cassowary/ClTableau.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cassowary/ClTableau.cc')
-rw-r--r--libs/cassowary/ClTableau.cc297
1 files changed, 297 insertions, 0 deletions
diff --git a/libs/cassowary/ClTableau.cc b/libs/cassowary/ClTableau.cc
new file mode 100644
index 0000000000..85ac841725
--- /dev/null
+++ b/libs/cassowary/ClTableau.cc
@@ -0,0 +1,297 @@
+// $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
+//
+// ClTableau.cc
+
+using namespace std;
+
+#include <cassowary/ClTableau.h>
+#include <cassowary/debug.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define CONFIG_H_INCLUDED
+#endif
+
+
+// delete the linear expressions
+// let ClSimplexSolver worry about deleting the variables
+ClTableau::~ClTableau()
+{
+ ClTableauRowsMap::iterator it = _rows.begin();
+ for (; it != _rows.end(); ++it)
+ {
+ // free the ClLinearExpression that we new-ed
+#ifdef CL_TRACE
+ cerr << "Deleting row delete@ " << ((*it).second) << endl;
+#endif
+ delete (*it).second;
+ }
+}
+
+#ifndef CL_NO_IO
+// Some extra debugging info
+ostream &
+ClTableau::PrintInternalInfo(ostream &xo) const
+{
+ xo << "ncns:" << _rows.size() -1
+ << "; cols:" << _columns.size()
+ << "; infrows:" << _infeasibleRows.size()
+ << "; ebvars:" << _externalRows.size()
+ << "; epvars:" << _externalParametricVars.size();
+ return xo;
+}
+
+
+ostream &
+ClTableau::printExternalVariablesTo(ostream &xo) const
+{
+ xo << "Parametric: ";
+ ClVarSet::iterator itParVars = _externalParametricVars.begin();
+ for ( ; itParVars != _externalParametricVars.end(); ++itParVars ) {
+ ClVariable v = *itParVars;
+ xo << v << " ";
+ }
+ xo << "\nBasic: ";
+ ClVarSet::iterator itRowVars = _externalRows.begin();
+ for ( ; itRowVars != _externalRows.end() ; ++itRowVars ) {
+ ClVariable v = *itRowVars;
+ xo << v << " ";
+ }
+ return xo << endl;
+}
+
+#endif
+
+
+// Add v, update column cross indices
+// v becomes a basic variable
+// expr is now owned by ClTableau class,
+// and ClTableauis responsible for deleting it
+// (also, expr better be allocated on the heap!)
+void
+ClTableau::addRow(ClVariable var, const ClLinearExpression &expr)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << var << ", " << expr << ")" << endl;
+#endif
+ _rows[var] = const_cast<ClLinearExpression *>(&expr);
+ ClVarToNumberMap::const_iterator it = expr.Terms().begin();
+ // for each variable in expr, Add var to the set of rows which have that variable
+ // in their Expression
+ for (; it != expr.Terms().end(); ++it)
+ {
+ ClVariable v = (*it).first;
+ _columns[v].insert(var);
+ if (v.IsExternal() && !FIsBasicVar(v))
+ {
+ _externalParametricVars.insert(v);
+ }
+ }
+ if (var.IsExternal())
+ {
+ _externalRows.insert(var);
+ }
+#ifdef CL_TRACE
+ cerr << *this << endl;
+#endif
+}
+
+// Remove var from the tableau -- remove the column cross indices for var
+// and remove var from every Expression in rows in which v occurs
+// Remove the parametric variable var, updating the appropriate column and row entries.
+// (Renamed from Smalltalk implementation's `removeParametricVar')
+ClVariable
+ClTableau::RemoveColumn(ClVariable var)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << var << ")" << endl;
+#endif
+ ClTableauColumnsMap::iterator it_var = _columns.find(var);
+ if (it_var == _columns.end())
+ return var; // nothing to do
+
+ ClVarSet &varset = (*it_var).second;
+ // remove the rows with the variables in varset
+ ClVarSet::iterator it = varset.begin();
+ for (; it != varset.end(); ++it)
+ {
+ ClVariable v = (*it);
+ ClVarToNumberMap &Terms = _rows[v]->Terms();
+ Terms.erase(Terms.find(var));
+ }
+ if (var.IsExternal())
+ {
+ _externalRows.erase(var);
+ _externalParametricVars.erase(var);
+ }
+ _columns.erase(it_var);
+ return var;
+}
+
+// Remove the basic variable v from the tableau row v=expr
+// Then update column cross indices
+ClLinearExpression *
+ClTableau::RemoveRow(ClVariable var)
+{
+#ifdef CL_TRACE
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << var << ")" << endl;
+#endif
+ ClTableauRowsMap::iterator it = _rows.find(var);
+ assert(it != _rows.end());
+ ClLinearExpression *pexpr = (*it).second;
+ ClVarToNumberMap &Terms = pexpr->Terms();
+ ClVarToNumberMap::iterator it_term = Terms.begin();
+ for (; it_term != Terms.end(); ++it_term)
+ {
+ ClVariable v = (*it_term).first;
+ _columns[v].erase(var);
+ if (_columns[v].size() == 0)
+ {
+ _columns.erase(v);
+ _externalParametricVars.erase(v);
+ }
+ }
+
+ _infeasibleRows.erase(var);
+
+ if (var.IsExternal())
+ {
+ _externalRows.erase(var);
+ _externalParametricVars.erase(var);
+ }
+
+ _rows.erase(it);
+#ifdef CL_TRACE
+ cerr << "- returning " << *pexpr << endl;
+#endif
+ return pexpr;
+}
+
+// Replace all occurrences of oldVar with expr, and update column cross indices
+// oldVar should now be a basic variable
+// Uses the Columns data structure and calls SubstituteOut on each
+// row that has oldVar in it
+// oldVar is leaving the basis, and becoming parametric
+void
+ClTableau::SubstituteOut(ClVariable oldVar, const ClLinearExpression &expr)
+{
+#ifdef CL_TRACE
+ cerr << "* ClTableau::";
+ Tracer TRACER(__FUNCTION__);
+ cerr << "(" << oldVar << ", " << expr << ")" << endl;
+ cerr << (*this) << endl;
+#endif
+
+ ClTableauColumnsMap::iterator it_oldVar = _columns.find(oldVar);
+ if (it_oldVar == _columns.end())
+ return;
+
+ ClVarSet &varset = (*it_oldVar).second;
+ ClVarSet::iterator it = varset.begin();
+ for (; it != varset.end(); ++it)
+ {
+ ClVariable v = (*it);
+ ClLinearExpression *prow = _rows[v];
+ prow->SubstituteOut(oldVar,expr,v,*this);
+ if (v.IsRestricted() && prow->Constant() < 0.0)
+ {
+ _infeasibleRows.insert(v);
+ }
+ }
+ _columns.erase(it_oldVar);
+ if (oldVar.IsExternal())
+ {
+ if (_columns[oldVar].size() > 0)
+ {
+ _externalRows.insert(oldVar);
+ }
+ _externalParametricVars.erase(oldVar);
+ }
+}
+
+
+#ifndef CL_NO_IO
+
+ostream &
+PrintTo(ostream &xo, const ClVarSet & varset)
+{
+ ClVarSet::const_iterator it = varset.begin();
+ xo << "{ ";
+ if (it != varset.end())
+ {
+ xo << *it;
+ ++it;
+ }
+ for (; it != varset.end(); ++it)
+ {
+ xo << ", " << *it;
+ }
+ xo << " }";
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClVarSet & varset)
+{ return PrintTo(xo,varset); }
+
+ostream &
+PrintTo(ostream &xo, const ClTableauColumnsMap & varmap)
+{
+ ClTableauColumnsMap::const_iterator it = varmap.begin();
+ for (; it != varmap.end(); ++it)
+ {
+ xo << (*it).first << " -> " << (*it).second << endl;
+ }
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClTableauColumnsMap & varmap)
+{ return PrintTo(xo,varmap); }
+
+ostream &
+PrintTo(ostream &xo, const ClTableauRowsMap & rows)
+{
+ ClTableauRowsMap::const_iterator it = rows.begin();
+ for (; it != rows.end(); ++it)
+ {
+ ClVariable v = it->first;
+ const ClLinearExpression *pe = it->second;
+ xo << v << " <-=-> ";
+ if (pe) xo << *pe; else xo << "NilExpr";
+ xo << endl;
+ }
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClTableauRowsMap & rows)
+{ return PrintTo(xo,rows); }
+
+ostream &
+ClTableau::PrintOn(ostream &xo) const
+{
+ xo << "Tableau:\n"
+ << _rows << endl;
+ xo << "Columns:\n"
+ << _columns << endl;
+ xo << "Infeasible rows: "
+ << _infeasibleRows << endl;
+ xo << "External basic variables: "
+ << _externalRows << endl;
+ xo << "External parametric variables: "
+ << _externalParametricVars << endl;
+ return xo;
+}
+
+ostream &operator<<(ostream &xo, const ClTableau &clt)
+{ return clt.PrintOn(xo); }
+
+#endif