Skip to content

Commit 649c94e

Browse files
committed
implement Instance
1 parent 6e5cb75 commit 649c94e

File tree

4 files changed

+96
-116
lines changed

4 files changed

+96
-116
lines changed

src/StochasticVehicleScheduling/StochasticVehicleScheduling.jl

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,49 @@ include("instance/task.jl")
1515
include("instance/district.jl")
1616
include("instance/city.jl")
1717
include("instance/features.jl")
18+
include("instance/instance.jl")
1819

19-
struct StochasticVehicleSchedulingBenchmark <: AbstractBenchmark end
20+
"""
21+
$TYPEDFIELDS
22+
23+
Data structure for a stochastic vehicle scheduling benchmark.
24+
25+
# Fields
26+
$TYPEDFIELDS
27+
"""
28+
@kwdef struct StochasticVehicleSchedulingBenchmark <: AbstractBenchmark
29+
"number of tasks in each instance"
30+
nb_tasks::Int = 25
31+
"number of scenarios in each instance"
32+
nb_scenarios::Int = 10
33+
end
34+
35+
"""
36+
$TYPEDSIGNATURES
37+
38+
Create a dataset of `dataset_size` instances for the given `StochasticVehicleSchedulingBenchmark`.
39+
"""
40+
function Utils.generate_dataset(
41+
benchmark::StochasticVehicleSchedulingBenchmark,
42+
dataset_size::Int;
43+
seed=nothing,
44+
rng=MersenneTwister(0),
45+
)
46+
(; nb_tasks, nb_scenarios) = benchmark
47+
Random.seed!(rng, seed)
48+
instances = [Instance(; nb_tasks, nb_scenarios, rng=rng) for _ in 1:dataset_size]
49+
features = get_features.(instances)
50+
return [
51+
DataSample(; x=feature, instance) for
52+
(instance, feature) in zip(instances, features)
53+
]
54+
end
55+
56+
function Utils.generate_maximizer(bench::StochasticVehicleSchedulingBenchmark) end
57+
function Utils.generate_statistical_model(bench::StochasticVehicleSchedulingBenchmark) end
2058

2159
export StochasticVehicleSchedulingBenchmark
22-
export create_random_city, compute_features
60+
61+
export create_random_city, compute_features, Instance
2362

2463
end

src/StochasticVehicleScheduling/instance/city.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ $TYPEDSIGNATURES
7070
and one `destination` task ending at time=end at depot
7171
- Roll every scenario.
7272
"""
73-
function create_random_city(; # TODO: use an rng here
73+
function create_random_city(;
7474
αᵥ_low=default_αᵥ_low,
7575
αᵥ_high=default_αᵥ_high,
7676
first_begin_time=default_first_begin_time,
@@ -80,10 +80,10 @@ function create_random_city(; # TODO: use an rng here
8080
task_μ=default_task_μ,
8181
task_σ=default_task_σ,
8282
seed=nothing,
83-
rng=MersenneTwister(0),
83+
rng=Random.default_rng(),
8484
city_kwargs...,
8585
)
86-
Random.seed!(rng, seed)
86+
isnothing(seed) || Random.seed!(rng, seed)
8787
city = City(; city_kwargs...)
8888
init_districts!(city, district_μ, district_σ; rng=rng)
8989
init_tasks!(

src/StochasticVehicleScheduling/instance/features.jl

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -26,48 +26,6 @@ end
2626
"""
2727
$TYPEDSIGNATURES
2828
29-
Return a `MetaDiGraph` computed from `city`.
30-
Each vertex represents a task. Vertices are ordered by start time of corresponding task.
31-
There is an edge from task u to task v the (end time of u + tie distance between u and v <= start time of v).
32-
Every (u, v) edge has a :travel_time property, corresponding to time istance between u and v.
33-
"""
34-
function create_VSP_graph(city::City)
35-
# Initialize directed graph
36-
nb_vertices = city.nb_tasks + 2
37-
graph = SimpleDiGraph(nb_vertices)
38-
starting_task = 1
39-
end_task = nb_vertices
40-
job_tasks = 2:(city.nb_tasks + 1)
41-
42-
travel_times = [
43-
distance(task1.end_point, task2.start_point) for task1 in city.tasks,
44-
task2 in city.tasks
45-
]
46-
47-
# Create existing edges
48-
for iorigin in job_tasks
49-
# link every task to base
50-
add_edge!(graph, starting_task, iorigin)
51-
add_edge!(graph, iorigin, end_task)
52-
53-
for idestination in (iorigin + 1):(city.nb_tasks + 1)
54-
travel_time = travel_times[iorigin, idestination]
55-
origin_end_time = city.tasks[iorigin].end_time
56-
destination_begin_time = city.tasks[idestination].start_time # get_prop(graph, idestination, :task).start_time
57-
58-
# there is an edge only if we can reach destination from origin before start of task
59-
if origin_end_time + travel_time <= destination_begin_time
60-
add_edge!(graph, iorigin, idestination)
61-
end
62-
end
63-
end
64-
65-
return graph
66-
end
67-
68-
"""
69-
$TYPEDSIGNATURES
70-
7129
Compute slack for features.
7230
"""
7331
function compute_slacks(city::City, old_task_index::Int, new_task_index::Int)
Lines changed: 52 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
"""
2-
$TYPEDEF
3-
"""
4-
abstract type AbstractInstance end
5-
61
"""
72
$TYPEDEF
83
@@ -11,86 +6,85 @@ Instance of the stochastic VSP problem.
116
# Fields
127
$TYPEDFIELDS
138
"""
14-
struct Instance{G<:AbstractGraph,M1<:AbstractMatrix,M2<:AbstractMatrix,F,C} <:
15-
AbstractInstance
16-
"associated city"
17-
city::City
18-
"graph computed from `city` with the `create_VSP_graph(city::City)` method."
19-
graph::G
20-
"features matrix computed from `city`"
21-
features::Matrix{F}
22-
""
23-
slacks::M1
24-
""
25-
delays::M2
26-
""
27-
vehicle_cost::C
28-
""
29-
delay_cost::C
30-
end
31-
32-
"""
33-
$TYPEDEF
34-
35-
Instance of the stochastic VSP problem.
36-
37-
# Fields
38-
$TYPEDFIELDS
39-
"""
40-
struct CompactInstance{G<:AbstractGraph,M1<:AbstractMatrix,M2<:AbstractMatrix,F,C} <:
41-
AbstractInstance
9+
struct Instance{G<:AbstractGraph,M1<:AbstractMatrix,M2<:AbstractMatrix,F,C}
4210
"graph computed from `city` with the `create_VSP_graph(city::City)` method"
4311
graph::G
4412
"features matrix computed from `city`"
4513
features::Matrix{F}
46-
""
14+
"slack matrix"
4715
slacks::M1
48-
""
16+
"intrinsic delays scenario matrix"
4917
delays::M2
50-
""
18+
"cost of a vehicle"
5119
vehicle_cost::C
52-
""
20+
"cost of one minute delay"
5321
delay_cost::C
5422
end
5523

5624
"""
5725
$TYPEDSIGNATURES
5826
59-
Constructor for [`Instance`](@ref).
60-
Build an `Instance` from a `City`, by computing its graph, features, slacks and delays.
61-
"""
62-
function Instance(city::City)
63-
graph = create_VSP_graph(city)
64-
features = compute_features(city)
65-
slacks = compute_slacks(city, graph)
66-
delays = compute_delays(city)
67-
return Instance(
68-
city, graph, features, slacks, delays, city.vehicle_cost, city.delay_cost
69-
)
27+
Return the acyclic directed graph corresponding to `city`.
28+
Each vertex represents a task. Vertices are ordered by start time of corresponding task.
29+
There is an edge from task u to task v the (end time of u + tie distance between u and v <= start time of v).
30+
"""
31+
function create_VSP_graph(city::City)
32+
# Initialize directed graph
33+
nb_vertices = city.nb_tasks + 2
34+
graph = SimpleDiGraph(nb_vertices)
35+
starting_task = 1
36+
end_task = nb_vertices
37+
job_tasks = 2:(city.nb_tasks + 1)
38+
39+
travel_times = [
40+
distance(task1.end_point, task2.start_point) for task1 in city.tasks,
41+
task2 in city.tasks
42+
]
43+
44+
# Create existing edges
45+
for iorigin in job_tasks
46+
# link every task to base
47+
add_edge!(graph, starting_task, iorigin)
48+
add_edge!(graph, iorigin, end_task)
49+
50+
for idestination in (iorigin + 1):(city.nb_tasks + 1)
51+
travel_time = travel_times[iorigin, idestination]
52+
origin_end_time = city.tasks[iorigin].end_time
53+
destination_begin_time = city.tasks[idestination].start_time # get_prop(graph, idestination, :task).start_time
54+
55+
# there is an edge only if we can reach destination from origin before start of task
56+
if origin_end_time + travel_time <= destination_begin_time
57+
add_edge!(graph, iorigin, idestination)
58+
end
59+
end
60+
end
61+
62+
return graph
7063
end
7164

7265
"""
7366
$TYPEDSIGNATURES
7467
75-
Constructor for [`CompactInstance`](@ref).
76-
Build a `CompactInstance` from a `City`, by computing its graph, features, slacks and delays.
68+
Constructor for [`Instance`](@ref).
69+
Build an `Instance` for the stochatsic vehicle scheduling problem, with `nb_tasks` tasks and `nb_scenarios` scenarios.
7770
"""
78-
function CompactInstance(city::City)
71+
function Instance(;
72+
nb_tasks::Int, nb_scenarios::Int, rng::AbstractRNG=Random.default_rng(), kwargs...
73+
)
74+
city = create_random_city(; rng=rng, nb_tasks, nb_scenarios, kwargs...)
7975
graph = create_VSP_graph(city)
8076
features = compute_features(city)
8177
slacks = compute_slacks(city, graph)
8278
delays = compute_delays(city)
83-
return CompactInstance(
84-
graph, features, slacks, delays, city.vehicle_cost, city.delay_cost
85-
)
79+
return Instance(graph, features, slacks, delays, city.vehicle_cost, city.delay_cost)
8680
end
8781

8882
"""
8983
$TYPEDSIGNATURES
9084
9185
Returns the number of scenarios in instance.
9286
"""
93-
function get_nb_scenarios(instance::AbstractInstance)
87+
function get_nb_scenarios(instance::Instance)
9488
return size(instance.delays, 2)
9589
end
9690

@@ -99,22 +93,11 @@ $TYPEDSIGNATURES
9993
10094
Returns the number of tasks in `instance`.
10195
"""
102-
get_nb_tasks(instance::AbstractInstance) = nv(instance.graph) - 2
103-
104-
"""
105-
$TYPEDSIGNATURES
106-
107-
Returns a random instance created with city_kwargs.
108-
"""
109-
function create_random_instance(; city_kwargs...)
110-
return Instance(create_random_city(; city_kwargs...))
111-
end
96+
get_nb_tasks(instance::Instance) = nv(instance.graph) - 2
11297

11398
"""
11499
$TYPEDSIGNATURES
115100
116-
Returns a random instance created with city_kwargs.
101+
Returns the feature matrix associated to `instance`.
117102
"""
118-
function create_random_compact_instance(; city_kwargs...)
119-
return CompactInstance(create_random_city(; city_kwargs...))
120-
end
103+
get_features(instance::Instance) = instance.features

0 commit comments

Comments
 (0)