mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 07:52:05 +03:00
moving RNG helpers from sim to abstutil
This commit is contained in:
parent
df5a151f8b
commit
b2e3f25393
@ -6,7 +6,9 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
multimap = "0.4.0"
|
multimap = "0.4.0"
|
||||||
|
rand = { version = "0.5.1", features = ["serde1"] }
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_cbor = "0.8.2"
|
serde_cbor = "0.8.2"
|
||||||
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
yansi = "0.4.0"
|
yansi = "0.4.0"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use WeightedUsizeChoice;
|
||||||
|
|
||||||
// Trick to make a cloneable Any from
|
// Trick to make a cloneable Any from
|
||||||
// https://stackoverflow.com/questions/30353462/how-to-clone-a-struct-storing-a-boxed-trait-object/30353928#30353928.
|
// https://stackoverflow.com/questions/30353462/how-to-clone-a-struct-storing-a-boxed-trait-object/30353928#30353928.
|
||||||
@ -34,3 +35,4 @@ impl Cloneable for usize {}
|
|||||||
impl Cloneable for f64 {}
|
impl Cloneable for f64 {}
|
||||||
impl Cloneable for String {}
|
impl Cloneable for String {}
|
||||||
impl Cloneable for (String, Box<Cloneable>) {}
|
impl Cloneable for (String, Box<Cloneable>) {}
|
||||||
|
impl Cloneable for WeightedUsizeChoice {}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
extern crate log;
|
extern crate log;
|
||||||
extern crate multimap;
|
extern crate multimap;
|
||||||
|
extern crate rand;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate serde_cbor;
|
extern crate serde_cbor;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate yansi;
|
extern crate yansi;
|
||||||
|
|
||||||
@ -11,6 +14,7 @@ mod collections;
|
|||||||
mod error;
|
mod error;
|
||||||
mod io;
|
mod io;
|
||||||
mod logs;
|
mod logs;
|
||||||
|
mod random;
|
||||||
mod time;
|
mod time;
|
||||||
|
|
||||||
pub use abst_multimap::MultiMap;
|
pub use abst_multimap::MultiMap;
|
||||||
@ -23,6 +27,7 @@ pub use io::{
|
|||||||
write_json, FileWithProgress,
|
write_json, FileWithProgress,
|
||||||
};
|
};
|
||||||
pub use logs::{format_log_record, LogAdapter};
|
pub use logs::{format_log_record, LogAdapter};
|
||||||
|
pub use random::{fork_rng, WeightedUsizeChoice};
|
||||||
pub use time::{elapsed_seconds, Timer};
|
pub use time::{elapsed_seconds, Timer};
|
||||||
|
|
||||||
const PROGRESS_FREQUENCY_SECONDS: f64 = 0.2;
|
const PROGRESS_FREQUENCY_SECONDS: f64 = 0.2;
|
||||||
|
41
abstutil/src/random.rs
Normal file
41
abstutil/src/random.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use rand::distributions::{Distribution, Weighted, WeightedChoice};
|
||||||
|
use rand::{RngCore, SeedableRng, XorShiftRng};
|
||||||
|
|
||||||
|
// Need to explain this trick -- basically keeps consistency between two different simulations when
|
||||||
|
// each one might make slightly different sequences of calls to the RNG.
|
||||||
|
pub fn fork_rng(base_rng: &mut XorShiftRng) -> XorShiftRng {
|
||||||
|
XorShiftRng::from_seed([base_rng.next_u32() as u8; 16])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Represents the probability of sampling 0, 1, 2, 3... The sum can be anything.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct WeightedUsizeChoice {
|
||||||
|
pub weights: Vec<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WeightedUsizeChoice {
|
||||||
|
pub fn parse(string: &str) -> Option<WeightedUsizeChoice> {
|
||||||
|
let parts: Vec<&str> = string.split(",").collect();
|
||||||
|
if parts.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut weights: Vec<u32> = Vec::new();
|
||||||
|
for x in parts.into_iter() {
|
||||||
|
let x = x.parse::<u32>().ok()?;
|
||||||
|
weights.push(x);
|
||||||
|
}
|
||||||
|
Some(WeightedUsizeChoice { weights })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sample(&self, rng: &mut XorShiftRng) -> u32 {
|
||||||
|
let mut items: Vec<Weighted<u32>> = self
|
||||||
|
.weights
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, pr)| Weighted {
|
||||||
|
weight: *pr,
|
||||||
|
item: idx as u32,
|
||||||
|
}).collect();
|
||||||
|
WeightedChoice::new(&mut items).sample(rng)
|
||||||
|
}
|
||||||
|
}
|
@ -28,14 +28,12 @@ pub mod turn_cycler;
|
|||||||
pub mod warp;
|
pub mod warp;
|
||||||
|
|
||||||
use abstutil;
|
use abstutil;
|
||||||
|
use abstutil::WeightedUsizeChoice;
|
||||||
use downcast::Any;
|
use downcast::Any;
|
||||||
use ezgui::{Color, GfxCtx, WrappedWizard};
|
use ezgui::{Color, GfxCtx, WrappedWizard};
|
||||||
use map_model::{IntersectionID, Map};
|
use map_model::{IntersectionID, Map};
|
||||||
use objects::{Ctx, ID};
|
use objects::{Ctx, ID};
|
||||||
use sim::{
|
use sim::{ABTest, Neighborhood, NeighborhoodBuilder, OriginDestination, Scenario, Tick};
|
||||||
ABTest, Neighborhood, NeighborhoodBuilder, OriginDestination, Scenario, Tick,
|
|
||||||
WeightedUsizeChoice,
|
|
||||||
};
|
|
||||||
use ui::PluginCtx;
|
use ui::PluginCtx;
|
||||||
|
|
||||||
pub trait Plugin: Any {
|
pub trait Plugin: Any {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use abstutil::WeightedUsizeChoice;
|
||||||
use control::ControlMap;
|
use control::ControlMap;
|
||||||
use driving::DrivingGoal;
|
use driving::DrivingGoal;
|
||||||
use map_model::{BuildingID, BusRoute, BusStopID, LaneID, Map, RoadID};
|
use map_model::{BuildingID, BusRoute, BusStopID, LaneID, Map, RoadID};
|
||||||
@ -5,7 +6,7 @@ use std::collections::{BTreeSet, VecDeque};
|
|||||||
use walking::SidewalkSpot;
|
use walking::SidewalkSpot;
|
||||||
use {
|
use {
|
||||||
BorderSpawnOverTime, CarID, Event, OriginDestination, PedestrianID, RouteID, Scenario,
|
BorderSpawnOverTime, CarID, Event, OriginDestination, PedestrianID, RouteID, Scenario,
|
||||||
SeedParkedCars, Sim, SpawnOverTime, Tick, WeightedUsizeChoice,
|
SeedParkedCars, Sim, SpawnOverTime, Tick,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helpers to run the sim
|
// Helpers to run the sim
|
||||||
|
@ -58,7 +58,6 @@ pub use make::{
|
|||||||
OriginDestination, Scenario, SeedParkedCars, SimFlags, SpawnOverTime,
|
OriginDestination, Scenario, SeedParkedCars, SimFlags, SpawnOverTime,
|
||||||
};
|
};
|
||||||
use map_model::{BuildingID, LaneID, Trace, TurnID};
|
use map_model::{BuildingID, LaneID, Trace, TurnID};
|
||||||
use rand::{RngCore, SeedableRng, XorShiftRng};
|
|
||||||
pub use sim::{Benchmark, Sim, Summary};
|
pub use sim::{Benchmark, Sim, Summary};
|
||||||
pub use stats::SimStats;
|
pub use stats::SimStats;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -335,42 +334,3 @@ 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 {}
|
||||||
impl Cloneable for WeightedUsizeChoice {}
|
|
||||||
|
|
||||||
fn fork_rng(base_rng: &mut XorShiftRng) -> XorShiftRng {
|
|
||||||
XorShiftRng::from_seed([base_rng.next_u32() as u8; 16])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Represents the probability of sampling 0, 1, 2, 3... The sum can be anything.
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct WeightedUsizeChoice {
|
|
||||||
weights: Vec<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WeightedUsizeChoice {
|
|
||||||
pub fn parse(string: &str) -> Option<WeightedUsizeChoice> {
|
|
||||||
let parts: Vec<&str> = string.split(",").collect();
|
|
||||||
if parts.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let mut weights: Vec<u32> = Vec::new();
|
|
||||||
for x in parts.into_iter() {
|
|
||||||
let x = x.parse::<u32>().ok()?;
|
|
||||||
weights.push(x);
|
|
||||||
}
|
|
||||||
Some(WeightedUsizeChoice { weights })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn weighted_sample(choices: &WeightedUsizeChoice, rng: &mut XorShiftRng) -> u32 {
|
|
||||||
use rand::distributions::{Distribution, Weighted, WeightedChoice};
|
|
||||||
let mut items: Vec<Weighted<u32>> = choices
|
|
||||||
.weights
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(idx, pr)| Weighted {
|
|
||||||
weight: *pr,
|
|
||||||
item: idx as u32,
|
|
||||||
}).collect();
|
|
||||||
WeightedChoice::new(&mut items).sample(rng)
|
|
||||||
}
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use abstutil;
|
use abstutil;
|
||||||
|
use abstutil::WeightedUsizeChoice;
|
||||||
use driving::DrivingGoal;
|
use driving::DrivingGoal;
|
||||||
use map_model::{BuildingID, IntersectionID, LaneType, Map, RoadID};
|
use map_model::{BuildingID, IntersectionID, LaneType, Map, RoadID};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rand::XorShiftRng;
|
use rand::XorShiftRng;
|
||||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||||
use walking::SidewalkSpot;
|
use walking::SidewalkSpot;
|
||||||
use {CarID, Neighborhood, Sim, Tick, WeightedUsizeChoice};
|
use {CarID, Neighborhood, Sim, Tick};
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||||
pub struct Scenario {
|
pub struct Scenario {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use abstutil::elapsed_seconds;
|
use abstutil::{elapsed_seconds, fork_rng, WeightedUsizeChoice};
|
||||||
use dimensioned::si;
|
use dimensioned::si;
|
||||||
use driving::{CreateCar, DrivingGoal, DrivingSimState};
|
use driving::{CreateCar, DrivingGoal, DrivingSimState};
|
||||||
use kinematics::Vehicle;
|
use kinematics::Vehicle;
|
||||||
@ -12,8 +12,7 @@ use transit::TransitSimState;
|
|||||||
use trips::{TripLeg, TripManager};
|
use trips::{TripLeg, TripManager};
|
||||||
use walking::{SidewalkSpot, WalkingSimState};
|
use walking::{SidewalkSpot, WalkingSimState};
|
||||||
use {
|
use {
|
||||||
fork_rng, weighted_sample, AgentID, CarID, Distance, Event, ParkedCar, ParkingSpot,
|
AgentID, CarID, Distance, Event, ParkedCar, ParkingSpot, PedestrianID, RouteID, Tick, TripID,
|
||||||
PedestrianID, RouteID, Tick, TripID, WeightedUsizeChoice,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
||||||
@ -329,7 +328,7 @@ impl Spawner {
|
|||||||
|
|
||||||
let mut new_cars = 0;
|
let mut new_cars = 0;
|
||||||
for b in owner_buildings {
|
for b in owner_buildings {
|
||||||
for _ in 0..weighted_sample(&cars_per_building, base_rng) {
|
for _ in 0..cars_per_building.sample(base_rng) {
|
||||||
if let Some(spot) =
|
if let Some(spot) =
|
||||||
find_spot_near_building(*b, &mut open_spots_per_road, neighborhoods_roads, map)
|
find_spot_near_building(*b, &mut open_spots_per_road, neighborhoods_roads, map)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user