Skip to content

Commit b89854f

Browse files
committed
fix tests
1 parent 33bc086 commit b89854f

File tree

9 files changed

+109
-99
lines changed

9 files changed

+109
-99
lines changed

src/FixedSizeShortestPath/FixedSizeShortestPath.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ function FixedSizeShortestPathBenchmark(;
5454
return FixedSizeShortestPathBenchmark(g, grid_size, p, deg, ν)
5555
end
5656

57+
function Utils.objective_value(
58+
::FixedSizeShortestPathBenchmark, θ::AbstractArray, y::AbstractArray
59+
)
60+
return -dot(θ, y)
61+
end
62+
5763
"""
5864
$TYPEDSIGNATURES
5965

src/StochasticVehicleScheduling/StochasticVehicleScheduling.jl

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,7 @@ using Graphs:
2626
inneighbors,
2727
outneighbors
2828
using JuMP:
29-
Model,
30-
@variable,
31-
@objective,
32-
@constraint,
33-
optimize!,
34-
value,
35-
objective_value,
36-
set_silent,
37-
dual
29+
JuMP, Model, @variable, @objective, @constraint, optimize!, value, set_silent, dual
3830
using Plots: Plots, plot, plot!, scatter!, annotate!, text
3931
using Printf: @printf
4032
using Random: Random, AbstractRNG, MersenneTwister
@@ -81,7 +73,7 @@ end
8173
$TYPEDSIGNATURES
8274
8375
Create a dataset of `dataset_size` instances for the given `StochasticVehicleSchedulingBenchmark`.
84-
If you want to also add label solutions in the dataset, set `compute_solutions=true`.
76+
If you want to not add label solutions in the dataset, set `compute_solutions=false`.
8577
By default, they will be computed using column generation.
8678
Note that computing solutions can be time-consuming, especially for large instances.
8779
You can also use instead `compact_mip` or `compact_linearized_mip` as the algorithm to compute solutions.
@@ -92,7 +84,7 @@ If `store_city=false`, the coordinates and unnecessary information about instanc
9284
function Utils.generate_dataset(
9385
benchmark::StochasticVehicleSchedulingBenchmark,
9486
dataset_size::Int;
95-
compute_solutions=false,
87+
compute_solutions=true,
9688
seed=nothing,
9789
rng=MersenneTwister(0),
9890
algorithm=column_generation_algorithm,
@@ -133,6 +125,9 @@ function Utils.generate_statistical_model(bench::StochasticVehicleSchedulingBenc
133125
return Chain(Dense(20 => 1; bias=false), vec)
134126
end
135127

128+
"""
129+
$TYPEDSIGNATURES
130+
"""
136131
function plot_instance(
137132
::StochasticVehicleSchedulingBenchmark,
138133
sample::DataSample{<:Instance{City}};
@@ -193,6 +188,9 @@ function plot_instance(
193188
return fig
194189
end
195190

191+
"""
192+
$TYPEDSIGNATURES
193+
"""
196194
function plot_solution(
197195
::StochasticVehicleSchedulingBenchmark, sample::DataSample{<:Instance{City}}; kwargs...
198196
)

src/StochasticVehicleScheduling/solution/algorithms/column_generation.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ function column_generation(
8787
)
8888
end
8989

90-
c_low = Float64(objective_value(model))
90+
c_low = JuMP.objective_value(model)
9191
columns = unique(cat(initial_paths, new_paths; dims=1))
92-
return columns, c_low, value.(λ)
92+
return columns, c_low::Float64, value.(λ)
9393
end
9494

9595
"""
@@ -140,7 +140,7 @@ function compute_solution_from_selected_columns(
140140
optimize!(model)
141141

142142
sol = value.(y)
143-
return Float64(objective_value(model)),
143+
return JuMP.objective_value(model)::Float64,
144144
sol,
145145
paths[isapprox.([sol[p] for p in paths], 1.0)]
146146
end

src/StochasticVehicleScheduling/solution/algorithms/local_search.jl

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function solve_deterministic_VSP(
4949

5050
solution = solution_from_JuMP_array(value.(x), graph)
5151

52-
return objective_value(model), solution
52+
return JuMP.objective_value(model), solution
5353
end
5454

5555
"""
@@ -74,7 +74,9 @@ function move_one_random_task!(path_value::BitMatrix, graph::AbstractGraph)
7474
if selected_task > 1
7575
before = @view path_value[i, 1:(selected_task - 1)]
7676
if any(before)
77-
precedent_task = selected_task - find_first_one(reverse(before))
77+
aaa = find_first_one(reverse(before))
78+
@assert aaa >= 0
79+
precedent_task = selected_task - aaa
7880
if !has_edge(graph, precedent_task + 1, selected_task + 1)
7981
continue
8082
end
@@ -88,9 +90,10 @@ function move_one_random_task!(path_value::BitMatrix, graph::AbstractGraph)
8890
if selected_task < nb_tasks
8991
after = @view path_value[i, (selected_task + 1):end]
9092
if any(after)
91-
next_task =
92-
selected_task +
93-
find_first_one(@view path_value[i, (selected_task + 1):end])
93+
bbb = find_first_one(@view path_value[i, (selected_task + 1):end])
94+
@assert bbb >= 0
95+
next_task = selected_task + bbb
96+
9497
if !has_edge(graph, selected_task + 1, next_task + 1)
9598
continue
9699
end
@@ -138,7 +141,6 @@ function _local_search(solution::Solution, instance::Instance; nb_it::Integer=10
138141
candidate_solution = copy(best_solution)
139142
end
140143
end
141-
142144
return Solution(best_solution, instance), best_value, history_x, history_y
143145
end
144146

src/StochasticVehicleScheduling/solution/solution.jl

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,32 @@ struct Solution
1515
path_value::BitMatrix # list of vehicles paths
1616
end
1717

18-
function get_nb_vehicles(path_value::BitMatrix)
19-
return sum(any(path_value; dims=2))
20-
end
21-
22-
function get_nb_vehicles(solution::Solution)
23-
return get_nb_vehicles(solution.path_value)
24-
end
25-
26-
"""
27-
$TYPEDSIGNATURES
28-
29-
Compute routes of solution.
30-
"""
31-
function get_routes(solution::Solution)
32-
res = Vector{Int}[]
33-
for vehicle in 1:get_nb_vehicles(solution)
34-
resv = Int[]
35-
for (index, value) in enumerate(solution.path_value[vehicle, :])
36-
if value
37-
push!(resv, index + 1)
38-
end
39-
end
40-
push!(res, resv)
41-
end
42-
return res
43-
end
18+
# function get_nb_vehicles(path_value::BitMatrix)
19+
# return sum(any(path_value; dims=2))
20+
# end
21+
22+
# function get_nb_vehicles(solution::Solution)
23+
# return get_nb_vehicles(solution.path_value)
24+
# end
25+
26+
# """
27+
# $TYPEDSIGNATURES
28+
29+
# Compute routes of solution.
30+
# """
31+
# function get_routes(solution::Solution)
32+
# res = Vector{Int}[]
33+
# for vehicle in 1:get_nb_vehicles(solution)
34+
# resv = Int[]
35+
# for (index, value) in enumerate(solution.path_value[vehicle, :])
36+
# if value
37+
# push!(resv, index + 1)
38+
# end
39+
# end
40+
# push!(res, resv)
41+
# end
42+
# return res
43+
# end
4444

4545
"""
4646
$TYPEDSIGNATURES
@@ -152,32 +152,32 @@ function path_solution_from_JuMP_array(x::AbstractArray, graph::AbstractGraph)
152152
return sol
153153
end
154154

155-
function basic_path_solution(graph::AbstractGraph)
156-
nb_tasks = nv(graph) - 2
157-
sol = falses(nb_tasks, nb_tasks)
158-
for i_task in 1:nb_tasks
159-
sol[i_task, i_task] = true
160-
end
161-
return sol
162-
end
163-
164-
"""
165-
$TYPEDSIGNATURES
166-
167-
Create a solution with one vehicle per task.
168-
"""
169-
function basic_solution(instance::Instance)
170-
graph = instance.graph
171-
value = falses(ne(graph))
172-
173-
for (a, edge) in enumerate(edges(graph))
174-
if edge.src == 1 || edge.dst == nv(graph)
175-
value[a] = true
176-
end
177-
end
178-
179-
return Solution(value, basic_path_solution(graph))
180-
end
155+
# function basic_path_solution(graph::AbstractGraph)
156+
# nb_tasks = nv(graph) - 2
157+
# sol = falses(nb_tasks, nb_tasks)
158+
# for i_task in 1:nb_tasks
159+
# sol[i_task, i_task] = true
160+
# end
161+
# return sol
162+
# end
163+
164+
# """
165+
# $TYPEDSIGNATURES
166+
167+
# Create a solution with one vehicle per task.
168+
# """
169+
# function basic_solution(instance::Instance)
170+
# graph = instance.graph
171+
# value = falses(ne(graph))
172+
173+
# for (a, edge) in enumerate(edges(graph))
174+
# if edge.src == 1 || edge.dst == nv(graph)
175+
# value[a] = true
176+
# end
177+
# end
178+
179+
# return Solution(value, basic_path_solution(graph))
180+
# end
181181

182182
"""
183183
$TYPEDSIGNATURES
@@ -290,7 +290,7 @@ function to_array(path_value::BitMatrix, instance::Instance)
290290
current_task = 1
291291
while true
292292
index_shift = find_first_one(@view path_value[i, current_task:end])
293-
if isnothing(index_shift)
293+
if index_shift === -1
294294
mat[current_task, nb_nodes] = true
295295
break
296296
end
@@ -323,7 +323,7 @@ $TYPEDSIGNATURES
323323
324324
Check if `solution` is an admissible solution of `instance`.
325325
"""
326-
function is_feasible(solution::Solution, instance::Instance)
326+
function is_feasible(solution::Solution, instance::Instance; verbose=true)
327327
graph = instance.graph
328328
nb_nodes = nv(graph)
329329
nb_tasks = nb_nodes - 2
@@ -339,14 +339,13 @@ function is_feasible(solution::Solution, instance::Instance)
339339
current_task = 1
340340
while true
341341
index_shift = find_first_one(@view solution.path_value[i, current_task:end])
342-
if isnothing(index_shift)
342+
if index_shift == -1
343343
mat[current_task, nb_nodes] = true
344344
break
345345
end
346346
next_task = current_task + index_shift
347347
if !has_edge(graph, current_task, next_task)
348-
@warn "Flow not respected" current_task next_task
349-
@warn "" outneighbors(graph, current_task)
348+
verbose && @warn "Flow not respected" current_task next_task
350349
return false
351350
end
352351
mat[current_task, next_task] = true
@@ -355,21 +354,15 @@ function is_feasible(solution::Solution, instance::Instance)
355354
end
356355

357356
if !all(sum(solution.path_value; dims=1) .== 1)
358-
@warn "One task done by more than one vehicle (or less than once)"
357+
verbose && @warn "One task done by more than one vehicle (or less than once)"
359358
return false
360359
end
361360

362361
for i in job_indices
363362
s1 = sum(mat[j, i] for j in inneighbors(graph, i))
364363
s2 = sum(mat[i, j] for j in outneighbors(graph, i))
365364
if s1 != s2 || s1 != 1
366-
@warn "Flow is broken" i s1 s2
367-
@warn "" inneighbors(graph, i)
368-
@warn "" [mat[j, i] for j in inneighbors(graph, i)]
369-
@warn "" outneighbors(graph, i)
370-
@warn "" [mat[i, j] for j in outneighbors(graph, i)]
371-
@warn "" mat
372-
@warn "" solution.path_value
365+
verbose && @warn "Flow is broken" i s1 s2
373366
return false
374367
end
375368
end
@@ -380,7 +373,7 @@ end
380373
function compute_path_list(solution::Solution)
381374
(; path_value) = solution
382375
paths = Vector{Int64}[]
383-
for v in 1:size(path_value, 1)
376+
for v in axes(path_value, 1)
384377
path = [1]
385378
for (i, elem) in enumerate(path_value[v, :])
386379
if elem == 1

src/StochasticVehicleScheduling/utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function find_first_one(A::AbstractVector)
4646
return i
4747
end
4848
end
49-
return nothing
49+
return -1
5050
end
5151

5252
# Config stuff, probably not needed in this package

src/Utils/interface.jl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,20 +122,31 @@ end
122122
"""
123123
$TYPEDSIGNATURES
124124
125+
Check if the benchmark is a minimization problem.
126+
"""
127+
function is_minimization_problem(::AbstractBenchmark)
128+
return true
129+
end
130+
131+
"""
132+
$TYPEDSIGNATURES
133+
125134
Default behaviour of `compute_gap` for a benchmark problem where `features`, `solutions` and `costs` are all defined.
126135
"""
127136
function compute_gap(
128137
bench::AbstractBenchmark, dataset::Vector{<:DataSample}, statistical_model, maximizer
129138
)
130139
res = 0.0
140+
check = is_minimization_problem(bench)
131141

132142
for sample in dataset
133143
target_obj = objective_value(bench, sample)
134144
x = sample.x
135145
θ = statistical_model(x)
136146
y = maximizer(θ; maximizer_kwargs(bench, sample)...)
137147
obj = objective_value(bench, sample, y)
138-
res += (target_obj - obj) / abs(target_obj)
148+
Δ = check ? obj - target_obj : target_obj - obj
149+
res += Δ / abs(target_obj)
139150
end
140151
return res / length(dataset)
141152
end

src/Warcraft/Warcraft.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Does not have any field.
2525
"""
2626
struct WarcraftBenchmark <: AbstractBenchmark end
2727

28+
function Utils.objective_value(::WarcraftBenchmark, θ::AbstractArray, y::AbstractArray)
29+
return -dot(θ, y)
30+
end
31+
2832
"""
2933
$TYPEDSIGNATURES
3034

0 commit comments

Comments
 (0)