Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pool and parallel computing issues #132

Merged
merged 3 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "LocalSearchSolvers"
uuid = "2b10edaa-728d-4283-ac71-07e312d6ccf3"
authors = ["Jean-Francois Baffier"]
version = "0.4.7"
version = "0.4.8"

[deps]
CompositionalNetworks = "4b67e4b5-442d-4ef5-b760-3f5df3a57537"
Expand Down
1 change: 0 additions & 1 deletion src/configuration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ get_values(c) = c.values
get_value(c, x) = get_values(c)[x]

set_value!(c, val) = c.value = val
# set_value!(c, x, val) = get_values(c)[x] = val
set_values!(c, values) = c.values = values
set_sat!(c, b) = c.solution = b

Expand Down
6 changes: 2 additions & 4 deletions src/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,11 @@ Add `x` to the constraint `c` list of restricted variables.
"""
add_var_to_cons!(m::_Model, c, x) = _add!(get_constraint(m, c), x)

""" mts = - get_time_stamp(model)
return TimeStamps(mts, mts, mts, mts, mts, mts, mts)
end

"""
add!(m::M, x) where M <: Union{Model, AbstractSolver}
add!(m::M, c) where M <: Union{Model, AbstractSolver}
add!(m::M, o) where M <: Union{Model, AbstractSolver}

Add a variable `x`, a constraint `c`, or an objective `o` to `m`.
"""
function add!(m::_Model, x::Variable)
Expand Down
38 changes: 25 additions & 13 deletions src/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@ const print_levels = Dict(
:verbose => 3
)

# # Tabu times
# get!(s, :tabu_time, length_vars(s) ÷ 2) # 10?
# get!(s, :local_tabu, setting(s, :tabu_time) ÷ 2)
# get!(s, :δ_tabu, setting(s, :tabu_time) - setting(s, :local_tabu))# 20-30

"""
Options()
# Arguments:
Expand All @@ -36,28 +31,28 @@ set_time_limit_sec(model, 5.0)
mutable struct Options
dynamic::Bool
info_path::String
iteration::Union{Int, Float64}
iteration::Tuple{Bool, Union{Int, Float64}}
print_level::Symbol
process_threads_map::Dict{Int, Int}
solutions::Int
specialize::Bool
tabu_time::Int
tabu_local::Int
tabu_delta::Float64
time_limit::Float64 # seconds
time_limit::Tuple{Bool, Float64} # seconds

function Options(;
dynamic = false,
info_path = "",
iteration = 10000,
iteration = (false, 100),
print_level = :minimal,
process_threads_map = Dict{Int, Int}(1 => typemax(0)),
solutions = 1,
specialize = !dynamic,
tabu_time = 0,
tabu_local = 0,
tabu_delta = 0.0,
time_limit = 60 # seconds
time_limit = (false, 1.0) # seconds
)
ds_str = "The model types are specialized to the starting domains, constraints," *
" and objectives types. Dynamic elements that add a new type will raise an error!"
Expand All @@ -69,20 +64,33 @@ mutable struct Options

itertime_str = "Both iteration and time limits are disabled. " *
"Optimization runs will run infinitely."
iteration == Inf && time_limit == Inf && @warn itertime_str

new_iteration = if iteration isa Tuple{Bool, Union{Int, Float64}}
iteration
else
iteration = (false, iteration)
end

new_time_limit = if time_limit isa Tuple{Bool, Float64}
time_limit
else
time_limit = (false, time_limit)
end

new_iteration[2] == Inf && new_time_limit[2] == Inf && @warn itertime_str

new(
dynamic,
info_path,
iteration,
new_iteration,
print_level,
process_threads_map,
solutions,
specialize,
tabu_time,
tabu_local,
tabu_delta,
time_limit
new_time_limit
)
end
end
Expand Down Expand Up @@ -137,6 +145,9 @@ _iteration(options) = options.iteration
DOCSTRING
"""
_iteration!(options, iterations) = options.iteration = iterations
function _iteration!(options, iterations::Union{Int, Float64})
options.iteration = (false, iterations)
end

"""
_print_level(options) = begin
Expand Down Expand Up @@ -266,7 +277,8 @@ _time_limit(options) = options.time_limit

DOCSTRING
"""
_time_limit!(options, time) = options.time_limit = time
_time_limit!(options, time::Tuple{Bool, Float64}) = options.time_limit = time
_time_limit!(options, time::Float64) = options.time_limit = (false, time)

function set_option!(options, name, value)
eval(Symbol("_" * name * "!"))(options, value)
Expand Down
4 changes: 4 additions & 0 deletions src/pool.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ function pool(config::Configuration)
value = get_value(config)
return _Pool(best, configs, status, value)
end
function pool!(s)
has_solution(s) || _draw!(s)
s.pool = pool(s.state.configuration)
end

is_empty(::EmptyPool) = true
is_empty(pool) = isempty(pool.configurations)
Expand Down
3 changes: 2 additions & 1 deletion src/solver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,14 @@ function _init!(s, ::Val{:remote})
end
end

function _init!(s, ::Val{:local}; pool = pool())
function _init!(s, ::Val{:local})
get_option(s, "tabu_time") == 0 && set_option!(s, "tabu_time", length_vars(s) ÷ 2) # 10?
get_option(s, "tabu_local") == 0 &&
set_option!(s, "tabu_local", get_option(s, "tabu_time") ÷ 2)
get_option(s, "tabu_delta") == 0 && set_option!(
s, "tabu_delta", get_option(s, "tabu_time") - get_option(s, "tabu_local")) # 20-30
state!(s)
pool!(s)
return has_solution(s)
end

Expand Down
14 changes: 3 additions & 11 deletions src/solvers/lead.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ end
function solver(
mlid, model, options, pool, rc_report, rc_sol, rc_stop, strats, ::Val{:lead})
l_options = deepcopy(options)
set_option!(options, "print_level", :silent)
set_option!(l_options, "print_level", :silent)
ss = Vector{_SubSolver}()
return LeadSolver(
mlid, model, l_options, pool, rc_report, rc_sol, rc_stop, state(), strats, ss)
Expand All @@ -33,14 +33,6 @@ stop_while_loop(s::LeadSolver, ::Atomic{Bool}, ::Int, ::Float64) = isready(s.rc_

function remote_stop!(s::LeadSolver)
isready(s.rc_stop) && take!(s.rc_stop)
sat = is_sat(s)
if !sat || !has_solution(s)
while isready(s.rc_report)
wait(s.rc_sol)
t = take!(s.rc_sol)
update_pool!(s, t)
sat && has_solution(t) && break
take!(s.rc_report)
end
end
put!(s.rc_sol, s.pool)
take!(s.rc_report)
end
40 changes: 34 additions & 6 deletions src/solvers/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,26 @@ function _init!(s::MainSolver)
end

function stop_while_loop(s::MainSolver, ::Atomic{Bool}, iter, start_time)
remote_limit = isready(s.rc_stop) # Add ! when MainSolver is passive
iter_limit = iter < get_option(s, "iteration")
time_limit = time() - start_time < get_option(s, "time_limit")
if !remote_limit
@debug "debug stop" iter (time()-start_time)
if !isready(s.rc_stop)
s.status = :solution_limit
return false
end
if !iter_limit

iter_sat = get_option(s, "iteration")[1] && has_solution(s)
iter_limit = iter > get_option(s, "iteration")[2]
if (iter_sat && iter_limit) || iter_limit
s.status = :iteration_limit
return false
end
if !time_limit

time_sat = get_option(s, "time_limit")[1] && has_solution(s)
time_limit = time() - start_time > get_option(s, "time_limit")[2]
if (time_sat && time_limit) || time_limit
s.status = :time_limit
return false
end

return true
end

Expand All @@ -111,3 +116,26 @@ function post_process(s::MainSolver)
write(path, JSON.json(info))
end
end

function remote_stop!(s::MainSolver)
isready(s.rc_stop) && take!(s.rc_stop)
sat = is_sat(s)
@info "Remote stop: report main pool" best_values(s.pool) has_solution(s) s.rc_report s.rc_sol s.rc_stop length(s.remotes)
if !sat || !has_solution(s)
@warn "debugging remote stop" nworkers() length(s.remotes)
while isready(s.rc_report) || isready(s.rc_sol)
wait(s.rc_sol)
t = take!(s.rc_sol)
@info "Remote stop: report remote pool" best_values(t) length(s.remotes)
update_pool!(s, t)
if sat && has_solution(t)
empty!(s.rc_report)
break
end
@info "mark 1"
isready(s.rc_report) && take!(s.rc_report)
@info "mark 2"
end
end
@info "Remote stop: report best pool" best_values(s.pool) length(s.remotes)
end
2 changes: 1 addition & 1 deletion src/solvers/sub.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ end
function solver(mlid, model, options, pool, ::RemoteChannel,
::RemoteChannel, ::RemoteChannel, strats, ::Val{:sub})
sub_options = deepcopy(options)
set_option!(options, "print_level", :silent)
set_option!(sub_options, "print_level", :silent)
return _SubSolver(mlid, model, sub_options, pool, state(), strats)
end

Expand Down
Loading