shuffle parked cars to use without offsetting the RNG

This commit is contained in:
Dustin Carlino 2018-10-16 11:44:26 -07:00
parent 77786c9483
commit 14c341d86a
4 changed files with 24 additions and 18 deletions

View File

@ -136,7 +136,7 @@ though... Can we fork RNG for that too?
Problems: Problems:
- CarIDs are different, could make them be original parking spot - CarIDs are different, could make them be original parking spot
- Missing trip ID, different ped IDs - Missing trip ID, different ped IDs
- gen_range on different inputs = gen_range on different inputs

View File

@ -59,6 +59,7 @@ use geom::{Angle, Pt2D};
pub use helpers::{load, SimFlags}; pub use helpers::{load, SimFlags};
pub use instrument::save_backtraces; pub use instrument::save_backtraces;
use map_model::{LaneID, Trace, TurnID}; use map_model::{LaneID, Trace, TurnID};
use rand::{Rng, SeedableRng, XorShiftRng};
pub use scenario::{Neighborhood, Scenario, SeedParkedCars, SpawnOverTime}; pub use scenario::{Neighborhood, Scenario, SeedParkedCars, SpawnOverTime};
pub use sim::{Benchmark, Sim}; pub use sim::{Benchmark, Sim};
use std::fmt; use std::fmt;
@ -322,3 +323,7 @@ impl Cloneable for Scenario {}
impl Cloneable for Tick {} impl Cloneable for Tick {}
impl Cloneable for MapEdits {} impl Cloneable for MapEdits {}
impl Cloneable for ABTest {} impl Cloneable for ABTest {}
fn fork_rng<R: Rng + ?Sized>(base_rng: &mut R) -> XorShiftRng {
XorShiftRng::from_seed([base_rng.next_u32() as u8; 16])
}

View File

@ -2,8 +2,8 @@ use abstutil;
use geom::{Polygon, Pt2D}; use geom::{Polygon, Pt2D};
use map_model::{BuildingID, LaneID, Map}; use map_model::{BuildingID, LaneID, Map};
use rand::Rng; use rand::Rng;
use std::collections::HashMap; use std::collections::{BTreeMap, HashMap};
use {ParkedCar, Sim, Tick}; use {fork_rng, ParkedCar, Sim, Tick};
#[derive(Clone, Serialize, Deserialize, Debug)] #[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Scenario { pub struct Scenario {
@ -101,7 +101,7 @@ impl Scenario {
); );
} }
let mut parked_cars_per_neighborhood: HashMap<String, Vec<ParkedCar>> = HashMap::new(); let mut parked_cars_per_neighborhood: BTreeMap<String, Vec<ParkedCar>> = BTreeMap::new();
for (name, neighborhood) in &neighborhoods { for (name, neighborhood) in &neighborhoods {
parked_cars_per_neighborhood.insert( parked_cars_per_neighborhood.insert(
name.to_string(), name.to_string(),
@ -109,6 +109,11 @@ impl Scenario {
.get_all_parked_cars(Some(&Polygon::new(&neighborhood.points))), .get_all_parked_cars(Some(&Polygon::new(&neighborhood.points))),
); );
} }
// Shuffle the list of parked cars, but be sure to fork the RNG to be stable across map
// edits.
for cars in parked_cars_per_neighborhood.values_mut() {
fork_rng(&mut sim.rng).shuffle(cars);
}
for s in &self.spawn_over_time { for s in &self.spawn_over_time {
for _ in 0..s.num_agents { for _ in 0..s.num_agents {
@ -126,22 +131,16 @@ impl Scenario {
.unwrap(); .unwrap();
if sim.rng.gen_bool(s.percent_drive) { if sim.rng.gen_bool(s.percent_drive) {
if parked_cars_per_neighborhood[&s.start_from_neighborhood].is_empty() {
panic!(
"{} has no parked cars; can't instantiate {}",
s.start_from_neighborhood, self.scenario_name
);
}
// TODO Probably prefer parked cars close to from_bldg, unless the particular // TODO Probably prefer parked cars close to from_bldg, unless the particular
// area is tight on parking. :) // area is tight on parking. :)
let idx = sim.rng.gen_range(
0,
parked_cars_per_neighborhood[&s.start_from_neighborhood].len(),
);
let parked_car = parked_cars_per_neighborhood let parked_car = parked_cars_per_neighborhood
.get_mut(&s.start_from_neighborhood) .get_mut(&s.start_from_neighborhood)
.unwrap() .unwrap()
.remove(idx); .pop()
.expect(&format!(
"{} has no parked cars; can't instantiate {}",
s.start_from_neighborhood, self.scenario_name
));
sim.spawner.start_trip_using_parked_car( sim.spawner.start_trip_using_parked_car(
spawn_time, spawn_time,

View File

@ -3,14 +3,16 @@ use driving::DrivingSimState;
use kinematics::Vehicle; use kinematics::Vehicle;
use map_model::{BuildingID, BusRoute, BusStopID, LaneID, Map, Pathfinder}; use map_model::{BuildingID, BusRoute, BusStopID, LaneID, Map, Pathfinder};
use parking::ParkingSimState; use parking::ParkingSimState;
use rand::{Rng, SeedableRng, XorShiftRng}; use rand::Rng;
use router::Router; use router::Router;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::time::Instant; use std::time::Instant;
use transit::TransitSimState; use transit::TransitSimState;
use trips::{TripLeg, TripManager}; use trips::{TripLeg, TripManager};
use walking::{SidewalkSpot, WalkingSimState}; use walking::{SidewalkSpot, WalkingSimState};
use {AgentID, CarID, Event, ParkedCar, ParkingSpot, PedestrianID, RouteID, Tick, TripID}; use {
fork_rng, AgentID, CarID, Event, ParkedCar, ParkingSpot, PedestrianID, RouteID, Tick, TripID,
};
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
enum Command { enum Command {
@ -213,7 +215,7 @@ impl Spawner {
// Fork a new RNG for each candidate lane. This keeps things more deterministic, invariant // Fork a new RNG for each candidate lane. This keeps things more deterministic, invariant
// of lane edits. // of lane edits.
for l in in_lanes.into_iter() { for l in in_lanes.into_iter() {
let mut rng = XorShiftRng::from_seed([base_rng.next_u32() as u8; 16]); let mut rng = fork_rng(base_rng);
for spot in parking_sim.get_free_spots(l) { for spot in parking_sim.get_free_spots(l) {
total_capacity += 1; total_capacity += 1;