Commit 2f238da2 authored by David Bommes's avatar David Bommes
Browse files

added Marcel's efficent rhs-update solve

(with minor modifications)

git-svn-id: http://www.openflipper.org/svnrepo/CoMISo/trunk@166 1355f012-dd97-4b2f-ae87-10fa9f823a57
parent c50aadf2
...@@ -58,7 +58,8 @@ namespace COMISO { ...@@ -58,7 +58,8 @@ namespace COMISO {
class COMISODLLEXPORT ConstrainedSolver class COMISODLLEXPORT ConstrainedSolver
{ {
public: public:
typedef gmm::csc_matrix<double> CSCMatrix; typedef gmm::csc_matrix<double> CSCMatrix;
typedef gmm::row_matrix< gmm::wsvector< double > > RowMatrix;
/// default Constructor /// default Constructor
...@@ -111,6 +112,23 @@ public: ...@@ -111,6 +112,23 @@ public:
bool _show_miso_settings = true, bool _show_miso_settings = true,
bool _show_timings = true ); bool _show_timings = true );
// efficent re-solve with modified _rhs by keeping previous _constraints and _A fixed
template<class RMatrixT, class VectorT >
void resolve(
VectorT& _x,
VectorT& _rhs,
double _reg_factor = 0.0,
bool _show_miso_settings = true,
bool _show_timings = true );
// const version of above function
template<class RMatrixT, class VectorT >
void resolve_const(
VectorT& _x,
const VectorT& _rhs,
double _reg_factor = 0.0,
bool _show_miso_settings = true,
bool _show_timings = true );
/// Non-Quadratic matrix constrained solver /// Non-Quadratic matrix constrained solver
/** /**
...@@ -138,16 +156,35 @@ public: ...@@ -138,16 +156,35 @@ public:
// const version of above function // const version of above function
template<class RMatrixT, class VectorT, class VectorIT > template<class RMatrixT, class VectorT, class VectorIT >
void solve_const( void solve_const(
RMatrixT& _constraints, const RMatrixT& _constraints,
RMatrixT& _B, const RMatrixT& _B,
VectorT& _x,
const VectorIT& _idx_to_round,
double _reg_factor = 0.0,
bool _show_miso_settings = true,
bool _show_timings = true );
// efficent re-solve with modified _rhs by keeping previous _constraints and _A fixed
template<class RMatrixT, class VectorT >
void resolve(
const RMatrixT& _B,
VectorT& _x,
double _reg_factor = 0.0,
bool _show_miso_settings = true,
bool _show_timings = true );
// const version of above function
template<class RMatrixT, class VectorT >
void resolve_const(
const RMatrixT& _B,
VectorT& _x, VectorT& _x,
VectorIT& _idx_to_round,
double _reg_factor = 0.0, double _reg_factor = 0.0,
bool _show_miso_settings = true, bool _show_miso_settings = true,
bool _show_timings = true ); bool _show_timings = true );
/*@}*/ /*@}*/
/** @name Eliminate constraints /** @name Eliminate constraints
* Functions to eliminate (or integrate) linear constraints from an equation system. These functions are used internally by the \a solve functions. * Functions to eliminate (or integrate) linear constraints from an equation system. These functions are used internally by the \a solve functions.
*/ */
...@@ -342,6 +379,77 @@ private: ...@@ -342,6 +379,77 @@ private:
double epsilon_; double epsilon_;
int noisy_; int noisy_;
bool do_gcd_; bool do_gcd_;
// --------------- Update by Marcel to enable efficient re-solve with changed rhs ----------------------
// Store for symbolic elimination information for rhs
class rhsUpdateTable {
public:
void append(int _i, double _f, int _j = -1) { table_.push_back(rhsUpdateTableEntry(_i, _j, _f)); }
void add_elim_id(int _i) { elim_var_ids_.push_back(_i); }
void clear() { table_.clear(); elim_var_ids_.clear(); }
// apply stored transformations to _rhs
void apply(std::vector<double>& _rhs)
{
std::vector<rhsUpdateTableEntry>::const_iterator t_it, t_end;
t_end = table_.end();
int cur_j = -1;
double cur_rhs = 0.0;
for(t_it = table_.begin(); t_it != t_end; ++t_it)
{
if(t_it->j >= 0) {
if(t_it->j != cur_j) { cur_j = t_it->j; cur_rhs = _rhs[cur_j]; }
_rhs[t_it->i] += t_it->f * cur_rhs;
}
else
_rhs[t_it->i] += t_it->f;
}
}
// remove eliminated elements from _rhs
void eliminate(std::vector<double>& _rhs)
{
std::vector<int> evar( elim_var_ids_ );
std::sort( evar.begin(), evar.end() );
evar.push_back( std::numeric_limits<int>::max() );
int cur_evar_idx=0;
unsigned int nc = _rhs.size();
for( unsigned int i=0; i<nc; ++i )
{
unsigned int next_i = evar[cur_evar_idx];
if ( i != next_i ) _rhs[i-cur_evar_idx] = _rhs[i];
else ++cur_evar_idx;
}
_rhs.resize( nc - cur_evar_idx );
}
// store transformed constraint matrix and index map to allow for later re-substitution
template<class RMatrixT>
void store(const RMatrixT& _constraints, const std::vector<int>& _c_elim, const std::vector<int>& _new_idx)
{
constraints_p_.resize( gmm::mat_nrows(_constraints), gmm::mat_ncols(_constraints));
gmm::copy(_constraints, constraints_p_);
c_elim_ = _c_elim;
new_idx_ = _new_idx;
}
private:
class rhsUpdateTableEntry {
public:
rhsUpdateTableEntry(int _i, int _j, double _f) : i(_i), j(_j), f(_f) {}
int i;
int j;
double f;
};
std::vector<rhsUpdateTableEntry> table_;
std::vector<int> elim_var_ids_;
public:
std::vector<int> c_elim_;
std::vector<int> new_idx_;
RowMatrix constraints_p_;
} rhs_update_table_;
}; };
......
...@@ -87,10 +87,10 @@ solve_const( const RMatrixT& _constraints, ...@@ -87,10 +87,10 @@ solve_const( const RMatrixT& _constraints,
template<class RMatrixT, class VectorT, class VectorIT > template<class RMatrixT, class VectorT, class VectorIT >
void void
ConstrainedSolver:: ConstrainedSolver::
solve_const( RMatrixT& _constraints, solve_const( const RMatrixT& _constraints,
RMatrixT& _B, const RMatrixT& _B,
VectorT& _x, VectorT& _x,
VectorIT& _idx_to_round, const VectorIT& _idx_to_round,
double _reg_factor, double _reg_factor,
bool _show_miso_settings, bool _show_miso_settings,
bool _show_timings ) bool _show_timings )
...@@ -253,6 +253,7 @@ solve( ...@@ -253,6 +253,7 @@ solve(
miso_.solve( Acsc, _x, _rhs, _idx_to_round); miso_.solve( Acsc, _x, _rhs, _idx_to_round);
double time_miso = sw.stop()/1000.0; sw.start(); double time_miso = sw.stop()/1000.0; sw.start();
rhs_update_table_.store(_constraints, c_elim, new_idx);
// restore eliminated vars to fulfill the given conditions // restore eliminated vars to fulfill the given conditions
restore_eliminated_vars( _constraints, _x, c_elim, new_idx); restore_eliminated_vars( _constraints, _x, c_elim, new_idx);
...@@ -270,6 +271,145 @@ solve( ...@@ -270,6 +271,145 @@ solve(
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template<class RMatrixT, class VectorT >
void
ConstrainedSolver::
resolve_const(
VectorT& _x,
const VectorT& _rhs,
double _reg_factor,
bool _show_miso_settings,
bool _show_timings )
{
VectorT rhs(_rhs);
// call non-const function
resolve<RMatrixT>(_x,
rhs,
_reg_factor,
_show_miso_settings,
_show_timings);
}
//-----------------------------------------------------------------------------
template<class RMatrixT, class VectorT >
void
ConstrainedSolver::
resolve_const( const RMatrixT& _B,
VectorT& _x,
double _reg_factor,
bool _show_miso_settings,
bool _show_timings )
{
resolve(_B,
_x,
_reg_factor,
_show_miso_settings,
_show_timings);
}
//-----------------------------------------------------------------------------
template<class RMatrixT, class VectorT >
void
ConstrainedSolver::
resolve(
const RMatrixT& _B,
VectorT& _x,
double _reg_factor,
bool _show_miso_settings,
bool _show_timings )
{
// extract rhs from quadratic system
VectorT rhs;
// gmm::col_matrix< gmm::rsvector< double > > A;
// COMISO_GMM::factored_to_quadratic(_B, A, rhs);
//TODO only compute rhs, not complete A for efficiency
unsigned int m = gmm::mat_nrows(_B);
unsigned int n = gmm::mat_ncols(_B);
typedef typename gmm::linalg_traits<RMatrixT>::const_sub_row_type CRowT;
typedef typename gmm::linalg_traits<RMatrixT>::sub_row_type RowT;
typedef typename gmm::linalg_traits<CRowT>::const_iterator RIter;
typedef typename gmm::linalg_traits<CRowT>::value_type VecValT;
gmm::resize(rhs, n-1);
gmm::clear(rhs);
for(unsigned int i = 0; i < m; ++i)
{
// get current condition row
CRowT row = gmm::mat_const_row( _B, i);
RIter row_it = gmm::vect_const_begin( row);
RIter row_end = gmm::vect_const_end( row);
if(row_end == row_it) continue;
--row_end;
if(row_end.index() != n-1) continue;
VecValT n_i = *row_end;
while(row_end != row_it)
{
--row_end;
rhs[row_end.index()] -= (*row_end) * n_i;
}
}
// solve
resolve<RMatrixT>(_x, rhs, _reg_factor,
_show_miso_settings,
_show_timings);
}
//-----------------------------------------------------------------------------
template<class RMatrixT, class VectorT >
void
ConstrainedSolver::
resolve(
VectorT& _x,
VectorT& _rhs,
double _reg_factor,
bool _show_miso_settings,
bool _show_timings )
{
// show options dialog
if( _show_miso_settings)
miso_.show_options_dialog();
// StopWatch for Timings
COMISO::StopWatch sw;
sw.start();
// apply stored updates and eliminations to exchanged rhs
rhs_update_table_.apply(_rhs);
rhs_update_table_.eliminate(_rhs);
miso_.resolve(_x, _rhs);
double time_miso = sw.stop()/1000.0; sw.start();
// restore eliminated vars to fulfill the given conditions
restore_eliminated_vars( rhs_update_table_.constraints_p_, _x, rhs_update_table_.c_elim_, rhs_update_table_.new_idx_);
double time_resubstitute = sw.stop()/1000.0; sw.start();
double time_total = time_miso + time_resubstitute;
if( _show_timings) std::cerr << "Timings: \n\t" <<
"\tMi-Solver " << time_miso << " s\n\t" <<
"\tResubstitution " << time_resubstitute << " s\n\t" <<
"\tTotal " << time_total << std::endl << std::endl;
}
//-----------------------------------------------------------------------------
template<class RMatrixT, class VectorIT > template<class RMatrixT, class VectorIT >
void void
ConstrainedSolver:: ConstrainedSolver::
...@@ -833,6 +973,8 @@ eliminate_constraints( ...@@ -833,6 +973,8 @@ eliminate_constraints(
std::vector<int> elim_varids; std::vector<int> elim_varids;
elim_varids.reserve( _v_elim.size()); elim_varids.reserve( _v_elim.size());
rhs_update_table_.clear();
for( unsigned int i=0; i < _v_elim.size(); ++i) for( unsigned int i=0; i < _v_elim.size(); ++i)
{ {
int cur_j = _v_elim[i]; int cur_j = _v_elim[i];
...@@ -842,7 +984,8 @@ eliminate_constraints( ...@@ -842,7 +984,8 @@ eliminate_constraints(
double cur_val = _constraints(i, cur_j); double cur_val = _constraints(i, cur_j);
// store index // store index
elim_varids.push_back(_v_elim[i]); elim_varids.push_back(cur_j);
rhs_update_table_.add_elim_id(cur_j);
// copy col // copy col
SVector2T col ( _A.col( cur_j)); SVector2T col ( _A.col( cur_j));
...@@ -876,7 +1019,9 @@ eliminate_constraints( ...@@ -876,7 +1019,9 @@ eliminate_constraints(
for ( ; col_it != col_end; ++col_it ) for ( ; col_it != col_end; ++col_it )
_A( con_it.index(), col_it.index() ) -= ( *col_it )*(( *con_it )/cur_val); _A( con_it.index(), col_it.index() ) -= ( *col_it )*(( *con_it )/cur_val);
_rhs[con_it.index()] -= cur_rhs * (( *con_it )/cur_val); //_rhs[con_it.index()] -= cur_rhs * (( *con_it )/cur_val);
rhs_update_table_.append(con_it.index(), -1.0 * (( *con_it )/cur_val), cur_j);
//std::cerr << con_it.index() << " += " << -1.0*(( *con_it )/cur_val) << " * " << cur_rhs << " (["<<cur_j<<"] = "<<_rhs[cur_j]<<") " << std::endl;
} }
// TODO FIXME must use copy col (referens sometimes yields infinite loop below no col_it++?!?) // TODO FIXME must use copy col (referens sometimes yields infinite loop below no col_it++?!?)
...@@ -894,13 +1039,18 @@ eliminate_constraints( ...@@ -894,13 +1039,18 @@ eliminate_constraints(
for ( ; con_it != con_end; ++con_it ) for ( ; con_it != con_end; ++con_it )
_A( col_it.index(), con_it.index() ) -= ( *col_it )*(( *con_it )/cur_val); _A( col_it.index(), con_it.index() ) -= ( *col_it )*(( *con_it )/cur_val);
_rhs[col_it.index()] += constraint_rhs*( *col_it )/cur_val; //_rhs[col_it.index()] += constraint_rhs*( *col_it )/cur_val;
rhs_update_table_.append(col_it.index(), constraint_rhs*( *col_it )/cur_val);
//std::cerr << col_it.index() << " += " << constraint_rhs*( *col_it )/cur_val << std::endl;
} }
// reset last constraint entry to real value // reset last constraint entry to real value
constraint[ constraint.size()-1] = constraint_rhs; constraint[ constraint.size()-1] = constraint_rhs;
} }
} }
rhs_update_table_.apply(_rhs);
if( noisy_ > 2) if( noisy_ > 2)
std::cerr << __FUNCTION__ << " Constraints integrated " << sw.stop()/1000.0 << std::endl; std::cerr << __FUNCTION__ << " Constraints integrated " << sw.stop()/1000.0 << std::endl;
...@@ -1112,9 +1262,12 @@ restore_eliminated_vars( RMatrixT& _constraints, ...@@ -1112,9 +1262,12 @@ restore_eliminated_vars( RMatrixT& _constraints,
{ {
// get variable value and set to zero // get variable value and set to zero
double cur_val = _constraints(i, cur_var); double cur_val = _constraints(i, cur_var);
_constraints(i, cur_var) = 0.0;
_x[cur_var] = -gmm::vect_sp(_x, _constraints.row(i))/cur_val; //_constraints(i, cur_var) = 0.0;
//_x[cur_var] = -gmm::vect_sp(_x, _constraints.row(i))/cur_val;
//reformulated to keep _constraints intact for further use:
_x[cur_var] -= gmm::vect_sp(_x, _constraints.row(i))/cur_val;
} }
} }
......
...@@ -97,6 +97,18 @@ MISolver::solve_no_rounding( ...@@ -97,6 +97,18 @@ MISolver::solve_no_rounding(
void void
MISolver::resolve(
Vecd& _x,
Vecd& _rhs )
{
chol_.solve(_x, _rhs);
}
//-----------------------------------------------------------------------------
void
MISolver::solve_direct_rounding( MISolver::solve_direct_rounding(
CSCMatrix& _A, CSCMatrix& _A,
Vecd& _x, Vecd& _x,
......
...@@ -108,6 +108,10 @@ public: ...@@ -108,6 +108,10 @@ public:
Veci& _to_round, Veci& _to_round,
bool _fixed_order = false ); bool _fixed_order = false );
void resolve(
Vecd& _x,
Vecd& _rhs );
/// Compute greedy approximation to a mixed integer problem. /// Compute greedy approximation to a mixed integer problem.
/** @param _B mx(n+1) matrix with (still non-squared) equations of the energy, /** @param _B mx(n+1) matrix with (still non-squared) equations of the energy,
* including the right hand side (Will be \b destroyed!) * including the right hand side (Will be \b destroyed!)
...@@ -123,6 +127,7 @@ public: ...@@ -123,6 +127,7 @@ public:
Veci& _to_round, Veci& _to_round,
bool _fixed_order = false ); bool _fixed_order = false );
/// show Qt-Options-Dialog for setting algorithm parameters /// show Qt-Options-Dialog for setting algorithm parameters
/** Requires a Qt Application running and COMISO_GUI to be defined */ /** Requires a Qt Application running and COMISO_GUI to be defined */
void show_options_dialog(); void show_options_dialog();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment