Commit 1484741c authored by David Bommes's avatar David Bommes

added CPLEX solver and miqp example

+ some cmake corrections

git-svn-id: http://www.openflipper.org/svnrepo/CoMISo/trunk@131 1355f012-dd97-4b2f-ae87-10fa9f823a57
parent 871c5416
......@@ -202,6 +202,9 @@ if (CPLEX_FOUND )
# list( APPEND COMISO_LINK_DIRECTORIES ${CPLEX_LIBRARY_DIR} )
# list( APPEND COMISO_LINK_DIRECTORIES ${CPLEX_CONCERT_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${CPLEX_LIBRARIES} )
#enable c++ support
add_definitions(-DIL_STD)
else ()
message (STATUS "CPLEX not found!")
set (COMISO_ARPACK_CONFIG_FILE_SETTINGS "#define COMISO_CPLEX_AVAILABLE 0" )
......@@ -326,6 +329,9 @@ endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_nsolver/CMakeLists.txt" )
add_subdirectory (Examples/small_nsolver)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_miqp/CMakeLists.txt" )
add_subdirectory (Examples/small_miqp)
endif()
include (ACGCommon)
include (CoMISoExample)
# source code directories
set (directories
.
)
# collect all header and source files
acg_append_files (headers "*.hh" ${directories})
acg_append_files (sources "*.cc" ${directories})
# remove template cc files from source file list
acg_drop_templates (sources)
if (WIN32)
acg_add_executable (small_miqp WIN32 ${sources} ${headers} )
elseif (APPLE)
# generate bundle on mac
acg_add_executable (small_miqp MACOSX_BUNDLE ${sources} ${headers} )
else ()
acg_add_executable (small_miqp ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_miqp PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_miqp
CoMISo
${COMISO_LINK_LIBRARIES}
)
if (APPLE)
# create bundle in "Build" directory and set icon
# no install needed here, because the whole bundle will be installed in the
# toplevel CMakeLists.txt
set_target_properties (
Example PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Build"
MACOSX_BUNDLE_INFO_STRING "CoMISo small_miqp"
)
endif ()
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include <CoMISo/Utils/StopWatch.hh>
#include <vector>
#include <CoMISo/NSolver/NProblemInterface.hh>
#include <CoMISo/NSolver/NPDerivativeChecker.hh>
#include <CoMISo/NSolver/GUROBISolver.hh>
#include <CoMISo/NSolver/CPLEXSolver.hh>
#include <CoMISo/NSolver/LinearConstraint.hh>
// generate an instance of a nonlinear problem by deriving from base class NProblemInterface
// implement all virtual functions in order to solve this problem by any of the solvers located
// in CoMISo/NSolver
class SmallNProblem : public COMISO::NProblemInterface
{
public:
// Sparse Matrix Type
// typedef Eigen::DynamicSparseMatrix<double,Eigen::ColMajor> SMatrixNP;
// specify a function which has several local minima
// f(x,y)=(x-2y+1)^2 + (x-2)^2
// number of unknown variables, here x and y = 2
virtual int n_unknowns ( )
{
return 2;
}
// initial value where the optimization should start from
virtual void initial_x ( double* _x )
{
_x[0] = 0.0;
_x[1] = 0.0;
}
// function evaluation at location _x
virtual double eval_f ( const double* _x )
{
double term = _x[0] - 2.0*_x[1] + 1.0;
double term2 = _x[0] - 2.0;
return term*term + term2*term2;
}
// gradient evaluation at location _x
virtual void eval_gradient( const double* _x, double* _g)
{
double term = _x[0] - 2.0*_x[1] + 1.0;
double term2 = _x[0] - 2.0;
_g[0] = 2.0*term + 2.0*term2;
_g[1] = -4.0*term;
}
// hessian matrix evaluation at location _x
virtual void eval_hessian ( const double* _x, SMatrixNP& _H)
{
_H.resize(n_unknowns(), n_unknowns());
_H.setZero();
_H.coeffRef(0,0) = 4.0;
_H.coeffRef(1,0) = -4.0;
_H.coeffRef(0,1) = -4.0;
_H.coeffRef(1,1) = 8.0;
}
// print result
virtual void store_result ( const double* _x )
{
std::cerr << "Energy: " << eval_f(_x) << std::endl;
std::cerr << "(x,y) = (" << _x[0] << "," << _x[1] << ")" << std::endl;
}
// advanced properties
virtual bool constant_hessian() { return true; }
};
//------------------------------------------------------------------------------------------------------
// Example main
int main(void)
{
std::cout << "---------- 1) Get an instance of a NProblem..." << std::endl;
SmallNProblem snp;
std::cout << "---------- 2) (optional for debugging) Check derivatives of problem..." << std::endl;
COMISO::NPDerivativeChecker npd;
npd.check_all(&snp);
std::cout << "---------- 3) setup list of integer variables..." << std::endl;
std::vector<COMISO::PairIndexVtype> discrete_variables;
discrete_variables.push_back( COMISO::PairIndexVtype(0,COMISO::Integer) );
std::cout << "---------- 4) setup constraints..." << std::endl;
std::vector<COMISO::NConstraintInterface*> constraints;
// check if IPOPT solver available in current configuration
#if( COMISO_GUROBI_AVAILABLE)
std::cout << "---------- 5) Get GUROBI solver... " << std::endl;
COMISO::GUROBISolver gsol;
std::cout << "---------- 4) Solve..." << std::endl;
gsol.solve(&snp, constraints, discrete_variables);
#endif
// check if TAO solver available in current configuration
#if( COMISO_CPLEX_AVAILABLE)
std::cout << "---------- 5) Solve with CPLEX solver... " << std::endl;
COMISO::CPLEXSolver csol;
std::cout << "---------- 4) Solve..." << std::endl;
csol.solve(&snp, constraints, discrete_variables);
#endif
return 0;
}
//=============================================================================
//
// CLASS GUROBISolver - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include "CPLEXSolver.hh"
#if COMISO_CPLEX_AVAILABLE
//=============================================================================
#include <stdexcept>
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
CPLEXSolver::
CPLEXSolver()
{
}
//-----------------------------------------------------------------------------
// ********** SOLVE **************** //
bool
CPLEXSolver::
solve(NProblemInterface* _problem,
std::vector<NConstraintInterface*>& _constraints,
std::vector<PairIndexVtype>& _discrete_constraints,
const double _time_limit)
{
try
{
// //----------------------------------------------
// // 0. set up environment
// //----------------------------------------------
//
// GRBEnv env = GRBEnv();
// GRBModel model = GRBModel(env);
//
// model.getEnv().set(GRB_DoubleParam_TimeLimit, _time_limit);
//
//
// //----------------------------------------------
// // 1. allocate variables
// //----------------------------------------------
//
// // determine variable types: 0->real, 1->integer, 2->bool
// std::vector<char> vtypes(_problem->n_unknowns(),0);
// for(unsigned int i=0; i<_discrete_constraints.size(); ++i)
// switch(_discrete_constraints[i].second)
// {
// case Integer: vtypes[_discrete_constraints[i].first] = 1; break;
// case Binary : vtypes[_discrete_constraints[i].first] = 2; break;
// default : break;
// }
//
// // GUROBI variables
// std::vector<GRBVar> vars;
// // first all
// for( int i=0; i<_problem->n_unknowns(); ++i)
// switch(vtypes[i])
// {
// case 0 : vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_CONTINUOUS) ); break;
// case 1 : vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_INTEGER ) ); break;
// case 2 : vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_BINARY ) ); break;
// }
//
//
// // Integrate new variables
// model.update();
//
// //----------------------------------------------
// // 2. setup constraints
// //----------------------------------------------
//
// // get zero vector
// std::vector<double> x(_problem->n_unknowns(), 0.0);
//
// for(unsigned int i=0; i<_constraints.size(); ++i)
// {
// if(!_constraints[i]->is_linear())
// std::cerr << "Warning: GUROBISolver received a problem with non-linear constraints!!!" << std::endl;
//
// GRBLinExpr lin_expr;
// NConstraintInterface::SVectorNC gc;
// _constraints[i]->eval_gradient(P(x), gc);
//
// NConstraintInterface::SVectorNC::InnerIterator v_it(gc);
// for(; v_it; ++v_it)
//// lin_expr += v_it.value()*vars[v_it.index()];
// lin_expr = lin_expr + vars[v_it.index()]*v_it.value();
//
// double b = _constraints[i]->eval_constraint(P(x));
//
// switch(_constraints[i]->constraint_type())
// {
// case NConstraintInterface::NC_EQUAL : model.addConstr(lin_expr + b == 0); break;
// case NConstraintInterface::NC_LESS_EQUAL : model.addConstr(lin_expr + b <= 0); break;
// case NConstraintInterface::NC_GREATER_EQUAL : model.addConstr(lin_expr + b >= 0); break;
// }
// }
// model.update();
//
// //----------------------------------------------
// // 3. setup energy
// //----------------------------------------------
//
// if(!_problem->constant_hessian())
// std::cerr << "Warning: GUROBISolver received a problem with non-constant hessian!!!" << std::endl;
//
// GRBQuadExpr objective;
//
// // add quadratic part
// NProblemInterface::SMatrixNP H;
// _problem->eval_hessian(P(x), H);
// for( int i=0; i<H.outerSize(); ++i)
// for (NProblemInterface::SMatrixNP::InnerIterator it(H,i); it; ++it)
// objective += 0.5*it.value()*vars[it.row()]*vars[it.col()];
//
//
// // add linear part
// std::vector<double> g(_problem->n_unknowns());
// _problem->eval_gradient(P(x), P(g));
// for(unsigned int i=0; i<g.size(); ++i)
// objective += g[i]*vars[i];
//
// // add constant part
// objective += _problem->eval_f(P(x));
//
// model.set(GRB_IntAttr_ModelSense, 1);
// model.setObjective(objective);
// model.update();
//
//
// //----------------------------------------------
// // 4. solve problem
// //----------------------------------------------
//
//
// if (solution_input_path_.empty())
// {
// if (!problem_env_output_path_.empty())
// {
// std::cout << "Writing problem's environment into file \"" << problem_env_output_path_ << "\"." << std::endl;
// model.getEnv().writeParams(problem_env_output_path_);
// }
// if (!problem_output_path_.empty())
// {
// std::cout << "Writing problem into file \"" << problem_output_path_ << "\"." << std::endl;
// GurobiHelper::outputModelToMpsGz(model, problem_output_path_);
// }
//
// model.optimize();
// }
// else
// {
// std::cout << "Reading solution from file \"" << solution_input_path_ << "\"." << std::endl;
// }
//
// //----------------------------------------------
// // 5. store result
// //----------------------------------------------
//
// if (solution_input_path_.empty())
// {
// // store computed result
// for(unsigned int i=0; i<vars.size(); ++i)
// x[i] = vars[i].get(GRB_DoubleAttr_X);
// }
// else
// {
// std::cout << "Loading stored solution from \"" << solution_input_path_ << "\"." << std::endl;
// // store loaded result
// const size_t oldSize = x.size();
// x.clear();
// GurobiHelper::readSolutionVectorFromSOL(x, solution_input_path_);
// if (oldSize != x.size()) {
// std::cerr << "oldSize != x.size() <=> " << oldSize << " != " << x.size() << std::endl;
// throw std::runtime_error("Loaded solution vector doesn't have expected dimension.");
// }
// }
//
// _problem->store_result(P(x));
//
// // ObjVal is only available if the optimize was called.
// if (solution_input_path_.empty())
// std::cout << "GUROBI Objective: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;
return true;
}
catch (IloException& e)
{
cerr << "Concert exception caught: " << e << endl;
return false;
}
catch (...)
{
cerr << "Unknown exception caught" << endl;
return false;
}
return false;
}
//-----------------------------------------------------------------------------
//void
//CPLEXSolver::
//set_problem_output_path( const std::string &_problem_output_path)
//{
// problem_output_path_ = _problem_output_path;
//}
//
//
////-----------------------------------------------------------------------------
//
//
//void
//CPLEXSolver::
//set_problem_env_output_path( const std::string &_problem_env_output_path)
//{
// problem_env_output_path_ = _problem_env_output_path;
//}
//
//
////-----------------------------------------------------------------------------
//
//
//void
//CPLEXSolver::
//set_solution_input_path(const std::string &_solution_input_path)
//{
// solution_input_path_ = _solution_input_path;
//}
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_CPLEX_AVAILABLE
//=============================================================================
//=============================================================================
//
// CLASS CPLEXSolver
//
//=============================================================================
#ifndef COMISO_CPLEXSOLVER_HH
#define COMISO_CPLEXSOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_CPLEX_AVAILABLE
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <vector>
#include <string>
#include "NProblemInterface.hh"
#include "NConstraintInterface.hh"
#include "VariableType.hh"
#include <ilcplex/ilocplex.h>
ILOSTLBEGIN
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NewtonSolver CPLEXSolver.hh
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT CPLEXSolver
{
public:
/// Default constructor
CPLEXSolver();
/// Destructor
~CPLEXSolver() { cplex_env_.end();}
// ********** SOLVE **************** //
bool solve(NProblemInterface* _problem, // problem instance
std::vector<NConstraintInterface*>& _constraints, // linear constraints
std::vector<PairIndexVtype>& _discrete_constraints, // discrete constraints
const double _time_limit = 60 ); // time limit in seconds
// void set_problem_output_path ( const std::string &_problem_output_path);
// void set_problem_env_output_path( const std::string &_problem_env_output_path);
// void set_solution_input_path ( const std::string &_solution_input_path);
protected:
double* P(std::vector<double>& _v)
{
if( !_v.empty())
return ((double*)&_v[0]);
else
return 0;
}
private:
// CPLEX environment
IloEnv cplex_env_;
// filenames for exporting/importing gurobi solutions
// if string is empty nothing is imported or exported
// std::string problem_output_path_;
// std::string problem_env_output_path_;
// std::string solution_input_path_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_CPLEX_AVAILABLE
//=============================================================================
#endif // ACG_CPLEXSOLVER_HH defined
//=============================================================================
......@@ -36,7 +36,7 @@ bool
GUROBISolver::
solve(NProblemInterface* _problem,
std::vector<NConstraintInterface*>& _constraints,
std::vector<PairUiV>& _discrete_constraints,
std::vector<PairIndexVtype>& _discrete_constraints,
const double _time_limit)
{
try
......
......@@ -44,8 +44,6 @@ namespace COMISO {
class COMISODLLEXPORT GUROBISolver
{
public:
typedef std::pair<unsigned int, VariableType> PairUiV;
/// Default constructor
GUROBISolver();
......@@ -56,7 +54,7 @@ public:
// ********** SOLVE **************** //
bool solve(NProblemInterface* _problem, // problem instance
std::vector<NConstraintInterface*>& _constraints, // linear constraints
std::vector<PairUiV>& _discrete_constraints, // discrete constraints
std::vector<PairIndexVtype>& _discrete_constraints, // discrete constraints
const double _time_limit = 60 ); // time limit in seconds
void set_problem_output_path ( const std::string &_problem_output_path);
......
......@@ -24,6 +24,8 @@ namespace COMISO {
enum VariableType { Real, Integer, Binary};
typedef std::pair<unsigned int, VariableType> PairIndexVtype;
//=============================================================================
} // namespace COMISO
//=============================================================================
......
......@@ -7,66 +7,42 @@
if (CPLEX_INCLUDE_DIR)
# in cache already
set(CPLEX_FOUND TRUE)
set(CPLEX_INCLUDE_DIRS "${CPLEX_INCLUDE_DIR};${CPLEX_CONCERT_INCLUDE_DIR}" )
set(CPLEX_LIBRARIES "${CPLEX_LIBRARY};${CPLEX_ILO_LIBRARY};${CPLEX_CONCERT_LIBRARY}" )
else (CPLEX_INCLUDE_DIR)
if (WIN32)
#TODO #######################################################################
find_path(CPLEX_INCLUDE_DIR NAMES SRC/gurobi_c++.h
PATHS
"C:\\libs\\gurobi45"
${GUROBI_INCLUDE_PATH}
)
find_library( GUROBI_LIBRARY_RELEASE
SuperLU
PATHS "C:\\libs\\gurobi45\\lib" )
find_library( GUROBI_LIBRARY_DEBUG
SuperLUd
PATHS "C:\\libs\\gurobi45\\lib" )
set ( GUROBI_LIBRARY "optimized;${GUROBI_LIBRARY_RELEASE};debug;${GUROBI_LIBRARY_DEBUG}" CACHE STRING "GUROBI Libraries" )
ELSEIF(APPLE)
#TODO #######################################################################
find_path(GUROBI_INCLUDE_DIR NAMES gurobi_c++.h
PATHS "${CMAKE_SOURCE_DIR}/MacOS/Libs/gurobi40"
${GUROBI_INCLUDE_PATH}
)
find_library( GUROBI_LIBRARY
SuperLU
PATHS "${CMAKE_SOURCE_DIR}/MacOS/Libs/gurobi40")
ELSE( WIN32 )
find_path(CPLEX_INCLUDE_DIR NAMES ilcplex/cplex.h
PATHS "$ENV{CPLEX_DIR}/cplex/include"
)
find_path(CPLEX_CONCERT_INCLUDE_DIR NAMES ilconcert/ilomodel.h
PATHS "$ENV{CPLEX_DIR}/concert/include"
)
# MESSAGE(STATUS "CPLEX include dir: ${CPLEX_INCLUDE_DIR}")
# MESSAGE(STATUS "CPLEX concert include dir: ${CPLEX_CONCERT_INCLUDE_DIR}")
find_library( CPLEX_LIBRARY
cplex
PATHS "$ENV{CPLEX_DIR}/cplex/lib/x86-64_sles10_4.1/static_pic" )
find_library( CPLEX_ILO_LIBRARY
ilocplex
PATHS "$ENV{CPLEX_DIR}/cplex/lib/x86-64_sles10_4.1/static_pic" )
find_library( CPLEX_CONCERT_LIBRARY
concert
PATHS "$ENV{CPLEX_DIR}/concert/lib/x86-64_sles10_4.1/static_pic" )
ENDIF()
find_path(CPLEX_INCLUDE_DIR
NAMES ilcplex/cplex.h
PATHS "$ENV{CPLEX_DIR}/cplex/include"
)
find_path(CPLEX_CONCERT_INCLUDE_DIR
NAMES ilconcert/ilomodel.h
PATHS "$ENV{CPLEX_DIR}/concert/include"
)
find_library( CPLEX_LIBRARY
cplex
PATHS "$ENV{CPLEX_DIR}/cplex/lib/x86-64_sles10_4.1/static_pic"
)
find_library( CPLEX_ILO_LIBRARY
ilocplex
PATHS "$ENV{CPLEX_DIR}/cplex/lib/x86-64_sles10_4.1/static_pic"
)
find_library( CPLEX_CONCERT_LIBRARY
concert
PATHS "$ENV{CPLEX_DIR}/concert/lib/x86-64_sles10_4.1/static_pic"
)
set(CPLEX_INCLUDE_DIRS "${CPLEX_INCLUDE_DIR};${CPLEX_CONCERT_INCLUDE_DIR}" )
set(CPLEX_LIBRARIES "${CPLEX_LIBRARY};${CPLEX_ILO_LIBRARY};${CPLEX_CONCERT_LIBRARY}" )
# use c++ headers as default
set(CPLEX_COMPILER_FLAGS "-DIL_STD" CACHE STRING "Cplex Compiler Flags")
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE
# if all listed variables are TRUE
......
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