Commit d93ac64e authored by David Bommes's avatar David Bommes

added GurobiHelper

added load/save problem via gurobi

git-svn-id: http://www.openflipper.org/svnrepo/CoMISo/trunk@110 1355f012-dd97-4b2f-ae87-10fa9f823a57
parent f40d074a
......@@ -21,12 +21,11 @@ namespace COMISO {
//== IMPLEMENTATION ==========================================================
//// Constructor
//GUROBISolver::
//GUROBISolver()
//{
//
//}
GUROBISolver::
GUROBISolver()
{
}
//-----------------------------------------------------------------------------
......@@ -140,18 +139,49 @@ solve(NProblemInterface* _problem,
model.set(GRB_IntAttr_ModelSense, 1);
model.setObjective(objective);
//----------------------------------------------
// 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;
}
model.optimize();
//----------------------------------------------
// 5. store result
//----------------------------------------------
for(unsigned int i=0; i<vars.size(); ++i)
x[i] = vars[i].get(GRB_DoubleAttr_X);
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
{
// store loaded result
GurobiHelper::readSolutionVectorFromSOL(x, solution_input_path_);
}
_problem->store_result(P(x));
......@@ -174,6 +204,39 @@ solve(NProblemInterface* _problem,
}
//-----------------------------------------------------------------------------
void
GUROBISolver::
set_problem_output_path( const std::string &_problem_output_path)
{
problem_output_path_ = _problem_output_path;
}
//-----------------------------------------------------------------------------
void
GUROBISolver::
set_problem_env_output_path( const std::string &_problem_env_output_path)
{
problem_env_output_path_ = _problem_env_output_path;
}
//-----------------------------------------------------------------------------
void
GUROBISolver::
set_solution_input_path(const std::string &_solution_input_path)
{
solution_input_path_ = _solution_input_path;
}
//=============================================================================
} // namespace COMISO
//=============================================================================
......
......@@ -17,9 +17,11 @@
#include <CoMISo/Config/CoMISoDefines.hh>
#include <vector>
#include <string>
#include "NProblemInterface.hh"
#include "NConstraintInterface.hh"
#include "VariableType.hh"
#include "GurobiHelper.hh"
#include <gurobi_c++.h>
......@@ -45,8 +47,8 @@ public:
typedef std::pair<unsigned int, VariableType> PairUiV;
/// Default constructor -> set up IpOptApplication
GUROBISolver() {}
/// Default constructor
GUROBISolver();
/// Destructor
~GUROBISolver() {}
......@@ -57,6 +59,10 @@ public:
std::vector<PairUiV>& _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)
{
......@@ -68,6 +74,11 @@ protected:
private:
// 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_;
};
......
/*
* GurobiHelper.cc
*
* Created on: Jan 4, 2012
* Author: ebke
*/
#include "GurobiHelper.hh"
#if COMISO_GUROBI_AVAILABLE
#include <QTemporaryFile>
#include <QFileInfo>
#include <boost/filesystem.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <cstdio>
#include <fstream>
#include <string>
#define OUTPUT_UNCOMPRESSED_WITH_CONSTANT_COMMENT 0
#define OUTPUT_CONSTANT_AS_CONT 1
namespace COMISO {
/**
* Helper class that ensures exception safe deletion
* of a temporary file.
*/
class TempFileGuard {
public:
TempFileGuard(const std::string &_filePath) : filePath_(_filePath) {
}
~TempFileGuard() {
if (boost::filesystem::exists(filePath_))
boost::filesystem::remove(filePath_);
}
const boost::filesystem::path &filePath() const { return filePath_; };
private:
boost::filesystem::path filePath_;
};
static void moveConstantTermIntoConstrainedVariable(GRBModel &model) {
const double constantTerm = model.getObjective().getLinExpr().getConstant();
//tmpModel.getObjective().addConstant(-constantTerm);
model.getObjective() -= constantTerm;
#if OUTPUT_CONSTANT_AS_CONT
model.addVar(constantTerm, constantTerm, 1, GRB_CONTINUOUS, "constant");
#else
model.addVar(1, 1, constantTerm, GRB_INTEGER, "constant");
#endif
}
static void copyFile(const char *from, const char *to) {
FILE *inF = fopen(from, "r");
FILE *outF = fopen(to, "w");
const int bufsize = 4096;
unsigned char buffer[bufsize];
do {
size_t readBytes = fread(buffer, 1, bufsize, inF);
fwrite(buffer, 1, readBytes, outF);
} while(!feof(inF));
fclose(inF);
fclose(outF);
}
/**
* WARNING: Never call outputModelToMpsGz and importInitialSolutionIntoModel
* on the same model. Both try to move the constant term into a variable and
* consequently, the second attempt to do so will fail.
*/
void GurobiHelper::outputModelToMpsGz(GRBModel &model, const std::string &problem_output_path_) {
#if OUTPUT_UNCOMPRESSED_WITH_CONSTANT_COMMENT
boost::scoped_ptr<TempFileGuard> tempFileGuard;
{
QTemporaryFile tempFile("XXXXXX.mps");
tempFile.setAutoRemove(false);
tempFile.open();
// In order to minimize the likelihood of race conditions,
// we initialize tempFileGuard right here.
tempFileGuard.reset(new TempFileGuard(QFileInfo(tempFile).absoluteFilePath().toStdString()));
tempFile.close();
}
const std::string fileName = tempFileGuard->filePath().string();
model.write(fileName);
const double constantTerm = model.getObjective().getLinExpr().getConstant();
FILE *inF = fopen(fileName.c_str(), "r");
FILE *outF = fopen(problem_output_path_.c_str(), "w");
fprintf(outF, "* Constant Term: %.16e\n", constantTerm);
const int bufsize = 4096;
unsigned char buffer[bufsize];
int readBytes;
do {
readBytes = fread(buffer, 1, bufsize, inF);
fwrite(buffer, 1, readBytes, outF);
} while(!feof(inF));
fclose(inF);
fclose(outF);
#else
GRBModel tmpModel(model);
moveConstantTermIntoConstrainedVariable(tmpModel);
tmpModel.update();
tmpModel.write(problem_output_path_);
#endif
}
/**
* WARNING: Never call outputModelToMpsGz and importInitialSolutionIntoModel
* on the same model. Both try to move the constant term into a variable and
* consequently, the second attempt to do so will fail.
*/
void GurobiHelper::importInitialSolutionIntoModel(GRBModel &model, const std::string &solution_path_) {
boost::scoped_ptr<TempFileGuard> tempFileGuard;
{
QTemporaryFile tempFile("XXXXXX.mst");
tempFile.setAutoRemove(false);
tempFile.open();
// In order to minimize the likelihood of race conditions,
// we initialize tempFileGuard right here.
tempFileGuard.reset(new TempFileGuard(QFileInfo(tempFile).absoluteFilePath().toStdString()));
tempFile.close();
}
const std::string fileName = tempFileGuard->filePath().string();
copyFile(solution_path_.c_str(), fileName.c_str());
//moveConstantTermIntoConstrainedVariable(model);
const double constantTerm = model.getObjective().getLinExpr().getConstant();
model.addVar(constantTerm, constantTerm, 0, GRB_CONTINUOUS, "constant");
model.update();
model.read(fileName);
model.update();
}
void GurobiHelper::readSolutionVectorFromSOL(std::vector<double> &out_solution_, const std::string &fileName_) {
std::ifstream solFile(fileName_.c_str());
//if (!solFile.good())
// throw std::runtime_error("Unable to open file \"" + fileName + "\".");
static const boost::regex commentRe("\\s*#", boost::regex_constants::perl);
static const boost::regex variableRe("\\s*\\S+\\s+([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)", boost::regex_constants::perl);
std::string line;
while (solFile) {
std::getline(solFile, line);
if (boost::regex_search(line, commentRe, boost::match_continuous)) continue;
boost::smatch match;
if (boost::regex_search(line, match, variableRe, boost::match_continuous)) {
out_solution_.push_back(boost::lexical_cast<double>(match[1]));
}
}
}
} /* namespace COMISO */
#endif
/*
* GurobiHelper.hh
*
* Created on: Jan 4, 2012
* Author: ebke
*/
#ifndef GUROBIHELPER_HH_
#define GUROBIHELPER_HH_
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_GUROBI_AVAILABLE
//=============================================================================
#include <gurobi_c++.h>
#include <string>
#include <vector>
namespace COMISO {
class GurobiHelper {
public:
/**
* WARNING: Never call outputModelToMpsGz and importInitialSolutionIntoModel
* on the same model. Both try to move the constant term into a variable and
* consequently, the second attempt to do so will fail.
*/
static void outputModelToMpsGz(GRBModel &model, const std::string &problem_output_path_);
/**
* WARNING: Never call outputModelToMpsGz and importInitialSolutionIntoModel
* on the same model. Both try to move the constant term into a variable and
* consequently, the second attempt to do so will fail.
*/
static void importInitialSolutionIntoModel(GRBModel &model, const std::string &solution_path_);
/**
* Reads the solution vector from a SOL file and appends it to
* out_solution_.
*/
static void readSolutionVectorFromSOL(std::vector<double> &out_solution_, const std::string &fileName_);
};
} /* namespace COMISO */
#endif /* COMISO_GUROBI_AVAILABLE */
#endif /* GUROBIHELPER_HH_ */
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