Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A Julia interface to the Gurobi Optimizer

License

NotificationsYou must be signed in to change notification settings

jump-dev/Gurobi.jl

Repository files navigation

Build Statuscodecov

Gurobi.jl is a wrapper for theGurobi Optimizer.

It has two components:

Affiliation

This wrapper is maintained by the JuMP community with help from Gurobi.

Getting help

If you are a commercial customer, please contact Gurobi directly through theGurobi Help Center.

Otherwise, you should ask a question on theJuMP community forum.with thegurobi tag, or post inGurobi’sCommunity Forum

If you have a reproducible example of a bug, pleaseopen a GitHub issue.

MPS files for support

To create an MPS file for Gurobi's support team, do:

using JuMP, Gurobimodel=Model(Gurobi.Optimizer)# ... construct model ...optimize!(model)GRBwrite(unsafe_backend(model),"model.mps")

License

Gurobi.jl is licensed under theMIT License.

The underlying solver is a closed-source commercial product for which you mustobtain a license.

Free Gurobi licenses are available foracademics and students.

Installation

Install Gurobi.jl as follows:

import PkgPkg.add("Gurobi")

In addition to installing the Gurobi.jl package, this will also download andinstall the Gurobi binaries fromGurobi_jll.jl.You do not need to install the Gurobi binaries separately.

To install a particular version of Gurobi, install the corresponding version ofGurobi_jll.jl. For example:

import Pkg; Pkg.pkg"add Gurobi_jll@11.0.3"

Install a license

To use Gurobi, you need a license, which you can obtain fromgurobi.com.

Once you have a license, follow Gurobi's instructions toretrieve and set up a Gurobi license.

The instructions depend on the type of license that you have obtained.

WLS

If you are using the Web License Service (WLS), place the license file inyour home directory.

grbgetkey

If Gurobi's instructions call forgrbgetkey, do:

import PkgPkg.add("Gurobi_jll")import Gurobi_jll# Replace the contents xxxxx with your actual keykey="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"run(`$(Gurobi_jll.grbgetkey())$key`)

You do not need to run this code if you are using the Web License Service.

Custom binary installation

To opt-out of using theGurobi_jll binaries, set theGUROBI_HOME environmentvariable to point to your local installation and set theGUROBI_JL_USE_GUROBI_JLL environment variable to"false", then runPkg.add andPkg.build:

# On Windows, this might beENV["GUROBI_HOME"]="C:\\Program Files\\gurobi1100\\win64"# ... or perhaps ...ENV["GUROBI_HOME"]="C:\\gurobi1100\\win64"# On Mac, this might beENV["GUROBI_HOME"]="/Library/gurobi1100/macos_universal2"# Opt-out of using Gurobi_jllENV["GUROBI_JL_USE_GUROBI_JLL"]="false"import PkgPkg.add("Gurobi")Pkg.build("Gurobi")

To change the location of a custom install, change the value ofGUROBI_HOME,re-runPkg.build("Gurobi"), and then re-start Julia for the change to takeeffect.

Gurobi Error 10009: Version number is XX.X, license is for version XX.X

This error occurs when Gurobi cannot find a valid license for the version thatis running.

If you intended to install and use an older version of Gurobi, but it reportsthat theVersion number is a newer version, this means that your custominstallation did not work and we have automatically installed the latestversion. Double check the "Custom binary installation" instructions above.

Use with JuMP

To use Gurobi with JuMP, useGurobi.Optimizer:

using JuMP, Gurobimodel=Model(Gurobi.Optimizer)set_attribute(model,"TimeLimit",100)set_attribute(model,"Presolve",0)

MathOptInterface API

The Gurobi optimizer supports the following constraints and attributes.

List of supported objective functions:

List of supported variable types:

List of supported constraint types:

List of supported model attributes:

Options

See theGurobi Documentationfor a list and description of allowable parameters.

C API

The C API can be accessed viaGurobi.GRBxx functions, where the names andarguments are identical to the C API.

See theGurobi documentationfor details.

As general rules when converting from Julia to C:

  • When Gurobi requires the column index of a variablex, useGurobi.c_column(model, x)
  • When Gurobi requires aPtr{T} that holds one element, likedouble *,use aRef{T}().
  • When Gurobi requires aPtr{T} that holds multiple elements, useaVector{T}.
  • When Gurobi requires adouble, useCdouble
  • When Gurobi requires anint, useCint
  • When Gurobi requires aNULL, useC_NULL

For example:

julia>import MathOptInterface as MOIjulia>using Gurobijulia> model= Gurobi.Optimizer();julia> x= MOI.add_variable(model)MOI.VariableIndex(1)julia> x_col= Gurobi.c_column(model, x)0julia>GRBupdatemodel(model)0julia> pValue=Ref{Cdouble}(NaN)Base.RefValue{Float64}(NaN)julia>GRBgetdblattrelement(model,"LB", x_col, pValue)0julia> pValue[]-1.0e100julia>GRBsetdblattrelement(model,"LB", x_col,1.5)0julia>GRBupdatemodel(model)0julia>GRBgetdblattrelement(model,"LB", x_col, pValue)0julia> pValue[]1.5

The C API from JuMP

You can call the C API from JuMP if you usedirect_model. This is most usefulfor addingGRBaddgenXXX constraints. Here are some examples:

using JuMP, Gurobicolumn(x::VariableRef)= Gurobi.c_column(backend(owner_model(x)),index(x))model=direct_model(Gurobi.Optimizer())@variable(model, x)@variable(model, y)p= [3.0,0.0,0.0,7.0,3.0]GRBaddgenconstrPoly(backend(model),C_NULL,column(x),column(y),5, p,"")optimize!(model)
using JuMP, Gurobicolumn(x::VariableRef)= Gurobi.c_column(backend(owner_model(x)),index(x))model=direct_model(Gurobi.Optimizer())@variable(model, x[iin1:2])@variable(model, y[1:2])GRBaddgenconstrPow(backend(model),"x1^0.7",column(x[1]),column(y[1]),0.7,"")GRBaddgenconstrPow(backend(model),"x2^3",column(x[2]),column(y[2]),3.0,"")@objective(model, Min, y[1]+ y[2])optimize!(model)

Reusing the same Gurobi environment for multiple solves

The default behavior ofGurobi.Optimizer() is to create a new Gurobienvironment (and license token) for each model.

If you are using Gurobi in a setting where the number of concurrent Gurobilicenses is limited you might instead prefer to obtain a single license tokenthat is shared by all models that your program solves.

You can do this by passing aGurobi.Env() object as the first parameter toGurobi.Optimizer. For example:

using JuMP, Gurobiconst GRB_ENV= Gurobi.Env()model_1=Model(()-> Gurobi.Optimizer(GRB_ENV))# The solvers can have different options toomodel_2=direct_model(Gurobi.Optimizer(GRB_ENV))set_attribute(model_2,"OutputFlag",0)

Environments are not thread-safe

Gurobi.Env are NOT thread-safe. If two models both use the same environmentyou must not solve them simultaneously on different threads.

Environments inside a module

If you create a module with aGurobi.Env as a module-level constant, use an__init__ function to ensure that a new environment is created each time themodule is loaded:

module MyModuleimport Gurobiconst GRB_ENV_REF=Ref{Gurobi.Env}()function__init__()global GRB_ENV_REF    GRB_ENV_REF[]= Gurobi.Env()returnend# Note the need for GRB_ENV_REF[] not GRB_ENV_REFcreate_optimizer()= Gurobi.Optimizer(GRB_ENV_REF[])end# MyModule

Pass parameters to an Environment

To set parameters in an environment before the environment is started, pass aDict{String,Any} that maps parameter names to values:

env= Gurobi.Env(Dict{String,Any}("CSAppName"=>"some name","CSManager"=>"some url","CSPriority"=>10,    ),)

Accessing Gurobi-specific attributes

Get and set Gurobi-specific variable, constraint, and model attributes asfollows:

using JuMP, Gurobimodel=direct_model(Gurobi.Optimizer())@variable(model, x>=0)@constraint(model, c,2x>=1)@objective(model, Min, x)grb=backend(model)MOI.set(grb, Gurobi.ConstraintAttribute("Lazy"),index(c),2)optimize!(model)MOI.get(grb, Gurobi.VariableAttribute("LB"),index(x))# Returns 0.0MOI.get(grb, Gurobi.ModelAttribute("NumConstrs"))# Returns 1

A complete list of supported Gurobi attributes can be found intheir online documentation.

Callbacks

Here is an example using Gurobi's solver-specific callbacks.

using JuMP, Gurobi, Testmodel=direct_model(Gurobi.Optimizer())@variable(model,0<= x<=2.5, Int)@variable(model,0<= y<=2.5, Int)@objective(model, Max, y)cb_calls= Cint[]functionmy_callback_function(cb_data, cb_where::Cint)# You can reference variables outside the function as normalpush!(cb_calls, cb_where)# You can select where the callback is runif cb_where!= GRB_CB_MIPSOL&& cb_where!= GRB_CB_MIPNODEreturnend# You can query a callback attribute using GRBcbgetif cb_where== GRB_CB_MIPNODE        resultP=Ref{Cint}()GRBcbget(cb_data, cb_where, GRB_CB_MIPNODE_STATUS, resultP)if resultP[]!= GRB_OPTIMALreturn# Solution is something other than optimal.endend# Before querying `callback_value`, you must call:    Gurobi.load_callback_variable_primal(cb_data, cb_where)    x_val=callback_value(cb_data, x)    y_val=callback_value(cb_data, y)# You can submit solver-independent MathOptInterface attributes such as# lazy constraints, user-cuts, and heuristic solutions.if y_val- x_val>1+1e-6        con=@build_constraint(y- x<=1)        MOI.submit(model, MOI.LazyConstraint(cb_data), con)elseif y_val+ x_val>3+1e-6        con=@build_constraint(y+ x<=3)        MOI.submit(model, MOI.LazyConstraint(cb_data), con)endifrand()<0.1# You can terminate the callback as follows:GRBterminate(backend(model))endreturnend# You _must_ set this parameter if using lazy constraints.MOI.set(model, MOI.RawOptimizerAttribute("LazyConstraints"),1)MOI.set(model, Gurobi.CallbackFunction(), my_callback_function)optimize!(model)@testtermination_status(model)== MOI.OPTIMAL@testprimal_status(model)== MOI.FEASIBLE_POINT@testvalue(x)==1@testvalue(y)==2

See theGurobi documentationfor other information that can be queried withGRBcbget.

Common Performance Pitfall with JuMP

Gurobi's API works differently than most solvers. Any changes to the model arenot applied immediately, but instead go sit in a internal buffer (making anymodifications appear to be instantaneous) waiting for a call toGRBupdatemodel(where the work is done).

This leads to a common performance pitfall that has the following message as itsmain symptom:

Warning: excessive time spent in model updates. Consider calling update less frequently.

This often means the JuMP program was structured in such a way that Gurobi.jlends up callingGRBupdatemodel in each iteration of a loop.

Usually, it is possible (and easy) to restructure the JuMP program in a way itstays solver-agnostic and has a close-to-ideal performance with Gurobi.

To guide such restructuring it is good to keep in mind the following bits ofinformation:

  1. GRBupdatemodel is only called if changes were done since lastGRBupdatemodel (that is, if the internal buffer is not empty).
  2. GRBupdatemodel is called whenJuMP.optimize! is called, but this oftenis not the source of the problem.
  3. GRBupdatemodelmay be called whenany model attribute is queried,even if that specific attribute was not changed. This often the source ofthe problem.

The worst-case scenario is, therefore, a loop of modify-query-modify-query, evenif what is being modified and what is being queried are two completely distinctthings.

As an example, instead of:

model=Model(Gurobi.Optimizer)@variable(model, x[1:100]>=0)for iin1:100set_upper_bound(x[i], i)# `GRBupdatemodel` called on each iteration of this loop.println(lower_bound(x[i]))end

do

model=Model(Gurobi.Optimizer)@variable(model, x[1:100]>=0)# All modifications are done before any queries.for iin1:100set_upper_bound(x[i], i)endfor iin1:100# Only the first `lower_bound` query may trigger an `GRBupdatemodel`.println(lower_bound(x[i]))end

Common errors

Using Gurobi v9.0 and you got an error likeQ not PSD?

You need to set the NonConvex parameter:

model=Model(Gurobi.Optimizer)set_attribute(model,"NonConvex",2)

[8]ページ先頭

©2009-2025 Movatter.jp