Skip to content

Commit bfa6139

Browse files
authored
Add Env(params::Dict) for setting parameters before GRBstartenv (#596)
1 parent 5a9b7d9 commit bfa6139

File tree

3 files changed

+94
-29
lines changed

3 files changed

+94
-29
lines changed

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,22 @@ end
285285
# Note the need for GRB_ENV_REF[] not GRB_ENV_REF
286286
create_optimizer() = Gurobi.Optimizer(GRB_ENV_REF[])
287287

288-
end
288+
end # MyModule
289+
```
290+
291+
## Pass parameters to an Environment
292+
293+
To set parameters in an environment before the environment is started, pass a
294+
`Dict{String,Any}` that maps parameter names to values:
295+
296+
```julia
297+
env = Gurobi.Env(
298+
Dict{String,Any}(
299+
"CSAppName" => "some name",
300+
"CSManager" => "some url",
301+
"CSPriority" => 10,
302+
),
303+
)
289304
```
290305

291306
## Accessing Gurobi-specific attributes
@@ -368,7 +383,7 @@ optimize!(model)
368383
See the [Gurobi documentation](https://www.gurobi.com/documentation/current/refman/cb_codes.html)
369384
for other information that can be queried with `GRBcbget`.
370385

371-
### Common Performance Pitfall with JuMP
386+
## Common Performance Pitfall with JuMP
372387

373388
Gurobi's API works differently than most solvers. Any changes to the model are
374389
not applied immediately, but instead go sit in a internal buffer (making any

src/MOI_wrapper/MOI_wrapper.jl

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,36 @@ mutable struct _NLConstraintInfo
102102
end
103103
end
104104

105+
"""
106+
Env(
107+
params::Dict{String,Any} = Dict{String,Any}();
108+
started::Bool = true,
109+
)
110+
111+
Create a new Gurobi environment object.
112+
113+
Optionally pass a `params` dictionary which sets parameters for the created
114+
environment before starting.
115+
116+
## kwargs
117+
118+
The extra keyword argument `started` delays starting the environment if set to
119+
`false`.
120+
121+
## Example
122+
123+
```julia
124+
using JuMP, Gurobi
125+
const GRB_ENV = Gurobi.Env(
126+
Dict(
127+
"ComputeServer" => "localhost:61000",
128+
"OutputFlag" => 0,
129+
);
130+
started = true,
131+
)
132+
model = Model(() -> Gurobi.Optimizer(GRB_ENV))
133+
```
134+
"""
105135
mutable struct Env
106136
ptr_env::Ptr{Cvoid}
107137
# These fields keep track of how many models the `Env` is used for to help
@@ -110,34 +140,41 @@ mutable struct Env
110140
finalize_called::Bool
111141
attached_models::Int
112142

113-
function Env(;
143+
function Env(
144+
params::Union{Nothing,Dict{String,Any}} = nothing;
145+
started::Bool = true,
146+
# These kwargs are provided for legacy backwards compatibility
114147
output_flag::Int = 1,
115148
memory_limit::Union{Nothing,Real} = nothing,
116-
started::Bool = true,
117149
)
118150
a = Ref{Ptr{Cvoid}}()
119151
ret = GRBemptyenv(a)
120152
env = new(a[], false, 0)
121153
_check_ret(env, ret)
122-
ret = GRBsetintparam(env.ptr_env, GRB_INT_PAR_OUTPUTFLAG, output_flag)
123-
_check_ret(env, ret)
124-
if _GUROBI_VERSION >= v"9.5.0" && memory_limit !== nothing
125-
ret = GRBsetdblparam(env, GRB_DBL_PAR_MEMLIMIT, memory_limit)
126-
_check_ret(env, ret)
127-
end
128-
if started
129-
ret = GRBstartenv(env.ptr_env)
130-
end
131154
finalizer(env) do e
132155
e.finalize_called = true
133156
if e.attached_models == 0
134157
# Only finalize the model if there are no models using it.
135158
GRBfreeenv(e.ptr_env)
136159
e.ptr_env = C_NULL
137160
end
161+
return
162+
end
163+
if params === nothing
164+
# These two parameters are provided for backwards compability
165+
_set_param(env.ptr_env, GRB_INT_PAR_OUTPUTFLAG, 1)
166+
if _GUROBI_VERSION >= v"9.5.0" && memory_limit !== nothing
167+
_set_param(env.ptr_env, GRB_DBL_PAR_MEMLIMIT, memory_limit)
168+
end
169+
else
170+
for (param_name, value) in params
171+
_set_param(env.ptr_env, param_name, value)
172+
end
173+
end
174+
if started
175+
ret = GRBstartenv(env.ptr_env)
176+
_check_ret(env, ret)
138177
end
139-
# Even if the loadenv fails, the pointer is still valid.
140-
_check_ret(env, ret)
141178
return env
142179
end
143180
end
@@ -170,22 +207,11 @@ function Env(
170207
server_password::Union{String,Nothing} = nothing;
171208
started::Bool = true,
172209
)
173-
env = Env(; started = false)
174-
ret = GRBsetstrparam(env.ptr_env, GRB_STR_PAR_COMPUTESERVER, server_address)
175-
_check_ret(env, ret)
210+
params = Dict{String,Any}(GRB_STR_PAR_COMPUTESERVER => server_address)
176211
if server_password !== nothing
177-
ret = GRBsetstrparam(
178-
env.ptr_env,
179-
GRB_STR_PAR_SERVERPASSWORD,
180-
server_password,
181-
)
182-
_check_ret(env, ret)
212+
params[GRB_STR_PAR_SERVERPASSWORD] = server_password
183213
end
184-
if started
185-
ret = GRBstartenv(env.ptr_env)
186-
_check_ret(env, ret)
187-
end
188-
return env
214+
return Env(params; started)
189215
end
190216

191217
Base.cconvert(::Type{Ptr{Cvoid}}, x::Env) = x
@@ -685,6 +711,11 @@ function MOI.set(model::Optimizer, raw::MOI.RawOptimizerAttribute, value)
685711
env = GRBgetenv(model)
686712
param = raw.name
687713
model.params[param] = value
714+
_set_param(env, param, value)
715+
return
716+
end
717+
718+
function _set_param(env, param::String, value)
688719
param_type = GRBgetparamtype(env, param)
689720
ret = if param_type == -1
690721
throw(MOI.UnsupportedAttribute(MOI.RawOptimizerAttribute(param)))

test/MOI/MOI_wrapper.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,25 @@ function test_multiple_solution_nonlinear_objective()
15081508
return
15091509
end
15101510

1511+
function test_Env()
1512+
function test_err(f)
1513+
try
1514+
f()
1515+
@assert false
1516+
catch err
1517+
@test occursin("Gurobi Error 10022:", err.msg)
1518+
end
1519+
end
1520+
test_err(() -> Gurobi.Env("localhost:1234"))
1521+
test_err(() -> Gurobi.Env("localhost:1234", "password"))
1522+
test_err(() -> Gurobi.Env("localhost:1234", "password"; started = true))
1523+
env = Gurobi.Env(; output_flag = 2, memory_limit = 1)
1524+
p = Ref{Cdouble}()
1525+
@test GRBgetdblparam(env, "MemLimit", p) == 0
1526+
@test p[] == 1.0
1527+
return
1528+
end
1529+
15111530
end # TestMOIWrapper
15121531

15131532
TestMOIWrapper.runtests()

0 commit comments

Comments
 (0)