-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathStochasticVehicleScheduling.jl
More file actions
212 lines (179 loc) · 6.1 KB
/
StochasticVehicleScheduling.jl
File metadata and controls
212 lines (179 loc) · 6.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
module StochasticVehicleScheduling
export StochasticVehicleSchedulingBenchmark
export generate_dataset, generate_maximizer, generate_statistical_model
export compact_linearized_mip,
compact_mip, column_generation_algorithm, local_search, deterministic_mip
export evaluate_solution, is_feasible
export VSPScenario, build_stochastic_instance
using ..Utils
using DocStringExtensions: TYPEDEF, TYPEDFIELDS, TYPEDSIGNATURES
using ConstrainedShortestPaths:
stochastic_routing_shortest_path, stochastic_routing_shortest_path_with_threshold
using Distributions: Distribution, LogNormal, Uniform, DiscreteUniform
using Flux: Chain, Dense
using Graphs:
AbstractGraph,
SimpleDiGraph,
add_edge!,
nv,
ne,
edges,
src,
dst,
has_edge,
inneighbors,
outneighbors
using JuMP:
JuMP, Model, @variable, @objective, @constraint, optimize!, value, set_silent, dual
using Printf: @printf
using Random: Random, AbstractRNG, MersenneTwister
using SparseArrays: sparse, SparseMatrixCSC
using Statistics: quantile, mean
include("utils.jl")
include("instance/constants.jl")
include("instance/task.jl")
include("instance/district.jl")
include("instance/city.jl")
include("instance/features.jl")
include("instance/instance.jl")
include("scenario.jl")
include("solution/solution.jl")
include("solution/algorithms/mip.jl")
include("solution/algorithms/column_generation.jl")
include("solution/algorithms/local_search.jl")
include("solution/algorithms/deterministic_mip.jl")
include("solution/algorithms/anticipative_solver.jl")
include("maximizer.jl")
"""
$TYPEDEF
Data structure for a stochastic vehicle scheduling benchmark.
# Fields
$TYPEDFIELDS
"""
@kwdef struct StochasticVehicleSchedulingBenchmark <: AbstractStochasticBenchmark{true}
"number of tasks in each instance"
nb_tasks::Int = 25
"number of scenarios in each instance (only used to compute features and objective evaluation)"
nb_scenarios::Int = 10
end
include("policies.jl")
function Utils.objective_value(
::StochasticVehicleSchedulingBenchmark,
sample::DataSample,
y::BitVector,
scenario::VSPScenario,
)
stoch = build_stochastic_instance(sample.instance, [scenario])
return evaluate_solution(y, stoch)
end
function Utils.objective_value(
bench::StochasticVehicleSchedulingBenchmark, sample::DataSample, y::BitVector
)
if hasproperty(sample.extra, :scenario)
return Utils.objective_value(bench, sample, y, sample.extra.scenario)
elseif hasproperty(sample.extra, :scenarios)
stoch = build_stochastic_instance(sample.instance, sample.extra.scenarios)
return evaluate_solution(y, stoch)
end
return error("Sample must have scenario or scenarios")
end
"""
$TYPEDSIGNATURES
Draw a single fresh [`VSPScenario`](@ref) for the given instance.
Requires `store_city=true` (the default) when generating instances.
"""
function Utils.generate_scenario(
::StochasticVehicleSchedulingBenchmark, rng::AbstractRNG; instance::Instance, kwargs...
)
@assert !isnothing(instance.city) "`generate_scenario` requires `store_city=true`"
return draw_scenario(instance.city, instance.graph, rng)
end
"""
$TYPEDSIGNATURES
"""
function Utils.generate_baseline_policies(bench::StochasticVehicleSchedulingBenchmark)
return svs_generate_baseline_policies(bench)
end
"""
$TYPEDSIGNATURES
Return the anticipative solver: a callable `(scenario::VSPScenario; instance, kwargs...) -> y`
that solves the 1-scenario stochastic VSP.
# Keyword Arguments
- `model_builder`: a function returning an empty `JuMP.Model` with a solver attached (defaults to `scip_model`).
"""
function Utils.generate_anticipative_solver(
::StochasticVehicleSchedulingBenchmark; model_builder=scip_model
)
return AnticipativeSolver(; model_builder=model_builder)
end
"""
$TYPEDSIGNATURES
Return the parametric anticipative solver: a callable `(θ, scenario::VSPScenario; instance, kwargs...) -> y`.
# Keyword Arguments
- `model_builder`: a function returning an empty `JuMP.Model` with a solver attached (defaults to `scip_model`).
"""
function Utils.generate_parametric_anticipative_solver(
::StochasticVehicleSchedulingBenchmark; model_builder=scip_model
)
return AnticipativeSolver(; model_builder=model_builder)
end
"""
$TYPEDSIGNATURES
Generate an unlabeled instance for the given `StochasticVehicleSchedulingBenchmark`.
Returns a [`DataSample`](@ref) with features `x` and `instance` set, but `y=nothing`.
To obtain labeled samples, pass a `target_policy` to [`generate_dataset`](@ref):
```julia
policy = sample -> DataSample(; sample.context..., x=sample.x,
y=column_generation_algorithm(sample.instance))
dataset = generate_dataset(benchmark, N; target_policy=policy)
```
If `store_city=false`, coordinates and city information are not stored in the instance,
and `generate_scenario` will not work. This can be used to save memory if you only need to evaluate
solutions on a fixed set of scenarios.
"""
function Utils.generate_instance(
benchmark::StochasticVehicleSchedulingBenchmark,
rng::AbstractRNG;
store_city=true,
kwargs...,
)
(; nb_tasks, nb_scenarios) = benchmark
instance = Instance(; nb_tasks, nb_scenarios, rng, store_city)
x = get_features(instance)
return DataSample(; x, instance)
end
"""
$TYPEDEF
Deterministic vsp maximizer for the [StochasticVehicleSchedulingBenchmark](@ref).
"""
struct StochasticVechicleSchedulingMaximizer{M}
"mip solver model to use"
model_builder::M
end
"""
$TYPEDSIGNATURES
"""
function Utils.generate_maximizer(
::StochasticVehicleSchedulingBenchmark; model_builder=highs_model
)
return StochasticVechicleSchedulingMaximizer(model_builder)
end
"""
$TYPEDSIGNATURES
Apply the maximizer with the stored model builder.
"""
function (maximizer::StochasticVechicleSchedulingMaximizer)(
θ::AbstractVector; instance::Instance, kwargs...
)
return vsp_maximizer(θ; instance, model_builder=maximizer.model_builder, kwargs...)
end
"""
$TYPEDSIGNATURES
"""
function Utils.generate_statistical_model(
::StochasticVehicleSchedulingBenchmark; seed=nothing
)
Random.seed!(seed)
return Chain(Dense(20 => 1; bias=false), vec)
end
end