Skip to content

Commit

Permalink
Basic doc done
Browse files Browse the repository at this point in the history
  • Loading branch information
Shushman committed Sep 28, 2019
1 parent 53883ed commit 40cc723
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 41 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ I've given a brief overview of the code in the `src/` folder, and an even more b
- `src/mapf_transit.jl`: Implements everything necessary to use the Enhanced CBS Solver from [MultiAgentPathFinding.jl](https://github.com/Shushman/MultiAgentPathFinding.jl) for the MAPF-TN layer.
- `scripts/test_*.jl`: Hacked scripts for playing around. Ignore.
- `scripts/benchmark_*.jl`: The various scripts used for the results in the paper. The benchmarks should be reproducible if you parse the GTFS files (not uploaded) to the corresponding JSON files, run `preprocess_travel_time_estimates.jl` to save the surrogate object that is the loaded by the benchmark scripts, and use the same `MersenneTwister` as mentioned in the script. The separate `benchmark_mult_agents_light.jl` script uses the direct flight time as the surrogate instead of the preprocessed estimate (this could have been an argument to `benchmark_multi_agents.jl`, but I got lazy).
Finally, note that for the arguments to the `benchmark_*` scripts, you'll need
some combination of the parsed GTFS files, preprocessing outputs, and
parameter files (in `param_files`) for the various arguments.


**Note on Reproducibility**
</br>
Expand Down
2 changes: 2 additions & 0 deletions scripts/alloc_alpha_beta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ using MultiAgentAllocationTransit
using Statistics
using JSON

## IGNORE - Just used to get some alpha beta values for supporting the theorem.

rng = MersenneTwister(2345)

const params_file = ARGS[1]
Expand Down
4 changes: 1 addition & 3 deletions scripts/benchmark_mult_agents.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ using NearestNeighbors
using StaticArrays
global_logger(SimpleLogger(stderr, Logging.Error))

## NOTE : Example Calls
# julia scripts/benchmark_mult_agents.jl data/sfmta/sf_params.toml data/sfmta/stop_to_coords.json data/sfmta/trips.json data/drone_params.toml data/sfmta/sf_bb_params.toml data/sf_mapf_20trials data/sfmta/sf_halton_tt_estimates.jld2 5 10 20

# julia scripts/benchmark_mult_agents.jl data/wmata/wdc_params.toml data/wmata/stop_to_coords.json data/wmata/trips.json data/drone_params.toml data/wmata/wdc_params.toml data/wdc_mapf_20trials 5 10 20


rng = MersenneTwister(6789)

# Script arguments relating to transit files etc.
Expand Down
4 changes: 3 additions & 1 deletion scripts/benchmark_replanning.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ const N_TRIALS = parse(Int64, ARGS[10])
const TRANSIT_CAP_RANGE = (3, 5)
const ECBS_WEIGHT = 1.1

# julia scripts/benchmark_replanning.jl data/sfmta/sf_params.toml data/sfmta/stop_to_coords.json data/sfmta/trips.json data/drone_params.toml data/sfmta/sf_bb_params.toml data/sf_replan_20trials data/sfmta/sf_halton_tt_estimates.jld2 5 10 20
## NOTE: EXAMPLE CALL
# julia scripts/benchmark_replanning.jl data/sfmta/sf_params.toml data/sfmta/stop_to_coords.json data/sfmta/trips.json
# data/drone_params.toml data/sfmta/sf_bb_params.toml data/sf_replan_20trials data/sfmta/sf_halton_tt_estimates.jld2 5 10 20


function main()
Expand Down
4 changes: 1 addition & 3 deletions scripts/preprocess_travel_time_estimates.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ global_logger(SimpleLogger(stderr, Logging.Error))

rng = MersenneTwister(6789)

# julia scripts/preprocess_travel_time_estimates.jl data/sfmta/sf_bb_params.toml data/sfmta/stop_to_coords.json data/sfmta/trips.json data/drone_params.toml data/sfmta/sf_halton_tt_estimates.jld2 100


# EXAMPLES OF ARGUMENTS
# const bb_params_file = "./data/sfmta/sf_bb_params.toml"
# const stop_coords_file = "./data/sfmta/stop_to_coords.json"
# const trips_file = "./data/sfmta/trips.json"
Expand Down
2 changes: 1 addition & 1 deletion scripts/test_replanning_heuristics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const out_file = "./data/temp_mult_generic.json"

# MAPF-TN params
const TRANSIT_CAP_RANGE = (2, 4)
const ECBS_WEIGHT = 1.05
const ECBS_WEIGHT = 1.1
const N_DEPOTS = 3

# Change this one
Expand Down
24 changes: 22 additions & 2 deletions src/load_transit_env.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
## Define ALL the functions needed to load an environment
"""
load_depot_site_locations_latlong(filename::String)
Loads saved depot and/or site locations from a file. Not currently used.
"""
function load_depot_site_locations_latlong(filename::String)

locations = Vector{LatLonCoords}(undef, 0)
Expand All @@ -15,7 +19,11 @@ function load_depot_site_locations_latlong(filename::String)
return locations
end

"""
load_off_transit_graph_latlong(depot_file::String, site_file::String)
Load depots and sites to create OffTransitGraph. Also not used currently.
"""
function load_off_transit_graph_latlong(depot_file::String, site_file::String)

depots = load_depot_site_locations_latlong(depot_file)
Expand All @@ -25,6 +33,14 @@ function load_off_transit_graph_latlong(depot_file::String, site_file::String)
end


"""
function load_transit_graph_latlong(stop_coords_file::String, trips_file::String,
transit_cap_range::Tuple{Int64,Int64}, rng::RNG) where {RNG <: AbstractRNG}
Given the stop_to_coordinates.json file, the trips_file, and the range of capacities
for a transit vehicle, load up the TransitGraph and assign randomly sampled capacities
to the transit routes.
"""
function load_transit_graph_latlong(stop_coords_file::String, trips_file::String,
transit_cap_range::Tuple{Int64,Int64}, rng::RNG) where {RNG <: AbstractRNG}

Expand Down Expand Up @@ -71,7 +87,11 @@ function load_transit_graph_latlong(stop_coords_file::String, trips_file::String

end

# return the state_graph and depot_sites_to_vtx
"""
setup_state_graph(transit_graph::TG, off_transit_graph::OTG) where {TG <: TransitGraph, OTG <: OffTransitGraph}
Generate the vertices of the operation graph G_O. Create the reverse index from vertex_str to ID.
"""
function setup_state_graph(transit_graph::TG, off_transit_graph::OTG) where {TG <: TransitGraph, OTG <: OffTransitGraph}

state_graph = SimpleVListGraph{MAPFTransitVertexState}()
Expand Down
118 changes: 88 additions & 30 deletions src/mapf_transit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,13 @@ function MultiAgentPathFinding.create_constraints_from_conflict(env::MAPFTransit
end
end

"""
elapsed_time(env::MAPFTransitEnv,
s1::MAPFTransitVertexState, s2::MAPFTransitVertexState)
Compute the time difference between time-stamped vertices.
If any not time-stamped, computes the average traversal time.
"""
function elapsed_time(env::MAPFTransitEnv,
s1::MAPFTransitVertexState, s2::MAPFTransitVertexState)

Expand All @@ -237,6 +243,11 @@ function elapsed_time(env::MAPFTransitEnv,
end
end

"""
elapsed_time_heuristic(env::MAPFTransitEnv, s::MAPFTransitVertexState)
Computes the trivial heuristic for traversal time from a vertex to the goal.
"""
function elapsed_time_heuristic(env::MAPFTransitEnv, s::MAPFTransitVertexState)

# Just direct flight time to goal
Expand All @@ -245,7 +256,11 @@ function elapsed_time_heuristic(env::MAPFTransitEnv, s::MAPFTransitVertexState)

end

"""
distance_traversed(env::MAPFTransitEnv, s1::MAPFTransitVertexState, s2::MAPFTransitVertexState)
Computes the flight distance between two operation graph vertices (0 for transit edges).
"""
function distance_traversed(env::MAPFTransitEnv, s1::MAPFTransitVertexState, s2::MAPFTransitVertexState)

split1 = split(s1.vertex_str, "-")
Expand All @@ -258,7 +273,11 @@ function distance_traversed(env::MAPFTransitEnv, s1::MAPFTransitVertexState, s2:
end
end

"""
distance_heuristic(env::MAPFTransitEnv, s::MAPFTransitVertexState)
Computes the admissible heuristic on flight distance between vertices. See Appendix II-B
"""
function distance_heuristic(env::MAPFTransitEnv, s::MAPFTransitVertexState)

ssplit = split(s.vertex_str, "-")
Expand All @@ -267,7 +286,7 @@ function distance_heuristic(env::MAPFTransitEnv, s::MAPFTransitVertexState)
n_depots = length(env.off_transit_graph.depots)
n_sites = length(env.off_transit_graph.sites)

# TODO : Should be correct since state graph is first populated with depots and then sites
# NOTE : Should be correct since state graph is first populated with depots and then sites
depot_site_idx = goal_vtx.idx

if ssplit[1] == "r"
Expand All @@ -286,7 +305,8 @@ function distance_heuristic(env::MAPFTransitEnv, s::MAPFTransitVertexState)
end
end

# Focal state heuristic - min boarding conflicts
## N.B The focal heuristic functions that follow are the lowest hanging fruit for
## improving empirical performance of ECBS for search.
function focal_transition_heuristic_transit(env::MAPFTransitEnv, solution::Vector{PR},
agent_idx::Int64, u::MAPFTransitVertexState, v::MAPFTransitVertexState) where {PR <: PlanResult}

Expand Down Expand Up @@ -342,10 +362,11 @@ function reachable_by_agent(env::MAPFTransitEnv, s1::MAPFTransitState, s2::MAPFT
end


# Run low level search from current state for agent_idx
# Agent task is obtained from env.agent_states
# If site is crossed, don't need to care about that
# Search is done from the current env reference time (which accounts for rolling horizon)
"""
Implements the actual single-agent low-level search for MultiAgentPathFinding.jl's Enhanced CBS.
Computes the dpd' path with Focal-MCSP twice. Does some hacking to concat paths and to avoid
searching for a subpath that has no constraints.
"""
function MultiAgentPathFinding.low_level_search!(solver::ECBSSolver, agent_idx::Int64,
s::MAPFTransitVertexState, constraints::MAPFTransitConstraints,
solution::Vector{PR}) where {PR <: PlanResult}
Expand All @@ -360,7 +381,7 @@ function MultiAgentPathFinding.low_level_search!(solver::ECBSSolver, agent_idx::
edge_constr_fn(u, v) = distance_traversed(env, u, v)
edge_constr_functions = [edge_constr_fn]

edge_constraints = [env.drone_params.max_distance - agent_state.dist_flown] # TODO: Check this!!!
edge_constraints = [env.drone_params.max_distance - agent_state.dist_flown]

admissible_heuristic(u) = elapsed_time_heuristic(env, u)

Expand Down Expand Up @@ -501,11 +522,15 @@ function MultiAgentPathFinding.low_level_search!(solver::ECBSSolver, agent_idx::
return PlanResult{MAPFTransitVertexState, MAPFTransitAction, Float64}(states, actions, cost, fmin)
end

# Returns the next state of each agent based on its currently executing solution
# Also updates the site_crossed flag if so
# TODO: Assumes that solution[i].states has the correct tuple of (state, cost)
# Also assumes that agent has not finished yet
# Also assumes that solution[i].actions tracks the weight costs
# NOTE: Assumes that solution[i].states has the correct tuple of (state, cost)
"""
update_agent_states!(env::MAPFTransitEnv, time_val::Float64, agent_idx::Int64,
solution::Vector{PR}) where {PR <: PlanResult}
Returns the next state of each agent based on its currently executing solution. Also updates the site_crossed flag if so
Assumes that agent has not finished yet
Assumes that solution[i].actions tracks the weight costs
"""
function update_agent_states!(env::MAPFTransitEnv, time_val::Float64, agent_idx::Int64,
solution::Vector{PR}) where {PR <: PlanResult}

Expand All @@ -529,7 +554,7 @@ function update_agent_states!(env::MAPFTransitEnv, time_val::Float64, agent_idx:
# Now deal with state_idx
@assert state_idx <= length(agt_soln_states) "Agent $(agent_idx) has inconsistent time trajectory!; $(time_val); $(agt_soln_states)"

# TODO: hack to avoid pathological case of agent being at end of solution
# NOTE: hack to avoid pathological case of agent being at end of solution
if state_idx == length(agt_soln_states)
state_idx = state_idx - 1
state_time = agt_soln_states[state_idx][2]
Expand Down Expand Up @@ -569,7 +594,7 @@ function Graphs.include_vertex!(vis::MAPFTransitGoalVisitor, u::MAPFTransitVerte
goal_vtx = env.state_graph.vertices[env.curr_goal_idx]

if goal_vtx.vertex_str == v.vertex_str
# TODO: Commented out to have a rolling horizon of trips
# NOTE: Commented out to have a rolling horizon of trips
# reset_time(env.state_graph.vertices[env.curr_goal_idx], d)
return false
end
Expand Down Expand Up @@ -634,10 +659,11 @@ function Graphs.include_vertex!(vis::MAPFTransitGoalVisitor, u::MAPFTransitVerte
return true
end

"""
get_depot_to_site_travel_time(env::MAPFTransitEnv, weight::Float64, orig_str::String, goal_str::String)

# Run a single search over a snapshot of the transit network to get the travel time
# If not reachable, then return Inf
Runs a single search over a snapshot of the transit network to get the travel time. If not reachable, then return Inf
"""
function get_depot_to_site_travel_time(env::MAPFTransitEnv, weight::Float64, orig_str::String, goal_str::String)

# Get origin idx and destination idx
Expand Down Expand Up @@ -667,7 +693,7 @@ function get_depot_to_site_travel_time(env::MAPFTransitEnv, weight::Float64, ori
edge_constr_heuristics,
edge_constraints)

# TODO: Not returning Inf to avoid instability?
# TODO: Not returning Inf to avoid instability? Hack
if tgt_entry.v_idx == orig_idx
@warn "In allocation, edge from $(orig_str) to $(goal_str) is empty!"
return 100000.
Expand All @@ -679,7 +705,12 @@ function get_depot_to_site_travel_time(env::MAPFTransitEnv, weight::Float64, ori
return costs[end]
end

"""
allocation_cost_wrapper_truett(env::MAPFTransitEnv, weight::Float64, n_depots::Int64, n_sites::Int64,
orig_ds_idx::Int64, goal_ds_idx::Int64)
Use actual travel time between locations by running a full search. Not Used.
"""
function allocation_cost_wrapper_truett(env::MAPFTransitEnv, weight::Float64, n_depots::Int64, n_sites::Int64,
orig_ds_idx::Int64, goal_ds_idx::Int64)

Expand All @@ -699,6 +730,13 @@ function allocation_cost_wrapper_truett(env::MAPFTransitEnv, weight::Float64, n_
return get_depot_to_site_travel_time(env, weight, orig_str, goal_str)
end

"""
allocation_cost_wrapper_estimate(env::MAPFTransitEnv, weight::Float64, n_depots::Int64, n_sites::Int64,
halton_nn_tree::BallTree, estimate_matrix::Matrix{Float64},
orig_ds_idx::Int64, goal_ds_idx::Int64)
Get the surrogate travel time using the estimate matrix.
"""
function allocation_cost_wrapper_estimate(env::MAPFTransitEnv, weight::Float64, n_depots::Int64, n_sites::Int64,
halton_nn_tree::BallTree, estimate_matrix::Matrix{Float64},
orig_ds_idx::Int64, goal_ds_idx::Int64)
Expand All @@ -724,9 +762,11 @@ function allocation_cost_wrapper_estimate(env::MAPFTransitEnv, weight::Float64,
end


"""
get_first_finish(solution::Vector{PR}) where {PR <: PlanResult}
# Get the agent that will finish first
# Also returns the time at which it finishes
Get the agent that will finish first. Also returns the time at which it finishes
"""
function get_first_finish(solution::Vector{PR}) where {PR <: PlanResult}

min_cost = Inf
Expand All @@ -742,9 +782,14 @@ function get_first_finish(solution::Vector{PR}) where {PR <: PlanResult}
return (min_idx, min_cost)
end

# For single agent replanning, we need the set of all vertex constraints of other
# agents to ignore as constraints to the replanning agent
# TODO: How to handle the time issue here? (Just take route vertex indices)

# NOTE: How to handle the time issue here? (Just take route vertex indices)
"""
get_replan_constraints(env::MAPFTransitEnv, time_val::Float64, agent_idx::Int64,
solution::Vector{PR}) where {PR <: PlanResult}
For single agent replanning, we need the set of all vertex constraints of other agents to ignore as constraints to the replanning agent
"""
function get_replan_constraints(env::MAPFTransitEnv, time_val::Float64, agent_idx::Int64,
solution::Vector{PR}) where {PR <: PlanResult}

Expand All @@ -769,9 +814,13 @@ function get_replan_constraints(env::MAPFTransitEnv, time_val::Float64, agent_id
return MAPFTransitConstraints(avoid_vertex_map)
end

# Get all the info necessary to replan for INDIVIDUAL
# Returns false if drone has no further task
# Also returns the planning time
"""
replan_individual!(env::MAPFTransitEnv, solution::Vector{PR},
n_depots::Int64, n_sites::Int64,
agent_tours::Vector{Vector{Int64}}, weight::Float64) where {PR <: PlanResult}
Get all the info necessary to replan for INDIVIDUAL. Returns false if drone has no further task. Also returns the planning time
"""
function replan_individual!(env::MAPFTransitEnv, solution::Vector{PR},
n_depots::Int64, n_sites::Int64,
agent_tours::Vector{Vector{Int64}}, weight::Float64) where {PR <: PlanResult}
Expand Down Expand Up @@ -799,9 +848,14 @@ function replan_individual!(env::MAPFTransitEnv, solution::Vector{PR},
end


# Replan collectively! In this we want to update the agent states for all agents
# and then re-run the solver
# Returns true if valid, the elapsed time, and the new solution
"""
replan_collective!(env::MAPFTransitEnv, solution::Vector{PR},
n_depots::Int64, n_sites::Int64,
agent_tours::Vector{Vector{Int64}}, weight::Float64) where {PR <: PlanResult}
Replan collectively! In this we want to update the agent states for all agents and then re-run the solver.
Returns true if valid, the elapsed time, and the new solution
"""
function replan_collective!(env::MAPFTransitEnv, solution::Vector{PR},
n_depots::Int64, n_sites::Int64,
agent_tours::Vector{Vector{Int64}}, weight::Float64) where {PR <: PlanResult}
Expand Down Expand Up @@ -839,7 +893,11 @@ function replan_collective!(env::MAPFTransitEnv, solution::Vector{PR},
return (true, el_time, new_solution)
end

## Set the number of transit options and valid distances
"""
set_solution_diagnostics!(env::MAPFTransitEnv, solution::Vector{PR}) where {PR <: PlanResult}
Set the number of transit options and valid distances
"""
function set_solution_diagnostics!(env::MAPFTransitEnv, solution::Vector{PR}) where {PR <: PlanResult}

# Iterate over solutions and only update if valid
Expand Down
Loading

0 comments on commit 40cc723

Please sign in to comment.