forked from pz4kybsvg/Conception
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
8.8 KiB
209 lines
8.8 KiB
#pragma once
|
|
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "drake/common/autodiff.h"
|
|
#include "drake/common/drake_copyable.h"
|
|
#include "drake/solvers/decision_variable.h"
|
|
#include "drake/solvers/solver_base.h"
|
|
|
|
namespace drake {
|
|
namespace solvers {
|
|
|
|
/// The Gurobi solver details after calling Solve() function. The user can call
|
|
/// MathematicalProgramResult::get_solver_details<GurobiSolver>() to obtain the
|
|
/// details.
|
|
struct GurobiSolverDetails {
|
|
/// The gurobi optimization time. Please refer to
|
|
/// https://www.gurobi.com/documentation/9.5/refman/runtime.html
|
|
double optimizer_time{};
|
|
|
|
/// The error message returned from Gurobi call. Please refer to
|
|
/// https://www.gurobi.com/documentation/9.5/refman/error_codes.html
|
|
int error_code{};
|
|
|
|
/// The status code when the optimize call has returned. Please refer to
|
|
/// https://www.gurobi.com/documentation/9.5/refman/optimization_status_codes.html
|
|
int optimization_status{};
|
|
|
|
/// The best known bound on the optimal objective. This is used in mixed
|
|
/// integer optimization. Please refer to
|
|
/// https://www.gurobi.com/documentation/9.5/refman/objbound.html
|
|
double objective_bound{NAN};
|
|
};
|
|
|
|
/// An implementation of SolverInterface for the commercially-licensed Gurobi
|
|
/// solver (https://www.gurobi.com/).
|
|
///
|
|
/// The default build of Drake is not configured to use Gurobi, so therefore
|
|
/// SolverInterface::available() will return false. You must compile Drake
|
|
/// from source in order to link against Gurobi. For details, refer to the
|
|
/// documentation at https://drake.mit.edu/bazel.html#proprietary-solvers.
|
|
///
|
|
/// The GRB_LICENSE_FILE environment variable controls whether or not
|
|
/// SolverInterface::enabled() returns true. If it is set to any non-empty
|
|
/// value, then the solver is enabled; otherwise, the solver is not enabled.
|
|
///
|
|
/// Gurobi solver supports options/parameters listed in
|
|
/// https://www.gurobi.com/documentation/9.1/refman/parameters.html. On top of
|
|
/// these options, we provide the following additional options
|
|
/// 1. "GRBwrite", set to a file name so that Gurobi solver will write the
|
|
/// optimization model to this file, check
|
|
/// https://www.gurobi.com/documentation/9.1/refman/py_model_write.html for
|
|
/// more details, such as all supported file extensions. Set this option to
|
|
/// "" if you don't want to write to file. Default is not to write to a file.
|
|
/// 2. "GRBcomputeIIS", set to 1 to compute an Irreducible Inconsistent
|
|
/// Subsystem (IIS) when the problem is infeasible. Refer to
|
|
/// https://www.gurobi.com/documentation/9.1/refman/py_model_computeiis.html
|
|
/// for more details. Often this method is called together with
|
|
/// setting GRBwrite to "FILENAME.ilp" to write IIS to a file with extension
|
|
/// "ilp". Default is not to compute IIS.
|
|
///
|
|
/// If the "Threads" integer solver option has not been set by the user, then
|
|
/// %GurobiSolver uses environment variable GUROBI_NUM_THREADS (if set) as a
|
|
/// default value for "Threads".
|
|
class GurobiSolver final : public SolverBase {
|
|
public:
|
|
DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN(GurobiSolver)
|
|
|
|
/// Type of details stored in MathematicalProgramResult.
|
|
using Details = GurobiSolverDetails;
|
|
|
|
GurobiSolver();
|
|
~GurobiSolver() final;
|
|
|
|
/// Contains info returned to a user function that handles
|
|
/// a Node or Solution callback.
|
|
/// @see MipNodeCallbackFunction
|
|
/// @see MipSolCallbackFunction
|
|
struct SolveStatusInfo {
|
|
/// Runtime as of this callback.
|
|
double reported_runtime{};
|
|
/// Objective of current solution.
|
|
double current_objective{};
|
|
/// Objective of best solution yet.
|
|
double best_objective{};
|
|
/// Best known objective lower bound.
|
|
double best_bound{};
|
|
/// Number of nodes explored so far.
|
|
int explored_node_count{};
|
|
/// Number of feasible sols found so far.
|
|
int feasible_solutions_count{};
|
|
};
|
|
|
|
/// Users can supply a callback to be called when the Gurobi solver
|
|
/// finds an intermediate solution node, which may not be feasible.
|
|
/// See Gurobi reference manual for more detail on callbacks:
|
|
/// https://www.gurobi.com/documentation/9.5/refman/callback_codes.html.
|
|
/// The user may supply a partial solution in the VectorXd and
|
|
/// VectorXDecisionVariable arguments that will be passed to Gurobi
|
|
/// as a candidate feasible solution.
|
|
/// See gurobi_solver_test.cc for an example of using std::bind
|
|
/// to create a callback of this signature, while allowing
|
|
/// additional data to be passed through.
|
|
/// @param MathematicalProgram& The optimization wrapper, whose
|
|
/// current variable values (accessible via
|
|
/// MathematicalProgram::GetSolution) will be set to the intermediate
|
|
/// solution values.
|
|
/// @param SolveStatusInfo& Intermediate solution status information values
|
|
/// queried from Gurobi.
|
|
/// @param VectorXd* User may assign this to be the values of the variable
|
|
/// assignments.
|
|
/// @param VectorXDecisionVariable* User may assign this to be the decision
|
|
/// variables being assigned. Must have the same number of elements as
|
|
/// the VectorXd assignment.
|
|
typedef std::function<void(const MathematicalProgram&,
|
|
const SolveStatusInfo& callback_info,
|
|
Eigen::VectorXd*, VectorXDecisionVariable*)>
|
|
MipNodeCallbackFunction;
|
|
|
|
/// Registers a callback to be called at intermediate solutions
|
|
/// during the solve.
|
|
/// @param callback User callback function.
|
|
/// @param user_data Arbitrary data that will be passed to the user
|
|
/// callback function.
|
|
void AddMipNodeCallback(const MipNodeCallbackFunction& callback) {
|
|
mip_node_callback_ = callback;
|
|
}
|
|
|
|
/// Users can supply a callback to be called when the Gurobi solver
|
|
/// finds a feasible solution.
|
|
/// See Gurobi reference manual for more detail on callbacks:
|
|
/// https://www.gurobi.com/documentation/9.5/refman/callback_codes.html.
|
|
/// See gurobi_solver_test.cc for an example of using std::bind
|
|
/// to create a callback of this signature, while allowing
|
|
/// additional data to be passed through.
|
|
/// @param MathematicalProgram& The optimization wrapper, whose
|
|
/// current variable values (accessible via
|
|
/// MathematicalProgram::GetSolution) will be set to the intermediate
|
|
/// solution values.
|
|
/// @param SolveStatusInfo& Intermediate solution status information values
|
|
/// queried from Gurobi.
|
|
/// @param void* Arbitrary data supplied during callback registration.
|
|
typedef std::function<void(const MathematicalProgram&,
|
|
const SolveStatusInfo& callback_info)>
|
|
MipSolCallbackFunction;
|
|
|
|
/// Registers a callback to be called at feasible solutions
|
|
/// during the solve.
|
|
/// @param callback User callback function.
|
|
/// @param usrdata Arbitrary data that will be passed to the user
|
|
/// callback function.
|
|
void AddMipSolCallback(const MipSolCallbackFunction& callback) {
|
|
mip_sol_callback_ = callback;
|
|
}
|
|
|
|
/**
|
|
* This type contains a valid Gurobi license environment, and is only to be
|
|
* used from AcquireLicense().
|
|
*/
|
|
class License;
|
|
|
|
/**
|
|
* This acquires a Gurobi license environment shared among all GurobiSolver
|
|
* instances; the environment will stay valid as long as at least one
|
|
* shared_ptr returned by this function is alive.
|
|
* Call this ONLY if you must use different MathematicalProgram
|
|
* instances at different instances in time, and repeatedly acquiring the
|
|
* license is costly (e.g., requires contacting a license server).
|
|
* @return A shared pointer to a license environment that will stay valid
|
|
* as long as any shared_ptr returned by this function is alive. If Gurobi
|
|
* not available in your build, this will return a null (empty) shared_ptr.
|
|
* @throws std::exception if Gurobi is available but a license cannot be
|
|
* obtained.
|
|
*/
|
|
static std::shared_ptr<License> AcquireLicense();
|
|
|
|
/// @name Static versions of the instance methods with similar names.
|
|
//@{
|
|
static SolverId id();
|
|
static bool is_available();
|
|
/// Returns true iff the environment variable GRB_LICENSE_FILE has been set
|
|
/// to a non-empty value.
|
|
static bool is_enabled();
|
|
static bool ProgramAttributesSatisfied(const MathematicalProgram&);
|
|
static std::string UnsatisfiedProgramAttributes(const MathematicalProgram&);
|
|
//@}
|
|
|
|
// A using-declaration adds these methods into our class's Doxygen.
|
|
using SolverBase::Solve;
|
|
|
|
private:
|
|
void DoSolve(const MathematicalProgram&, const Eigen::VectorXd&,
|
|
const SolverOptions&, MathematicalProgramResult*) const final;
|
|
|
|
// Note that this is mutable to allow latching the allocation of env_
|
|
// during the first call of Solve() (which avoids grabbing a Gurobi license
|
|
// before we know that we actually want one).
|
|
mutable std::shared_ptr<License> license_;
|
|
// Callbacks and generic user data to pass through,
|
|
// or NULL if no callback has been supplied.
|
|
MipNodeCallbackFunction mip_node_callback_;
|
|
MipSolCallbackFunction mip_sol_callback_;
|
|
};
|
|
|
|
} // end namespace solvers
|
|
} // end namespace drake
|