Commit 21cab7a8 authored by David Bommes's avatar David Bommes

added GUROBI support

git-svn-id: http://www.openflipper.org/svnrepo/CoMISo/trunk@93 1355f012-dd97-4b2f-ae87-10fa9f823a57
parent 9773ab57
...@@ -145,6 +145,17 @@ else () ...@@ -145,6 +145,17 @@ else ()
set (COMISO_TAUCS_CONFIG_FILE_SETTINGS "#define COMISO_TAUCS_AVAILABLE 0" ) set (COMISO_TAUCS_CONFIG_FILE_SETTINGS "#define COMISO_TAUCS_AVAILABLE 0" )
endif () endif ()
find_package (GUROBI)
if (GUROBI_FOUND )
set (COMISO_GUROBI_CONFIG_FILE_SETTINGS "#define COMISO_GUROBI_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${GUROBI_INCLUDE_DIR} )
list( APPEND COMISO_LINK_DIRECTORIES ${GUROBI_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${GUROBI_LIBRARY} )
else ()
message (STATUS "GUROBI not found!")
set (COMISO_GUROBI_CONFIG_FILE_SETTINGS "#define COMISO_GUROBI_AVAILABLE 0" )
endif ()
include_directories ( include_directories (
.. ..
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
......
...@@ -9,5 +9,6 @@ ...@@ -9,5 +9,6 @@
@COMISO_IPOPT_CONFIG_FILE_SETTINGS@ @COMISO_IPOPT_CONFIG_FILE_SETTINGS@
@COMISO_MUMPS_CONFIG_FILE_SETTINGS@ @COMISO_MUMPS_CONFIG_FILE_SETTINGS@
@COMISO_TAUCS_CONFIG_FILE_SETTINGS@ @COMISO_TAUCS_CONFIG_FILE_SETTINGS@
@COMISO_GUROBI_CONFIG_FILE_SETTINGS@
...@@ -44,10 +44,18 @@ int LinearConstraint::n_unknowns() ...@@ -44,10 +44,18 @@ int LinearConstraint::n_unknowns()
return coeffs_.innerSize(); return coeffs_.innerSize();
} }
const LinearConstraint::SVectorNC& LinearConstraint::coeffs() const
{
return coeffs_;
}
LinearConstraint::SVectorNC& LinearConstraint::coeffs() LinearConstraint::SVectorNC& LinearConstraint::coeffs()
{ {
return coeffs_; return coeffs_;
} }
const double& LinearConstraint::b() const
{
return b_;
}
double& LinearConstraint::b() double& LinearConstraint::b()
{ {
return b_; return b_;
......
...@@ -52,8 +52,11 @@ public: ...@@ -52,8 +52,11 @@ public:
virtual int n_unknowns(); virtual int n_unknowns();
SVectorNC& coeffs(); const SVectorNC& coeffs() const;
double& b(); SVectorNC& coeffs();
const double& b() const;
double& b();
virtual double eval_constraint ( const double* _x ); virtual double eval_constraint ( const double* _x );
......
...@@ -67,12 +67,14 @@ get_parameters() ...@@ -67,12 +67,14 @@ get_parameters()
directRoundingCB ->setChecked( misolver_.get_direct_rounding()); directRoundingCB ->setChecked( misolver_.get_direct_rounding());
noRoundingCB ->setChecked( misolver_.get_no_rounding()); noRoundingCB ->setChecked( misolver_.get_no_rounding());
multipleRoundingCB->setChecked( misolver_.get_multiple_rounding()); multipleRoundingCB->setChecked( misolver_.get_multiple_rounding());
gurobiRoundingCB ->setChecked( misolver_.get_gurobi_rounding());
localItersSB ->setValue( misolver_.get_local_iters()); localItersSB ->setValue( misolver_.get_local_iters());
localErrorDSB->setValue( log(misolver_.get_local_error())/log(10.0f)); localErrorDSB->setValue( log(misolver_.get_local_error())/log(10.0f));
cgItersSB ->setValue( misolver_.get_cg_iters()); cgItersSB ->setValue( misolver_.get_cg_iters());
cgErrorDSB->setValue( log(misolver_.get_cg_error())/log(10.0f)); cgErrorDSB->setValue( log(misolver_.get_cg_error())/log(10.0f));
gurobiMaxTimeDSB->setValue(misolver_.get_gurobi_max_time());
multipleRoundingDSB->setValue( misolver_.get_multiple_rounding_threshold()); multipleRoundingDSB->setValue( misolver_.get_multiple_rounding_threshold());
...@@ -96,6 +98,7 @@ set_parameters() ...@@ -96,6 +98,7 @@ set_parameters()
misolver_.set_direct_rounding( directRoundingCB->isChecked()); misolver_.set_direct_rounding( directRoundingCB->isChecked());
misolver_.set_no_rounding( noRoundingCB->isChecked()); misolver_.set_no_rounding( noRoundingCB->isChecked());
misolver_.set_multiple_rounding( multipleRoundingCB->isChecked()); misolver_.set_multiple_rounding( multipleRoundingCB->isChecked());
misolver_.set_gurobi_rounding( gurobiRoundingCB->isChecked());
misolver_.set_local_iters( localItersSB ->value()); misolver_.set_local_iters( localItersSB ->value());
misolver_.set_local_error( pow(10, localErrorDSB->value())); misolver_.set_local_error( pow(10, localErrorDSB->value()));
...@@ -103,6 +106,8 @@ set_parameters() ...@@ -103,6 +106,8 @@ set_parameters()
misolver_.set_cg_iters( cgItersSB ->value()); misolver_.set_cg_iters( cgItersSB ->value());
misolver_.set_cg_error( pow(10, cgErrorDSB->value())); misolver_.set_cg_error( pow(10, cgErrorDSB->value()));
misolver_.set_gurobi_max_time(gurobiMaxTimeDSB->value());
misolver_.set_multiple_rounding_threshold( multipleRoundingDSB->value()); misolver_.set_multiple_rounding_threshold( multipleRoundingDSB->value());
misolver_.set_noise( infoSB->value()); misolver_.set_noise( infoSB->value());
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>363</width> <width>368</width>
<height>259</height> <height>259</height>
</rect> </rect>
</property> </property>
...@@ -253,6 +253,37 @@ ...@@ -253,6 +253,37 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>GUROBI</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="gurobiRoundingCB">
<property name="text">
<string>use gurobi</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QDoubleSpinBox" name="gurobiMaxTimeDSB">
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="value">
<double>60.000000000000000</double>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="QLabel" name="label_10">
<property name="text">
<string>s</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
......
...@@ -23,13 +23,17 @@ ...@@ -23,13 +23,17 @@
\*===========================================================================*/ \*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include "MISolver.hh" #include "MISolver.hh"
#ifdef QT4_FOUND #ifdef QT4_FOUND
#include <CoMISo/QtWidgets/MISolverDialogUI.hh> #include <CoMISo/QtWidgets/MISolverDialogUI.hh>
#endif #endif
#if COMISO_GUROBI_AVAILABLE
#include <gurobi_c++.h>
#endif
#include <CoMISo/Utils/StopWatch.hh> #include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h> #include <gmm/gmm.h>
...@@ -56,6 +60,7 @@ MISolver::MISolver() ...@@ -56,6 +60,7 @@ MISolver::MISolver()
direct_rounding_ = false; direct_rounding_ = false;
no_rounding_ = false; no_rounding_ = false;
multiple_rounding_ = true; multiple_rounding_ = true;
gurobi_rounding_ = false;
max_local_iters_ = 100000; max_local_iters_ = 100000;
max_local_error_ = 1e-3; max_local_error_ = 1e-3;
...@@ -64,6 +69,8 @@ MISolver::MISolver() ...@@ -64,6 +69,8 @@ MISolver::MISolver()
multiple_rounding_threshold_ = 0.5; multiple_rounding_threshold_ = 0.5;
gurobi_max_time_ = 60;
noisy_ = 0; noisy_ = 0;
stats_ = true; stats_ = true;
...@@ -86,16 +93,19 @@ MISolver::solve( ...@@ -86,16 +93,19 @@ MISolver::solve(
if( gmm::mat_ncols(_A) == 0 || gmm::mat_nrows(_A) == 0) if( gmm::mat_ncols(_A) == 0 || gmm::mat_nrows(_A) == 0)
return; return;
if( no_rounding_ || _to_round.size() == 0) if( gurobi_rounding_)
solve_no_rounding( _A, _x, _rhs); solve_gurobi(_A, _x, _rhs, _to_round);
else else
if( direct_rounding_) if( no_rounding_ || _to_round.size() == 0)
solve_direct_rounding( _A, _x, _rhs, _to_round); solve_no_rounding( _A, _x, _rhs);
else else
if( multiple_rounding_) if( direct_rounding_)
solve_multiple_rounding( _A, _x, _rhs, _to_round); solve_direct_rounding( _A, _x, _rhs, _to_round);
else else
solve_iterative( _A, _x, _rhs, _to_round, _fixed_order); if( multiple_rounding_)
solve_multiple_rounding( _A, _x, _rhs, _to_round);
else
solve_iterative( _A, _x, _rhs, _to_round, _fixed_order);
} }
...@@ -142,8 +152,10 @@ MISolver::solve_direct_rounding( ...@@ -142,8 +152,10 @@ MISolver::solve_direct_rounding(
{ {
StopWatch sw; StopWatch sw;
const bool enable_performance_test = false;
// performance comparison code // performance comparison code
if(0) if(enable_performance_test)
{ {
sw.start(); sw.start();
COMISO::SparseQRSolver spqr; COMISO::SparseQRSolver spqr;
...@@ -159,7 +171,7 @@ MISolver::solve_direct_rounding( ...@@ -159,7 +171,7 @@ MISolver::solve_direct_rounding(
} }
// performance comparison code // performance comparison code
if(0) if(enable_performance_test)
{ {
sw.start(); sw.start();
COMISO::UMFPACKSolver umf; COMISO::UMFPACKSolver umf;
...@@ -175,7 +187,7 @@ MISolver::solve_direct_rounding( ...@@ -175,7 +187,7 @@ MISolver::solve_direct_rounding(
} }
// performance comparison code // performance comparison code
if(0) if(enable_performance_test)
{ {
sw.start(); sw.start();
COMISO::CholmodSolver chol; COMISO::CholmodSolver chol;
...@@ -612,6 +624,94 @@ MISolver::solve_multiple_rounding( ...@@ -612,6 +624,94 @@ MISolver::solve_multiple_rounding(
} }
//-----------------------------------------------------------------------------
void
MISolver::solve_gurobi(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round)
{
#if COMISO_GUROBI_AVAILABLE
// get round-indices in set
std::set<int> to_round;
for(unsigned int i=0; i<_to_round.size();++i)
to_round.insert(_to_round[i]);
try {
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env);
// set time limite
model.getEnv().set(GRB_DoubleParam_TimeLimit, gurobi_max_time_);
unsigned int n = _rhs.size();
// 1. allocate variables
std::vector<GRBVar> vars;
for( unsigned int i=0; i<n; ++i)
if( to_round.count(i))
vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_INTEGER));
else
vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_CONTINUOUS));
// Integrate new variables
model.update();
// 2. setup_energy
// build objective function from linear system E = x^tAx - 2x^t*rhs
GRBQuadExpr objective;
for(unsigned int i=0; i<_A.nc; ++i)
for(unsigned int j=_A.jc[i]; j<_A.jc[i+1]; ++j)
{
objective += _A.pr[j]*vars[_A.ir[j]]*vars[i];
}
for(unsigned int i=0; i<n; ++i)
objective -= 2*_rhs[i]*vars[i];
// _A.jc[c+1]
// _A.pr[write]
// _A.ir[write]
// _A.nc
// _A.nr
// minimize
model.set(GRB_IntAttr_ModelSense, 1);
model.setObjective(objective);
// 4. solve
model.optimize();
// 5. store result
_x.resize(n);
for(unsigned int i=0; i<n; ++i)
_x[i] = vars[i].get(GRB_DoubleAttr_X);
std::cout << "GUROBI objective: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;
}
catch(GRBException e)
{
std::cout << "Error code = " << e.getErrorCode() << std::endl;
std::cout << e.getMessage() << std::endl;
}
catch(...)
{
std::cout << "Exception during optimization" << std::endl;
}
#else
std::cerr << "GUROBI solver is not available, please install it..." << std::endl;
#endif
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
......
...@@ -160,6 +160,12 @@ public: ...@@ -160,6 +160,12 @@ public:
/// Will multiple rounding be performed? /// Will multiple rounding be performed?
bool get_multiple_rounding() { return multiple_rounding_;} bool get_multiple_rounding() { return multiple_rounding_;}
/// Shall gurobi solver be used?
void set_gurobi_rounding( bool _b) { gurobi_rounding_=_b;}
/// Will gurobi rounding be performed?
bool get_gurobi_rounding() { return gurobi_rounding_;}
/// Set number of maximum Gauss-Seidel iterations /// Set number of maximum Gauss-Seidel iterations
void set_local_iters( unsigned int _i) { max_local_iters_ = _i;} void set_local_iters( unsigned int _i) { max_local_iters_ = _i;}
/// Get number of maximum Gauss-Seidel iterations /// Get number of maximum Gauss-Seidel iterations
...@@ -190,6 +196,11 @@ public: ...@@ -190,6 +196,11 @@ public:
/// Get noise level of algorithm /// Get noise level of algorithm
unsigned int get_noise() { return noisy_;} unsigned int get_noise() { return noisy_;}
/// Set time limit for gurobi solver (in seconds)
void set_gurobi_max_time( double _d) { gurobi_max_time_ = _d;}
/// Get time limit for gurobi solver (in seconds)
double get_gurobi_max_time() { return gurobi_max_time_;}
/// Set output statistics of solver /// Set output statistics of solver
void set_stats( bool _stats) { stats_ = _stats; } void set_stats( bool _stats) { stats_ = _stats; }
/// Get output statistics of solver /// Get output statistics of solver
...@@ -285,6 +296,12 @@ private: ...@@ -285,6 +296,12 @@ private:
Veci& _to_round, Veci& _to_round,
bool _fixed_order ); bool _fixed_order );
void solve_gurobi(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round );
void update_solution( void update_solution(
CSCMatrix& _A, CSCMatrix& _A,
...@@ -308,6 +325,7 @@ private: ...@@ -308,6 +325,7 @@ private:
bool direct_rounding_; bool direct_rounding_;
bool no_rounding_; bool no_rounding_;
bool multiple_rounding_; bool multiple_rounding_;
bool gurobi_rounding_;
double multiple_rounding_threshold_; double multiple_rounding_threshold_;
...@@ -319,6 +337,9 @@ private: ...@@ -319,6 +337,9 @@ private:
unsigned int noisy_; unsigned int noisy_;
bool stats_; bool stats_;
// time limit for gurobi solver (in seconds)
double gurobi_max_time_;
// flag // flag
bool cholmod_step_done_; bool cholmod_step_done_;
......
...@@ -20,6 +20,12 @@ if(LAPACK_FOUND AND TAUCS_FOUND) ...@@ -20,6 +20,12 @@ if(LAPACK_FOUND AND TAUCS_FOUND)
list( APPEND COMISO_LINK_LIBRARIES ${LAPACK_LIBRARIES} ) list( APPEND COMISO_LINK_LIBRARIES ${LAPACK_LIBRARIES} )
endif() endif()
find_package(GUROBI)
if( GUROBI_FOUND)
list( APPEND COMISO_INCLUDE_DIRECTORIES ${GUROBI_INCLUDE_DIR} )
list( APPEND COMISO_LINK_DIRECTORIES ${GUROBI_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${GUROBI_LIBRARY} )
endif()
list( APPEND COMISO_LINK_LIBRARIES ${SUITESPARSE_LIBRARIES} ) list( APPEND COMISO_LINK_LIBRARIES ${SUITESPARSE_LIBRARIES} )
list( APPEND COMISO_LINK_LIBRARIES ${MPI_CXX_LIBRARIES} ) list( APPEND COMISO_LINK_LIBRARIES ${MPI_CXX_LIBRARIES} )
......
...@@ -106,6 +106,21 @@ if ( COMISO_INCLUDE_DIR ) ...@@ -106,6 +106,21 @@ if ( COMISO_INCLUDE_DIR )
endif() endif()
STRING(REGEX MATCH "\#define COMISO_GUROBI_AVAILABLE 1" COMISO_GUROBI_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} )
if ( COMISO_GUROBI_BUILD_TIME_AVAILABLE )
find_package(GUROBI)
if ( NOT GUROBI_FOUND )
message(ERROR "COMISO configured with GUROBI but GUROBI not available")
endif()
list (APPEND COMISO_OPT_DEPS "GUROBI")
endif()
add_definitions (-DCOMISODLL -DUSECOMISO ) add_definitions (-DCOMISODLL -DUSECOMISO )
endif(COMISO_INCLUDE_DIR) endif(COMISO_INCLUDE_DIR)
......
Markdown is supported
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