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 ()
set (COMISO_TAUCS_CONFIG_FILE_SETTINGS "#define COMISO_TAUCS_AVAILABLE 0" )
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 (
..
${CMAKE_CURRENT_SOURCE_DIR}
......
......@@ -9,5 +9,6 @@
@COMISO_IPOPT_CONFIG_FILE_SETTINGS@
@COMISO_MUMPS_CONFIG_FILE_SETTINGS@
@COMISO_TAUCS_CONFIG_FILE_SETTINGS@
@COMISO_GUROBI_CONFIG_FILE_SETTINGS@
......@@ -44,10 +44,18 @@ int LinearConstraint::n_unknowns()
return coeffs_.innerSize();
}
const LinearConstraint::SVectorNC& LinearConstraint::coeffs() const
{
return coeffs_;
}
LinearConstraint::SVectorNC& LinearConstraint::coeffs()
{
return coeffs_;
}
const double& LinearConstraint::b() const
{
return b_;
}
double& LinearConstraint::b()
{
return b_;
......
......@@ -52,8 +52,11 @@ public:
virtual int n_unknowns();
SVectorNC& coeffs();
double& b();
const SVectorNC& coeffs() const;
SVectorNC& coeffs();
const double& b() const;
double& b();
virtual double eval_constraint ( const double* _x );
......
......@@ -67,12 +67,14 @@ get_parameters()
directRoundingCB ->setChecked( misolver_.get_direct_rounding());
noRoundingCB ->setChecked( misolver_.get_no_rounding());
multipleRoundingCB->setChecked( misolver_.get_multiple_rounding());
gurobiRoundingCB ->setChecked( misolver_.get_gurobi_rounding());
localItersSB ->setValue( misolver_.get_local_iters());
localErrorDSB->setValue( log(misolver_.get_local_error())/log(10.0f));
cgItersSB ->setValue( misolver_.get_cg_iters());
cgErrorDSB->setValue( log(misolver_.get_cg_error())/log(10.0f));
gurobiMaxTimeDSB->setValue(misolver_.get_gurobi_max_time());
multipleRoundingDSB->setValue( misolver_.get_multiple_rounding_threshold());
......@@ -96,6 +98,7 @@ set_parameters()
misolver_.set_direct_rounding( directRoundingCB->isChecked());
misolver_.set_no_rounding( noRoundingCB->isChecked());
misolver_.set_multiple_rounding( multipleRoundingCB->isChecked());
misolver_.set_gurobi_rounding( gurobiRoundingCB->isChecked());
misolver_.set_local_iters( localItersSB ->value());
misolver_.set_local_error( pow(10, localErrorDSB->value()));
......@@ -103,6 +106,8 @@ set_parameters()
misolver_.set_cg_iters( cgItersSB ->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_noise( infoSB->value());
......
......@@ -9,7 +9,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>363</width>
<width>368</width>
<height>259</height>
</rect>
</property>
......@@ -253,6 +253,37 @@
</property>
</widget>
</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>
</item>
<item>
......
......@@ -23,13 +23,17 @@
\*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include "MISolver.hh"
#ifdef QT4_FOUND
#include <CoMISo/QtWidgets/MISolverDialogUI.hh>
#endif
#if COMISO_GUROBI_AVAILABLE
#include <gurobi_c++.h>
#endif
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
......@@ -56,6 +60,7 @@ MISolver::MISolver()
direct_rounding_ = false;
no_rounding_ = false;
multiple_rounding_ = true;
gurobi_rounding_ = false;
max_local_iters_ = 100000;
max_local_error_ = 1e-3;
......@@ -64,6 +69,8 @@ MISolver::MISolver()
multiple_rounding_threshold_ = 0.5;
gurobi_max_time_ = 60;
noisy_ = 0;
stats_ = true;
......@@ -86,16 +93,19 @@ MISolver::solve(
if( gmm::mat_ncols(_A) == 0 || gmm::mat_nrows(_A) == 0)
return;
if( no_rounding_ || _to_round.size() == 0)
solve_no_rounding( _A, _x, _rhs);
if( gurobi_rounding_)
solve_gurobi(_A, _x, _rhs, _to_round);
else
if( direct_rounding_)
solve_direct_rounding( _A, _x, _rhs, _to_round);
if( no_rounding_ || _to_round.size() == 0)
solve_no_rounding( _A, _x, _rhs);
else
if( multiple_rounding_)
solve_multiple_rounding( _A, _x, _rhs, _to_round);
if( direct_rounding_)
solve_direct_rounding( _A, _x, _rhs, _to_round);
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(
{
StopWatch sw;
const bool enable_performance_test = false;
// performance comparison code
if(0)
if(enable_performance_test)
{
sw.start();
COMISO::SparseQRSolver spqr;
......@@ -159,7 +171,7 @@ MISolver::solve_direct_rounding(
}
// performance comparison code
if(0)
if(enable_performance_test)
{
sw.start();
COMISO::UMFPACKSolver umf;
......@@ -175,7 +187,7 @@ MISolver::solve_direct_rounding(
}
// performance comparison code
if(0)
if(enable_performance_test)
{
sw.start();
COMISO::CholmodSolver chol;
......@@ -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:
/// Will multiple rounding be performed?
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
void set_local_iters( unsigned int _i) { max_local_iters_ = _i;}
/// Get number of maximum Gauss-Seidel iterations
......@@ -190,6 +196,11 @@ public:
/// Get noise level of algorithm
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
void set_stats( bool _stats) { stats_ = _stats; }
/// Get output statistics of solver
......@@ -285,6 +296,12 @@ private:
Veci& _to_round,
bool _fixed_order );
void solve_gurobi(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round );
void update_solution(
CSCMatrix& _A,
......@@ -308,6 +325,7 @@ private:
bool direct_rounding_;
bool no_rounding_;
bool multiple_rounding_;
bool gurobi_rounding_;
double multiple_rounding_threshold_;
......@@ -319,6 +337,9 @@ private:
unsigned int noisy_;
bool stats_;
// time limit for gurobi solver (in seconds)
double gurobi_max_time_;
// flag
bool cholmod_step_done_;
......
......@@ -20,6 +20,12 @@ if(LAPACK_FOUND AND TAUCS_FOUND)
list( APPEND COMISO_LINK_LIBRARIES ${LAPACK_LIBRARIES} )
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 ${MPI_CXX_LIBRARIES} )
......
......@@ -106,6 +106,21 @@ if ( COMISO_INCLUDE_DIR )
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 )
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