13
0
livetrax/libs/cassowary/ClTableau.cc
Taybin Rutkin d09f6b3016 Initial revision
git-svn-id: svn://localhost/trunk/ardour2@4 d708f5d6-7413-0410-9779-e7cbd77b26cf
2005-05-13 20:47:18 +00:00

298 lines
7.3 KiB
C++

// $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