bbopt / NOMAD.jl

Julia interface to the NOMAD blackbox optimization software
Other
47 stars 6 forks source link

Can't easily modify the nomad options from the NomadProblem constructor #49

Closed MonssafToukal closed 2 years ago

MonssafToukal commented 2 years ago

I was fiddling with NomadProblem to try to set the max_time attribute of the NomadOption object to a certain value. It seems there is no easy way to do so. I tried to do it this way:

using NOMAD

parameters = [1.0, 2.0]

bb_output(parameters::AbstractVector{Float64}) = 0

function obj(v::AbstractVector{Float64})
    return true, true, bb_output(v)
end

nomad = NomadProblem(
               length(parameters),
               1,
               ["OBJ"],
               obj;
               input_types = ["R", "R"],
               granularity = [0.0, 0.0],
               lower_bound = [0.0, 0.0],
               upper_bound = [10.0, 10.0],
           )

options = NOMAD.NomadOptions(display_all_eval=true, display_infeasible=true, display_unsuccessful=true)

# This line fails because NomadProblem is an immutable struct
nomad.options = options

but NomadProblem is immutable. Is there a way to allow the user to specify some options? For example, we could change the inner constructor of NomadProblem to allow the user to pass the options he wants to change.

salomonl commented 2 years ago

Hey @MonssafToukal. NomadProblem is indeed immutable, because it is simple for us to check that all parameters given to Nomad are valid (and prevent a segmentation fault in the c++ code). If you want to modify an option parameter, you can just do the following:

using NOMAD

parameters = [1.0, 2.0]
max_time=1 # a max time for a second.

bb_output(parameters::AbstractVector{Float64}) = begin
    sleep(0.1) # force it to slow, otherwise under 1 second to end.
    0
end
function obj(v::AbstractVector{Float64})
    return true, true, bb_output(v)
end

nomad = NomadProblem(
               length(parameters),
               1,
               ["OBJ"],
               obj;
               input_types = ["R", "R"],
               granularity = [0.0, 0.0],
               lower_bound = [0.0, 0.0],
               upper_bound = [10.0, 10.0])

# your parameters.
nomad.options.display_all_eval=true
nomad.options.display_infeasible=true
nomad.options.max_time=max_time

solve(nomad, [2.0, 2.0])

On my machine, I get

BBE OBJ
1   0        *
2   0       
3   0       
4   0       
5   0       
A termination criterion is reached: Maximum allowed time reached (Base) No more points to evaluate

Best feasible solution:     #1 (   2          2        )        Evaluation OK    f = 0   h = 0

Best infeasible solution:   Undefined.

Blackbox evaluations: 5
MonssafToukal commented 2 years ago

Thank you for the quick reply! You can definitely modify the attributes of NomadOptions directly. Maybe we could pass arguments like so in the NomadProblem constructor:

function NomadProblem(nb_inputs::Int,
                          nb_outputs::Int,
                          output_types::Vector{String},
                          eval_bb::Function;
                          input_types::Vector{String} = ["R" for i in 1:nb_inputs],
                          granularity::Vector{Float64} = zeros(Float64, nb_inputs),
                          lower_bound::Vector{Float64} = -Inf * ones(Float64, nb_inputs),
                          upper_bound::Vector{Float64} = Inf * ones(Float64, nb_inputs),
                          A::Union{Nothing, Matrix{Float64}} = nothing,
                          b::Union{Nothing, Vector{Float64}} = nothing,
                          min_mesh_size::Vector{Float64} = zeros(Float64, nb_inputs),
                          initial_mesh_size::Vector{Float64} = Float64[],
                          kwargs...)
...
...
return new(nb_inputs, nb_outputs, input_types,
                   granularity, min_mesh_size, initial_mesh_size,
                   lower_bound, upper_bound,
                   output_types, A, b, eval_bb, NomadOptions(;kwargs...))

That way, we could also pass arguments like this: nomad = NomadProblem(length(parameters), 1, ["OBJ"];display_all_eval=true). Do you think that could work?

MonssafToukal commented 2 years ago

This is just an idea. I am just wondering if that could be easier for the user to set the options in the NomadProblem constructor. You did mention that it is currently implemented like that to prevent seg faults so I don't know if that can have an impact.

salomonl commented 2 years ago

We will think about that. I do not really like the kwargs argument, as it is not enough restrictive for us to prevent an user to enter wrong arguments. Otherwise, when you create a NomadProblem, the options are put by default. As I suppose you will not try to change all of them, you can just fix the ones that are indicated in the documentation via nomad.options.your_option=your_choice.

MonssafToukal commented 2 years ago

Ok! Thanks for the clarification and your quick responses.