From 6695c0906e7f32eac53c909fbdea1d4f8630b4c5 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Mon, 10 Jun 2024 15:03:32 +0200 Subject: [PATCH 01/17] add internal interface experiment --- src/experiments/internal_interface.rs | 150 ++++++++++++++++++++++++++ src/experiments/mod.rs | 1 + 2 files changed, 151 insertions(+) create mode 100644 src/experiments/internal_interface.rs diff --git a/src/experiments/internal_interface.rs b/src/experiments/internal_interface.rs new file mode 100644 index 0000000..f931e99 --- /dev/null +++ b/src/experiments/internal_interface.rs @@ -0,0 +1,150 @@ +use std::cell::RefCell; +use std::rc::Rc; + +enum State { + ACTIVITY, + TELEPORTATION, +} + +struct Agent { + id: String, + state: State, +} + +impl Agent { + fn new(id: String, state: State) -> Self { + Agent { id, state } + } +} + +struct InternalInterface { + activity_engine: Rc>, + teleportation_engine: Rc>, +} + +impl InternalInterface { + fn arrange_next_agent_state(&self, agent: Agent) { + match agent.state { + State::ACTIVITY => self.activity_engine.borrow_mut().receive_agent(agent), + State::TELEPORTATION => self.teleportation_engine.borrow_mut().receive_agent(agent), + } + } +} + +struct Simulation { + activity_engine: Rc>, + teleportation_engine: Rc>, + internal_interface: Rc>, +} + +impl Simulation { + fn new( + activity_engine: Rc>, + teleportation_engine: Rc>, + internal_interface: Rc>, + ) -> Self { + Simulation { + activity_engine, + teleportation_engine, + internal_interface, + } + } + + fn run(&mut self) { + let mut now = 0; + while now < 20 { + self.activity_engine + .borrow_mut() + .do_step(now, Rc::clone(&self.internal_interface)); + self.teleportation_engine + .borrow_mut() + .do_step(now, Rc::clone(&self.internal_interface)); + now += 1; + } + } +} + +trait Engine { + fn do_step(&mut self, now: u32, internal_interface: Rc>); +} + +struct ActivityEngine { + agents: Vec, +} + +impl ActivityEngine { + fn receive_agent(&mut self, agent: Agent) { + println!("Activity engine: Received agent"); + self.agents.push(agent); + } +} + +impl Engine for ActivityEngine { + fn do_step(&mut self, now: u32, internal_interface: Rc>) { + if now % 10 == 0 { + println!("Activity engine: Time step {}, stop activity", now); + self.agents.get_mut(0).unwrap().state = State::TELEPORTATION; + internal_interface + .borrow_mut() + .arrange_next_agent_state(self.agents.remove(0)) + } else { + // println!("Activity engine: Time step {}, doing nothing", now) + } + } +} + +struct TeleportationEngine { + agents: Vec, +} + +impl TeleportationEngine { + fn receive_agent(&mut self, agent: Agent) { + println!("Teleportation engine: Received agent"); + self.agents.push(agent); + } +} + +impl Engine for TeleportationEngine { + fn do_step(&mut self, now: u32, internal_interface: Rc>) { + if now % 10 == 5 { + println!( + "Teleportation engine: Time step {}, stop teleportation", + now + ); + self.agents.get_mut(0).unwrap().state = State::ACTIVITY; + internal_interface + .borrow_mut() + .arrange_next_agent_state(self.agents.remove(0)) + } else { + // println!("Teleportation engine: Time step {}, doing nothing", now) + } + } +} + +fn run() {} + +#[cfg(test)] +mod tests { + use crate::experiments::internal_interface::{ + ActivityEngine, Agent, InternalInterface, Simulation, State, TeleportationEngine, + }; + use std::cell::RefCell; + use std::rc::Rc; + + #[test] + fn test_run() { + let activity_engine = Rc::new(RefCell::new(ActivityEngine { + agents: vec![Agent::new(String::from("agent"), State::ACTIVITY)], + })); + let teleportation_engine = + Rc::new(RefCell::new(TeleportationEngine { agents: Vec::new() })); + let internal_interface = Rc::new(RefCell::new(InternalInterface { + activity_engine: Rc::clone(&activity_engine), + teleportation_engine: Rc::clone(&teleportation_engine), + })); + + let mut sim = Simulation::new(activity_engine, teleportation_engine, internal_interface); + + sim.run(); + } +} diff --git a/src/experiments/mod.rs b/src/experiments/mod.rs index 717e9cc..21976fb 100644 --- a/src/experiments/mod.rs +++ b/src/experiments/mod.rs @@ -1,5 +1,6 @@ mod concurrent_dispatch; mod concurrent_ping_pong; +mod internal_interface; mod lifetimes_example; mod link_automat_with_adjacency_list; mod link_automat_with_references; From f4bb2647b9351df58b61bf20f6179868eff73773 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Mon, 10 Jun 2024 15:15:27 +0200 Subject: [PATCH 02/17] use weak counts for internal interface --- src/experiments/internal_interface.rs | 40 +++++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/experiments/internal_interface.rs b/src/experiments/internal_interface.rs index f931e99..dfacdec 100644 --- a/src/experiments/internal_interface.rs +++ b/src/experiments/internal_interface.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use std::rc::Rc; +use std::rc::{Rc, Weak}; enum State { ACTIVITY, @@ -53,23 +53,21 @@ impl Simulation { fn run(&mut self) { let mut now = 0; while now < 20 { - self.activity_engine - .borrow_mut() - .do_step(now, Rc::clone(&self.internal_interface)); - self.teleportation_engine - .borrow_mut() - .do_step(now, Rc::clone(&self.internal_interface)); + self.activity_engine.borrow_mut().do_step(now); + self.teleportation_engine.borrow_mut().do_step(now); now += 1; } } } trait Engine { - fn do_step(&mut self, now: u32, internal_interface: Rc>); + fn do_step(&mut self, now: u32); } struct ActivityEngine { agents: Vec, + //to prevent memory leaks, we use Weak instead of Rc (https://doc.rust-lang.org/book/ch15-06-reference-cycles.html) + internal_interface: Weak>, } impl ActivityEngine { @@ -80,11 +78,13 @@ impl ActivityEngine { } impl Engine for ActivityEngine { - fn do_step(&mut self, now: u32, internal_interface: Rc>) { + fn do_step(&mut self, now: u32) { if now % 10 == 0 { println!("Activity engine: Time step {}, stop activity", now); self.agents.get_mut(0).unwrap().state = State::TELEPORTATION; - internal_interface + self.internal_interface + .upgrade() + .unwrap() .borrow_mut() .arrange_next_agent_state(self.agents.remove(0)) } else { @@ -95,6 +95,8 @@ impl Engine for ActivityEngine { struct TeleportationEngine { agents: Vec, + //to prevent memory leaks, we use Weak instead of Rc (https://doc.rust-lang.org/book/ch15-06-reference-cycles.html) + internal_interface: Weak>, } impl TeleportationEngine { @@ -105,14 +107,16 @@ impl TeleportationEngine { } impl Engine for TeleportationEngine { - fn do_step(&mut self, now: u32, internal_interface: Rc>) { + fn do_step(&mut self, now: u32) { if now % 10 == 5 { println!( "Teleportation engine: Time step {}, stop teleportation", now ); self.agents.get_mut(0).unwrap().state = State::ACTIVITY; - internal_interface + self.internal_interface + .upgrade() + .unwrap() .borrow_mut() .arrange_next_agent_state(self.agents.remove(0)) } else { @@ -129,20 +133,26 @@ mod tests { ActivityEngine, Agent, InternalInterface, Simulation, State, TeleportationEngine, }; use std::cell::RefCell; - use std::rc::Rc; + use std::rc::{Rc, Weak}; #[test] fn test_run() { let activity_engine = Rc::new(RefCell::new(ActivityEngine { agents: vec![Agent::new(String::from("agent"), State::ACTIVITY)], + internal_interface: Weak::new(), + })); + let teleportation_engine = Rc::new(RefCell::new(TeleportationEngine { + agents: Vec::new(), + internal_interface: Weak::new(), })); - let teleportation_engine = - Rc::new(RefCell::new(TeleportationEngine { agents: Vec::new() })); let internal_interface = Rc::new(RefCell::new(InternalInterface { activity_engine: Rc::clone(&activity_engine), teleportation_engine: Rc::clone(&teleportation_engine), })); + activity_engine.borrow_mut().internal_interface = Rc::downgrade(&internal_interface); + teleportation_engine.borrow_mut().internal_interface = Rc::downgrade(&internal_interface); + let mut sim = Simulation::new(activity_engine, teleportation_engine, internal_interface); sim.run(); From 285bce592f0d7c2a890f7c73016a52b9d5bc7cbb Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Mon, 10 Jun 2024 16:08:08 +0200 Subject: [PATCH 03/17] make engines dyn --- src/experiments/internal_interface.rs | 87 +++++++++++++++------------ 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/src/experiments/internal_interface.rs b/src/experiments/internal_interface.rs index dfacdec..029bb59 100644 --- a/src/experiments/internal_interface.rs +++ b/src/experiments/internal_interface.rs @@ -18,8 +18,8 @@ impl Agent { } struct InternalInterface { - activity_engine: Rc>, - teleportation_engine: Rc>, + activity_engine: Rc>>, + teleportation_engine: Rc>>, } impl InternalInterface { @@ -32,29 +32,27 @@ impl InternalInterface { } struct Simulation { - activity_engine: Rc>, - teleportation_engine: Rc>, + engines: Vec>>>, internal_interface: Rc>, } impl Simulation { fn new( - activity_engine: Rc>, - teleportation_engine: Rc>, + engines: Vec>>>, internal_interface: Rc>, ) -> Self { Simulation { - activity_engine, - teleportation_engine, internal_interface, + engines, } } fn run(&mut self) { let mut now = 0; while now < 20 { - self.activity_engine.borrow_mut().do_step(now); - self.teleportation_engine.borrow_mut().do_step(now); + for engine in &self.engines { + engine.borrow_mut().do_step(now); + } now += 1; } } @@ -62,6 +60,8 @@ impl Simulation { trait Engine { fn do_step(&mut self, now: u32); + fn set_internal_interface(&mut self, internal_interface: Weak>); + fn receive_agent(&mut self, agent: Agent); } struct ActivityEngine { @@ -70,13 +70,6 @@ struct ActivityEngine { internal_interface: Weak>, } -impl ActivityEngine { - fn receive_agent(&mut self, agent: Agent) { - println!("Activity engine: Received agent"); - self.agents.push(agent); - } -} - impl Engine for ActivityEngine { fn do_step(&mut self, now: u32) { if now % 10 == 0 { @@ -91,6 +84,15 @@ impl Engine for ActivityEngine { // println!("Activity engine: Time step {}, doing nothing", now) } } + + fn set_internal_interface(&mut self, internal_interface: Weak>) { + self.internal_interface = internal_interface; + } + + fn receive_agent(&mut self, agent: Agent) { + println!("Activity engine: Received agent"); + self.agents.push(agent); + } } struct TeleportationEngine { @@ -99,13 +101,6 @@ struct TeleportationEngine { internal_interface: Weak>, } -impl TeleportationEngine { - fn receive_agent(&mut self, agent: Agent) { - println!("Teleportation engine: Received agent"); - self.agents.push(agent); - } -} - impl Engine for TeleportationEngine { fn do_step(&mut self, now: u32) { if now % 10 == 5 { @@ -123,37 +118,53 @@ impl Engine for TeleportationEngine { // println!("Teleportation engine: Time step {}, doing nothing", now) } } -} -fn run() {} + fn set_internal_interface(&mut self, internal_interface: Weak>) { + self.internal_interface = internal_interface; + } + + fn receive_agent(&mut self, agent: Agent) { + println!("Teleportation engine: Received agent"); + self.agents.push(agent); + } +} #[cfg(test)] mod tests { use crate::experiments::internal_interface::{ - ActivityEngine, Agent, InternalInterface, Simulation, State, TeleportationEngine, + ActivityEngine, Agent, Engine, InternalInterface, Simulation, State, TeleportationEngine, }; use std::cell::RefCell; use std::rc::{Rc, Weak}; #[test] fn test_run() { - let activity_engine = Rc::new(RefCell::new(ActivityEngine { - agents: vec![Agent::new(String::from("agent"), State::ACTIVITY)], - internal_interface: Weak::new(), - })); - let teleportation_engine = Rc::new(RefCell::new(TeleportationEngine { - agents: Vec::new(), - internal_interface: Weak::new(), - })); + let activity_engine: Rc>> = + Rc::new(RefCell::new(Box::new(ActivityEngine { + agents: vec![Agent::new(String::from("agent"), State::ACTIVITY)], + internal_interface: Weak::new(), + }))); + let teleportation_engine: Rc>> = + Rc::new(RefCell::new(Box::new(TeleportationEngine { + agents: Vec::new(), + internal_interface: Weak::new(), + }))); let internal_interface = Rc::new(RefCell::new(InternalInterface { activity_engine: Rc::clone(&activity_engine), teleportation_engine: Rc::clone(&teleportation_engine), })); - activity_engine.borrow_mut().internal_interface = Rc::downgrade(&internal_interface); - teleportation_engine.borrow_mut().internal_interface = Rc::downgrade(&internal_interface); + activity_engine + .borrow_mut() + .set_internal_interface(Rc::downgrade(&internal_interface)); + teleportation_engine + .borrow_mut() + .set_internal_interface(Rc::downgrade(&internal_interface)); - let mut sim = Simulation::new(activity_engine, teleportation_engine, internal_interface); + let mut sim = Simulation::new( + vec![activity_engine, teleportation_engine], + internal_interface, + ); sim.run(); } From 211596533f56315afe73c0113dd76960e1e711a4 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 11 Jun 2024 16:51:46 +0200 Subject: [PATCH 04/17] implemented engines in simulation --- src/experiments/internal_interface.rs | 23 +- src/simulation/controller.rs | 7 +- src/simulation/engines/activity_engine.rs | 80 ++++++ src/simulation/engines/leg_engine.rs | 127 +++++++++ src/simulation/engines/mod.rs | 42 +++ src/simulation/engines/network_engine.rs | 66 +++++ .../engines/teleportation_engine.rs | 69 +++++ src/simulation/mod.rs | 1 + src/simulation/network/sim_network.rs | 6 +- src/simulation/population/population_data.rs | 18 ++ src/simulation/simulation.rs | 249 ++++-------------- tests/test_simulation.rs | 9 +- 12 files changed, 485 insertions(+), 212 deletions(-) create mode 100644 src/simulation/engines/activity_engine.rs create mode 100644 src/simulation/engines/leg_engine.rs create mode 100644 src/simulation/engines/mod.rs create mode 100644 src/simulation/engines/network_engine.rs create mode 100644 src/simulation/engines/teleportation_engine.rs diff --git a/src/experiments/internal_interface.rs b/src/experiments/internal_interface.rs index 029bb59..969debf 100644 --- a/src/experiments/internal_interface.rs +++ b/src/experiments/internal_interface.rs @@ -18,8 +18,8 @@ impl Agent { } struct InternalInterface { - activity_engine: Rc>>, - teleportation_engine: Rc>>, + activity_engine: Rc>, + teleportation_engine: Rc>, } impl InternalInterface { @@ -32,13 +32,13 @@ impl InternalInterface { } struct Simulation { - engines: Vec>>>, + engines: Vec>>, internal_interface: Rc>, } impl Simulation { fn new( - engines: Vec>>>, + engines: Vec>>, internal_interface: Rc>, ) -> Self { Simulation { @@ -139,16 +139,15 @@ mod tests { #[test] fn test_run() { - let activity_engine: Rc>> = - Rc::new(RefCell::new(Box::new(ActivityEngine { - agents: vec![Agent::new(String::from("agent"), State::ACTIVITY)], - internal_interface: Weak::new(), - }))); - let teleportation_engine: Rc>> = - Rc::new(RefCell::new(Box::new(TeleportationEngine { + let activity_engine: Rc> = Rc::new(RefCell::new(ActivityEngine { + agents: vec![Agent::new(String::from("agent"), State::ACTIVITY)], + internal_interface: Weak::new(), + })); + let teleportation_engine: Rc> = + Rc::new(RefCell::new(TeleportationEngine { agents: Vec::new(), internal_interface: Weak::new(), - }))); + })); let internal_interface = Rc::new(RefCell::new(InternalInterface { activity_engine: Rc::clone(&activity_engine), teleportation_engine: Rc::clone(&teleportation_engine), diff --git a/src/simulation/controller.rs b/src/simulation/controller.rs index 6cefa2c..bc62ff9 100644 --- a/src/simulation/controller.rs +++ b/src/simulation/controller.rs @@ -1,3 +1,4 @@ +use std::cell::RefCell; use std::path::{Path, PathBuf}; use std::rc::Rc; use std::thread::{sleep, JoinHandle}; @@ -138,7 +139,7 @@ fn execute_partition(comm: C, args: &CommandLineAr population.persons.len() ); - let mut events = EventsPublisher::new(); + let events = Rc::new(RefCell::new(EventsPublisher::new())); if config.output().write_events == WriteEvents::Proto { let events_file = format!("events.{rank}.binpb"); @@ -147,10 +148,10 @@ fn execute_partition(comm: C, args: &CommandLineAr &output_path.join(events_file).to_str().unwrap().to_string(), ); info!("adding events writer with path: {events_path:?}"); - events.add_subscriber(Box::new(ProtoEventsWriter::new(&events_path))); + events.borrow_mut().add_subscriber(Box::new(ProtoEventsWriter::new(&events_path))); } let travel_time_collector = Box::new(TravelTimeCollector::new()); - events.add_subscriber(travel_time_collector); + events.borrow_mut().add_subscriber(travel_time_collector); let rc = Rc::new(comm); diff --git a/src/simulation/engines/activity_engine.rs b/src/simulation/engines/activity_engine.rs new file mode 100644 index 0000000..de4f5ac --- /dev/null +++ b/src/simulation/engines/activity_engine.rs @@ -0,0 +1,80 @@ +use crate::simulation::engines::{Engine, InternalInterface}; +use crate::simulation::id::Id; +use crate::simulation::messaging::events::EventsPublisher; +use crate::simulation::time_queue::TimeQueue; +use crate::simulation::wire_types::events::Event; +use crate::simulation::wire_types::population::Person; +use std::cell::RefCell; +use std::rc::{Rc, Weak}; + +pub struct ActivityEngine { + activity_q: TimeQueue, + events: Rc>, + internal_interface: Weak>, +} + +impl Engine for ActivityEngine { + fn do_step(&mut self, now: u32) { + let agents = self.wake_up(now); + for mut agent in agents { + agent.advance_plan(); + + self.internal_interface + .upgrade() + .unwrap() + .borrow_mut() + .arrange_next_agent_state(now, agent); + } + } + + fn receive_agent(&mut self, now: u32, agent: Person) { + self.events.borrow_mut().publish_event( + now, + &Event::new_arrival( + agent.id, + agent.curr_act().link_id, + agent.previous_leg().mode, + ), + ); + + // emmit act start event + let act = agent.curr_act(); + let act_type: Id = Id::get(act.act_type); + self.events.borrow_mut().publish_event( + now, + &Event::new_act_start(agent.id, act.link_id, act_type.internal()), + ); + self.activity_q.add(agent, now); + } + + fn set_internal_interface(&mut self, internal_interface: Weak>) { + self.internal_interface = internal_interface + } +} + +impl ActivityEngine { + pub fn new(activity_q: TimeQueue, events: Rc>) -> Self { + ActivityEngine { + activity_q, + events, + internal_interface: Weak::new(), + } + } + + pub fn wake_up(&mut self, now: u32) -> Vec { + let mut agents = self.activity_q.pop(now); + + for agent in agents.iter_mut() { + // self.update_agent(&mut agent, now); + //TODO (used for routing) + + let act_type: Id = Id::get(agent.curr_act().act_type); + self.events.borrow_mut().publish_event( + now, + &Event::new_act_end(agent.id, agent.curr_act().link_id, act_type.internal()), + ); + } + + agents + } +} diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs new file mode 100644 index 0000000..bd43de1 --- /dev/null +++ b/src/simulation/engines/leg_engine.rs @@ -0,0 +1,127 @@ +use crate::simulation::engines::network_engine::NetworkEngine; +use crate::simulation::engines::teleportation_engine::TeleportationEngine; +use crate::simulation::engines::{Engine, InternalInterface}; +use crate::simulation::id::Id; +use crate::simulation::messaging::communication::communicators::SimCommunicator; +use crate::simulation::messaging::communication::message_broker::NetMessageBroker; +use crate::simulation::messaging::events::EventsPublisher; +use crate::simulation::network::sim_network::SimNetworkPartition; +use crate::simulation::vehicles::garage::Garage; +use crate::simulation::wire_types::events::Event; +use crate::simulation::wire_types::messages::Vehicle; +use crate::simulation::wire_types::population::Person; +use crate::simulation::wire_types::vehicles::LevelOfDetail; +use std::cell::RefCell; +use std::rc::{Rc, Weak}; + +pub struct LegEngine { + teleportation_engine: TeleportationEngine, + network_engine: NetworkEngine, + garage: Garage, + net_message_broker: NetMessageBroker, + events: Rc>, + internal_interface: Weak>, +} + +impl Engine for LegEngine { + fn do_step(&mut self, now: u32) { + let teleported_agents = self.teleportation_engine.do_step(now); + let network_agents = self.network_engine.move_nodes(now, &mut self.garage); + + for mut agent in teleported_agents.into_iter().chain(network_agents) { + agent.advance_plan(); + + self.internal_interface + .upgrade() + .unwrap() + .borrow_mut() + .arrange_next_agent_state(now, agent); + } + + self.network_engine + .move_links(now, &mut self.net_message_broker); + let sync_messages = self.net_message_broker.send_recv(now); + + for msg in sync_messages { + self.network_engine + .network + .apply_storage_cap_updates(msg.storage_capacities); + + for veh in msg.vehicles { + self.pass_vehicle_to_engine(now, veh, false); + } + } + } + + fn receive_agent(&mut self, now: u32, agent: Person) { + let vehicle = self.place_agent_in_vehicle(now, agent); + self.pass_vehicle_to_engine(now, vehicle, true); + } + + fn set_internal_interface(&mut self, internal_interface: Weak>) { + self.internal_interface = internal_interface + } +} + +impl LegEngine { + //TODO route begin is a bit hacky + fn pass_vehicle_to_engine(&mut self, now: u32, vehicle: Vehicle, route_begin: bool) { + let veh_type_id = Id::get(vehicle.r#type); + let veh_type = self.garage.vehicle_types.get(&veh_type_id).unwrap(); + + match veh_type.lod() { + LevelOfDetail::Network => { + self.network_engine + .receive_vehicle(now, vehicle, route_begin); + } + LevelOfDetail::Teleported => { + self.teleportation_engine.receive_vehicle( + now, + vehicle, + &mut self.net_message_broker, + ); + } + } + } +} + +impl LegEngine { + pub fn new( + network: SimNetworkPartition, + garage: Garage, + net_message_broker: NetMessageBroker, + events: Rc>, + ) -> Self { + LegEngine { + teleportation_engine: TeleportationEngine::new(events.clone()), + network_engine: NetworkEngine::new(network, events.clone()), + internal_interface: Weak::new(), + garage, + net_message_broker, + events, + } + } + + pub fn net_message_broker(&self) -> &NetMessageBroker { + &self.net_message_broker + } + + pub fn network(&self) -> &SimNetworkPartition { + &self.network_engine.network + } + + fn place_agent_in_vehicle(&mut self, now: u32, agent: Person) -> Vehicle { + assert_ne!(agent.curr_plan_elem % 2, 0); + + let leg = agent.curr_leg(); + let route = leg.route.as_ref().unwrap(); + let leg_mode: Id = Id::get(leg.mode); + self.events.borrow_mut().publish_event( + now, + &Event::new_departure(agent.id, route.start_link(), leg_mode.internal()), + ); + + let veh_id = Id::get(route.veh_id); + self.garage.unpark_veh(agent, &veh_id) + } +} diff --git a/src/simulation/engines/mod.rs b/src/simulation/engines/mod.rs new file mode 100644 index 0000000..c3e0275 --- /dev/null +++ b/src/simulation/engines/mod.rs @@ -0,0 +1,42 @@ +use crate::simulation::population::population_data::State; +use crate::simulation::wire_types::population::Person; +use std::cell::RefCell; +use std::rc::{Rc, Weak}; + +pub mod activity_engine; +pub mod leg_engine; +pub mod network_engine; +pub mod teleportation_engine; + +pub trait Engine { + fn do_step(&mut self, now: u32); + fn receive_agent(&mut self, now: u32, agent: Person); + fn set_internal_interface(&mut self, internal_interface: Weak>); +} + +pub struct InternalInterface { + activity_engine: Rc>, + teleportation_engine: Rc>, +} + +impl InternalInterface { + fn arrange_next_agent_state(&self, now: u32, agent: Person) { + match agent.state() { + State::ACTIVITY => self.activity_engine.borrow_mut().receive_agent(now, agent), + State::LEG => self + .teleportation_engine + .borrow_mut() + .receive_agent(now, agent), + } + } + + pub(crate) fn new( + activity_engine: Rc>, + teleportation_engine: Rc>, + ) -> Self { + InternalInterface { + activity_engine, + teleportation_engine, + } + } +} diff --git a/src/simulation/engines/network_engine.rs b/src/simulation/engines/network_engine.rs new file mode 100644 index 0000000..0f2b501 --- /dev/null +++ b/src/simulation/engines/network_engine.rs @@ -0,0 +1,66 @@ +use crate::simulation::messaging::communication::communicators::SimCommunicator; +use crate::simulation::messaging::communication::message_broker::NetMessageBroker; +use crate::simulation::messaging::events::EventsPublisher; +use crate::simulation::network::sim_network::SimNetworkPartition; +use crate::simulation::vehicles::garage::Garage; +use crate::simulation::wire_types::events::Event; +use crate::simulation::wire_types::messages::Vehicle; +use crate::simulation::wire_types::population::Person; +use std::cell::RefCell; +use std::ops::DerefMut; +use std::rc::Rc; + +pub struct NetworkEngine { + pub(crate) network: SimNetworkPartition, + pub events: Rc>, +} + +impl NetworkEngine { + pub fn new(network: SimNetworkPartition, events: Rc>) -> Self { + NetworkEngine { network, events } + } + + pub fn receive_vehicle(&mut self, now: u32, vehicle: Vehicle, route_begin: bool) { + if route_begin { + self.events.borrow_mut().publish_event( + now, + &Event::new_person_enters_veh(vehicle.driver().id, vehicle.id), + ) + } + //we don't pass the event publisher because a link enter event should not be published + self.network.send_veh_en_route(vehicle, None, now) + } + + pub(crate) fn move_nodes(&mut self, now: u32, garage: &mut Garage) -> Vec { + let exited_vehicles = self + .network + .move_nodes(self.events.borrow_mut().deref_mut(), now); + let mut agents = vec![]; + + for veh in exited_vehicles { + self.events + .borrow_mut() + .publish_event(now, &Event::new_person_leaves_veh(veh.driver().id, veh.id)); + + let agent = garage.park_veh(veh); + agents.push(agent); + } + agents + } + + pub(crate) fn move_links( + &mut self, + now: u32, + net_message_broker: &mut NetMessageBroker, + ) { + let (vehicles, storage_cap_updates) = self.network.move_links(now); + + for veh in vehicles { + net_message_broker.add_veh(veh, now); + } + + for cap in storage_cap_updates { + net_message_broker.add_cap_update(cap, now); + } + } +} diff --git a/src/simulation/engines/teleportation_engine.rs b/src/simulation/engines/teleportation_engine.rs new file mode 100644 index 0000000..0480a36 --- /dev/null +++ b/src/simulation/engines/teleportation_engine.rs @@ -0,0 +1,69 @@ +use crate::simulation::id::Id; +use crate::simulation::messaging::communication::communicators::SimCommunicator; +use crate::simulation::messaging::communication::message_broker::NetMessageBroker; +use crate::simulation::messaging::events::EventsPublisher; +use crate::simulation::simulation::Simulation; +use crate::simulation::time_queue::TimeQueue; +use crate::simulation::wire_types::events::Event; +use crate::simulation::wire_types::messages::Vehicle; +use crate::simulation::wire_types::population::Person; +use std::cell::RefCell; +use std::rc::Rc; + +pub struct TeleportationEngine { + queue: TimeQueue, + pub events: Rc>, +} + +impl TeleportationEngine { + pub fn new(events: Rc>) -> Self { + TeleportationEngine { + queue: TimeQueue::new(), + events, + } + } + + pub fn receive_vehicle( + &mut self, + now: u32, + mut vehicle: Vehicle, + net_message_broker: &mut NetMessageBroker, + ) { + if Simulation::is_local_route(&vehicle, net_message_broker) { + self.queue.add(vehicle, now); + } else { + // set the pointer of the route to the last element, so that the current link + // is the destination of this leg. Setting this to the last element makes this + // logic independent of whether the agent has a Generic-Route with only start + // and end link or a full Network-Route, which is often the case for ride modes. + vehicle.route_index_to_last(); + net_message_broker.add_veh(vehicle, now); + } + } + + pub fn do_step(&mut self, now: u32) -> Vec { + let teleportation_vehicles = self.queue.pop(now); + let mut agents = vec![]; + for vehicle in teleportation_vehicles { + let agent = vehicle.driver.unwrap(); + + // emmit travelled + let leg = agent.curr_leg(); + let route = leg.route.as_ref().unwrap(); + let mode: Id = Id::get(leg.mode); + self.events.borrow_mut().publish_event( + now, + &Event::new_travelled(agent.id, route.distance, mode.internal()), + ); + + //TODO better do in activity engine + // emmit arrival + // self.events.borrow_mut().publish_event( + // now, + // &Event::new_arrival(agent.id, route.end_link(), mode.internal()), + // ); + agents.push(agent); + } + agents + } +} diff --git a/src/simulation/mod.rs b/src/simulation/mod.rs index 15ea9c3..6059eaa 100644 --- a/src/simulation/mod.rs +++ b/src/simulation/mod.rs @@ -1,5 +1,6 @@ pub mod config; pub mod controller; +pub mod engines; pub mod id; pub mod io; pub mod logging; diff --git a/src/simulation/network/sim_network.rs b/src/simulation/network/sim_network.rs index 2dc3026..e4938dd 100644 --- a/src/simulation/network/sim_network.rs +++ b/src/simulation/network/sim_network.rs @@ -1,4 +1,6 @@ +use std::cell::RefCell; use std::collections::HashSet; +use std::rc::Rc; use nohash_hasher::{IntMap, IntSet}; use rand::rngs::ThreadRng; @@ -175,7 +177,7 @@ impl SimNetworkPartition { pub fn send_veh_en_route( &mut self, vehicle: Vehicle, - events_publisher: Option<&mut EventsPublisher>, + events_publisher: Option>>, now: u32, ) { let link_id = vehicle.curr_link_id().unwrap_or_else(|| { @@ -194,7 +196,7 @@ impl SimNetworkPartition { }); if let Some(publisher) = events_publisher { - publisher.publish_event( + publisher.borrow_mut().publish_event( now, &Event::new_link_enter(link.id().internal(), vehicle.id), ); diff --git a/src/simulation/population/population_data.rs b/src/simulation/population/population_data.rs index 510427d..9e4a04b 100644 --- a/src/simulation/population/population_data.rs +++ b/src/simulation/population/population_data.rs @@ -12,6 +12,11 @@ use crate::simulation::wire_types::messages::Vehicle; use crate::simulation::wire_types::population::{Activity, Leg, Person, Plan, Route}; use crate::simulation::wire_types::vehicles::VehicleType; +pub enum State { + ACTIVITY, + LEG, +} + impl Person { pub fn from_io(io_person: &IOPerson) -> Person { let person_id = Id::get_from_ext(&io_person.id); @@ -41,6 +46,14 @@ impl Person { self.id } + pub fn state(&self) -> State { + if self.curr_plan_elem % 2 == 0 { + State::ACTIVITY + } else { + State::LEG + } + } + pub fn add_act_after_curr(&mut self, to_add: Vec) { let next_act_index = self.next_act_index() as usize; self.plan @@ -118,6 +131,11 @@ impl Person { .unwrap() } + pub fn previous_leg(&self) -> &Leg { + let leg_index = self.next_leg_index() - 1; + self.get_leg_at_index(leg_index) + } + pub fn next_leg(&self) -> &Leg { let next_leg_index = self.next_leg_index(); self.get_leg_at_index(next_leg_index) diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index fa0f7fa..e6f67f1 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -1,10 +1,14 @@ +use std::cell::RefCell; use std::fmt::Debug; use std::fmt::Formatter; +use std::rc::Rc; use tracing::{info, instrument}; use crate::simulation::config::Config; -use crate::simulation::id::Id; +use crate::simulation::engines::activity_engine::ActivityEngine; +use crate::simulation::engines::leg_engine::LegEngine; +use crate::simulation::engines::{Engine, InternalInterface}; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; @@ -13,21 +17,13 @@ use crate::simulation::population::population::Population; use crate::simulation::replanning::replanner::Replanner; use crate::simulation::time_queue::TimeQueue; use crate::simulation::vehicles::garage::Garage; -use crate::simulation::wire_types::events::Event; use crate::simulation::wire_types::messages::Vehicle; -use crate::simulation::wire_types::population::Person; -use crate::simulation::wire_types::vehicles::LevelOfDetail; -pub struct Simulation -where - C: SimCommunicator, -{ - activity_q: TimeQueue, - teleportation_q: TimeQueue, - network: SimNetworkPartition, - garage: Garage, - net_message_broker: NetMessageBroker, - events: EventsPublisher, +pub struct Simulation { + activity_engine: Rc>, + leg_engine: Rc>>, + internal_interface: Rc>, + events: Rc>, replanner: Box, start_time: u32, end_time: u32, @@ -43,7 +39,7 @@ where garage: Garage, mut population: Population, net_message_broker: NetMessageBroker, - events: EventsPublisher, + events: Rc>, replanner: Box, ) -> Self { let mut activity_q = TimeQueue::new(); @@ -56,12 +52,40 @@ where activity_q.add(agent, config.simulation().start_time); } - Simulation { + let activity_engine = Rc::new(RefCell::new(ActivityEngine::new( + activity_q, + events.clone(), + ))); + + let leg_engine = Rc::new(RefCell::new(LegEngine::new( network, garage, - teleportation_q: TimeQueue::new(), - activity_q, net_message_broker, + events.clone(), + ))); + + let activity_engine_trait: Rc> = activity_engine.clone(); + let leg_engine_trait: Rc> = leg_engine.clone(); + + //TODO + //let d = Rc::downcast::>(activity_engine_trait).unwrap(); + + let internal_interface = Rc::new(RefCell::new(InternalInterface::new( + activity_engine_trait, + leg_engine_trait, + ))); + + activity_engine + .borrow_mut() + .set_internal_interface(Rc::downgrade(&internal_interface)); + leg_engine + .borrow_mut() + .set_internal_interface(Rc::downgrade(&internal_interface)); + + Simulation { + activity_engine, + leg_engine, + internal_interface, events, replanner, start_time: config.simulation().start_time, @@ -69,14 +93,14 @@ where } } - #[tracing::instrument(level = "info", skip(self), fields(rank = self.net_message_broker.rank()))] + // #[tracing::instrument(level = "info", skip(self), fields(rank = self.net_message_broker.rank()))] pub fn run(&mut self) { // use fixed start and end times let mut now = self.start_time; info!( "Starting #{}. Network neighbors: {:?}, Start time {}, End time {}", - self.net_message_broker.rank(), - self.network.neighbors(), + self.leg_engine.borrow().net_message_broker().rank(), + self.leg_engine.borrow().network().neighbors(), self.start_time, self.end_time, ); @@ -87,185 +111,26 @@ where let _min = (now % 3600) / 60; info!( "#{} of Qsim at {_hour:02}:{_min:02}; Active Nodes: {}, Active Links: {}, Vehicles on Network Partition: {}", - self.net_message_broker.rank(), - self.network.active_nodes(), - self.network.active_links(), - self.network.veh_on_net() + self.leg_engine.borrow().net_message_broker().rank(), + self.leg_engine.borrow().network().active_nodes(), + self.leg_engine.borrow().network().active_links(), + self.leg_engine.borrow().network().veh_on_net() ); } - self.wakeup(now); - self.terminate_teleportation(now); - self.move_nodes(now); - self.move_links(now); + self.activity_engine.borrow_mut().do_step(now); + self.leg_engine.borrow_mut().do_step(now); - self.replanner.update_time(now, &mut self.events); + //TODO + // self.replanner.update_time(now, &mut self.events); now += 1; } // maybe this belongs into the controller? Then this would have to be a &mut instead of owned. - self.events.finish(); - } - - #[tracing::instrument(level = "trace", skip(self), fields(rank = self.net_message_broker.rank()))] - fn wakeup(&mut self, now: u32) { - let agents = self.activity_q.pop(now); - - for mut agent in agents { - self.update_agent(&mut agent, now); - - let act_type: Id = Id::get(agent.curr_act().act_type); - self.events.publish_event( - now, - &Event::new_act_end(agent.id, agent.curr_act().link_id, act_type.internal()), - ); - - let mut vehicle = self.departure(agent, now); - let veh_type_id = Id::get(vehicle.r#type); - let veh_type = self.garage.vehicle_types.get(&veh_type_id).unwrap(); - - match veh_type.lod() { - LevelOfDetail::Network => { - self.events.publish_event( - now, - &Event::new_person_enters_veh(vehicle.driver().id, vehicle.id), - ); - //we don't pass the event publisher because a link enter event should not be published - self.network.send_veh_en_route(vehicle, None, now); - } - LevelOfDetail::Teleported => { - if Simulation::is_local_route(&vehicle, &self.net_message_broker) { - self.teleportation_q.add(vehicle, now); - } else { - // set the pointer of the route to the last element, so that the current link - // is the destination of this leg. Setting this to the last element makes this - // logic independent of whether the agent has a Generic-Route with only start - // and end link or a full Network-Route, which is often the case for ride modes. - vehicle.route_index_to_last(); - self.net_message_broker.add_veh(vehicle, now); - } - } - } - } - } - - fn departure(&mut self, mut agent: Person, now: u32) -> Vehicle { - //here, current element counter is going to be increased - agent.advance_plan(); - - assert_ne!(agent.curr_plan_elem % 2, 0); - - let leg = agent.curr_leg(); - let route = leg.route.as_ref().unwrap(); - let leg_mode: Id = Id::get(leg.mode); - self.events.publish_event( - now, - &Event::new_departure(agent.id, route.start_link(), leg_mode.internal()), - ); - - let veh_id = Id::get(route.veh_id); - self.garage.unpark_veh(agent, &veh_id) - } - - fn update_agent(&mut self, agent: &mut Person, now: u32) { - self.replanner.replan(now, agent, &self.garage) - } - - #[instrument(level = "trace", skip(self), fields(rank = self.net_message_broker.rank()))] - fn terminate_teleportation(&mut self, now: u32) { - let teleportation_vehicles = self.teleportation_q.pop(now); - for vehicle in teleportation_vehicles { - // park the vehice - get the agent out of the vehicle - let mut agent = self.garage.park_veh(vehicle); - - // emmit travelled - let leg = agent.curr_leg(); - let route = leg.route.as_ref().unwrap(); - let mode: Id = Id::get(leg.mode); - self.events.publish_event( - now, - &Event::new_travelled(agent.id, route.distance, mode.internal()), - ); - - // emmit arrival - self.events.publish_event( - now, - &Event::new_arrival(agent.id, route.end_link(), mode.internal()), - ); - - // advance plan to activity and put agent into activity q. - agent.advance_plan(); - - // emmit act start event - let act = agent.curr_act(); - let act_type: Id = Id::get(act.act_type); - self.events.publish_event( - now, - &Event::new_act_start(agent.id, act.link_id, act_type.internal()), - ); - self.activity_q.add(agent, now); - } - } - - //#[instrument(level = "trace", skip(self), fields(rank = self.net_message_broker.rank()))] - fn move_nodes(&mut self, now: u32) { - let exited_vehicles = self.network.move_nodes(&mut self.events, now); - - for veh in exited_vehicles { - self.events - .publish_event(now, &Event::new_person_leaves_veh(veh.driver().id, veh.id)); - let veh_type_id = Id::get(veh.r#type); - let veh_type = self.garage.vehicle_types.get(&veh_type_id).unwrap(); - let mode = veh_type.net_mode; - let mut agent = self.garage.park_veh(veh); - - // move to next activity - agent.advance_plan(); - let act = agent.curr_act(); - self.events - .publish_event(now, &Event::new_arrival(agent.id, act.link_id, mode)); - let act_type: Id = Id::get(act.act_type); - self.events.publish_event( - now, - &Event::new_act_start(agent.id, act.link_id, act_type.internal()), - ); - self.activity_q.add(agent, now); - } - } - - #[instrument(level = "trace", skip(self), fields(rank = self.net_message_broker.rank()))] - fn move_links(&mut self, now: u32) { - let (vehicles, storage_cap_updates) = self.network.move_links(now); - - for veh in vehicles { - self.net_message_broker.add_veh(veh, now); - } - - for cap in storage_cap_updates { - self.net_message_broker.add_cap_update(cap, now); - } - - let sync_messages = self.net_message_broker.send_recv(now); - - for msg in sync_messages { - self.network - .apply_storage_cap_updates(msg.storage_capacities); - - for veh in msg.vehicles { - let veh_type_id = Id::get(veh.r#type); - let veh_type = self.garage.vehicle_types.get(&veh_type_id).unwrap(); - match veh_type.lod() { - LevelOfDetail::Network => { - self.network - .send_veh_en_route(veh, Some(&mut self.events), now) - } - LevelOfDetail::Teleported => self.teleportation_q.add(veh, now), - } - } - } + self.events.borrow_mut().finish(); } - fn is_local_route(veh: &Vehicle, message_broker: &NetMessageBroker) -> bool { + pub(crate) fn is_local_route(veh: &Vehicle, message_broker: &NetMessageBroker) -> bool { let leg = veh.driver.as_ref().unwrap().curr_leg(); let route = leg.route.as_ref().unwrap(); let to = message_broker.rank_for_link(route.end_link()); @@ -273,12 +138,12 @@ where } } -impl Debug for Simulation { +impl Debug for Simulation { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!( f, "Simulation with Rank #{}", - self.net_message_broker.rank() + self.leg_engine.borrow().net_message_broker().rank() ) } } diff --git a/tests/test_simulation.rs b/tests/test_simulation.rs index 3da10a1..c22da5e 100644 --- a/tests/test_simulation.rs +++ b/tests/test_simulation.rs @@ -1,4 +1,5 @@ use std::any::Any; +use std::cell::RefCell; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::PathBuf; @@ -100,9 +101,11 @@ pub fn execute_sim( ); let sim_net = SimNetworkPartition::from_network(&network, rank, config.simulation()); - let mut events = EventsPublisher::new(); - events.add_subscriber(test_subscriber); - events.add_subscriber(Box::new(TravelTimeCollector::new())); + let mut events = Rc::new(RefCell::new(EventsPublisher::new())); + events.borrow_mut().add_subscriber(test_subscriber); + events + .borrow_mut() + .add_subscriber(Box::new(TravelTimeCollector::new())); let rc = Rc::new(comm); let broker = NetMessageBroker::new(rc.clone(), &network, &sim_net); From adacbc7fb73211915ce85031a7c5a03ee95142d5 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Wed, 12 Jun 2024 15:13:15 +0200 Subject: [PATCH 05/17] rename InternalState and fix bug --- build.rs | 31 +++++++++++++---------- src/simulation/engines/activity_engine.rs | 15 ++++++----- src/simulation/engines/leg_engine.rs | 15 ++++++----- src/simulation/engines/mod.rs | 11 +++++--- src/simulation/engines/network_engine.rs | 11 ++++++-- src/simulation/simulation.rs | 12 ++++----- tests/test_simulation.rs | 2 +- 7 files changed, 58 insertions(+), 39 deletions(-) diff --git a/build.rs b/build.rs index 2e91a65..36c9a43 100644 --- a/build.rs +++ b/build.rs @@ -1,22 +1,25 @@ extern crate prost_build; +extern crate protobuf_src; fn main() { // we use the protobuf-src which provides the protoc compiler. This line makes it available // to prost-build std::env::set_var("PROTOC", protobuf_src::protoc()); - // this line comes from the prost-build example and compiles items.proto into corresponding types. - // the generated code is under ./target//build/-/out - prost_build::compile_protos( - &[ - "src/simulation/wire_types/messages.proto", - "src/simulation/wire_types/events.proto", - "src/simulation/wire_types/ids.proto", - "src/simulation/wire_types/network.proto", - "src/simulation/wire_types/population.proto", - "src/simulation/wire_types/vehicles.proto", - ], - &["src/"], - ) - .unwrap(); + let proto_files = [ + "src/simulation/wire_types/messages.proto", + "src/simulation/wire_types/events.proto", + "src/simulation/wire_types/ids.proto", + "src/simulation/wire_types/network.proto", + "src/simulation/wire_types/population.proto", + "src/simulation/wire_types/vehicles.proto", + ]; + + // tell cargo to rerun this build script if any of the proto files change + for proto in &proto_files { + println!("cargo:rerun-if-changed={}", proto); + } + + // Compiling the protobuf files + prost_build::compile_protos(&proto_files, &["src/"]).unwrap(); } diff --git a/src/simulation/engines/activity_engine.rs b/src/simulation/engines/activity_engine.rs index de4f5ac..6062df6 100644 --- a/src/simulation/engines/activity_engine.rs +++ b/src/simulation/engines/activity_engine.rs @@ -1,4 +1,4 @@ -use crate::simulation::engines::{Engine, InternalInterface}; +use crate::simulation::engines::{AgentStateTransitionLogic, Engine}; use crate::simulation::id::Id; use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::time_queue::TimeQueue; @@ -10,7 +10,7 @@ use std::rc::{Rc, Weak}; pub struct ActivityEngine { activity_q: TimeQueue, events: Rc>, - internal_interface: Weak>, + agent_state_transition_logic: Weak>, } impl Engine for ActivityEngine { @@ -19,7 +19,7 @@ impl Engine for ActivityEngine { for mut agent in agents { agent.advance_plan(); - self.internal_interface + self.agent_state_transition_logic .upgrade() .unwrap() .borrow_mut() @@ -47,8 +47,11 @@ impl Engine for ActivityEngine { self.activity_q.add(agent, now); } - fn set_internal_interface(&mut self, internal_interface: Weak>) { - self.internal_interface = internal_interface + fn set_agent_state_transition_logic( + &mut self, + agent_state_transition_logic: Weak>, + ) { + self.agent_state_transition_logic = agent_state_transition_logic } } @@ -57,7 +60,7 @@ impl ActivityEngine { ActivityEngine { activity_q, events, - internal_interface: Weak::new(), + agent_state_transition_logic: Weak::new(), } } diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index bd43de1..6538402 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -1,6 +1,6 @@ use crate::simulation::engines::network_engine::NetworkEngine; use crate::simulation::engines::teleportation_engine::TeleportationEngine; -use crate::simulation::engines::{Engine, InternalInterface}; +use crate::simulation::engines::{AgentStateTransitionLogic, Engine}; use crate::simulation::id::Id; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; @@ -20,7 +20,7 @@ pub struct LegEngine { garage: Garage, net_message_broker: NetMessageBroker, events: Rc>, - internal_interface: Weak>, + agent_state_transition_logic: Weak>, } impl Engine for LegEngine { @@ -31,7 +31,7 @@ impl Engine for LegEngine { for mut agent in teleported_agents.into_iter().chain(network_agents) { agent.advance_plan(); - self.internal_interface + self.agent_state_transition_logic .upgrade() .unwrap() .borrow_mut() @@ -58,8 +58,11 @@ impl Engine for LegEngine { self.pass_vehicle_to_engine(now, vehicle, true); } - fn set_internal_interface(&mut self, internal_interface: Weak>) { - self.internal_interface = internal_interface + fn set_agent_state_transition_logic( + &mut self, + agent_state_transition_logic: Weak>, + ) { + self.agent_state_transition_logic = agent_state_transition_logic } } @@ -95,7 +98,7 @@ impl LegEngine { LegEngine { teleportation_engine: TeleportationEngine::new(events.clone()), network_engine: NetworkEngine::new(network, events.clone()), - internal_interface: Weak::new(), + agent_state_transition_logic: Weak::new(), garage, net_message_broker, events, diff --git a/src/simulation/engines/mod.rs b/src/simulation/engines/mod.rs index c3e0275..bce7ba6 100644 --- a/src/simulation/engines/mod.rs +++ b/src/simulation/engines/mod.rs @@ -11,15 +11,18 @@ pub mod teleportation_engine; pub trait Engine { fn do_step(&mut self, now: u32); fn receive_agent(&mut self, now: u32, agent: Person); - fn set_internal_interface(&mut self, internal_interface: Weak>); + fn set_agent_state_transition_logic( + &mut self, + internal_interface: Weak>, + ); } -pub struct InternalInterface { +pub struct AgentStateTransitionLogic { activity_engine: Rc>, teleportation_engine: Rc>, } -impl InternalInterface { +impl AgentStateTransitionLogic { fn arrange_next_agent_state(&self, now: u32, agent: Person) { match agent.state() { State::ACTIVITY => self.activity_engine.borrow_mut().receive_agent(now, agent), @@ -34,7 +37,7 @@ impl InternalInterface { activity_engine: Rc>, teleportation_engine: Rc>, ) -> Self { - InternalInterface { + AgentStateTransitionLogic { activity_engine, teleportation_engine, } diff --git a/src/simulation/engines/network_engine.rs b/src/simulation/engines/network_engine.rs index 0f2b501..3f9d39e 100644 --- a/src/simulation/engines/network_engine.rs +++ b/src/simulation/engines/network_engine.rs @@ -27,8 +27,15 @@ impl NetworkEngine { &Event::new_person_enters_veh(vehicle.driver().id, vehicle.id), ) } - //we don't pass the event publisher because a link enter event should not be published - self.network.send_veh_en_route(vehicle, None, now) + + let events = match route_begin { + //if route has just begun, no link enter event should be published + true => None, + //if route is already in progress, this method gets vehicles from another partition and should publish link enter event + //this is because the receiving partition is the owner of this link and should publish the event + false => Some(self.events.clone()), + }; + self.network.send_veh_en_route(vehicle, events, now) } pub(crate) fn move_nodes(&mut self, now: u32, garage: &mut Garage) -> Vec { diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index e6f67f1..e14bc82 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -3,12 +3,12 @@ use std::fmt::Debug; use std::fmt::Formatter; use std::rc::Rc; -use tracing::{info, instrument}; +use tracing::info; use crate::simulation::config::Config; use crate::simulation::engines::activity_engine::ActivityEngine; use crate::simulation::engines::leg_engine::LegEngine; -use crate::simulation::engines::{Engine, InternalInterface}; +use crate::simulation::engines::{AgentStateTransitionLogic, Engine}; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; @@ -22,7 +22,7 @@ use crate::simulation::wire_types::messages::Vehicle; pub struct Simulation { activity_engine: Rc>, leg_engine: Rc>>, - internal_interface: Rc>, + internal_interface: Rc>, events: Rc>, replanner: Box, start_time: u32, @@ -70,17 +70,17 @@ where //TODO //let d = Rc::downcast::>(activity_engine_trait).unwrap(); - let internal_interface = Rc::new(RefCell::new(InternalInterface::new( + let internal_interface = Rc::new(RefCell::new(AgentStateTransitionLogic::new( activity_engine_trait, leg_engine_trait, ))); activity_engine .borrow_mut() - .set_internal_interface(Rc::downgrade(&internal_interface)); + .set_agent_state_transition_logic(Rc::downgrade(&internal_interface)); leg_engine .borrow_mut() - .set_internal_interface(Rc::downgrade(&internal_interface)); + .set_agent_state_transition_logic(Rc::downgrade(&internal_interface)); Simulation { activity_engine, diff --git a/tests/test_simulation.rs b/tests/test_simulation.rs index c22da5e..b7147d9 100644 --- a/tests/test_simulation.rs +++ b/tests/test_simulation.rs @@ -101,7 +101,7 @@ pub fn execute_sim( ); let sim_net = SimNetworkPartition::from_network(&network, rank, config.simulation()); - let mut events = Rc::new(RefCell::new(EventsPublisher::new())); + let events = Rc::new(RefCell::new(EventsPublisher::new())); events.borrow_mut().add_subscriber(test_subscriber); events .borrow_mut() From 9f10c49cce25a170d98f1442f06213f7ecf2c82f Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Mon, 17 Jun 2024 11:53:37 +0200 Subject: [PATCH 06/17] remove Engine trait --- src/simulation/engines/activity_engine.rs | 21 +++++++++--------- src/simulation/engines/leg_engine.rs | 16 ++++++-------- src/simulation/engines/mod.rs | 26 +++++++++-------------- src/simulation/simulation.rs | 20 +++++++---------- 4 files changed, 35 insertions(+), 48 deletions(-) diff --git a/src/simulation/engines/activity_engine.rs b/src/simulation/engines/activity_engine.rs index 6062df6..f02e0e1 100644 --- a/src/simulation/engines/activity_engine.rs +++ b/src/simulation/engines/activity_engine.rs @@ -1,5 +1,6 @@ -use crate::simulation::engines::{AgentStateTransitionLogic, Engine}; +use crate::simulation::engines::AgentStateTransitionLogic; use crate::simulation::id::Id; +use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::time_queue::TimeQueue; use crate::simulation::wire_types::events::Event; @@ -7,14 +8,14 @@ use crate::simulation::wire_types::population::Person; use std::cell::RefCell; use std::rc::{Rc, Weak}; -pub struct ActivityEngine { +pub struct ActivityEngine { activity_q: TimeQueue, events: Rc>, - agent_state_transition_logic: Weak>, + agent_state_transition_logic: Weak>>, } -impl Engine for ActivityEngine { - fn do_step(&mut self, now: u32) { +impl ActivityEngine { + pub(crate) fn do_step(&mut self, now: u32) { let agents = self.wake_up(now); for mut agent in agents { agent.advance_plan(); @@ -27,7 +28,7 @@ impl Engine for ActivityEngine { } } - fn receive_agent(&mut self, now: u32, agent: Person) { + pub(crate) fn receive_agent(&mut self, now: u32, agent: Person) { self.events.borrow_mut().publish_event( now, &Event::new_arrival( @@ -47,15 +48,13 @@ impl Engine for ActivityEngine { self.activity_q.add(agent, now); } - fn set_agent_state_transition_logic( + pub(crate) fn set_agent_state_transition_logic( &mut self, - agent_state_transition_logic: Weak>, + agent_state_transition_logic: Weak>>, ) { self.agent_state_transition_logic = agent_state_transition_logic } -} -impl ActivityEngine { pub fn new(activity_q: TimeQueue, events: Rc>) -> Self { ActivityEngine { activity_q, @@ -64,7 +63,7 @@ impl ActivityEngine { } } - pub fn wake_up(&mut self, now: u32) -> Vec { + fn wake_up(&mut self, now: u32) -> Vec { let mut agents = self.activity_q.pop(now); for agent in agents.iter_mut() { diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index 6538402..df5a734 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -1,6 +1,6 @@ use crate::simulation::engines::network_engine::NetworkEngine; use crate::simulation::engines::teleportation_engine::TeleportationEngine; -use crate::simulation::engines::{AgentStateTransitionLogic, Engine}; +use crate::simulation::engines::AgentStateTransitionLogic; use crate::simulation::id::Id; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; @@ -20,11 +20,11 @@ pub struct LegEngine { garage: Garage, net_message_broker: NetMessageBroker, events: Rc>, - agent_state_transition_logic: Weak>, + agent_state_transition_logic: Weak>>, } -impl Engine for LegEngine { - fn do_step(&mut self, now: u32) { +impl LegEngine { + pub(crate) fn do_step(&mut self, now: u32) { let teleported_agents = self.teleportation_engine.do_step(now); let network_agents = self.network_engine.move_nodes(now, &mut self.garage); @@ -53,20 +53,18 @@ impl Engine for LegEngine { } } - fn receive_agent(&mut self, now: u32, agent: Person) { + pub(crate) fn receive_agent(&mut self, now: u32, agent: Person) { let vehicle = self.place_agent_in_vehicle(now, agent); self.pass_vehicle_to_engine(now, vehicle, true); } - fn set_agent_state_transition_logic( + pub(crate) fn set_agent_state_transition_logic( &mut self, - agent_state_transition_logic: Weak>, + agent_state_transition_logic: Weak>>, ) { self.agent_state_transition_logic = agent_state_transition_logic } -} -impl LegEngine { //TODO route begin is a bit hacky fn pass_vehicle_to_engine(&mut self, now: u32, vehicle: Vehicle, route_begin: bool) { let veh_type_id = Id::get(vehicle.r#type); diff --git a/src/simulation/engines/mod.rs b/src/simulation/engines/mod.rs index bce7ba6..52d6892 100644 --- a/src/simulation/engines/mod.rs +++ b/src/simulation/engines/mod.rs @@ -1,28 +1,22 @@ +use crate::simulation::engines::activity_engine::ActivityEngine; +use crate::simulation::engines::leg_engine::LegEngine; +use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::population::population_data::State; use crate::simulation::wire_types::population::Person; use std::cell::RefCell; -use std::rc::{Rc, Weak}; +use std::rc::Rc; pub mod activity_engine; pub mod leg_engine; pub mod network_engine; pub mod teleportation_engine; -pub trait Engine { - fn do_step(&mut self, now: u32); - fn receive_agent(&mut self, now: u32, agent: Person); - fn set_agent_state_transition_logic( - &mut self, - internal_interface: Weak>, - ); +pub struct AgentStateTransitionLogic { + activity_engine: Rc>>, + teleportation_engine: Rc>>, } -pub struct AgentStateTransitionLogic { - activity_engine: Rc>, - teleportation_engine: Rc>, -} - -impl AgentStateTransitionLogic { +impl AgentStateTransitionLogic { fn arrange_next_agent_state(&self, now: u32, agent: Person) { match agent.state() { State::ACTIVITY => self.activity_engine.borrow_mut().receive_agent(now, agent), @@ -34,8 +28,8 @@ impl AgentStateTransitionLogic { } pub(crate) fn new( - activity_engine: Rc>, - teleportation_engine: Rc>, + activity_engine: Rc>>, + teleportation_engine: Rc>>, ) -> Self { AgentStateTransitionLogic { activity_engine, diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index e14bc82..df24e5a 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -8,7 +8,7 @@ use tracing::info; use crate::simulation::config::Config; use crate::simulation::engines::activity_engine::ActivityEngine; use crate::simulation::engines::leg_engine::LegEngine; -use crate::simulation::engines::{AgentStateTransitionLogic, Engine}; +use crate::simulation::engines::AgentStateTransitionLogic; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; @@ -20,9 +20,9 @@ use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::messages::Vehicle; pub struct Simulation { - activity_engine: Rc>, + activity_engine: Rc>>, leg_engine: Rc>>, - internal_interface: Rc>, + internal_interface: Rc>>, events: Rc>, replanner: Box, start_time: u32, @@ -52,10 +52,9 @@ where activity_q.add(agent, config.simulation().start_time); } - let activity_engine = Rc::new(RefCell::new(ActivityEngine::new( - activity_q, - events.clone(), - ))); + let activity_engine: Rc>> = Rc::new(RefCell::new( + ActivityEngine::new(activity_q, events.clone()), + )); let leg_engine = Rc::new(RefCell::new(LegEngine::new( network, @@ -64,15 +63,12 @@ where events.clone(), ))); - let activity_engine_trait: Rc> = activity_engine.clone(); - let leg_engine_trait: Rc> = leg_engine.clone(); - //TODO //let d = Rc::downcast::>(activity_engine_trait).unwrap(); let internal_interface = Rc::new(RefCell::new(AgentStateTransitionLogic::new( - activity_engine_trait, - leg_engine_trait, + activity_engine.clone(), + leg_engine.clone(), ))); activity_engine From 313d459508aea2f93746033f1aea57138af7bb73 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Mon, 17 Jun 2024 11:55:16 +0200 Subject: [PATCH 07/17] add tracing --- src/simulation/simulation.rs | 2 +- tests/test_simulation.rs | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index df24e5a..1a7779f 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -89,7 +89,7 @@ where } } - // #[tracing::instrument(level = "info", skip(self), fields(rank = self.net_message_broker.rank()))] + #[tracing::instrument(level = "info", skip(self), fields(rank = self.leg_engine.borrow().net_message_broker().rank()))] pub fn run(&mut self) { // use fixed start and end times let mut now = self.start_time; diff --git a/tests/test_simulation.rs b/tests/test_simulation.rs index b7147d9..35ae147 100644 --- a/tests/test_simulation.rs +++ b/tests/test_simulation.rs @@ -149,18 +149,6 @@ fn try_join(mut handles: IntMap>) { } } -struct EmptySubscriber {} - -impl EventsSubscriber for EmptySubscriber { - fn receive_event(&mut self, _time: u32, _event: &Event) { - // nothing. - } - - fn as_any(&mut self) -> &mut dyn Any { - self - } -} - pub struct TestSubscriber { next_index: usize, expected_events: Vec, From 1f2511509928d51961ad9a7a9c8e66c58a24ae21 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 18 Jun 2024 09:42:35 +0200 Subject: [PATCH 08/17] on the way to handling passengers --- src/simulation/engines/activity_engine.rs | 19 ++- src/simulation/engines/leg_engine.rs | 136 +++++++++++++++--- src/simulation/engines/mod.rs | 13 +- .../engines/teleportation_engine.rs | 4 + src/simulation/network/sim_network.rs | 18 +++ src/simulation/simulation.rs | 17 ++- src/simulation/vehicles/garage.rs | 13 +- 7 files changed, 182 insertions(+), 38 deletions(-) diff --git a/src/simulation/engines/activity_engine.rs b/src/simulation/engines/activity_engine.rs index f02e0e1..92d6fcb 100644 --- a/src/simulation/engines/activity_engine.rs +++ b/src/simulation/engines/activity_engine.rs @@ -3,7 +3,9 @@ use crate::simulation::id::Id; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::time_queue::TimeQueue; +use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::events::Event; +use crate::simulation::wire_types::messages::Vehicle; use crate::simulation::wire_types::population::Person; use std::cell::RefCell; use std::rc::{Rc, Weak}; @@ -15,6 +17,14 @@ pub struct ActivityEngine { } impl ActivityEngine { + pub fn new(activity_q: TimeQueue, events: Rc>) -> Self { + ActivityEngine { + activity_q, + events, + agent_state_transition_logic: Weak::new(), + } + } + pub(crate) fn do_step(&mut self, now: u32) { let agents = self.wake_up(now); for mut agent in agents { @@ -55,12 +65,9 @@ impl ActivityEngine { self.agent_state_transition_logic = agent_state_transition_logic } - pub fn new(activity_q: TimeQueue, events: Rc>) -> Self { - ActivityEngine { - activity_q, - events, - agent_state_transition_logic: Weak::new(), - } + pub fn agents(&mut self) -> Vec<&mut Person> { + //TODO + vec![] } fn wake_up(&mut self, now: u32) -> Vec { diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index df5a734..0da6f44 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -11,6 +11,8 @@ use crate::simulation::wire_types::events::Event; use crate::simulation::wire_types::messages::Vehicle; use crate::simulation::wire_types::population::Person; use crate::simulation::wire_types::vehicles::LevelOfDetail; +use ahash::HashSet; +use nohash_hasher::IntMap; use std::cell::RefCell; use std::rc::{Rc, Weak}; @@ -21,9 +23,29 @@ pub struct LegEngine { net_message_broker: NetMessageBroker, events: Rc>, agent_state_transition_logic: Weak>>, + departure_handler: IntMap>, + waiting_passengers: HashSet, } impl LegEngine { + pub fn new( + network: SimNetworkPartition, + garage: Garage, + net_message_broker: NetMessageBroker, + events: Rc>, + ) -> Self { + LegEngine { + teleportation_engine: TeleportationEngine::new(events.clone()), + network_engine: NetworkEngine::new(network, events.clone()), + agent_state_transition_logic: Weak::new(), + garage, + net_message_broker, + events, + departure_handler: IntMap::default(), //TODO + waiting_passengers: HashSet::default(), + } + } + pub(crate) fn do_step(&mut self, now: u32) { let teleported_agents = self.teleportation_engine.do_step(now); let network_agents = self.network_engine.move_nodes(now, &mut self.garage); @@ -54,7 +76,15 @@ impl LegEngine { } pub(crate) fn receive_agent(&mut self, now: u32, agent: Person) { - let vehicle = self.place_agent_in_vehicle(now, agent); + let d = self + .departure_handler + .get_mut(&agent.curr_leg().mode) + .expect(&format!( + "No departure handler for mode {:?}", + &agent.curr_leg().mode + )); + let vehicle = + d.handle_departure(now, agent, &mut self.garage, &mut self.waiting_passengers); self.pass_vehicle_to_engine(now, vehicle, true); } @@ -65,6 +95,12 @@ impl LegEngine { self.agent_state_transition_logic = agent_state_transition_logic } + pub fn agents(&mut self) -> Vec<&mut Person> { + let mut agents = self.network_engine.network.active_agents(); + agents.extend(self.teleportation_engine.agents()); + agents + } + //TODO route begin is a bit hacky fn pass_vehicle_to_engine(&mut self, now: u32, vehicle: Vehicle, route_begin: bool) { let veh_type_id = Id::get(vehicle.r#type); @@ -84,24 +120,6 @@ impl LegEngine { } } } -} - -impl LegEngine { - pub fn new( - network: SimNetworkPartition, - garage: Garage, - net_message_broker: NetMessageBroker, - events: Rc>, - ) -> Self { - LegEngine { - teleportation_engine: TeleportationEngine::new(events.clone()), - network_engine: NetworkEngine::new(network, events.clone()), - agent_state_transition_logic: Weak::new(), - garage, - net_message_broker, - events, - } - } pub fn net_message_broker(&self) -> &NetMessageBroker { &self.net_message_broker @@ -110,8 +128,40 @@ impl LegEngine { pub fn network(&self) -> &SimNetworkPartition { &self.network_engine.network } +} + +trait DepartureHandler { + fn handle_departure( + &mut self, + now: u32, + agent: Person, + garage: &mut Garage, + waiting_passengers: &mut HashSet, + ) -> Vehicle; +} + +struct VehicularDepartureHandler { + events: Rc>, + leg_engine: Weak>>, +} + +impl VehicularDepartureHandler { + pub fn new(events: Rc>) -> Self { + VehicularDepartureHandler { + events, + leg_engine: Weak::new(), //TODO + } + } +} - fn place_agent_in_vehicle(&mut self, now: u32, agent: Person) -> Vehicle { +impl DepartureHandler for VehicularDepartureHandler { + fn handle_departure( + &mut self, + now: u32, + agent: Person, + garage: &mut Garage, + waiting_passengers: &mut HashSet, + ) -> Vehicle { assert_ne!(agent.curr_plan_elem % 2, 0); let leg = agent.curr_leg(); @@ -123,6 +173,50 @@ impl LegEngine { ); let veh_id = Id::get(route.veh_id); - self.garage.unpark_veh(agent, &veh_id) + garage.unpark_veh(agent, &veh_id) + } +} + +struct PassengerDepartureHandler { + events: Rc>, +} + +impl DepartureHandler for PassengerDepartureHandler { + fn handle_departure( + &mut self, + now: u32, + agent: Person, + garage: &mut Garage, + waiting_passengers: &mut HashSet, + ) -> Vehicle { + todo!() + //place agent in dummy vehicle and hand it over to stop engine + } +} + +struct DrtDriverDepartureHandler { + events: Rc>, + leg_engine: Weak>>, +} + +impl DepartureHandler for DrtDriverDepartureHandler { + fn handle_departure( + &mut self, + now: u32, + agent: Person, + garage: &mut Garage, + waiting_passengers: &mut HashSet, + ) -> Vehicle { + // remove passenger from stop engine, place driver and passenger in vehicle and hand it over to leg engine + // requirements: + // 1. DrtDepartureHandler needs to know the passenger to be picked up + let passenger: Vec = todo!(); + + // 2. DrtDepartureHandler needs to be able to access the stop engine + let stop_engine = todo!(); //not possible without handing it over (even with that I'm not sure) + + // 3. DrtDepartureHandler needs hand over the vehicle to the leg engine (right now done by the code calling the departure handler) + let veh_id = agent.curr_leg().route.as_ref().unwrap().veh_id; + garage.unpark_veh_with_passengers(agent, passenger, &Id::get(veh_id)) } } diff --git a/src/simulation/engines/mod.rs b/src/simulation/engines/mod.rs index 52d6892..ce5dff2 100644 --- a/src/simulation/engines/mod.rs +++ b/src/simulation/engines/mod.rs @@ -11,19 +11,20 @@ pub mod leg_engine; pub mod network_engine; pub mod teleportation_engine; +pub trait ReplanEngine { + fn do_sim_step(&mut self, now: u32, agents: &Vec<&mut Person>); +} + pub struct AgentStateTransitionLogic { activity_engine: Rc>>, - teleportation_engine: Rc>>, + pub leg_engine: Rc>>, } impl AgentStateTransitionLogic { fn arrange_next_agent_state(&self, now: u32, agent: Person) { match agent.state() { State::ACTIVITY => self.activity_engine.borrow_mut().receive_agent(now, agent), - State::LEG => self - .teleportation_engine - .borrow_mut() - .receive_agent(now, agent), + State::LEG => self.leg_engine.borrow_mut().receive_agent(now, agent), } } @@ -33,7 +34,7 @@ impl AgentStateTransitionLogic { ) -> Self { AgentStateTransitionLogic { activity_engine, - teleportation_engine, + leg_engine: teleportation_engine, } } } diff --git a/src/simulation/engines/teleportation_engine.rs b/src/simulation/engines/teleportation_engine.rs index 0480a36..8422e51 100644 --- a/src/simulation/engines/teleportation_engine.rs +++ b/src/simulation/engines/teleportation_engine.rs @@ -66,4 +66,8 @@ impl TeleportationEngine { } agents } + + pub fn agents(&self) -> Vec<&mut Person> { + todo!() + } } diff --git a/src/simulation/network/sim_network.rs b/src/simulation/network/sim_network.rs index e4938dd..5d2c6fd 100644 --- a/src/simulation/network/sim_network.rs +++ b/src/simulation/network/sim_network.rs @@ -153,6 +153,24 @@ impl SimNetworkPartition { self.active_links.len() } + pub fn active_agents(&mut self) -> Vec<&mut Person> { + // one has to iterate here over all links and filter then, because otherwise the borrow checker will complain + // something like self.active_links.map(|id| self.links.get(id)) borrows self mutably in FnMut closure + self.links + .iter_mut() + .filter(|(id, link)| self.active_links.contains(id)) + .map(|(_, link)| link) + .map(|link| match link { + SimLink::Local(ll) => ll, + SimLink::In(il) => &mut il.local_link, + SimLink::Out(ol) => todo!(), + }) + .flat_map(|link| link.q.iter_mut()) + .map(|v| &mut v.vehicle) + .flat_map(|v| v.passengers.iter_mut().chain(v.driver.iter_mut())) + .collect::>() + } + pub fn veh_on_net(&self) -> usize { self.veh_counter } diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index 1a7779f..1dbaf86 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -8,7 +8,7 @@ use tracing::info; use crate::simulation::config::Config; use crate::simulation::engines::activity_engine::ActivityEngine; use crate::simulation::engines::leg_engine::LegEngine; -use crate::simulation::engines::AgentStateTransitionLogic; +use crate::simulation::engines::{AgentStateTransitionLogic, ReplanEngine}; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; @@ -24,7 +24,7 @@ pub struct Simulation { leg_engine: Rc>>, internal_interface: Rc>>, events: Rc>, - replanner: Box, + replan_engines: Vec>, start_time: u32, end_time: u32, } @@ -83,7 +83,7 @@ where leg_engine, internal_interface, events, - replanner, + replan_engines: vec![], start_time: config.simulation().start_time, end_time: config.simulation().end_time, } @@ -113,6 +113,17 @@ where self.leg_engine.borrow().network().veh_on_net() ); } + + // let mut act_ref = self.activity_engine.borrow_mut(); + // let mut leg_ref = self.leg_engine.borrow_mut(); + + // let mut agents = act_ref.agents(); + // agents.extend(leg_ref.agents()); + // + // for engine in &mut self.replan_engines { + // engine.do_sim_step(now, &agents); + // } + self.activity_engine.borrow_mut().do_step(now); self.leg_engine.borrow_mut().do_step(now); diff --git a/src/simulation/vehicles/garage.rs b/src/simulation/vehicles/garage.rs index 8263b6d..6c7bf62 100644 --- a/src/simulation/vehicles/garage.rs +++ b/src/simulation/vehicles/garage.rs @@ -102,7 +102,12 @@ impl Garage { vehicle.driver.unwrap() } - pub fn unpark_veh(&mut self, person: Person, id: &Id) -> Vehicle { + pub fn unpark_veh_with_passengers( + &mut self, + person: Person, + passengers: Vec, + id: &Id, + ) -> Vehicle { let veh_type_id = self .vehicles .get(id) @@ -134,9 +139,13 @@ impl Garage { max_v: veh_type.max_v, pce: veh_type.pce, driver: Some(person), - passengers: vec![], + passengers, } } + + pub fn unpark_veh(&mut self, person: Person, id: &Id) -> Vehicle { + self.unpark_veh_with_passengers(person, vec![], id) + } } #[cfg(test)] From dbcd6a7e86e53f8a3d9420a10dc858efb2b6f6fc Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 18 Jun 2024 14:02:26 +0200 Subject: [PATCH 09/17] implemented passenger departure and arrival --- src/simulation/engines/activity_engine.rs | 2 - src/simulation/engines/leg_engine.rs | 157 +++++++++++++----- src/simulation/engines/network_engine.rs | 24 +-- .../engines/teleportation_engine.rs | 17 +- src/simulation/io/xml_events.rs | 14 ++ src/simulation/messaging/events.rs | 30 +++- src/simulation/messaging/messages.rs | 4 + src/simulation/network/sim_network.rs | 28 ++-- src/simulation/population/population_data.rs | 11 ++ src/simulation/vehicles/garage.rs | 8 +- src/simulation/wire_types/events.proto | 16 ++ src/simulation/wire_types/population.proto | 10 ++ 12 files changed, 223 insertions(+), 98 deletions(-) diff --git a/src/simulation/engines/activity_engine.rs b/src/simulation/engines/activity_engine.rs index 92d6fcb..e800ba2 100644 --- a/src/simulation/engines/activity_engine.rs +++ b/src/simulation/engines/activity_engine.rs @@ -3,9 +3,7 @@ use crate::simulation::id::Id; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::time_queue::TimeQueue; -use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::events::Event; -use crate::simulation::wire_types::messages::Vehicle; use crate::simulation::wire_types::population::Person; use std::cell::RefCell; use std::rc::{Rc, Weak}; diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index 0da6f44..73cf3e2 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -9,9 +9,9 @@ use crate::simulation::network::sim_network::SimNetworkPartition; use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::events::Event; use crate::simulation::wire_types::messages::Vehicle; -use crate::simulation::wire_types::population::Person; +use crate::simulation::wire_types::population::attribute_value::Type; +use crate::simulation::wire_types::population::{Leg, Person}; use crate::simulation::wire_types::vehicles::LevelOfDetail; -use ahash::HashSet; use nohash_hasher::IntMap; use std::cell::RefCell; use std::rc::{Rc, Weak}; @@ -24,7 +24,7 @@ pub struct LegEngine { events: Rc>, agent_state_transition_logic: Weak>>, departure_handler: IntMap>, - waiting_passengers: HashSet, + waiting_passengers: IntMap, } impl LegEngine { @@ -42,15 +42,40 @@ impl LegEngine { net_message_broker, events, departure_handler: IntMap::default(), //TODO - waiting_passengers: HashSet::default(), + waiting_passengers: IntMap::default(), } } pub(crate) fn do_step(&mut self, now: u32) { - let teleported_agents = self.teleportation_engine.do_step(now); - let network_agents = self.network_engine.move_nodes(now, &mut self.garage); + let teleported_vehicles = self.teleportation_engine.do_step(now); + let network_vehicles = self.network_engine.move_nodes(now); - for mut agent in teleported_agents.into_iter().chain(network_agents) { + let mut agents = vec![]; + + for veh in network_vehicles.into_iter().chain(teleported_vehicles) { + self.events + .borrow_mut() + .publish_event(now, &Event::new_person_leaves_veh(veh.driver().id, veh.id)); + + for passenger in veh.passengers() { + self.events.borrow_mut().publish_event( + now, + &Event::new_passenger_dropped_off( + passenger.id, + passenger.curr_leg().mode, + 0, //TODO + veh.id, + ), + ); + self.events + .borrow_mut() + .publish_event(now, &Event::new_person_leaves_veh(passenger.id, veh.id)); + } + + agents.extend(self.garage.park_veh(veh)); + } + + for mut agent in agents { agent.advance_plan(); self.agent_state_transition_logic @@ -85,7 +110,10 @@ impl LegEngine { )); let vehicle = d.handle_departure(now, agent, &mut self.garage, &mut self.waiting_passengers); - self.pass_vehicle_to_engine(now, vehicle, true); + + if let Some(vehicle) = vehicle { + self.pass_vehicle_to_engine(now, vehicle, true); + } } pub(crate) fn set_agent_state_transition_logic( @@ -101,7 +129,6 @@ impl LegEngine { agents } - //TODO route begin is a bit hacky fn pass_vehicle_to_engine(&mut self, now: u32, vehicle: Vehicle, route_begin: bool) { let veh_type_id = Id::get(vehicle.r#type); let veh_type = self.garage.vehicle_types.get(&veh_type_id).unwrap(); @@ -136,44 +163,45 @@ trait DepartureHandler { now: u32, agent: Person, garage: &mut Garage, - waiting_passengers: &mut HashSet, - ) -> Vehicle; + waiting_passengers: &mut IntMap, + ) -> Option; } -struct VehicularDepartureHandler { +struct VehicularDepartureHandler { events: Rc>, - leg_engine: Weak>>, } -impl VehicularDepartureHandler { +impl VehicularDepartureHandler { pub fn new(events: Rc>) -> Self { - VehicularDepartureHandler { - events, - leg_engine: Weak::new(), //TODO - } + VehicularDepartureHandler { events } } } -impl DepartureHandler for VehicularDepartureHandler { +impl DepartureHandler for VehicularDepartureHandler { fn handle_departure( &mut self, now: u32, agent: Person, garage: &mut Garage, - waiting_passengers: &mut HashSet, - ) -> Vehicle { + _: &mut IntMap, + ) -> Option { assert_ne!(agent.curr_plan_elem % 2, 0); let leg = agent.curr_leg(); let route = leg.route.as_ref().unwrap(); let leg_mode: Id = Id::get(leg.mode); + let veh_id = Id::get(route.veh_id); + self.events.borrow_mut().publish_event( now, &Event::new_departure(agent.id, route.start_link(), leg_mode.internal()), ); + self.events.borrow_mut().publish_event( + now, + &Event::new_person_enters_veh(agent.id, veh_id.internal()), + ); - let veh_id = Id::get(route.veh_id); - garage.unpark_veh(agent, &veh_id) + Some(garage.unpark_veh(agent, &veh_id)) } } @@ -186,37 +214,84 @@ impl DepartureHandler for PassengerDepartureHandler { &mut self, now: u32, agent: Person, - garage: &mut Garage, - waiting_passengers: &mut HashSet, - ) -> Vehicle { - todo!() - //place agent in dummy vehicle and hand it over to stop engine + _: &mut Garage, + waiting_passengers: &mut IntMap, + ) -> Option { + let act_before = agent.previous_act(); + let leg = agent.curr_leg(); + let leg_mode: Id = Id::get(leg.mode); + self.events.borrow_mut().publish_event( + now, + &Event::new_departure(agent.id, act_before.link_id, leg_mode.internal()), + ); + + waiting_passengers.insert(agent.id, agent); + None } } -struct DrtDriverDepartureHandler { +struct DrtDriverDepartureHandler { events: Rc>, - leg_engine: Weak>>, } -impl DepartureHandler for DrtDriverDepartureHandler { +impl DepartureHandler for DrtDriverDepartureHandler { fn handle_departure( &mut self, now: u32, agent: Person, garage: &mut Garage, - waiting_passengers: &mut HashSet, - ) -> Vehicle { - // remove passenger from stop engine, place driver and passenger in vehicle and hand it over to leg engine - // requirements: - // 1. DrtDepartureHandler needs to know the passenger to be picked up - let passenger: Vec = todo!(); + waiting_passengers: &mut IntMap, + ) -> Option { + // remove passenger from waiting queue, place driver and passenger in vehicle and hand it over to leg engine + let passenger_id = match agent + .curr_leg() + .attributes + .get(Leg::PASSENGER_ID_ATTRIBUTE) + .expect("No passenger id found") + .r#type + .as_ref() + .unwrap() + { + Type::IntValue(id) => id, + Type::StringValue(_) => { + unreachable!() + } + Type::DoubleValue(_) => { + unreachable!() + } + }; - // 2. DrtDepartureHandler needs to be able to access the stop engine - let stop_engine = todo!(); //not possible without handing it over (even with that I'm not sure) + let passengers: Vec = vec![waiting_passengers + .remove(&passenger_id) + .expect("No such passenger is waiting.")]; - // 3. DrtDepartureHandler needs hand over the vehicle to the leg engine (right now done by the code calling the departure handler) + let leg = agent.curr_leg(); + let route = leg.route.as_ref().unwrap(); + let leg_mode: Id = Id::get(leg.mode); let veh_id = agent.curr_leg().route.as_ref().unwrap().veh_id; - garage.unpark_veh_with_passengers(agent, passenger, &Id::get(veh_id)) + + // emit events for passengers + for passenger in &passengers { + let mode = passenger.curr_leg().mode; + self.events + .borrow_mut() + .publish_event(now, &Event::new_person_enters_veh(passenger.id, veh_id)); + self.events.borrow_mut().publish_event( + now, + &Event::new_passenger_picked_up(passenger.id, mode, 0, veh_id), + ); + } + + // emit event for driver + self.events.borrow_mut().publish_event( + now, + &Event::new_departure(agent.id, route.start_link(), leg_mode.internal()), + ); + + Some(garage.unpark_veh_with_passengers(agent, passengers, &Id::get(veh_id))) } } + +trait ArrivalHandler { + fn handle_arrival(&mut self, now: u32, agent: Person, garage: &mut Garage); +} diff --git a/src/simulation/engines/network_engine.rs b/src/simulation/engines/network_engine.rs index 3f9d39e..f91a5db 100644 --- a/src/simulation/engines/network_engine.rs +++ b/src/simulation/engines/network_engine.rs @@ -2,10 +2,7 @@ use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::network::sim_network::SimNetworkPartition; -use crate::simulation::vehicles::garage::Garage; -use crate::simulation::wire_types::events::Event; use crate::simulation::wire_types::messages::Vehicle; -use crate::simulation::wire_types::population::Person; use std::cell::RefCell; use std::ops::DerefMut; use std::rc::Rc; @@ -21,13 +18,6 @@ impl NetworkEngine { } pub fn receive_vehicle(&mut self, now: u32, vehicle: Vehicle, route_begin: bool) { - if route_begin { - self.events.borrow_mut().publish_event( - now, - &Event::new_person_enters_veh(vehicle.driver().id, vehicle.id), - ) - } - let events = match route_begin { //if route has just begun, no link enter event should be published true => None, @@ -38,21 +28,11 @@ impl NetworkEngine { self.network.send_veh_en_route(vehicle, events, now) } - pub(crate) fn move_nodes(&mut self, now: u32, garage: &mut Garage) -> Vec { + pub(crate) fn move_nodes(&mut self, now: u32) -> Vec { let exited_vehicles = self .network .move_nodes(self.events.borrow_mut().deref_mut(), now); - let mut agents = vec![]; - - for veh in exited_vehicles { - self.events - .borrow_mut() - .publish_event(now, &Event::new_person_leaves_veh(veh.driver().id, veh.id)); - - let agent = garage.park_veh(veh); - agents.push(agent); - } - agents + exited_vehicles } pub(crate) fn move_links( diff --git a/src/simulation/engines/teleportation_engine.rs b/src/simulation/engines/teleportation_engine.rs index 8422e51..4e4e056 100644 --- a/src/simulation/engines/teleportation_engine.rs +++ b/src/simulation/engines/teleportation_engine.rs @@ -41,11 +41,10 @@ impl TeleportationEngine { } } - pub fn do_step(&mut self, now: u32) -> Vec { + pub fn do_step(&mut self, now: u32) -> Vec { let teleportation_vehicles = self.queue.pop(now); - let mut agents = vec![]; - for vehicle in teleportation_vehicles { - let agent = vehicle.driver.unwrap(); + for vehicle in &teleportation_vehicles { + let agent = vehicle.driver.as_ref().unwrap(); // emmit travelled let leg = agent.curr_leg(); @@ -55,16 +54,8 @@ impl TeleportationEngine { now, &Event::new_travelled(agent.id, route.distance, mode.internal()), ); - - //TODO better do in activity engine - // emmit arrival - // self.events.borrow_mut().publish_event( - // now, - // &Event::new_arrival(agent.id, route.end_link(), mode.internal()), - // ); - agents.push(agent); } - agents + teleportation_vehicles } pub fn agents(&self) -> Vec<&mut Person> { diff --git a/src/simulation/io/xml_events.rs b/src/simulation/io/xml_events.rs index 4b51528..f7e8a64 100644 --- a/src/simulation/io/xml_events.rs +++ b/src/simulation/io/xml_events.rs @@ -92,6 +92,20 @@ impl XmlEventsWriter { e.distance, Id::::get(e.mode).external()) } + Type::PassengerPickedUp(e) => { + format!("\n", + Id::::get(e.person).external(), + Id::::get(e.mode).external(), + Id::::get(e.request).external(), + Id::::get(e.vehicle).external()) + } + Type::PassengerDroppedOff(e) => { + format!("\n", + Id::::get(e.person).external(), + Id::::get(e.mode).external(), + Id::::get(e.request).external(), + Id::::get(e.vehicle).external()) + } } } diff --git a/src/simulation/messaging/events.rs b/src/simulation/messaging/events.rs index 239f6f7..e5572c4 100644 --- a/src/simulation/messaging/events.rs +++ b/src/simulation/messaging/events.rs @@ -5,13 +5,13 @@ use std::fmt::Debug; use tracing::{info, instrument}; use crate::simulation::wire_types::events::event::Type::{ - ActEnd, ActStart, Arrival, Departure, Generic, LinkEnter, LinkLeave, PersonEntersVeh, - PersonLeavesVeh, Travelled, + ActEnd, ActStart, Arrival, Departure, Generic, LinkEnter, LinkLeave, PassengerDroppedOff, + PassengerPickedUp, PersonEntersVeh, PersonLeavesVeh, Travelled, }; use crate::simulation::wire_types::events::{ ActivityEndEvent, ActivityStartEvent, ArrivalEvent, DepartureEvent, Event, GenericEvent, - LinkEnterEvent, LinkLeaveEvent, PersonEntersVehicleEvent, PersonLeavesVehicleEvent, - TravelledEvent, + LinkEnterEvent, LinkLeaveEvent, PassengerDroppedOffEvent, PassengerPickedUpEvent, + PersonEntersVehicleEvent, PersonLeavesVehicleEvent, TravelledEvent, }; pub trait EventsSubscriber { @@ -203,4 +203,26 @@ impl Event { })), } } + + pub fn new_passenger_picked_up(person: u64, mode: u64, request: u64, vehicle: u64) -> Event { + Event { + r#type: Some(PassengerPickedUp(PassengerPickedUpEvent { + person, + mode, + request, + vehicle, + })), + } + } + + pub fn new_passenger_dropped_off(person: u64, mode: u64, request: u64, vehicle: u64) -> Event { + Event { + r#type: Some(PassengerDroppedOff(PassengerDroppedOffEvent { + person, + mode, + request, + vehicle, + })), + } + } } diff --git a/src/simulation/messaging/messages.rs b/src/simulation/messaging/messages.rs index b5bea72..ecf3f41 100644 --- a/src/simulation/messaging/messages.rs +++ b/src/simulation/messaging/messages.rs @@ -126,6 +126,10 @@ impl Vehicle { self.driver.as_ref().unwrap() } + pub fn passengers(&self) -> &Vec { + &self.passengers + } + pub fn id(&self) -> usize { self.id as usize } diff --git a/src/simulation/network/sim_network.rs b/src/simulation/network/sim_network.rs index 5d2c6fd..9c5369c 100644 --- a/src/simulation/network/sim_network.rs +++ b/src/simulation/network/sim_network.rs @@ -156,19 +156,21 @@ impl SimNetworkPartition { pub fn active_agents(&mut self) -> Vec<&mut Person> { // one has to iterate here over all links and filter then, because otherwise the borrow checker will complain // something like self.active_links.map(|id| self.links.get(id)) borrows self mutably in FnMut closure - self.links - .iter_mut() - .filter(|(id, link)| self.active_links.contains(id)) - .map(|(_, link)| link) - .map(|link| match link { - SimLink::Local(ll) => ll, - SimLink::In(il) => &mut il.local_link, - SimLink::Out(ol) => todo!(), - }) - .flat_map(|link| link.q.iter_mut()) - .map(|v| &mut v.vehicle) - .flat_map(|v| v.passengers.iter_mut().chain(v.driver.iter_mut())) - .collect::>() + + // self.links + // .iter_mut() + // .filter(|(id, link)| self.active_links.contains(id)) + // .map(|(_, link)| link) + // .map(|link| match link { + // SimLink::Local(ll) => ll, + // SimLink::In(il) => &mut il.local_link, + // SimLink::Out(ol) => todo!(), + // }) + // .flat_map(|link| link.q.iter_mut()) + // .map(|v| &mut v.vehicle) + // .flat_map(|v| v.passengers.iter_mut().chain(v.driver.iter_mut())) + // .collect::>() + vec![] } pub fn veh_on_net(&self) -> usize { diff --git a/src/simulation/population/population_data.rs b/src/simulation/population/population_data.rs index 9e4a04b..2d44838 100644 --- a/src/simulation/population/population_data.rs +++ b/src/simulation/population/population_data.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use tracing::debug; use crate::simulation::id::Id; @@ -84,6 +85,11 @@ impl Person { self.get_act_at_index(act_index) } + pub fn previous_act(&self) -> &Activity { + let act_index = self.next_act_index() - 1; + self.get_act_at_index(act_index) + } + pub fn curr_act_mut(&mut self) -> &mut Activity { if self.curr_plan_elem % 2 != 0 { panic!("Current element is not an activity"); @@ -355,6 +361,8 @@ impl Activity { } impl Leg { + pub const PASSENGER_ID_ATTRIBUTE: &'static str = "passenger_id"; + fn from_io(io_leg: &IOLeg, person_id: &Id) -> Self { let routing_mode_ext = Attrs::find_or_else_opt(&io_leg.attributes, "routingMode", || "car"); @@ -368,6 +376,7 @@ impl Leg { trav_time: Self::parse_trav_time(&io_leg.trav_time, &io_leg.route.trav_time), dep_time: parse_time_opt(&io_leg.dep_time), routing_mode: routing_mode.internal(), + attributes: HashMap::new(), } } @@ -378,6 +387,7 @@ impl Leg { trav_time, dep_time, routing_mode: 0, + attributes: HashMap::new(), } } @@ -392,6 +402,7 @@ impl Leg { distance: 0.0, route: Vec::new(), }), + attributes: HashMap::new(), } } diff --git a/src/simulation/vehicles/garage.rs b/src/simulation/vehicles/garage.rs index 6c7bf62..885aa4f 100644 --- a/src/simulation/vehicles/garage.rs +++ b/src/simulation/vehicles/garage.rs @@ -87,7 +87,7 @@ impl Garage { Id::get_from_ext(&external) } - pub(crate) fn park_veh(&mut self, vehicle: Vehicle) -> Person { + pub(crate) fn park_veh(&mut self, vehicle: Vehicle) -> Vec { /*let id = self.vehicle_ids.get(vehicle.id); let veh_type = self.vehicle_type_ids.get(vehicle.r#type); let garage_veh = GarageVehicle { id, veh_type }; @@ -98,8 +98,10 @@ impl Garage { // the above logic would park a vehicle within a garage. This only works if we have mass // conservation enabled. The scenario we're testing with doesn't. Therfore, we just take - // the agent out of the vehicle and pretend we have parked the car. - vehicle.driver.unwrap() + // the agents out of the vehicle and pretend we have parked the car. + let mut agents = vehicle.passengers; + agents.push(vehicle.driver.unwrap()); + agents } pub fn unpark_veh_with_passengers( diff --git a/src/simulation/wire_types/events.proto b/src/simulation/wire_types/events.proto index 512c776..6f3b99b 100644 --- a/src/simulation/wire_types/events.proto +++ b/src/simulation/wire_types/events.proto @@ -18,6 +18,8 @@ message Event { DepartureEvent departure = 8; ArrivalEvent arrival = 9; TravelledEvent travelled = 10; + PassengerPickedUpEvent passengerPickedUp = 11; + PassengerDroppedOffEvent passengerDroppedOff = 12; } } @@ -76,4 +78,18 @@ message TravelledEvent { uint64 person = 1; uint64 mode = 3; double distance = 2; +} + +message PassengerPickedUpEvent{ + uint64 person = 1; + uint64 mode = 2; + uint64 request = 3; + uint64 vehicle = 4; +} + +message PassengerDroppedOffEvent{ + uint64 person = 1; + uint64 mode = 2; + uint64 request = 3; + uint64 vehicle = 4; } \ No newline at end of file diff --git a/src/simulation/wire_types/population.proto b/src/simulation/wire_types/population.proto index e520aeb..cec24c6 100644 --- a/src/simulation/wire_types/population.proto +++ b/src/simulation/wire_types/population.proto @@ -33,10 +33,20 @@ message Leg { optional uint32 dep_time = 3; uint32 trav_time = 4; Route route = 5; + map attributes = 6; } message Route { uint64 veh_id = 1; double distance = 2; repeated uint64 route = 3; +} + +message AttributeValue { + oneof type { + uint64 int_value = 1; + string string_value = 2; + double double_value = 3; + // to be expanded + } } \ No newline at end of file From bcdf4bc1cbb64f1790d7acaab6a2a9a169b8e8bd Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 18 Jun 2024 16:27:33 +0200 Subject: [PATCH 10/17] without replanning works --- src/simulation/config.rs | 6 +- src/simulation/engines/leg_engine.rs | 147 +++++++++++++-------- src/simulation/engines/network_engine.rs | 7 +- src/simulation/network/link.rs | 20 +-- src/simulation/network/sim_network.rs | 4 +- src/simulation/simulation.rs | 12 +- src/simulation/wire_types/population.proto | 1 + 7 files changed, 126 insertions(+), 71 deletions(-) diff --git a/src/simulation/config.rs b/src/simulation/config.rs index 3330627..76a155e 100644 --- a/src/simulation/config.rs +++ b/src/simulation/config.rs @@ -120,7 +120,7 @@ impl Config { let default = Simulation::default(); self.modules .borrow_mut() - .insert("simulation".to_string(), Box::new(default)); + .insert("simulation".to_string(), Box::new(default.clone())); default } } @@ -177,12 +177,13 @@ pub struct Routing { pub mode: RoutingMode, } -#[derive(Serialize, Deserialize, Clone, Copy)] +#[derive(Serialize, Deserialize, Clone)] pub struct Simulation { pub start_time: u32, pub end_time: u32, pub sample_size: f32, pub stuck_threshold: u32, + pub passenger_modes: Vec, } #[typetag::serde(tag = "type")] @@ -232,6 +233,7 @@ impl Default for Simulation { end_time: 86400, sample_size: 1.0, stuck_threshold: u32::MAX, + passenger_modes: vec![], } } } diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index 73cf3e2..7507659 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -12,7 +12,7 @@ use crate::simulation::wire_types::messages::Vehicle; use crate::simulation::wire_types::population::attribute_value::Type; use crate::simulation::wire_types::population::{Leg, Person}; use crate::simulation::wire_types::vehicles::LevelOfDetail; -use nohash_hasher::IntMap; +use nohash_hasher::{IntMap, IntSet}; use std::cell::RefCell; use std::rc::{Rc, Weak}; @@ -23,7 +23,7 @@ pub struct LegEngine { net_message_broker: NetMessageBroker, events: Rc>, agent_state_transition_logic: Weak>>, - departure_handler: IntMap>, + departure_handler: Vec>, waiting_passengers: IntMap, } @@ -33,7 +33,23 @@ impl LegEngine { garage: Garage, net_message_broker: NetMessageBroker, events: Rc>, + passenger_modes: IntSet, ) -> Self { + let departure_handler: Vec> = vec![ + Box::new(VehicularDepartureHandler { + events: events.clone(), + passenger_modes: passenger_modes.clone(), + }), + Box::new(PassengerDepartureHandler { + events: events.clone(), + passenger_modes: passenger_modes.clone(), + }), + Box::new(DrtDriverDepartureHandler { + events: events.clone(), + driver_agents: IntSet::default(), //TODO + }), + ]; + LegEngine { teleportation_engine: TeleportationEngine::new(events.clone()), network_engine: NetworkEngine::new(network, events.clone()), @@ -41,7 +57,7 @@ impl LegEngine { garage, net_message_broker, events, - departure_handler: IntMap::default(), //TODO + departure_handler, waiting_passengers: IntMap::default(), } } @@ -51,29 +67,8 @@ impl LegEngine { let network_vehicles = self.network_engine.move_nodes(now); let mut agents = vec![]; - - for veh in network_vehicles.into_iter().chain(teleported_vehicles) { - self.events - .borrow_mut() - .publish_event(now, &Event::new_person_leaves_veh(veh.driver().id, veh.id)); - - for passenger in veh.passengers() { - self.events.borrow_mut().publish_event( - now, - &Event::new_passenger_dropped_off( - passenger.id, - passenger.curr_leg().mode, - 0, //TODO - veh.id, - ), - ); - self.events - .borrow_mut() - .publish_event(now, &Event::new_person_leaves_veh(passenger.id, veh.id)); - } - - agents.extend(self.garage.park_veh(veh)); - } + agents.extend(self.publish_end_events(now, network_vehicles, true)); + agents.extend(self.publish_end_events(now, teleported_vehicles, false)); for mut agent in agents { agent.advance_plan(); @@ -100,16 +95,53 @@ impl LegEngine { } } + fn publish_end_events( + &mut self, + now: u32, + vehicles: Vec, + publish_leave_vehicle: bool, + ) -> Vec { + let mut agents = vec![]; + for veh in vehicles { + if publish_leave_vehicle { + self.events + .borrow_mut() + .publish_event(now, &Event::new_person_leaves_veh(veh.driver().id, veh.id)); + } + + for passenger in veh.passengers() { + self.events.borrow_mut().publish_event( + now, + &Event::new_passenger_dropped_off( + passenger.id, + passenger.curr_leg().mode, + 0, //TODO + veh.id, + ), + ); + if publish_leave_vehicle { + self.events + .borrow_mut() + .publish_event(now, &Event::new_person_leaves_veh(passenger.id, veh.id)); + } + } + agents.extend(self.garage.park_veh(veh)); + } + agents + } + pub(crate) fn receive_agent(&mut self, now: u32, agent: Person) { - let d = self - .departure_handler - .get_mut(&agent.curr_leg().mode) - .expect(&format!( - "No departure handler for mode {:?}", - &agent.curr_leg().mode - )); - let vehicle = - d.handle_departure(now, agent, &mut self.garage, &mut self.waiting_passengers); + let mut departure_handler = None; + for dh in &mut self.departure_handler { + if dh.is_responsible(&agent) { + departure_handler = Some(dh); + break; + } + } + + let vehicle = departure_handler + .expect("No departure handler found") + .handle_departure(now, agent, &mut self.garage, &mut self.waiting_passengers); if let Some(vehicle) = vehicle { self.pass_vehicle_to_engine(now, vehicle, true); @@ -158,6 +190,8 @@ impl LegEngine { } trait DepartureHandler { + fn is_responsible(&self, agent: &Person) -> bool; + fn handle_departure( &mut self, now: u32, @@ -169,15 +203,14 @@ trait DepartureHandler { struct VehicularDepartureHandler { events: Rc>, + passenger_modes: IntSet, } -impl VehicularDepartureHandler { - pub fn new(events: Rc>) -> Self { - VehicularDepartureHandler { events } +impl DepartureHandler for VehicularDepartureHandler { + fn is_responsible(&self, agent: &Person) -> bool { + !self.passenger_modes.contains(&agent.curr_leg().mode) } -} -impl DepartureHandler for VehicularDepartureHandler { fn handle_departure( &mut self, now: u32, @@ -196,10 +229,17 @@ impl DepartureHandler for VehicularDepartureHandler { now, &Event::new_departure(agent.id, route.start_link(), leg_mode.internal()), ); - self.events.borrow_mut().publish_event( - now, - &Event::new_person_enters_veh(agent.id, veh_id.internal()), - ); + + let veh_type_id = garage.vehicles.get(&veh_id).unwrap(); + match LevelOfDetail::try_from(garage.vehicle_types.get(veh_type_id).unwrap().lod).unwrap() { + LevelOfDetail::Network => { + self.events.borrow_mut().publish_event( + now, + &Event::new_person_enters_veh(agent.id, veh_id.internal()), + ); + } + _ => {} + } Some(garage.unpark_veh(agent, &veh_id)) } @@ -207,9 +247,14 @@ impl DepartureHandler for VehicularDepartureHandler { struct PassengerDepartureHandler { events: Rc>, + passenger_modes: IntSet, } impl DepartureHandler for PassengerDepartureHandler { + fn is_responsible(&self, agent: &Person) -> bool { + self.passenger_modes.contains(&agent.curr_leg().mode) + } + fn handle_departure( &mut self, now: u32, @@ -232,9 +277,14 @@ impl DepartureHandler for PassengerDepartureHandler { struct DrtDriverDepartureHandler { events: Rc>, + driver_agents: IntSet, } impl DepartureHandler for DrtDriverDepartureHandler { + fn is_responsible(&self, agent: &Person) -> bool { + self.driver_agents.contains(&agent.id()) + } + fn handle_departure( &mut self, now: u32, @@ -253,10 +303,7 @@ impl DepartureHandler for DrtDriverDepartureHandler { .unwrap() { Type::IntValue(id) => id, - Type::StringValue(_) => { - unreachable!() - } - Type::DoubleValue(_) => { + _ => { unreachable!() } }; @@ -291,7 +338,3 @@ impl DepartureHandler for DrtDriverDepartureHandler { Some(garage.unpark_veh_with_passengers(agent, passengers, &Id::get(veh_id))) } } - -trait ArrivalHandler { - fn handle_arrival(&mut self, now: u32, agent: Person, garage: &mut Garage); -} diff --git a/src/simulation/engines/network_engine.rs b/src/simulation/engines/network_engine.rs index f91a5db..e588866 100644 --- a/src/simulation/engines/network_engine.rs +++ b/src/simulation/engines/network_engine.rs @@ -18,12 +18,13 @@ impl NetworkEngine { } pub fn receive_vehicle(&mut self, now: u32, vehicle: Vehicle, route_begin: bool) { - let events = match route_begin { + let events = if route_begin { //if route has just begun, no link enter event should be published - true => None, + None + } else { //if route is already in progress, this method gets vehicles from another partition and should publish link enter event //this is because the receiving partition is the owner of this link and should publish the event - false => Some(self.events.clone()), + Some(self.events.clone()) }; self.network.send_veh_en_route(vehicle, events, now) } diff --git a/src/simulation/network/link.rs b/src/simulation/network/link.rs index cc5912a..e881560 100644 --- a/src/simulation/network/link.rs +++ b/src/simulation/network/link.rs @@ -165,7 +165,7 @@ struct VehicleQEntry { } impl LocalLink { - pub fn from_link(link: &Link, effective_cell_size: f32, config: config::Simulation) -> Self { + pub fn from_link(link: &Link, effective_cell_size: f32, config: &config::Simulation) -> Self { LocalLink::new( link.id.clone(), link.capacity, @@ -200,7 +200,7 @@ impl LocalLink { perm_lanes: f32, length: f64, effective_cell_size: f32, - config: config::Simulation, + config: &config::Simulation, from: Id, to: Id, ) -> Self { @@ -392,7 +392,7 @@ mod sim_link_tests { 3., 100., 7.5, - test_utils::config(), + &test_utils::config(), Id::new_internal(1), Id::new_internal(2), )); @@ -414,7 +414,7 @@ mod sim_link_tests { 3., 100., 7.5, - test_utils::config(), + &test_utils::config(), Id::new_internal(1), Id::new_internal(2), )); @@ -445,7 +445,7 @@ mod sim_link_tests { 3., 100., 7.5, - test_utils::config(), + &test_utils::config(), Id::new_internal(1), Id::new_internal(2), )); @@ -485,7 +485,7 @@ mod sim_link_tests { 3., 100., 7.5, - test_utils::config(), + &test_utils::config(), Id::new_internal(1), Id::new_internal(2), )); @@ -515,7 +515,7 @@ mod sim_link_tests { 1., 15.0, 10.0, - test_utils::config(), + &test_utils::config(), Id::new_internal(0), Id::new_internal(0), )); @@ -549,6 +549,7 @@ mod sim_link_tests { end_time: 0, sample_size: 1.0, stuck_threshold, + passenger_modes: vec![], }; let mut link = SimLink::Local(LocalLink::new( Id::create("stuck-link"), @@ -557,7 +558,7 @@ mod sim_link_tests { 1.0, 10.0, 7.5, - config, + &config, Id::create("from-node"), Id::create("to-node"), )); @@ -587,6 +588,7 @@ mod sim_link_tests { end_time: 0, sample_size: 1.0, stuck_threshold, + passenger_modes: vec![], }; let mut link = SimLink::Local(LocalLink::new( Id::create("stuck-link"), @@ -595,7 +597,7 @@ mod sim_link_tests { 1.0, earliest_exit as f64, 7.5, - config, + &config, Id::create("from-node"), Id::create("to-node"), )); diff --git a/src/simulation/network/sim_network.rs b/src/simulation/network/sim_network.rs index 9c5369c..fa7aa4d 100644 --- a/src/simulation/network/sim_network.rs +++ b/src/simulation/network/sim_network.rs @@ -70,7 +70,7 @@ impl SimNetworkPartition { link, partition, global_network.effective_cell_size, - config, + &config, global_network, ), ) @@ -98,7 +98,7 @@ impl SimNetworkPartition { link: &Link, partition: u32, effective_cell_size: f32, - config: config::Simulation, + config: &config::Simulation, global_network: &Network, ) -> SimLink { let from_part = global_network.get_node(&link.from).partition; //all_nodes.get(link.from.internal()).unwrap().partition; diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index 1dbaf86..8eea81b 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -9,6 +9,7 @@ use crate::simulation::config::Config; use crate::simulation::engines::activity_engine::ActivityEngine; use crate::simulation::engines::leg_engine::LegEngine; use crate::simulation::engines::{AgentStateTransitionLogic, ReplanEngine}; +use crate::simulation::id::Id; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; @@ -56,16 +57,21 @@ where ActivityEngine::new(activity_q, events.clone()), )); + let passenger_modes = config + .simulation() + .passenger_modes + .iter() + .map(|mode| Id::::get_from_ext(mode).internal()) + .collect(); + let leg_engine = Rc::new(RefCell::new(LegEngine::new( network, garage, net_message_broker, events.clone(), + passenger_modes, ))); - //TODO - //let d = Rc::downcast::>(activity_engine_trait).unwrap(); - let internal_interface = Rc::new(RefCell::new(AgentStateTransitionLogic::new( activity_engine.clone(), leg_engine.clone(), diff --git a/src/simulation/wire_types/population.proto b/src/simulation/wire_types/population.proto index cec24c6..962dfdb 100644 --- a/src/simulation/wire_types/population.proto +++ b/src/simulation/wire_types/population.proto @@ -47,6 +47,7 @@ message AttributeValue { uint64 int_value = 1; string string_value = 2; double double_value = 3; + bool bool_value = 4; // to be expanded } } \ No newline at end of file From a9c3f3a78067b4029c92ad547313c6f886bc0ea8 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 18 Jun 2024 16:36:29 +0200 Subject: [PATCH 11/17] adapt test --- src/simulation/messaging/communication/message_broker.rs | 1 + src/test_utils.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/simulation/messaging/communication/message_broker.rs b/src/simulation/messaging/communication/message_broker.rs index 1dba0ba..593278e 100644 --- a/src/simulation/messaging/communication/message_broker.rs +++ b/src/simulation/messaging/communication/message_broker.rs @@ -359,6 +359,7 @@ mod tests { end_time: 0, sample_size: 0.0, stuck_threshold: 0, + passenger_modes: vec![], }; let broker = NetMessageBroker::new( Rc::new(communicator), diff --git a/src/test_utils.rs b/src/test_utils.rs index 7c40db9..25584ff 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -48,5 +48,6 @@ pub fn config() -> config::Simulation { end_time: 0, sample_size: 1.0, stuck_threshold: u32::MAX, + passenger_modes: vec![], } } From b3e066677413f967dfa9dd5074e374a7b9595723 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 10 Sep 2024 15:39:56 +0200 Subject: [PATCH 12/17] add barebone code for drt messaging --- src/simulation/controller.rs | 58 +++++----- src/simulation/engines/activity_engine.rs | 13 ++- src/simulation/engines/leg_engine.rs | 2 +- src/simulation/engines/mod.rs | 6 +- src/simulation/engines/network_engine.rs | 2 +- .../engines/teleportation_engine.rs | 2 +- .../messaging/communication/communicators.rs | 101 +++++++++++++++++- .../messaging/communication/message_broker.rs | 28 +++++ src/simulation/population/population_data.rs | 10 +- src/simulation/replanning/replanner.rs | 15 ++- src/simulation/simulation.rs | 13 +-- src/simulation/time_queue.rs | 68 ++++++++++++ src/simulation/wire_types/messages.proto | 28 +++++ tests/test_adhoc_routing.rs | 4 + tests/test_simulation.rs | 20 +--- 15 files changed, 279 insertions(+), 91 deletions(-) diff --git a/src/simulation/controller.rs b/src/simulation/controller.rs index bc62ff9..8af4076 100644 --- a/src/simulation/controller.rs +++ b/src/simulation/controller.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::cell::{OnceCell, RefCell}; use std::path::{Path, PathBuf}; use std::rc::Rc; use std::thread::{sleep, JoinHandle}; @@ -10,9 +10,7 @@ use mpi::traits::{Communicator, CommunicatorCollectives}; use nohash_hasher::IntMap; use tracing::info; -use crate::simulation::config::{ - CommandLineArgs, Config, PartitionMethod, RoutingMode, WriteEvents, -}; +use crate::simulation::config::{CommandLineArgs, Config, PartitionMethod, WriteEvents}; use crate::simulation::io::proto_events::ProtoEventsWriter; use crate::simulation::messaging::communication::communicators::{ ChannelSimCommunicator, MpiSimCommunicator, SimCommunicator, @@ -22,7 +20,6 @@ use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::network::global_network::Network; use crate::simulation::network::sim_network::SimNetworkPartition; use crate::simulation::population::population::Population; -use crate::simulation::replanning::replanner::{DummyReplanner, ReRouteTripReplanner, Replanner}; use crate::simulation::replanning::routing::travel_time_collector::TravelTimeCollector; use crate::simulation::simulation::Simulation; use crate::simulation::vehicles::garage::Garage; @@ -61,29 +58,31 @@ pub fn run_channel() { pub fn run_mpi() { let universe = mpi::initialize().unwrap(); let world = universe.world(); - let comm = MpiSimCommunicator { - mpi_communicator: world, - }; + let send_buffer: Vec>> = vec![OnceCell::new(); 42]; //TODO set buffer length - let mut args = CommandLineArgs::parse(); - // override the num part argument, with the number of processes mpi has started. - args.num_parts = Some(world.size() as u32); - let config = Config::from_file(&args); + mpi::request::multiple_scope(1, |scope, requests| { + let comm = MpiSimCommunicator::new(world, scope, requests, &send_buffer); - let _guards = logging::init_logging(&config, &args.config_path, comm.rank()); + let mut args = CommandLineArgs::parse(); + // override the num part argument, with the number of processes mpi has started. + args.num_parts = Some(world.size() as u32); + let config = Config::from_file(&args); - info!( - "Starting MPI Simulation with {} partitions", - config.partitioning().num_parts - ); - execute_partition(comm, &args); + let _guards = logging::init_logging(&config, &args.config_path, comm.rank()); + + info!( + "Starting MPI Simulation with {} partitions", + config.partitioning().num_parts + ); + execute_partition(comm, &args); - info!("#{} at barrier.", world.rank()); - universe.world().barrier(); - info!("Process #{} finishing.", world.rank()); + info!("#{} at barrier.", world.rank()); + universe.world().barrier(); + info!("Process #{} finishing.", world.rank()); + }); } -fn execute_partition(comm: C, args: &CommandLineArgs) { +fn execute_partition(comm: C, args: &CommandLineArgs) { let config_path = &args.config_path; let config = Config::from_file(args); @@ -148,23 +147,15 @@ fn execute_partition(comm: C, args: &CommandLineAr &output_path.join(events_file).to_str().unwrap().to_string(), ); info!("adding events writer with path: {events_path:?}"); - events.borrow_mut().add_subscriber(Box::new(ProtoEventsWriter::new(&events_path))); + events + .borrow_mut() + .add_subscriber(Box::new(ProtoEventsWriter::new(&events_path))); } let travel_time_collector = Box::new(TravelTimeCollector::new()); events.borrow_mut().add_subscriber(travel_time_collector); let rc = Rc::new(comm); - let replanner: Box = if config.routing().mode == RoutingMode::AdHoc { - Box::new(ReRouteTripReplanner::new( - &network, - &network_partition, - &garage, - Rc::clone(&rc), - )) - } else { - Box::new(DummyReplanner {}) - }; let net_message_broker = NetMessageBroker::new(rc, &network, &network_partition); let mut simulation: Simulation = Simulation::new( @@ -174,7 +165,6 @@ fn execute_partition(comm: C, args: &CommandLineAr population, net_message_broker, events, - replanner, ); simulation.run(); diff --git a/src/simulation/engines/activity_engine.rs b/src/simulation/engines/activity_engine.rs index e800ba2..db34475 100644 --- a/src/simulation/engines/activity_engine.rs +++ b/src/simulation/engines/activity_engine.rs @@ -2,20 +2,20 @@ use crate::simulation::engines::AgentStateTransitionLogic; use crate::simulation::id::Id; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::events::EventsPublisher; -use crate::simulation::time_queue::TimeQueue; +use crate::simulation::time_queue::MutTimeQueue; use crate::simulation::wire_types::events::Event; use crate::simulation::wire_types::population::Person; use std::cell::RefCell; use std::rc::{Rc, Weak}; pub struct ActivityEngine { - activity_q: TimeQueue, + activity_q: MutTimeQueue, events: Rc>, agent_state_transition_logic: Weak>>, } -impl ActivityEngine { - pub fn new(activity_q: TimeQueue, events: Rc>) -> Self { +impl ActivityEngine { + pub fn new(activity_q: MutTimeQueue, events: Rc>) -> Self { ActivityEngine { activity_q, events, @@ -63,9 +63,8 @@ impl ActivityEngine { self.agent_state_transition_logic = agent_state_transition_logic } - pub fn agents(&mut self) -> Vec<&mut Person> { - //TODO - vec![] + pub fn agents(&mut self) -> impl Iterator { + self.activity_q.iter_mut() } fn wake_up(&mut self, now: u32) -> Vec { diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index 7507659..5c3594e 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -27,7 +27,7 @@ pub struct LegEngine { waiting_passengers: IntMap, } -impl LegEngine { +impl LegEngine { pub fn new( network: SimNetworkPartition, garage: Garage, diff --git a/src/simulation/engines/mod.rs b/src/simulation/engines/mod.rs index ce5dff2..0da37d4 100644 --- a/src/simulation/engines/mod.rs +++ b/src/simulation/engines/mod.rs @@ -11,16 +11,12 @@ pub mod leg_engine; pub mod network_engine; pub mod teleportation_engine; -pub trait ReplanEngine { - fn do_sim_step(&mut self, now: u32, agents: &Vec<&mut Person>); -} - pub struct AgentStateTransitionLogic { activity_engine: Rc>>, pub leg_engine: Rc>>, } -impl AgentStateTransitionLogic { +impl AgentStateTransitionLogic { fn arrange_next_agent_state(&self, now: u32, agent: Person) { match agent.state() { State::ACTIVITY => self.activity_engine.borrow_mut().receive_agent(now, agent), diff --git a/src/simulation/engines/network_engine.rs b/src/simulation/engines/network_engine.rs index e588866..f1b93b5 100644 --- a/src/simulation/engines/network_engine.rs +++ b/src/simulation/engines/network_engine.rs @@ -36,7 +36,7 @@ impl NetworkEngine { exited_vehicles } - pub(crate) fn move_links( + pub(crate) fn move_links( &mut self, now: u32, net_message_broker: &mut NetMessageBroker, diff --git a/src/simulation/engines/teleportation_engine.rs b/src/simulation/engines/teleportation_engine.rs index 4e4e056..713e055 100644 --- a/src/simulation/engines/teleportation_engine.rs +++ b/src/simulation/engines/teleportation_engine.rs @@ -23,7 +23,7 @@ impl TeleportationEngine { } } - pub fn receive_vehicle( + pub fn receive_vehicle( &mut self, now: u32, mut vehicle: Vehicle, diff --git a/src/simulation/messaging/communication/communicators.rs b/src/simulation/messaging/communication/communicators.rs index 1f29cef..e7bb583 100644 --- a/src/simulation/messaging/communication/communicators.rs +++ b/src/simulation/messaging/communication/communicators.rs @@ -1,3 +1,4 @@ +use std::cell::OnceCell; use std::collections::{HashMap, HashSet}; use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::{Arc, Barrier}; @@ -5,12 +6,20 @@ use std::sync::{Arc, Barrier}; use mpi::collective::CommunicatorCollectives; use mpi::datatype::PartitionMut; use mpi::point_to_point::{Destination, Source}; +use mpi::request::{LocalScope, RequestCollection}; use mpi::topology::{Communicator, SystemCommunicator}; use mpi::{Count, Rank}; use tracing::{debug, info, instrument, span, Level}; use crate::simulation::wire_types::messages::{SimMessage, SyncMessage, TravelTimesMessage}; +pub trait Message { + fn serialize(&self) -> Vec; + fn deserialize(data: &[u8]) -> Self; + fn to(&self) -> u32; + fn from(&self) -> u32; +} + pub trait SimCommunicator { fn send_receive_vehicles( &self, @@ -27,6 +36,14 @@ pub trait SimCommunicator { travel_times: HashMap, ) -> Vec; + fn isend_request(&mut self, message: M) + where + M: Message; + + fn irecv_request(&mut self) -> Vec + where + M: Message; + fn barrier(&self); fn rank(&self) -> u32; @@ -55,6 +72,20 @@ impl SimCommunicator for DummySimCommunicator { vec![TravelTimesMessage::from(travel_times)] } + fn isend_request(&mut self, message: M) + where + M: Message, + { + todo!() + } + + fn irecv_request(&mut self) -> Vec + where + M: Message, + { + todo!() + } + fn barrier(&self) { info!("Barrier was called on DummySimCommunicator, which doesn't do anything.") } @@ -183,6 +214,20 @@ impl SimCommunicator for ChannelSimCommunicator { result } + fn isend_request(&mut self, message: M) + where + M: Message, + { + todo!() + } + + fn irecv_request(&mut self) -> Vec + where + M: Message, + { + todo!() + } + fn barrier(&self) { self.barrier.wait(); } @@ -192,11 +237,21 @@ impl SimCommunicator for ChannelSimCommunicator { } } -pub struct MpiSimCommunicator { +pub struct MpiSimCommunicator<'data, 'scope, 'send_buffer> +where + 'send_buffer: 'scope, +{ pub mpi_communicator: SystemCommunicator, + pub scope: &'data LocalScope<'scope>, + pub requests: &'data mut RequestCollection<'scope, Vec>, + pub send_buffer: &'send_buffer Vec>>, + pub send_count: u64, } -impl SimCommunicator for MpiSimCommunicator { +impl<'a, 'b, 'send_buffer> SimCommunicator for MpiSimCommunicator<'a, 'b, 'send_buffer> +where + 'send_buffer: 'b, +{ #[instrument(level = "trace", skip(self, on_msg), fields(rank = self.rank()))] fn send_receive_vehicles( &self, @@ -230,10 +285,10 @@ impl SimCommunicator for MpiSimCommunicator { // can ensure that a buffer is not moved while the request is in progress. mpi::request::multiple_scope(buf_msg.len(), |scope, reqs| { // ------- Send Part --------- - for (message, buf) in buf_msg.iter() { + for (to, buf) in buf_msg.iter() { let req = self .mpi_communicator - .process_at_rank(*message as Rank) + .process_at_rank(*to as Rank) .immediate_send(scope, buf); reqs.add(req); } @@ -294,6 +349,27 @@ impl SimCommunicator for MpiSimCommunicator { messages } + fn isend_request(&mut self, message: M) + where + M: Message, + { + let vec = self.send_buffer[self.send_count as usize].get_or_init(|| message.serialize()); + let req = self + .mpi_communicator + .process_at_rank(message.to() as Rank) + .immediate_send(self.scope, vec); + self.requests.add(req); + self.send_count += 1; + } + + fn irecv_request(&mut self) -> Vec + where + M: Message, + { + let (encoded_msg, _status) = self.mpi_communicator.any_process().receive_vec(); + vec![M::deserialize(&encoded_msg)] + } + fn barrier(&self) { self.mpi_communicator.barrier(); } @@ -303,7 +379,22 @@ impl SimCommunicator for MpiSimCommunicator { } } -impl MpiSimCommunicator { +impl<'a, 'b, 'send_buffer> MpiSimCommunicator<'a, 'b, 'send_buffer> { + pub(crate) fn new( + mpi_communicator: SystemCommunicator, + scope: &'a LocalScope<'b>, + requests: &'a mut RequestCollection<'b, Vec>, + send_buffer: &'send_buffer Vec>>, + ) -> Self { + MpiSimCommunicator { + mpi_communicator, + scope, + requests, + send_buffer, + send_count: 0, + } + } + fn gather_travel_times(&self, sim_travel_times_message: &Vec) -> Vec { // ------- Gather traffic info lengths ------- let mut travel_times_length_buffer = diff --git a/src/simulation/messaging/communication/message_broker.rs b/src/simulation/messaging/communication/message_broker.rs index 593278e..0b8f3ec 100644 --- a/src/simulation/messaging/communication/message_broker.rs +++ b/src/simulation/messaging/communication/message_broker.rs @@ -8,6 +8,34 @@ use crate::simulation::wire_types::messages::{ StorageCap, SyncMessage, TravelTimesMessage, Vehicle, }; +pub struct DrtClientMessageBroker +where + C: SimCommunicator, +{ + communicator: Rc, + server_rank: u32, +} + +impl DrtClientMessageBroker +where + C: SimCommunicator, +{ + pub fn new(communicator: Rc, server_rank: u32) -> Self { + DrtClientMessageBroker { + communicator, + server_rank, + } + } + + pub fn rank(&self) -> u32 { + self.communicator.rank() + } + + pub fn send_recv(&self, now: u32) -> Vec { + todo!() + } +} + pub struct TravelTimesMessageBroker where C: SimCommunicator, diff --git a/src/simulation/population/population_data.rs b/src/simulation/population/population_data.rs index 2d44838..ccdba7d 100644 --- a/src/simulation/population/population_data.rs +++ b/src/simulation/population/population_data.rs @@ -7,7 +7,7 @@ use crate::simulation::network::global_network::Link; use crate::simulation::population::io::{ IOActivity, IOLeg, IOPerson, IOPlan, IOPlanElement, IORoute, }; -use crate::simulation::time_queue::EndTime; +use crate::simulation::time_queue::{EndTime, Identifiable}; use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::messages::Vehicle; use crate::simulation::wire_types::population::{Activity, Leg, Person, Plan, Route}; @@ -248,9 +248,13 @@ impl EndTime for Person { } } -impl Plan { - pub const DEFAULT_ROUTING_MODE: &'static str = "car"; +impl Identifiable for Person { + fn id(&self) -> u64 { + self.id + } +} +impl Plan { pub fn new() -> Plan { Plan { acts: Vec::new(), diff --git a/src/simulation/replanning/replanner.rs b/src/simulation/replanning/replanner.rs index a2265e7..97d7218 100644 --- a/src/simulation/replanning/replanner.rs +++ b/src/simulation/replanning/replanner.rs @@ -36,14 +36,13 @@ impl Replanner for DummyReplanner { fn replan(&self, _now: u32, _agent: &mut Person, _garage: &Garage) {} } -#[derive(Debug)] -pub struct ReRouteTripReplanner { - network_router: Box, +pub struct ReRouteTripReplanner<'comm> { + network_router: Box, teleported_router: Box, global_network: Network, } -impl Replanner for ReRouteTripReplanner { +impl<'comm> Replanner for ReRouteTripReplanner<'comm> { #[tracing::instrument(level = "trace", skip(self, events))] fn update_time(&mut self, now: u32, events: &mut EventsPublisher) { self.network_router.next_time_step(now, events) @@ -68,20 +67,20 @@ impl Replanner for ReRouteTripReplanner { } } -impl ReRouteTripReplanner { - pub fn new( +impl<'comm> ReRouteTripReplanner<'comm> { + pub fn new( global_network: &Network, sim_network: &SimNetworkPartition, garage: &Garage, communicator: Rc, - ) -> ReRouteTripReplanner { + ) -> ReRouteTripReplanner<'comm> { let forward_backward_graph_by_veh_type = TravelTimesCollectingAltRouter::::get_forward_backward_graph_by_veh_type( global_network, &garage.vehicle_types, ); - let router: Box = Box::new(TravelTimesCollectingAltRouter::new( + let router: Box = Box::new(TravelTimesCollectingAltRouter::new( forward_backward_graph_by_veh_type, communicator, sim_network.get_link_ids(), diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index 8eea81b..ec2fcc4 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -8,31 +8,30 @@ use tracing::info; use crate::simulation::config::Config; use crate::simulation::engines::activity_engine::ActivityEngine; use crate::simulation::engines::leg_engine::LegEngine; -use crate::simulation::engines::{AgentStateTransitionLogic, ReplanEngine}; +use crate::simulation::engines::AgentStateTransitionLogic; use crate::simulation::id::Id; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::network::sim_network::SimNetworkPartition; use crate::simulation::population::population::Population; -use crate::simulation::replanning::replanner::Replanner; -use crate::simulation::time_queue::TimeQueue; +use crate::simulation::time_queue::MutTimeQueue; use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::messages::Vehicle; pub struct Simulation { activity_engine: Rc>>, leg_engine: Rc>>, + #[allow(dead_code)] internal_interface: Rc>>, events: Rc>, - replan_engines: Vec>, start_time: u32, end_time: u32, } impl Simulation where - C: SimCommunicator + 'static, + C: SimCommunicator, { pub fn new( config: Config, @@ -41,9 +40,8 @@ where mut population: Population, net_message_broker: NetMessageBroker, events: Rc>, - replanner: Box, ) -> Self { - let mut activity_q = TimeQueue::new(); + let mut activity_q = MutTimeQueue::new(); // take Persons and copy them into queues. This way we can keep population around to translate // ids for events processing... @@ -89,7 +87,6 @@ where leg_engine, internal_interface, events, - replan_engines: vec![], start_time: config.simulation().start_time, end_time: config.simulation().end_time, } diff --git a/src/simulation/time_queue.rs b/src/simulation/time_queue.rs index 752d16f..6e6017a 100644 --- a/src/simulation/time_queue.rs +++ b/src/simulation/time_queue.rs @@ -1,3 +1,4 @@ +use nohash_hasher::IntMap; use std::cmp::Ordering; use std::collections::BinaryHeap; @@ -5,6 +6,10 @@ pub trait EndTime { fn end_time(&self, now: u32) -> u32; } +pub trait Identifiable { + fn id(&self) -> u64; +} + struct Entry where T: EndTime, @@ -80,3 +85,66 @@ where result } } + +#[derive(Default)] +struct ValueWrap { + id: u64, + end_time: u32, +} + +impl ValueWrap { + fn new(id: u64, end_time: u32) -> Self { + ValueWrap { id, end_time } + } +} + +impl EndTime for ValueWrap { + fn end_time(&self, _: u32) -> u32 { + self.end_time + } +} + +/// This is a mutable version of TimeQueue. It allows to mutate the values in the queue. +/// It is a logical error to mutate the end_time of the value such that the order of the queue is changed. +#[derive(Default)] +pub struct MutTimeQueue +where + T: EndTime + Identifiable, +{ + q: TimeQueue, + cache: IntMap, +} + +impl MutTimeQueue +where + T: EndTime + Identifiable, +{ + pub fn new() -> Self { + MutTimeQueue { + q: TimeQueue::new(), + cache: IntMap::default(), + } + } + + pub fn add(&mut self, value: T, now: u32) { + let id = value.id(); + self.q.add(ValueWrap::new(id, value.end_time(now)), now); + self.cache.insert(id, value); + } + + pub fn pop(&mut self, now: u32) -> Vec { + let ids = self.q.pop(now); + let mut result: Vec = Vec::new(); + + for id in ids { + let value = self.cache.remove(&id.id).unwrap(); + result.push(value); + } + + result + } + + pub fn iter_mut(&mut self) -> impl Iterator { + self.cache.values_mut() + } +} diff --git a/src/simulation/wire_types/messages.proto b/src/simulation/wire_types/messages.proto index 122f49c..f482cfd 100644 --- a/src/simulation/wire_types/messages.proto +++ b/src/simulation/wire_types/messages.proto @@ -11,6 +11,34 @@ message SimMessage{ } } +// messages from client to server +message DrtRequestMessage { + repeated DrtPassengerRequest passenger_requests = 1; + repeated DrtDriverNotification driver_notifications = 2; +} + +// messages from server to client +message DrtResponseMessage { + repeated DrtPassengerResponse passenger_responses = 1; + repeated DrtDriverUpdate driver_updates = 2; +} + +message DrtPassengerRequest { + +} + +message DrtDriverNotification { + +} + +message DrtPassengerResponse { + +} + +message DrtDriverUpdate{ + +} + message Empty {} message TravelTimesMessage { diff --git a/tests/test_adhoc_routing.rs b/tests/test_adhoc_routing.rs index 8c70603..83b2805 100644 --- a/tests/test_adhoc_routing.rs +++ b/tests/test_adhoc_routing.rs @@ -22,6 +22,7 @@ fn create_resources(in_dir: &PathBuf, out_dir: &PathBuf) { garage.to_file(&out_dir.join("vehicles.binpb")); } +#[ignore] #[test] fn execute_adhoc_routing_one_part_no_updates() { create_resources( @@ -42,6 +43,7 @@ fn execute_adhoc_routing_one_part_no_updates() { ); } +#[ignore] #[test] #[serial_test::serial] fn execute_adhoc_routing_two_parts_no_updates() { @@ -61,6 +63,7 @@ fn execute_adhoc_routing_two_parts_no_updates() { ); } +#[ignore] #[test] fn execute_adhoc_routing_one_part_with_updates() { create_resources( @@ -81,6 +84,7 @@ fn execute_adhoc_routing_one_part_with_updates() { ); } +#[ignore] #[test] #[serial_test::serial] fn execute_adhoc_routing_two_parts_with_updates() { diff --git a/tests/test_simulation.rs b/tests/test_simulation.rs index 35ae147..1b00a10 100644 --- a/tests/test_simulation.rs +++ b/tests/test_simulation.rs @@ -11,7 +11,7 @@ use std::{fs, thread}; use nohash_hasher::IntMap; use tracing::info; -use rust_q_sim::simulation::config::{CommandLineArgs, Config, RoutingMode}; +use rust_q_sim::simulation::config::{CommandLineArgs, Config}; use rust_q_sim::simulation::controller::{get_numbered_output_filename, partition_input}; use rust_q_sim::simulation::id; use rust_q_sim::simulation::io::xml_events::XmlEventsWriter; @@ -23,9 +23,6 @@ use rust_q_sim::simulation::messaging::events::{EventsPublisher, EventsSubscribe use rust_q_sim::simulation::network::global_network::Network; use rust_q_sim::simulation::network::sim_network::SimNetworkPartition; use rust_q_sim::simulation::population::population::Population; -use rust_q_sim::simulation::replanning::replanner::{ - DummyReplanner, ReRouteTripReplanner, Replanner, -}; use rust_q_sim::simulation::replanning::routing::travel_time_collector::TravelTimeCollector; use rust_q_sim::simulation::simulation::Simulation; use rust_q_sim::simulation::vehicles::garage::Garage; @@ -110,20 +107,7 @@ pub fn execute_sim( let rc = Rc::new(comm); let broker = NetMessageBroker::new(rc.clone(), &network, &sim_net); - let replanner: Box = if config.routing().mode == RoutingMode::AdHoc { - Box::new(ReRouteTripReplanner::new( - &network, - &sim_net, - &garage, - Rc::clone(&rc), - )) - } else { - Box::new(DummyReplanner {}) - }; - - let mut sim = Simulation::new( - config, sim_net, garage, population, broker, events, replanner, - ); + let mut sim = Simulation::new(config, sim_net, garage, population, broker, events); sim.run(); } From bd93931dcd51ec0165b90952a38be96a4231d33d Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Wed, 18 Sep 2024 17:22:42 +0200 Subject: [PATCH 13/17] add scenario container and introduce mass conservation for vehicles --- assets/3-links/vehicles.xml | 3 +- build.rs | 1 + src/dvrp/io.rs | 39 +++++ src/dvrp/mod.rs | 1 + src/lib.rs | 1 + src/simulation/config.rs | 91 +++++++++- src/simulation/controller.rs | 79 +++------ src/simulation/engines/leg_engine.rs | 10 +- .../messaging/communication/message_broker.rs | 1 - src/simulation/messaging/messages.rs | 30 ++++ src/simulation/mod.rs | 1 + src/simulation/network/link.rs | 2 - src/simulation/population/io.rs | 2 +- src/simulation/population/population_data.rs | 4 +- src/simulation/replanning/replanner.rs | 26 ++- src/simulation/scenario.rs | 162 ++++++++++++++++++ src/simulation/simulation.rs | 23 +-- src/simulation/vehicles/garage.rs | 152 ++++++++-------- src/simulation/vehicles/io.rs | 66 ++++--- src/simulation/vehicles/mod.rs | 2 +- src/simulation/wire_types/general.proto | 13 ++ src/simulation/wire_types/messages.proto | 2 + src/simulation/wire_types/mod.rs | 74 ++++++++ src/simulation/wire_types/population.proto | 14 +- src/simulation/wire_types/vehicles.proto | 9 +- src/test_utils.rs | 1 - tests/test_simulation.rs | 9 +- 27 files changed, 603 insertions(+), 215 deletions(-) create mode 100644 src/dvrp/io.rs create mode 100644 src/dvrp/mod.rs create mode 100644 src/simulation/scenario.rs create mode 100644 src/simulation/wire_types/general.proto diff --git a/assets/3-links/vehicles.xml b/assets/3-links/vehicles.xml index b409b0f..d45f178 100644 --- a/assets/3-links/vehicles.xml +++ b/assets/3-links/vehicles.xml @@ -1,5 +1,6 @@ - + diff --git a/build.rs b/build.rs index 36c9a43..942c9ca 100644 --- a/build.rs +++ b/build.rs @@ -7,6 +7,7 @@ fn main() { std::env::set_var("PROTOC", protobuf_src::protoc()); let proto_files = [ + "src/simulation/wire_types/general.proto", "src/simulation/wire_types/messages.proto", "src/simulation/wire_types/events.proto", "src/simulation/wire_types/ids.proto", diff --git a/src/dvrp/io.rs b/src/dvrp/io.rs new file mode 100644 index 0000000..9a0e343 --- /dev/null +++ b/src/dvrp/io.rs @@ -0,0 +1,39 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)] +#[serde(rename = "vehicles")] +pub struct IODrtVehicles { + #[serde(rename = "vehicle")] + pub vehicles: Vec, +} + +#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)] +pub struct IODrtVehicle { + pub id: String, + pub start_link: String, + pub t_0: u32, + pub t_1: u32, + pub capacity: u32, +} + +#[cfg(test)] +mod tests { + use crate::dvrp::io::IODrtVehicles; + + #[test] + fn test_read() { + let s = r#" + + + + "#; + let mut d = quick_xml::de::Deserializer::from_str(s); + let v: IODrtVehicles = serde_path_to_error::deserialize(&mut d).unwrap(); + assert_eq!(v.vehicles.len(), 1); + assert_eq!(v.vehicles[0].id, "taxi_one_A"); + assert_eq!(v.vehicles[0].start_link, "215"); + assert_eq!(v.vehicles[0].t_0, 0); + assert_eq!(v.vehicles[0].t_1, 8000); + assert_eq!(v.vehicles[0].capacity, 2); + } +} diff --git a/src/dvrp/mod.rs b/src/dvrp/mod.rs new file mode 100644 index 0000000..6352663 --- /dev/null +++ b/src/dvrp/mod.rs @@ -0,0 +1 @@ +mod io; diff --git a/src/lib.rs b/src/lib.rs index 4a593bb..3d4fb1b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,5 +5,6 @@ extern crate core; pub mod experiments; pub mod simulation; +mod dvrp; #[cfg(test)] mod test_utils; diff --git a/src/simulation/config.rs b/src/simulation/config.rs index 76a155e..83c8399 100644 --- a/src/simulation/config.rs +++ b/src/simulation/config.rs @@ -139,6 +139,10 @@ impl Config { } } + pub fn drt(&self) -> Option { + self.module::("drt") + } + fn module(&self, key: &str) -> Option { self.modules .borrow() @@ -177,13 +181,33 @@ pub struct Routing { pub mode: RoutingMode, } +#[derive(Serialize, Deserialize, Clone)] +pub struct Drt { + pub process_type: DrtProcessType, + pub services: Vec, +} + +#[derive(PartialEq, Debug, ValueEnum, Clone, Copy, Serialize, Deserialize)] +pub enum DrtProcessType { + OneProcess, + OneProcessPerService, +} + +#[derive(Serialize, Deserialize, Clone)] +pub struct DrtService { + pub mode: String, + pub stop_duration: u32, + pub max_wait_time: u32, + pub max_travel_time_alpha: f32, + pub max_travel_time_beta: f32, +} + #[derive(Serialize, Deserialize, Clone)] pub struct Simulation { pub start_time: u32, pub end_time: u32, pub sample_size: f32, pub stuck_threshold: u32, - pub passenger_modes: Vec, } #[typetag::serde(tag = "type")] @@ -226,6 +250,13 @@ impl ConfigModule for Simulation { } } +#[typetag::serde] +impl ConfigModule for Drt { + fn as_any(&self) -> &dyn Any { + self + } +} + impl Default for Simulation { fn default() -> Self { Self { @@ -233,7 +264,6 @@ impl Default for Simulation { end_time: 86400, sample_size: 1.0, stuck_threshold: u32::MAX, - passenger_modes: vec![], } } } @@ -390,7 +420,8 @@ fn default_profiling_level() -> String { #[cfg(test)] mod tests { use crate::simulation::config::{ - Config, EdgeWeight, MetisOptions, PartitionMethod, Partitioning, VertexWeight, + Config, Drt, DrtProcessType, DrtService, EdgeWeight, MetisOptions, PartitionMethod, + Partitioning, VertexWeight, }; #[test] @@ -507,4 +538,58 @@ mod tests { 1100 ); } + + #[test] + fn test_drt() { + let serde = r#" + modules: + drt: + type: Drt + process_type: OneProcess + services: + - mode: drt_a + stop_duration: 60 + max_wait_time: 900 + max_travel_time_alpha: 1.3 + max_travel_time_beta: 600. + "#; + + let config = Config { + modules: Default::default(), + }; + let drt = Drt { + process_type: DrtProcessType::OneProcess, + services: vec![DrtService { + mode: "drt_a".to_string(), + stop_duration: 60, + max_wait_time: 900, + max_travel_time_alpha: 1.3, + max_travel_time_beta: 600., + }], + }; + config + .modules + .borrow_mut() + .insert("drt".to_string(), Box::new(drt)); + + let parsed_config: Config = serde_yaml::from_str(serde).expect("failed to parse config"); + assert_eq!( + parsed_config.drt().unwrap().process_type, + DrtProcessType::OneProcess + ); + assert_eq!( + parsed_config.drt().unwrap().services[0].mode, + "drt_a".to_string() + ); + assert_eq!(parsed_config.drt().unwrap().services[0].stop_duration, 60); + assert_eq!(parsed_config.drt().unwrap().services[0].max_wait_time, 900); + assert_eq!( + parsed_config.drt().unwrap().services[0].max_travel_time_alpha, + 1.3 + ); + assert_eq!( + parsed_config.drt().unwrap().services[0].max_travel_time_beta, + 600. + ); + } } diff --git a/src/simulation/controller.rs b/src/simulation/controller.rs index 8af4076..97354c9 100644 --- a/src/simulation/controller.rs +++ b/src/simulation/controller.rs @@ -18,11 +18,8 @@ use crate::simulation::messaging::communication::communicators::{ use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::network::global_network::Network; -use crate::simulation::network::sim_network::SimNetworkPartition; -use crate::simulation::population::population::Population; -use crate::simulation::replanning::routing::travel_time_collector::TravelTimeCollector; +use crate::simulation::scenario::Scenario; use crate::simulation::simulation::Simulation; -use crate::simulation::vehicles::garage::Garage; use crate::simulation::{id, io, logging}; pub fn run_channel() { @@ -102,48 +99,34 @@ fn execute_partition(comm: C, args: &CommandLineArgs) { //comm.send_receive_travel_times(0, std::collections::HashMap::new()); comm.barrier(); - id::load_from_file(&io::resolve_path(config_path, &config.proto_files().ids)); - // if we partition the network is copied to the output folder. - // otherwise nothing is done and we can load the network from the input folder directly. - let network_path = if let PartitionMethod::Metis(_) = config.partitioning().method { - get_numbered_output_filename( - &output_path, - &io::resolve_path(config_path, &config.proto_files().network), - config.partitioning().num_parts, - ) - } else { - insert_number_in_proto_filename( - &io::resolve_path(config_path, &config.proto_files().network), - config.partitioning().num_parts, - ) - }; - let network = Network::from_file_as_is(&network_path); - let mut garage = Garage::from_file(&io::resolve_path( - config_path, - &config.proto_files().vehicles, - )); - - let population = Population::from_file_filtered_part( - &io::resolve_path(config_path, &config.proto_files().population), - &network, - &mut garage, - comm.rank(), - ); + let scenario = Scenario::build(&config, config_path, rank, &output_path); - let network_partition = SimNetworkPartition::from_network(&network, rank, config.simulation()); - info!( - "Partition #{rank} network has: {} nodes and {} links. Population has {} agents", - network_partition.nodes.len(), - network_partition.links.len(), - population.persons.len() + let events = create_events(config_path, &config, rank, &output_path); + + let net_message_broker = NetMessageBroker::new( + Rc::new(comm), + &scenario.network, + &scenario.network_partition, ); + let mut simulation: Simulation = + Simulation::new(config, scenario, net_message_broker, events); + + simulation.run(); +} + +fn create_events( + config_path: &String, + config: &Config, + rank: u32, + output_path: &PathBuf, +) -> Rc> { let events = Rc::new(RefCell::new(EventsPublisher::new())); if config.output().write_events == WriteEvents::Proto { let events_file = format!("events.{rank}.binpb"); let events_path = io::resolve_path( - &args.config_path, + config_path, &output_path.join(events_file).to_str().unwrap().to_string(), ); info!("adding events writer with path: {events_path:?}"); @@ -151,23 +134,7 @@ fn execute_partition(comm: C, args: &CommandLineArgs) { .borrow_mut() .add_subscriber(Box::new(ProtoEventsWriter::new(&events_path))); } - let travel_time_collector = Box::new(TravelTimeCollector::new()); - events.borrow_mut().add_subscriber(travel_time_collector); - - let rc = Rc::new(comm); - - let net_message_broker = NetMessageBroker::new(rc, &network, &network_partition); - - let mut simulation: Simulation = Simulation::new( - config, - network_partition, - garage, - population, - net_message_broker, - events, - ); - - simulation.run(); + events } /// Have this more complicated join logic, so that threads in the back of the handle vec can also @@ -226,7 +193,7 @@ fn create_output_filename(output_dir: &Path, input_file: &Path) -> PathBuf { output_dir.join(filename) } -fn insert_number_in_proto_filename(path: &Path, part: u32) -> PathBuf { +pub(crate) fn insert_number_in_proto_filename(path: &Path, part: u32) -> PathBuf { let filename = path.file_name().unwrap().to_str().unwrap(); let mut stripped = filename.strip_suffix(".binpb").unwrap(); if let Some(s) = stripped.strip_suffix(format!(".{part}").as_str()) { diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index 5c3594e..0aab182 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -8,8 +8,8 @@ use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::network::sim_network::SimNetworkPartition; use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::events::Event; +use crate::simulation::wire_types::general::attribute_value::Type; use crate::simulation::wire_types::messages::Vehicle; -use crate::simulation::wire_types::population::attribute_value::Type; use crate::simulation::wire_types::population::{Leg, Person}; use crate::simulation::wire_types::vehicles::LevelOfDetail; use nohash_hasher::{IntMap, IntSet}; @@ -230,8 +230,10 @@ impl DepartureHandler for VehicularDepartureHandler { &Event::new_departure(agent.id, route.start_link(), leg_mode.internal()), ); - let veh_type_id = garage.vehicles.get(&veh_id).unwrap(); - match LevelOfDetail::try_from(garage.vehicle_types.get(veh_type_id).unwrap().lod).unwrap() { + let veh_type_id = garage.vehicles.get(&veh_id).unwrap().r#type; + match LevelOfDetail::try_from(garage.vehicle_types.get(&Id::get(veh_type_id)).unwrap().lod) + .unwrap() + { LevelOfDetail::Network => { self.events.borrow_mut().publish_event( now, @@ -302,7 +304,7 @@ impl DepartureHandler for DrtDriverDepartureHandler { .as_ref() .unwrap() { - Type::IntValue(id) => id, + Type::IntValue(id) => *id as u64, _ => { unreachable!() } diff --git a/src/simulation/messaging/communication/message_broker.rs b/src/simulation/messaging/communication/message_broker.rs index 0b8f3ec..1b3a5f6 100644 --- a/src/simulation/messaging/communication/message_broker.rs +++ b/src/simulation/messaging/communication/message_broker.rs @@ -387,7 +387,6 @@ mod tests { end_time: 0, sample_size: 0.0, stuck_threshold: 0, - passenger_modes: vec![], }; let broker = NetMessageBroker::new( Rc::new(communicator), diff --git a/src/simulation/messaging/messages.rs b/src/simulation/messaging/messages.rs index ecf3f41..95508c2 100644 --- a/src/simulation/messaging/messages.rs +++ b/src/simulation/messaging/messages.rs @@ -2,14 +2,18 @@ use std::cmp::Ordering; use std::collections::HashMap; use std::io::Cursor; +use crate::simulation::id::Id; use prost::Message; use crate::simulation::time_queue::EndTime; +use crate::simulation::vehicles::io::IOVehicle; +use crate::simulation::wire_types::general::AttributeValue; use crate::simulation::wire_types::messages::sim_message::Type; use crate::simulation::wire_types::messages::{ Empty, SimMessage, StorageCap, SyncMessage, TravelTimesMessage, Vehicle, }; use crate::simulation::wire_types::population::Person; +use crate::simulation::wire_types::vehicles::VehicleType; impl SimMessage { pub fn sync_message(self) -> SyncMessage { @@ -119,6 +123,32 @@ impl Vehicle { max_v, pce, passengers: vec![], + attributes: Default::default(), + } + } + + pub fn from_io(io_veh: IOVehicle, veh_type: &VehicleType) -> Vehicle { + let veh_id = Id::::create(&io_veh.id); + let veh_type_id = Id::::get_from_ext(&io_veh.vehicle_type); + + let mut attributes = HashMap::new(); + if let Some(attr) = io_veh.attributes { + for x in attr.attributes { + let key = x.name.clone(); + let value = AttributeValue::from_io_attr(x); + attributes.insert(key, value); + } + } + + Vehicle { + id: veh_id.internal(), + curr_route_elem: 0, + r#type: veh_type_id.internal(), + max_v: veh_type.max_v, + pce: veh_type.pce, + driver: None, + passengers: vec![], + attributes, } } diff --git a/src/simulation/mod.rs b/src/simulation/mod.rs index 6059eaa..ea8132f 100644 --- a/src/simulation/mod.rs +++ b/src/simulation/mod.rs @@ -9,6 +9,7 @@ pub mod network; pub mod population; pub mod profiling; pub mod replanning; +pub mod scenario; #[allow(clippy::module_inception)] pub mod simulation; pub mod time_queue; diff --git a/src/simulation/network/link.rs b/src/simulation/network/link.rs index e881560..b1d6858 100644 --- a/src/simulation/network/link.rs +++ b/src/simulation/network/link.rs @@ -549,7 +549,6 @@ mod sim_link_tests { end_time: 0, sample_size: 1.0, stuck_threshold, - passenger_modes: vec![], }; let mut link = SimLink::Local(LocalLink::new( Id::create("stuck-link"), @@ -588,7 +587,6 @@ mod sim_link_tests { end_time: 0, sample_size: 1.0, stuck_threshold, - passenger_modes: vec![], }; let mut link = SimLink::Local(LocalLink::new( Id::create("stuck-link"), diff --git a/src/simulation/population/io.rs b/src/simulation/population/io.rs index ec18f93..0c6b74b 100644 --- a/src/simulation/population/io.rs +++ b/src/simulation/population/io.rs @@ -136,7 +136,7 @@ fn create_ids(io_pop: &IOPopulation, garage: &mut Garage) { info!("Creating vehicle ids"); for (person_id, type_id) in raw_veh { - garage.add_veh_id(&person_id, &type_id); + garage.add_veh_by_type(&person_id, &type_id); } info!("Creating activity types"); diff --git a/src/simulation/population/population_data.rs b/src/simulation/population/population_data.rs index ccdba7d..7b62de9 100644 --- a/src/simulation/population/population_data.rs +++ b/src/simulation/population/population_data.rs @@ -420,10 +420,10 @@ impl Leg { } } - pub fn vehicle_type_id<'gar>(&self, garage: &'gar Garage) -> &'gar Id { + pub fn vehicle_type_id(&self, garage: &Garage) -> Id { self.route .as_ref() - .map(|r| garage.vehicles.get(&Id::::get(r.veh_id)).unwrap()) + .map(|r| garage.vehicle_type_id(&Id::get(r.veh_id))) .unwrap() } } diff --git a/src/simulation/replanning/replanner.rs b/src/simulation/replanning/replanner.rs index 97d7218..a457974 100644 --- a/src/simulation/replanning/replanner.rs +++ b/src/simulation/replanning/replanner.rs @@ -11,7 +11,6 @@ use crate::simulation::replanning::routing::router::NetworkRouter; use crate::simulation::replanning::routing::travel_times_collecting_alt_router::TravelTimesCollectingAltRouter; use crate::simulation::replanning::teleported_router::{BeeLineDistanceRouter, TeleportedRouter}; use crate::simulation::vehicles::garage::Garage; -use crate::simulation::wire_types::messages::Vehicle; use crate::simulation::wire_types::population::{Activity, Leg, Person}; use crate::simulation::wire_types::vehicles::{LevelOfDetail, VehicleType}; @@ -135,19 +134,16 @@ impl<'comm> ReRouteTripReplanner<'comm> { fn replan_main(&self, agent: &mut Person, garage: &Garage) { let curr_act = agent.curr_act(); - let veh_type_id = garage - .vehicles - .get(&Id::::get( - agent.next_leg().route.as_ref().unwrap().veh_id, - )) - .unwrap(); + let veh_type_id = + garage.vehicle_type_id(&Id::get(agent.next_leg().route.as_ref().unwrap().veh_id)); - let (route, travel_time) = self.find_route(agent.curr_act(), agent.next_act(), veh_type_id); + let (route, travel_time) = + self.find_route(agent.curr_act(), agent.next_act(), &veh_type_id); let dep_time = curr_act.end_time; let vehicle_type_id = agent.next_leg().vehicle_type_id(garage); - let veh_id = garage.veh_id(&Id::::get(agent.id), vehicle_type_id); + let veh_id = garage.veh_id(&Id::::get(agent.id), &vehicle_type_id); let distance = self.calculate_distance(&route); @@ -167,7 +163,7 @@ impl<'comm> ReRouteTripReplanner<'comm> { assert_eq!(curr_act.link_id, next_act.link_id); let veh_type_id = agent.next_leg().vehicle_type_id(garage); - let access_egress_speed = garage.vehicle_types.get(veh_type_id).unwrap().max_v; + let access_egress_speed = garage.vehicle_types.get(&veh_type_id).unwrap().max_v; let dep_time; let walk = if curr_act.is_interaction() { @@ -188,7 +184,7 @@ impl<'comm> ReRouteTripReplanner<'comm> { ) }; - let vehicle_id = garage.veh_id(&Id::::get(agent.id), veh_type_id); + let vehicle_id = garage.veh_id(&Id::::get(agent.id), &veh_type_id); agent.update_next_leg( dep_time, @@ -204,14 +200,14 @@ impl<'comm> ReRouteTripReplanner<'comm> { let next_act = agent.next_act(); let veh_type_id = agent.next_leg().vehicle_type_id(garage); - let speed = garage.vehicle_types.get(veh_type_id).unwrap().max_v; + let speed = garage.vehicle_types.get(&veh_type_id).unwrap().max_v; let dep_time = curr_act.end_time; let teleportation = self .teleported_router .query_between_acts(curr_act, next_act, speed); - let vehicle_id = garage.veh_id(&Id::::get(agent.id), veh_type_id); + let vehicle_id = garage.veh_id(&Id::::get(agent.id), &veh_type_id); agent.update_next_leg( dep_time, teleportation.duration, @@ -257,7 +253,7 @@ impl<'comm> ReRouteTripReplanner<'comm> { let level_of_detail = LevelOfDetail::try_from( garage .vehicle_types - .get(agent.next_leg().vehicle_type_id(garage)) + .get(&agent.next_leg().vehicle_type_id(garage)) .unwrap() .lod, ) @@ -272,7 +268,7 @@ impl<'comm> ReRouteTripReplanner<'comm> { let level_of_detail = LevelOfDetail::try_from( garage .vehicle_types - .get(agent.next_leg().vehicle_type_id(garage)) + .get(&agent.next_leg().vehicle_type_id(garage)) .unwrap() .lod, ) diff --git a/src/simulation/scenario.rs b/src/simulation/scenario.rs new file mode 100644 index 0000000..717e037 --- /dev/null +++ b/src/simulation/scenario.rs @@ -0,0 +1,162 @@ +use crate::simulation::config::{Config, PartitionMethod}; +use crate::simulation::controller::get_numbered_output_filename; +use crate::simulation::id::Id; +use crate::simulation::network::global_network::{Link, Network}; +use crate::simulation::network::sim_network::SimNetworkPartition; +use crate::simulation::population::population::Population; +use crate::simulation::vehicles::garage::Garage; +use crate::simulation::wire_types::messages::Vehicle; +use crate::simulation::wire_types::population::{Activity, Person, Plan}; +use crate::simulation::{id, io}; +use std::path::PathBuf; +use tracing::info; + +pub struct Scenario { + pub network: Network, + pub garage: Garage, + pub population: Population, + pub network_partition: SimNetworkPartition, +} + +impl Scenario { + pub fn build(config: &Config, config_path: &String, rank: u32, output_path: &PathBuf) -> Self { + id::load_from_file(&io::resolve_path(config_path, &config.proto_files().ids)); + + let network = Self::create_network(config, config_path, output_path); + let mut garage = Self::create_garage(config, config_path); + let mut population = + Self::create_population(config, config_path, &network, &mut garage, rank); + let network_partition = Self::create_network_partition(config, rank, &network, &population); + Self::create_drt_driver( + config, + rank, + &mut garage, + &mut population, + &network, + &network_partition, + ); + + Scenario { + network, + garage, + population, + network_partition, + } + } + + fn create_network(config: &Config, config_path: &String, output_path: &PathBuf) -> Network { + // if we partition the network is copied to the output folder. + // otherwise nothing is done and we can load the network from the input folder directly. + let network_path = if let PartitionMethod::Metis(_) = config.partitioning().method { + get_numbered_output_filename( + &output_path, + &io::resolve_path(config_path, &config.proto_files().network), + config.partitioning().num_parts, + ) + } else { + crate::simulation::controller::insert_number_in_proto_filename( + &io::resolve_path(config_path, &config.proto_files().network), + config.partitioning().num_parts, + ) + }; + Network::from_file_as_is(&network_path) + } + + fn create_garage(config: &Config, config_path: &String) -> Garage { + Garage::from_file(&io::resolve_path( + config_path, + &config.proto_files().vehicles, + )) + } + + fn create_population( + config: &Config, + config_path: &String, + network: &Network, + garage: &mut Garage, + rank: u32, + ) -> Population { + Population::from_file_filtered_part( + &io::resolve_path(config_path, &config.proto_files().population), + &network, + garage, + rank, + ) + } + + fn create_network_partition( + config: &Config, + rank: u32, + network: &Network, + population: &Population, + ) -> SimNetworkPartition { + let partition = SimNetworkPartition::from_network(&network, rank, config.simulation()); + info!( + "Partition #{rank} network has: {} nodes and {} links. Population has {} agents", + partition.nodes.len(), + partition.links.len(), + population.persons.len() + ); + partition + } + + fn create_drt_driver( + config: &Config, + rank: u32, + garage: &mut Garage, + population: &mut Population, + network: &Network, + network_partition: &SimNetworkPartition, + ) { + if let Some(drt) = &config.drt() { + info!("Creating DRT drivers"); + + let drt_modes = drt + .services + .iter() + .map(|s| s.mode.clone()) + .collect::>(); + + //fetch all drt vehicles starting on this partition + let drt_vehicles = garage + .vehicles + .values() + .filter(|&v| { + if let Some(value) = v.attributes.get("dvrpMode") { + drt_modes.contains(&value.as_string()) + } else { + false + } + }) + .map(|v| { + let link = v.attributes.get("startLink").unwrap().as_string(); + let link_id = Id::::get_from_ext(link.as_str()).internal(); + (link_id, v) + }) + .filter(|(l, _)| network_partition.get_link_ids().contains(l)) + .collect::>(); + + //for each drt vehicle, create a driver agent + for (link, vehicle) in drt_vehicles { + let start = vehicle.attributes.get("serviceBeginTime").unwrap().as_int() as u32; + + let veh_id = Id::::get(vehicle.id); + let person_id = Id::::create(veh_id.external()).internal(); + let from = network_partition.links.get(&link).unwrap().from(); + let x = network.get_node(from).x; + let y = network.get_node(from).y; + + let mut plan = Plan::new(); + //TODO is Some(start) as end time correct? + plan.add_act(Activity::new(x, y, 0, link, Some(0), Some(start), None)); + Person::new(person_id, plan); + } + } + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test() {} +} diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index ec2fcc4..b83c540 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -1,3 +1,4 @@ +use nohash_hasher::IntSet; use std::cell::RefCell; use std::fmt::Debug; use std::fmt::Formatter; @@ -9,14 +10,11 @@ use crate::simulation::config::Config; use crate::simulation::engines::activity_engine::ActivityEngine; use crate::simulation::engines::leg_engine::LegEngine; use crate::simulation::engines::AgentStateTransitionLogic; -use crate::simulation::id::Id; use crate::simulation::messaging::communication::communicators::SimCommunicator; use crate::simulation::messaging::communication::message_broker::NetMessageBroker; use crate::simulation::messaging::events::EventsPublisher; -use crate::simulation::network::sim_network::SimNetworkPartition; -use crate::simulation::population::population::Population; +use crate::simulation::scenario::Scenario; use crate::simulation::time_queue::MutTimeQueue; -use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::messages::Vehicle; pub struct Simulation { @@ -35,9 +33,7 @@ where { pub fn new( config: Config, - network: SimNetworkPartition, - garage: Garage, - mut population: Population, + mut scenario: Scenario, net_message_broker: NetMessageBroker, events: Rc>, ) -> Self { @@ -45,7 +41,7 @@ where // take Persons and copy them into queues. This way we can keep population around to translate // ids for events processing... - let agents = std::mem::take(&mut population.persons); + let agents = std::mem::take(&mut scenario.population.persons); for agent in agents.into_values() { activity_q.add(agent, config.simulation().start_time); @@ -55,16 +51,11 @@ where ActivityEngine::new(activity_q, events.clone()), )); - let passenger_modes = config - .simulation() - .passenger_modes - .iter() - .map(|mode| Id::::get_from_ext(mode).internal()) - .collect(); + let passenger_modes = IntSet::default(); //TODO let leg_engine = Rc::new(RefCell::new(LegEngine::new( - network, - garage, + scenario.network_partition, + scenario.garage, net_message_broker, events.clone(), passenger_modes, diff --git a/src/simulation/vehicles/garage.rs b/src/simulation/vehicles/garage.rs index 885aa4f..dab2daf 100644 --- a/src/simulation/vehicles/garage.rs +++ b/src/simulation/vehicles/garage.rs @@ -10,16 +10,10 @@ use crate::simulation::wire_types::vehicles::VehicleType; #[derive(Debug)] pub struct Garage { - pub vehicles: IntMap, Id>, + pub vehicles: IntMap, Vehicle>, pub vehicle_types: IntMap, VehicleType>, } -#[derive(Debug)] -pub struct GarageVehicle { - pub id: Id, - pub veh_type: Id, -} - impl Default for Garage { fn default() -> Self { Garage::new() @@ -52,34 +46,35 @@ impl Garage { self.vehicle_types.insert(Id::get(veh_type.id), veh_type); } - pub fn add_veh_id(&mut self, person_id: &Id, type_id: &Id) -> Id { + pub fn add_veh_by_type( + &mut self, + person_id: &Id, + type_id: &Id, + ) -> Id { let veh_id_ext = format!("{}_{}", person_id.external(), type_id.external()); let veh_id = Id::create(&veh_id_ext); let veh_type = self.vehicle_types.get(type_id).unwrap(); - self.vehicles.insert(veh_id.clone(), Id::get(veh_type.id)); + + let vehicle = Vehicle { + id: veh_id.internal(), + curr_route_elem: 0, + r#type: veh_type.id, + max_v: veh_type.max_v, + pce: veh_type.pce, + driver: None, + passengers: vec![], + attributes: Default::default(), + }; + + self.add_veh(vehicle); veh_id } - pub fn add_veh(&mut self, _veh_id: Id, _veh_type_id: Id) { - panic!( - "This method can only be used with chained modes. Which is currently not implemented" - ); - /* - let veh_type = self.vehicle_types.get(&veh_type_id).unwrap(); - match veh_type.lod { - LevelOfDetail::Network => { - let vehicle = GarageVehicle { - id: _veh_id.clone(), - veh_type: veh_type_id.clone(), - }; - self.network_vehicles.insert(vehicle.id.clone(), vehicle); - } - LevelOfDetail::Teleported => {} - } - - */ + pub fn add_veh(&mut self, veh: Vehicle) { + let id = Id::::get(veh.id); + self.vehicles.insert(id, veh); } pub fn veh_id(&self, person_id: &Id, veh_type_id: &Id) -> Id { @@ -87,20 +82,11 @@ impl Garage { Id::get_from_ext(&external) } - pub(crate) fn park_veh(&mut self, vehicle: Vehicle) -> Vec { - /*let id = self.vehicle_ids.get(vehicle.id); - let veh_type = self.vehicle_type_ids.get(vehicle.r#type); - let garage_veh = GarageVehicle { id, veh_type }; - self.network_vehicles - .insert(garage_veh.id.clone(), garage_veh); - - */ - - // the above logic would park a vehicle within a garage. This only works if we have mass - // conservation enabled. The scenario we're testing with doesn't. Therfore, we just take - // the agents out of the vehicle and pretend we have parked the car. - let mut agents = vehicle.passengers; - agents.push(vehicle.driver.unwrap()); + pub(crate) fn park_veh(&mut self, mut vehicle: Vehicle) -> Vec { + let mut agents = std::mem::replace(&mut vehicle.passengers, Vec::new()); + let person = std::mem::replace(&mut vehicle.driver, None).expect("Vehicle has no driver."); + agents.push(person); + self.vehicles.insert(Id::get(vehicle.id), vehicle); agents } @@ -110,44 +96,20 @@ impl Garage { passengers: Vec, id: &Id, ) -> Vehicle { - let veh_type_id = self - .vehicles - .get(id) - .unwrap_or_else(|| panic!("Can't unpark vehicle with id {id}. It was not parked in this garage. Vehicle: {:?}", self.vehicles.len())); - - /* - let veh_type_id = if let Some(veh_type_id) = self.vehicles.get(id) { - veh_type_id.clone() - } else if let Some(garage_veh) = self.network_vehicles.remove(id) { - garage_veh.veh_type - } else { - panic!( - "Can't unpark vehicle with id {}. It was not parked in this garage.", - id.external() - ); - }; - - */ - - // this method would fetch parked vehicles. But as we don't want to run with mass conservation - // we just create vehicles on the fly. - - let veh_type = self.vehicle_types.get(veh_type_id).unwrap(); - - Vehicle { - id: id.internal(), - curr_route_elem: 0, - r#type: veh_type.id, - max_v: veh_type.max_v, - pce: veh_type.pce, - driver: Some(person), - passengers, - } + let vehicle = self.vehicles.remove(&id).unwrap(); + let mut vehicle = vehicle; + vehicle.driver = Some(person); + vehicle.passengers = passengers; + vehicle } pub fn unpark_veh(&mut self, person: Person, id: &Id) -> Vehicle { self.unpark_veh_with_passengers(person, vec![], id) } + + pub fn vehicle_type_id(&self, veh: &Id) -> Id { + self.vehicles.get(veh).map(|v| Id::get(v.r#type)).unwrap() + } } #[cfg(test)] @@ -156,6 +118,7 @@ mod tests { use crate::simulation::id::Id; use crate::simulation::vehicles::garage::Garage; + use crate::simulation::wire_types::messages::Vehicle; use crate::test_utils::create_vehicle_type; #[test] @@ -183,9 +146,50 @@ mod tests { garage.add_veh_type(veh_type2); } + #[test] + #[should_panic] + fn add_vehicle_without_type() { + let mut garage = Garage::new(); + garage.add_veh(Vehicle { + id: 0, + curr_route_elem: 0, + r#type: 0, + max_v: 0.0, + pce: 0.0, + driver: None, + passengers: vec![], + attributes: Default::default(), + }); + } + + #[test] + fn add_vehicle() { + // prepare garage with type + let mut garage = Garage::new(); + let type_id = Id::create("vehicle_type"); + let mode = Id::create("car"); + let veh_type = create_vehicle_type(&type_id, mode); + garage.add_veh_type(veh_type); + + let id = Id::::create("veh"); + garage.add_veh(Vehicle { + id: id.internal(), + curr_route_elem: 0, + r#type: type_id.internal(), + max_v: 0.0, + pce: 0.0, + driver: None, + passengers: vec![], + attributes: Default::default(), + }); + + assert_eq!(1, garage.vehicles.len()); + } + #[test] fn from_file() { let garage = Garage::from_file(&PathBuf::from("./assets/3-links/vehicles.xml")); assert_eq!(3, garage.vehicle_types.len()); + assert_eq!(0, garage.vehicles.len()); } } diff --git a/src/simulation/vehicles/io.rs b/src/simulation/vehicles/io.rs index 856abbc..4cd4e2a 100644 --- a/src/simulation/vehicles/io.rs +++ b/src/simulation/vehicles/io.rs @@ -8,9 +8,8 @@ use crate::simulation::id::Id; use crate::simulation::io::attributes::{Attr, Attrs}; use crate::simulation::io::xml; use crate::simulation::vehicles::garage::Garage; -use crate::simulation::wire_types::vehicles::{ - LevelOfDetail, VehicleToType, VehicleType, VehiclesContainer, -}; +use crate::simulation::wire_types::messages::Vehicle; +use crate::simulation::wire_types::vehicles::{LevelOfDetail, VehicleType, VehiclesContainer}; pub fn from_file(path: &Path) -> Garage { if path.extension().unwrap().eq("binpb") { @@ -38,6 +37,9 @@ fn load_from_xml(path: &Path) -> Garage { for io_veh_type in io_vehicles.veh_types { add_io_veh_type(&mut result, io_veh_type); } + for io_veh in io_vehicles.vehicles { + add_io_veh(&mut result, io_veh) + } let keys_ext: Vec<_> = result.vehicle_types.keys().map(|k| k.external()).collect(); info!( "Created Garage from file with vehicle types: {:?}", @@ -81,7 +83,10 @@ fn write_to_xml(garage: &Garage, path: &Path) { }) .collect(); - let io_vehicles = IOVehicleDefinitions { veh_types }; + let io_vehicles = IOVehicleDefinitions { + veh_types, + vehicles: vec![], + }; xml::write_to_file(&io_vehicles, path, "http://www.matsim.org/files/dtd http://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd") } @@ -89,14 +94,7 @@ fn write_to_xml(garage: &Garage, path: &Path) { fn write_to_proto(garage: &Garage, path: &Path) { info!("Converting Garage into wire type"); let vehicle_types = garage.vehicle_types.values().cloned().collect(); - let vehicles = garage - .vehicles - .iter() - .map(|e| VehicleToType { - id: e.0.internal(), - vehicle_type_id: e.1.internal(), - }) - .collect(); + let vehicles = garage.vehicles.values().cloned().collect(); let wire_format = VehiclesContainer { vehicle_types, @@ -110,8 +108,8 @@ fn load_from_proto(path: &Path) -> Garage { let wire_garage: VehiclesContainer = simulation::io::proto::read_from_file(path); let vehicles = wire_garage .vehicles - .iter() - .map(|v| (Id::get(v.id), Id::get(v.vehicle_type_id))) + .into_iter() + .map(|v| (Id::::get(v.id), v)) .collect(); let vehicle_types = wire_garage .vehicle_types @@ -166,18 +164,28 @@ fn add_io_veh_type(garage: &mut Garage, io_veh_type: IOVehicleType) { garage.add_veh_type(veh_type); } +fn add_io_veh(garage: &mut Garage, io_veh: IOVehicle) { + let veh_type = garage.vehicle_types.get(&Id::get_from_ext(io_veh.vehicle_type.as_str())) + .expect("Vehicle type of vehicle not found. There has to be a vehicle type defined before a vehicle can be added."); + let vehicle = Vehicle::from_io(io_veh, veh_type); + garage.add_veh(vehicle); +} + #[derive(Debug, Deserialize, Serialize, PartialEq, Clone)] #[serde(rename = "vehicleDefinitions")] pub struct IOVehicleDefinitions { #[serde(rename = "vehicleType")] pub veh_types: Vec, + #[serde(rename = "vehicle", default)] + pub vehicles: Vec, } #[derive(Debug, Deserialize, Serialize, PartialEq, Clone)] -#[serde(rename = "vehicleDefinitions")] -pub struct IOVehicles { - #[serde(rename = "vehicleType", default)] - vehicle_types: Vec, +pub struct IOVehicle { + pub id: String, + #[serde(rename = "type")] + pub vehicle_type: String, + pub attributes: Option, } #[derive(Debug, Deserialize, Serialize, PartialEq, Clone)] @@ -323,6 +331,14 @@ mod test { \ \ \ + + + drt + 42 + 0 + 84000 + + \ "; @@ -359,6 +375,16 @@ mod test { 9.5, veh_type.flow_efficiency_factor.as_ref().unwrap().factor ); + + let vehicle = veh_def.vehicles.first().unwrap(); + assert_eq!("drt", vehicle.id.as_str()); + assert_eq!("some-vehicle-id", vehicle.vehicle_type.as_str()); + let attrs = vehicle.attributes.as_ref().unwrap(); + assert_eq!(4, attrs.attributes.len()); + assert_eq!("drt", attrs.find_or_else("dvrpMode", || "")); + assert_eq!("42", attrs.find_or_else("startLink", || "")); + assert_eq!("0", attrs.find_or_else("serviceBeginTime", || "")); + assert_eq!("84000", attrs.find_or_else("serviceEndTime", || "")); } #[test] @@ -378,7 +404,7 @@ mod test { net_mode: Id::::create("some network type 🚕").internal(), lod: LevelOfDetail::Teleported as i32, }); - garage.add_veh_id(&Id::create("some-person"), &Id::get_from_ext("some-type")); + garage.add_veh_by_type(&Id::create("some-person"), &Id::get_from_ext("some-type")); to_file(&garage, file); let loaded_garage = from_file(file); @@ -402,7 +428,7 @@ mod test { net_mode: Id::::create("some network type 🚕").internal(), lod: LevelOfDetail::Teleported as i32, }); - garage.add_veh_id(&Id::create("some-person"), &Id::get_from_ext("some-type")); + garage.add_veh_by_type(&Id::create("some-person"), &Id::get_from_ext("some-type")); to_file(&garage, file); let loaded_garage = from_file(file); diff --git a/src/simulation/vehicles/mod.rs b/src/simulation/vehicles/mod.rs index 0e36b53..2b85302 100644 --- a/src/simulation/vehicles/mod.rs +++ b/src/simulation/vehicles/mod.rs @@ -1,3 +1,3 @@ pub mod garage; -mod io; +pub mod io; mod vehicles; diff --git a/src/simulation/wire_types/general.proto b/src/simulation/wire_types/general.proto new file mode 100644 index 0000000..a579135 --- /dev/null +++ b/src/simulation/wire_types/general.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +package general; + +message AttributeValue { + oneof type { + int64 int_value = 1; + string string_value = 2; + double double_value = 3; + bool bool_value = 4; + // to be expanded + } +} \ No newline at end of file diff --git a/src/simulation/wire_types/messages.proto b/src/simulation/wire_types/messages.proto index f482cfd..35bbe2e 100644 --- a/src/simulation/wire_types/messages.proto +++ b/src/simulation/wire_types/messages.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package messages; import "simulation/wire_types/population.proto"; +import "simulation/wire_types/general.proto"; message SimMessage{ oneof type { @@ -67,4 +68,5 @@ message Vehicle { float pce = 5; population.Person driver = 6; repeated population.Person passengers = 7; + map attributes = 8; } \ No newline at end of file diff --git a/src/simulation/wire_types/mod.rs b/src/simulation/wire_types/mod.rs index ab9ca16..99739af 100644 --- a/src/simulation/wire_types/mod.rs +++ b/src/simulation/wire_types/mod.rs @@ -18,3 +18,77 @@ pub mod population { pub mod vehicles { include!(concat!(env!("OUT_DIR"), "/vehicles.rs")); } + +pub mod general { + include!(concat!(env!("OUT_DIR"), "/general.rs")); +} + +pub mod wire_types { + use crate::simulation::io::attributes::Attr; + use crate::simulation::wire_types::general::attribute_value::Type; + use crate::simulation::wire_types::general::AttributeValue; + + impl AttributeValue { + fn new_int(value: i64) -> Self { + AttributeValue { + r#type: Some(Type::IntValue(value)), + } + } + + fn new_string(value: String) -> Self { + AttributeValue { + r#type: Some(Type::StringValue(value)), + } + } + + fn new_double(value: f64) -> Self { + AttributeValue { + r#type: Some(Type::DoubleValue(value)), + } + } + + fn new_bool(value: bool) -> Self { + AttributeValue { + r#type: Some(Type::BoolValue(value)), + } + } + + pub fn as_int(&self) -> i64 { + match self.r#type.as_ref().unwrap() { + Type::IntValue(value) => *value, + _ => panic!("Expected int, got {:?}", self), + } + } + + pub fn as_string(&self) -> String { + match self.r#type.as_ref().unwrap() { + Type::StringValue(value) => value.clone(), + _ => panic!("Expected string, got {:?}", self), + } + } + + pub fn as_double(&self) -> f64 { + match self.r#type.as_ref().unwrap() { + Type::DoubleValue(value) => *value, + _ => panic!("Expected double, got {:?}", self), + } + } + + pub fn as_bool(&self) -> bool { + match self.r#type.as_ref().unwrap() { + Type::BoolValue(value) => *value, + _ => panic!("Expected bool, got {:?}", self), + } + } + + pub fn from_io_attr(attr: Attr) -> AttributeValue { + match attr.class.as_str() { + "java.lang.String" => AttributeValue::new_string(attr.value), + "java.lang.Double" => AttributeValue::new_double(attr.value.parse().unwrap()), + "java.lang.Integer" => AttributeValue::new_int(attr.value.parse().unwrap()), + "java.lang.Boolean" => AttributeValue::new_bool(attr.value.parse().unwrap()), + _ => panic!("Unsupported attribute class: {}", attr.class), + } + } + } +} diff --git a/src/simulation/wire_types/population.proto b/src/simulation/wire_types/population.proto index 962dfdb..69cc768 100644 --- a/src/simulation/wire_types/population.proto +++ b/src/simulation/wire_types/population.proto @@ -1,4 +1,6 @@ syntax = "proto3"; +import "simulation/wire_types/general.proto"; + package population; message Header { @@ -33,7 +35,7 @@ message Leg { optional uint32 dep_time = 3; uint32 trav_time = 4; Route route = 5; - map attributes = 6; + map attributes = 6; } message Route { @@ -41,13 +43,3 @@ message Route { double distance = 2; repeated uint64 route = 3; } - -message AttributeValue { - oneof type { - uint64 int_value = 1; - string string_value = 2; - double double_value = 3; - bool bool_value = 4; - // to be expanded - } -} \ No newline at end of file diff --git a/src/simulation/wire_types/vehicles.proto b/src/simulation/wire_types/vehicles.proto index 5f07e24..4f5852f 100644 --- a/src/simulation/wire_types/vehicles.proto +++ b/src/simulation/wire_types/vehicles.proto @@ -1,9 +1,11 @@ syntax = "proto3"; +import "simulation/wire_types/messages.proto"; + package vehicles; message VehiclesContainer { repeated VehicleType vehicle_types = 1; - repeated VehicleToType vehicles = 2; + repeated messages.Vehicle vehicles = 2; } message VehicleType { @@ -17,11 +19,6 @@ message VehicleType { LevelOfDetail lod = 8; } -message VehicleToType { - uint64 id = 1; - uint64 vehicle_type_id = 2; -} - enum LevelOfDetail { Network = 0; Teleported = 1; diff --git a/src/test_utils.rs b/src/test_utils.rs index 25584ff..7c40db9 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -48,6 +48,5 @@ pub fn config() -> config::Simulation { end_time: 0, sample_size: 1.0, stuck_threshold: u32::MAX, - passenger_modes: vec![], } } diff --git a/tests/test_simulation.rs b/tests/test_simulation.rs index 1b00a10..42d97af 100644 --- a/tests/test_simulation.rs +++ b/tests/test_simulation.rs @@ -24,6 +24,7 @@ use rust_q_sim::simulation::network::global_network::Network; use rust_q_sim::simulation::network::sim_network::SimNetworkPartition; use rust_q_sim::simulation::population::population::Population; use rust_q_sim::simulation::replanning::routing::travel_time_collector::TravelTimeCollector; +use rust_q_sim::simulation::scenario::Scenario; use rust_q_sim::simulation::simulation::Simulation; use rust_q_sim::simulation::vehicles::garage::Garage; use rust_q_sim::simulation::wire_types::events::Event; @@ -107,8 +108,14 @@ pub fn execute_sim( let rc = Rc::new(comm); let broker = NetMessageBroker::new(rc.clone(), &network, &sim_net); - let mut sim = Simulation::new(config, sim_net, garage, population, broker, events); + let scenario = Scenario { + network, + garage, + population, + network_partition: sim_net, + }; + let mut sim = Simulation::new(config, scenario, broker, events); sim.run(); } From 19aaea2b404cab263d2029de8f06c0e67e7b8580 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Thu, 19 Sep 2024 17:12:30 +0200 Subject: [PATCH 14/17] add drt scenario --- assets/drt/bin-data/drt.ids.binpb | Bin 0 -> 1110 bytes assets/drt/bin-data/drt.network.1.binpb | Bin 0 -> 7342 bytes assets/drt/bin-data/drt.plans.binpb | Bin 0 -> 595 bytes assets/drt/bin-data/drt.vehicles.binpb | Bin 0 -> 278 bytes assets/drt/bin-data/readme.md | 5 + assets/drt/config.yml | 29 + assets/drt/grid_network.xml | 257 + .../multi_mode_one_shared_taxi_population.xml | 179 + assets/drt/vehicles.xml | 23 + assets/equil/equil-plans.binpb | 0 assets/equil/equil-plans.xml | 5008 +++++++++++++++++ src/bin/convert_to_binary.rs | 1 + src/simulation/config.rs | 8 +- src/simulation/engines/leg_engine.rs | 13 +- src/simulation/population/io.rs | 17 +- src/simulation/population/population_data.rs | 15 +- src/simulation/scenario.rs | 62 +- src/simulation/time_queue.rs | 1 + src/simulation/vehicles/io.rs | 6 + 19 files changed, 5596 insertions(+), 28 deletions(-) create mode 100644 assets/drt/bin-data/drt.ids.binpb create mode 100644 assets/drt/bin-data/drt.network.1.binpb create mode 100644 assets/drt/bin-data/drt.plans.binpb create mode 100644 assets/drt/bin-data/drt.vehicles.binpb create mode 100644 assets/drt/bin-data/readme.md create mode 100644 assets/drt/config.yml create mode 100644 assets/drt/grid_network.xml create mode 100644 assets/drt/multi_mode_one_shared_taxi_population.xml create mode 100644 assets/drt/vehicles.xml create mode 100644 assets/equil/equil-plans.binpb create mode 100644 assets/equil/equil-plans.xml diff --git a/assets/drt/bin-data/drt.ids.binpb b/assets/drt/bin-data/drt.ids.binpb new file mode 100644 index 0000000000000000000000000000000000000000..5a8975f9c5ab01e54328b7bcfee31cf14c07a97f GIT binary patch literal 1110 zcmYM!v1$}i7{&3KZ#S|Sa0@|n8^zK>=6>hgJ2Q=lgA6T(Cu<{cv&d@%1V;ulDt^>$>lEueR6MXP58JcEe%!ppYaYCY3ZY9(KQ`|JC`&!D_Mj zcCdfYm*8_tDI|%ANhOVpWFqsTd4N+0^)r-}sH+_>JHAjod4N+0<-mHZ_}?P2KdnUoAI3`~5HXD>tUkUcLL;w|?xWevUFk$ta5A zC^brpGDexA%#lN6iOfhvIH{TZj0#{bK4*&oF literal 0 HcmV?d00001 diff --git a/assets/drt/bin-data/drt.network.1.binpb b/assets/drt/bin-data/drt.network.1.binpb new file mode 100644 index 0000000000000000000000000000000000000000..eca275c85fe52b62c618880ffc1ddf82aba408cb GIT binary patch literal 7342 zcmai&^?qAN5QVkIHOLK3 z(!H9w`6oXepF4YJXZ@YE>f2jV`G0%+-TD7>=k~`3{7Cq?9X{fF z=6||FKi$KRtr@6u_1S>Zv$>g6YX8tmDs}AO4obO0rlK`#4b;1aU>SV5yrlvfTw}28 zA1`mIghrPRmLn(1TdE-Knu6v0sq&U;XmZW^LN(CrK)2KaxRzi^?Os?24s+8vYT81J zYb~ylE9}eZ17Tn4pw+eMmU?J+9lE6fI$US5B|d;g=yYAdk`iW=hA!vyDox;Aw{B^M zZr7tP1kmGpgGD+FEzs-w^o3fX&-Dk3bQs#8-wgzdbQszp;|7ZtiqEJ623@w;65riU z$T}Y^((ZPFcSCv=2SaXHw{*j>8_^f)fe|+vEYj}w!l)b57wUsCHy$j~?)JmDn+O(Z zcL!k7P3a3|V9HGwTjB#4glRWZY>5vb3o~vuSfl}Xn00e{l_8jO^SWgi=G}t6&fZ?T>BLqXKqsuTy5@2{a<_N)1>gWp05rUz#(3O}Y1Vd@-uEHE47)lFWjX6Rv zl(y~~%n^d2WVseYVnyfWbr=$>!6J2ZJ%+@ZUgZW1iFMs_BZkC=zR*n=5}UyyZQacn z5?lI0w_r$Y>s4;Wkl4|y+=i^H3l?c#Zb#P9{at$9JCJpBf0rhGC$f(2@6s6WLe|m! zUHT=t8(By9cWI$}kaY?7_j{3bbbps{cptKk?(botI1cZJw$dbtTOL3hwigc|ZaIQD zEV;kOiTNPnkitfq(L;zs3L9x(9!4A{+}|HT98%aw3q6WBq_B|=!()g;3LEKN9!DHf z*hq)r2^iq8kq*OABxXk6-6xTl33>Ds5;Gx>oo=0LPKHh$AkfCb) zc>9Gxh^qPH?Ux2Ass@m^Um3)xnn2!uZIGk%_fGi;^7b2plvD%8+iwkGQcW0dzca{5 zHDbK|-XJK|jPdpdgQQeL#@inaqEby6Z+|k#N;PJ@{n;Qa)tvG67lX7^zbNwdR|6}h zF%oCXZw6L5MX<&n+L|W@F1Dl*B<%7c8zYT10m`LyQ YkAZDY6RFO>26i}3%GT*mrT)wP4`wMGJ^%m! literal 0 HcmV?d00001 diff --git a/assets/drt/bin-data/drt.plans.binpb b/assets/drt/bin-data/drt.plans.binpb new file mode 100644 index 0000000000000000000000000000000000000000..a485d90749515b919b6e8ee6353dc3ea595580e7 GIT binary patch literal 595 zcmZ9IF-`+95Jl~cA(J3QD~kl;1~>th5D*~6N{9o{u@V&xa+?Ni6)7T!m2v}U=qV^T zz#Jn5#U6!;JWMf{5_NV9B`ydGyZF8JL*Gzn_A@euM zKT3wHCEDNA!;eAA<`FIlh6eoAhDDCH(jLBJ--3N<<0(jnH!U5750u9nJG9@4J|O8M z`nnpvf?adIt?MbkWXgRm(7q4!KByqn-Ir8Wr%~1|&lUG23;WvjBSV}hVWdJfw85j=O3*{mNoMgEKic^cqGLuuCQqwc@LNaqx zg*YXFYQexskc%Uwtf;^@KP6R&RfsvIsKiN#i?g^Sv8co+GcOw?W@u>WB+bPKHN`bA s1=$RT{SHDr9E=DHfjlM@9y1D$1%=0o!ec|>v7_)fP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/drt/multi_mode_one_shared_taxi_population.xml b/assets/drt/multi_mode_one_shared_taxi_population.xml new file mode 100644 index 0000000..e86e1dc --- /dev/null +++ b/assets/drt/multi_mode_one_shared_taxi_population.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + diff --git a/assets/drt/vehicles.xml b/assets/drt/vehicles.xml new file mode 100644 index 0000000..49fccdd --- /dev/null +++ b/assets/drt/vehicles.xml @@ -0,0 +1,23 @@ + + + + + + abc + + + + + + + + + + drt + 111 + 0 + 8000 + + + \ No newline at end of file diff --git a/assets/equil/equil-plans.binpb b/assets/equil/equil-plans.binpb new file mode 100644 index 0000000..e69de29 diff --git a/assets/equil/equil-plans.xml b/assets/equil/equil-plans.xml new file mode 100644 index 0000000..0fe0334 --- /dev/null +++ b/assets/equil/equil-plans.xml @@ -0,0 +1,5008 @@ + + + + + + + Atlantis + + + + + + + + {"car":"1"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"10"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"100"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"11"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"12"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"13"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"14"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"15"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"16"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"17"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"18"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"19"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"2"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"20"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"21"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"22"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"23"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"24"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"25"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"26"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"27"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"28"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"29"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"3"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"30"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"31"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"32"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"33"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"34"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"35"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"36"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"37"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"38"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"39"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"4"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"40"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"41"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"42"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"43"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"44"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"45"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"46"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"47"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"48"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"49"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"5"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"50"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"51"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"52"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"53"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"54"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"55"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"56"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"57"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"58"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"59"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"6"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"60"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"61"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"62"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"63"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"64"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"65"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"66"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"67"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"68"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"69"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"7"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"70"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"71"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"72"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"73"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"74"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"75"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"76"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"77"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"78"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"79"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"8"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"80"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"81"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"82"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"83"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"84"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"85"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"86"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"87"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"88"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"89"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"9"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"90"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"91"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"92"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"93"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"94"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"95"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 4 13 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 5 14 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 7 16 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"96"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"97"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 3 12 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"98"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 8 17 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + + {"car":"99"} + + + + + + + car + + 1 6 15 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + + car + + 1 9 18 20 + + + + + + car + + 20 21 22 23 1 + + + + + + + + + + diff --git a/src/bin/convert_to_binary.rs b/src/bin/convert_to_binary.rs index 9a03413..76df8d2 100644 --- a/src/bin/convert_to_binary.rs +++ b/src/bin/convert_to_binary.rs @@ -53,6 +53,7 @@ fn compute_computational_weights(pop: &Population) -> IntMap { .persons .values() .flat_map(|p| p.plan.as_ref().unwrap().legs.iter()) + .filter(|leg| leg.route.is_some()) .flat_map(|leg| leg.route.as_ref().unwrap().route.iter()) .fold(IntMap::new(), |mut map, link_id| { map.entry(*link_id) diff --git a/src/simulation/config.rs b/src/simulation/config.rs index 83c8399..ad3dd1f 100644 --- a/src/simulation/config.rs +++ b/src/simulation/config.rs @@ -183,12 +183,14 @@ pub struct Routing { #[derive(Serialize, Deserialize, Clone)] pub struct Drt { + #[serde(default)] pub process_type: DrtProcessType, pub services: Vec, } -#[derive(PartialEq, Debug, ValueEnum, Clone, Copy, Serialize, Deserialize)] +#[derive(PartialEq, Debug, ValueEnum, Clone, Copy, Serialize, Deserialize, Default)] pub enum DrtProcessType { + #[default] OneProcess, OneProcessPerService, } @@ -196,9 +198,13 @@ pub enum DrtProcessType { #[derive(Serialize, Deserialize, Clone)] pub struct DrtService { pub mode: String, + #[serde(default)] pub stop_duration: u32, + #[serde(default)] pub max_wait_time: u32, + #[serde(default)] pub max_travel_time_alpha: f32, + #[serde(default)] pub max_travel_time_beta: f32, } diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index 0aab182..eb47fa9 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -8,7 +8,6 @@ use crate::simulation::messaging::events::EventsPublisher; use crate::simulation::network::sim_network::SimNetworkPartition; use crate::simulation::vehicles::garage::Garage; use crate::simulation::wire_types::events::Event; -use crate::simulation::wire_types::general::attribute_value::Type; use crate::simulation::wire_types::messages::Vehicle; use crate::simulation::wire_types::population::{Leg, Person}; use crate::simulation::wire_types::vehicles::LevelOfDetail; @@ -295,20 +294,12 @@ impl DepartureHandler for DrtDriverDepartureHandler { waiting_passengers: &mut IntMap, ) -> Option { // remove passenger from waiting queue, place driver and passenger in vehicle and hand it over to leg engine - let passenger_id = match agent + let passenger_id = agent .curr_leg() .attributes .get(Leg::PASSENGER_ID_ATTRIBUTE) .expect("No passenger id found") - .r#type - .as_ref() - .unwrap() - { - Type::IntValue(id) => *id as u64, - _ => { - unreachable!() - } - }; + .as_int() as u64; let passengers: Vec = vec![waiting_passengers .remove(&passenger_id) diff --git a/src/simulation/population/io.rs b/src/simulation/population/io.rs index 0c6b74b..0d48d07 100644 --- a/src/simulation/population/io.rs +++ b/src/simulation/population/io.rs @@ -202,7 +202,7 @@ pub struct IOLeg { pub mode: String, pub dep_time: Option, pub trav_time: Option, - pub route: IORoute, + pub route: Option, pub attributes: Option, } @@ -366,13 +366,14 @@ mod tests { assert_eq!("car", leg.mode); assert_eq!(None, leg.trav_time); assert_eq!(None, leg.dep_time); - assert_eq!("links", leg.route.r#type); - assert_eq!("1", leg.route.start_link); - assert_eq!("20", leg.route.end_link); - assert_eq!("undefined", leg.route.trav_time.as_ref().unwrap()); - assert_eq!(25000.0, leg.route.distance); - assert_eq!("null", leg.route.vehicle.as_ref().unwrap()); - assert_eq!("1 6 15 20", leg.route.route.as_ref().unwrap()) + let route = leg.route.as_ref().unwrap(); + assert_eq!("links", route.r#type); + assert_eq!("1", route.start_link); + assert_eq!("20", route.end_link); + assert_eq!("undefined", route.trav_time.as_ref().unwrap()); + assert_eq!(25000.0, route.distance); + assert_eq!("null", route.vehicle.as_ref().unwrap()); + assert_eq!("1 6 15 20", route.route.as_ref().unwrap()) } } diff --git a/src/simulation/population/population_data.rs b/src/simulation/population/population_data.rs index 7b62de9..0eb3165 100644 --- a/src/simulation/population/population_data.rs +++ b/src/simulation/population/population_data.rs @@ -372,12 +372,19 @@ impl Leg { let routing_mode: Id = Id::create(routing_mode_ext); let mode = Id::get_from_ext(io_leg.mode.as_str()); - let route = Route::from_io(&io_leg.route, person_id, &mode); + + let route = io_leg + .route + .as_ref() + .and_then(|r| Some(Route::from_io(r, person_id, &mode))); Self { - route: Some(route), + route, mode: mode.internal(), - trav_time: Self::parse_trav_time(&io_leg.trav_time, &io_leg.route.trav_time), + trav_time: Self::parse_trav_time( + &io_leg.trav_time, + &io_leg.route.as_ref().and_then(|r| r.trav_time.clone()), + ), dep_time: parse_time_opt(&io_leg.dep_time), routing_mode: routing_mode.internal(), attributes: HashMap::new(), @@ -482,7 +489,7 @@ impl Route { } } } else { - panic!("vehicle id is expected to be set. ") + panic!("vehicle id is expected to be set.") } } } diff --git a/src/simulation/scenario.rs b/src/simulation/scenario.rs index 717e037..4123dc7 100644 --- a/src/simulation/scenario.rs +++ b/src/simulation/scenario.rs @@ -138,10 +138,14 @@ impl Scenario { //for each drt vehicle, create a driver agent for (link, vehicle) in drt_vehicles { - let start = vehicle.attributes.get("serviceBeginTime").unwrap().as_int() as u32; + let start = vehicle + .attributes + .get("serviceBeginTime") + .unwrap() + .as_double() as u32; let veh_id = Id::::get(vehicle.id); - let person_id = Id::::create(veh_id.external()).internal(); + let person_id = Id::::create(veh_id.external()); let from = network_partition.links.get(&link).unwrap().from(); let x = network.get_node(from).x; let y = network.get_node(from).y; @@ -149,7 +153,10 @@ impl Scenario { let mut plan = Plan::new(); //TODO is Some(start) as end time correct? plan.add_act(Activity::new(x, y, 0, link, Some(0), Some(start), None)); - Person::new(person_id, plan); + let person_id_internal = person_id.internal(); + population + .persons + .insert(person_id, Person::new(person_id_internal, plan)); } } } @@ -157,6 +164,53 @@ impl Scenario { #[cfg(test)] mod tests { + use crate::simulation::config::{CommandLineArgs, Config}; + use crate::simulation::id::Id; + use crate::simulation::scenario::Scenario; + use crate::simulation::wire_types::messages::Vehicle; + use crate::simulation::wire_types::population::Person; + use std::path::PathBuf; + #[test] - fn test() {} + fn test() { + let config_path = "./assets/drt/config.yml"; + let config = Config::from_file(&CommandLineArgs { + config_path: String::from(config_path), + num_parts: None, + }); + + let output_path = PathBuf::from(config.output().output_dir); + + let scenario = Scenario::build(&config, &String::from(config_path), 0, &output_path); + + assert_eq!(scenario.network.nodes.len(), 62); + assert_eq!(scenario.network.links.len(), 170); + + assert_eq!(scenario.garage.vehicle_types.len(), 1); + assert_eq!(scenario.garage.vehicles.len(), 10 + 1); + + assert_eq!(scenario.population.persons.len(), 10 + 1); + + let person_ids = scenario + .population + .persons + .keys() + .collect::>>(); + + let vehicle_ids = scenario + .garage + .vehicles + .keys() + .collect::>>(); + + for n in 0..10u64 { + assert!(person_ids.contains(&&Id::get_from_ext(format!("passenger{}", n).as_str()))); + assert!( + vehicle_ids.contains(&&Id::get_from_ext(format!("passenger{}_car", n).as_str())) + ); + } + + assert!(person_ids.contains(&&Id::get_from_ext("drt"))); + assert!(vehicle_ids.contains(&&Id::get_from_ext("drt"))); + } } diff --git a/src/simulation/time_queue.rs b/src/simulation/time_queue.rs index 6e6017a..2f2ebed 100644 --- a/src/simulation/time_queue.rs +++ b/src/simulation/time_queue.rs @@ -106,6 +106,7 @@ impl EndTime for ValueWrap { /// This is a mutable version of TimeQueue. It allows to mutate the values in the queue. /// It is a logical error to mutate the end_time of the value such that the order of the queue is changed. +/// TODO taxi driver needs to be able to change his end_time such that order is changed #[derive(Default)] pub struct MutTimeQueue where diff --git a/src/simulation/vehicles/io.rs b/src/simulation/vehicles/io.rs index 4cd4e2a..9e76f9e 100644 --- a/src/simulation/vehicles/io.rs +++ b/src/simulation/vehicles/io.rs @@ -168,6 +168,12 @@ fn add_io_veh(garage: &mut Garage, io_veh: IOVehicle) { let veh_type = garage.vehicle_types.get(&Id::get_from_ext(io_veh.vehicle_type.as_str())) .expect("Vehicle type of vehicle not found. There has to be a vehicle type defined before a vehicle can be added."); let vehicle = Vehicle::from_io(io_veh, veh_type); + + //add id for drt mode + if let Some(o) = vehicle.attributes.get("dvrpMode") { + Id::::create(o.as_string().as_str()); + } + garage.add_veh(vehicle); } From f04ca235cf77bfbce6461fffed766073920e7c43 Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Tue, 15 Oct 2024 12:13:00 +0200 Subject: [PATCH 15/17] add drt events and ids --- src/simulation/io/xml_events.rs | 16 +++++++ src/simulation/messaging/events.rs | 47 ++++++++++++++++++--- src/simulation/scenario.rs | 58 +++++++++++++++++++++----- src/simulation/wire_types/events.proto | 18 ++++++++ 4 files changed, 124 insertions(+), 15 deletions(-) diff --git a/src/simulation/io/xml_events.rs b/src/simulation/io/xml_events.rs index f7e8a64..b8f3c0d 100644 --- a/src/simulation/io/xml_events.rs +++ b/src/simulation/io/xml_events.rs @@ -106,6 +106,22 @@ impl XmlEventsWriter { Id::::get(e.request).external(), Id::::get(e.vehicle).external()) } + Type::DvrpTaskStarted(e) => { + format!("\n", + Id::::get(e.person).external(), + Id::::get(e.dvrp_vehicle).external(), + Id::::get(e.task_type).external(), + e.task_index, + Id::::get(e.dvrp_mode).external()) + } + Type::DvrpTaskEnded(e) => { + format!("\n", + Id::::get(e.person).external(), + Id::::get(e.dvrp_vehicle).external(), + Id::::get(e.task_type).external(), + e.task_index, + Id::::get(e.dvrp_mode).external()) + } } } diff --git a/src/simulation/messaging/events.rs b/src/simulation/messaging/events.rs index e5572c4..8a887db 100644 --- a/src/simulation/messaging/events.rs +++ b/src/simulation/messaging/events.rs @@ -5,13 +5,14 @@ use std::fmt::Debug; use tracing::{info, instrument}; use crate::simulation::wire_types::events::event::Type::{ - ActEnd, ActStart, Arrival, Departure, Generic, LinkEnter, LinkLeave, PassengerDroppedOff, - PassengerPickedUp, PersonEntersVeh, PersonLeavesVeh, Travelled, + ActEnd, ActStart, Arrival, Departure, DvrpTaskEnded, DvrpTaskStarted, Generic, LinkEnter, + LinkLeave, PassengerDroppedOff, PassengerPickedUp, PersonEntersVeh, PersonLeavesVeh, Travelled, }; use crate::simulation::wire_types::events::{ - ActivityEndEvent, ActivityStartEvent, ArrivalEvent, DepartureEvent, Event, GenericEvent, - LinkEnterEvent, LinkLeaveEvent, PassengerDroppedOffEvent, PassengerPickedUpEvent, - PersonEntersVehicleEvent, PersonLeavesVehicleEvent, TravelledEvent, + ActivityEndEvent, ActivityStartEvent, ArrivalEvent, DepartureEvent, DvrpTaskEndedEvent, + DvrpTaskStartedEvent, Event, GenericEvent, LinkEnterEvent, LinkLeaveEvent, + PassengerDroppedOffEvent, PassengerPickedUpEvent, PersonEntersVehicleEvent, + PersonLeavesVehicleEvent, TravelledEvent, }; pub trait EventsSubscriber { @@ -225,4 +226,40 @@ impl Event { })), } } + + pub fn new_dvrp_task_started( + person: u64, + dvrp_vehicle: u64, + task_type: u64, + task_index: u64, + dvrp_mode: u64, + ) -> Event { + Event { + r#type: Some(DvrpTaskStarted(DvrpTaskStartedEvent { + person, + dvrp_vehicle, + task_type, + task_index, + dvrp_mode, + })), + } + } + + pub fn new_dvrp_task_ended( + person: u64, + dvrp_vehicle: u64, + task_type: u64, + task_index: u64, + dvrp_mode: u64, + ) -> Event { + Event { + r#type: Some(DvrpTaskEnded(DvrpTaskEndedEvent { + person, + dvrp_vehicle, + task_type, + task_index, + dvrp_mode, + })), + } + } } diff --git a/src/simulation/scenario.rs b/src/simulation/scenario.rs index 4123dc7..2dc4a1b 100644 --- a/src/simulation/scenario.rs +++ b/src/simulation/scenario.rs @@ -22,14 +22,16 @@ impl Scenario { pub fn build(config: &Config, config_path: &String, rank: u32, output_path: &PathBuf) -> Self { id::load_from_file(&io::resolve_path(config_path, &config.proto_files().ids)); + // mandatory content to create a scenario let network = Self::create_network(config, config_path, output_path); let mut garage = Self::create_garage(config, config_path); let mut population = Self::create_population(config, config_path, &network, &mut garage, rank); let network_partition = Self::create_network_partition(config, rank, &network, &population); - Self::create_drt_driver( + + // optional stuff + Self::add_drt( config, - rank, &mut garage, &mut population, &network, @@ -100,9 +102,37 @@ impl Scenario { partition } - fn create_drt_driver( + fn add_drt( + config: &Config, + garage: &mut Garage, + population: &mut Population, + network: &Network, + network_partition: &SimNetworkPartition, + ) { + if config.drt().is_none() { + return; + } + + Self::add_drt_ids(); + Self::add_drt_driver(config, garage, population, network, network_partition); + } + + fn add_drt_ids() { + info!("Creating DRT ids."); + + //activity types + Id::::create("BeforeVrpSchedule"); + Id::::create("DrtStay"); + Id::::create("DrtBusStop"); + + //task types + Id::::create("DRIVE"); + Id::::create("STOP"); + Id::::create("STAY"); + } + + fn add_drt_driver( config: &Config, - rank: u32, garage: &mut Garage, population: &mut Population, network: &Network, @@ -118,7 +148,7 @@ impl Scenario { .collect::>(); //fetch all drt vehicles starting on this partition - let drt_vehicles = garage + let local_drt_vehicles = garage .vehicles .values() .filter(|&v| { @@ -129,7 +159,11 @@ impl Scenario { } }) .map(|v| { - let link = v.attributes.get("startLink").unwrap().as_string(); + let link = v + .attributes + .get("startLink") + .expect("No start link for drt vehicle provided.") + .as_string(); let link_id = Id::::get_from_ext(link.as_str()).internal(); (link_id, v) }) @@ -137,11 +171,11 @@ impl Scenario { .collect::>(); //for each drt vehicle, create a driver agent - for (link, vehicle) in drt_vehicles { + for (link, vehicle) in local_drt_vehicles { let start = vehicle .attributes .get("serviceBeginTime") - .unwrap() + .expect("No service begin time for drt vehicle provided.") .as_double() as u32; let veh_id = Id::::get(vehicle.id); @@ -186,10 +220,14 @@ mod tests { assert_eq!(scenario.network.nodes.len(), 62); assert_eq!(scenario.network.links.len(), 170); - assert_eq!(scenario.garage.vehicle_types.len(), 1); + // 10 agents, 1 drt agent + assert_eq!(scenario.population.persons.len(), 10 + 1); + + // 10 agent vehicles, 1 drt vehicle assert_eq!(scenario.garage.vehicles.len(), 10 + 1); - assert_eq!(scenario.population.persons.len(), 10 + 1); + //there is only one predefined vehicle type (car) + assert_eq!(scenario.garage.vehicle_types.len(), 1); let person_ids = scenario .population diff --git a/src/simulation/wire_types/events.proto b/src/simulation/wire_types/events.proto index 6f3b99b..f009771 100644 --- a/src/simulation/wire_types/events.proto +++ b/src/simulation/wire_types/events.proto @@ -20,6 +20,8 @@ message Event { TravelledEvent travelled = 10; PassengerPickedUpEvent passengerPickedUp = 11; PassengerDroppedOffEvent passengerDroppedOff = 12; + DvrpTaskStartedEvent dvrpTaskStarted = 13; + DvrpTaskEndedEvent dvrpTaskEnded = 14; } } @@ -92,4 +94,20 @@ message PassengerDroppedOffEvent{ uint64 mode = 2; uint64 request = 3; uint64 vehicle = 4; +} + +message DvrpTaskStartedEvent { + uint64 person = 1; + uint64 dvrpVehicle = 2; + uint64 taskType = 3; + uint64 taskIndex = 4; + uint64 dvrpMode = 5; +} + +message DvrpTaskEndedEvent { + uint64 person = 1; + uint64 dvrpVehicle = 2; + uint64 taskType = 3; + uint64 taskIndex = 4; + uint64 dvrpMode = 5; } \ No newline at end of file From 6ccc396ff87eb9d24e8984152190d1bff1256b9a Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Fri, 8 Nov 2024 09:43:26 +0100 Subject: [PATCH 16/17] minor comments --- src/simulation/engines/activity_engine.rs | 1 + .../engines/activity_replanning_strategy.rs | 34 +++++++++++++++++++ src/simulation/engines/leg_engine.rs | 2 ++ src/simulation/engines/mod.rs | 1 + src/simulation/simulation.rs | 2 +- 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/simulation/engines/activity_replanning_strategy.rs diff --git a/src/simulation/engines/activity_engine.rs b/src/simulation/engines/activity_engine.rs index db34475..5e9bb1a 100644 --- a/src/simulation/engines/activity_engine.rs +++ b/src/simulation/engines/activity_engine.rs @@ -11,6 +11,7 @@ use std::rc::{Rc, Weak}; pub struct ActivityEngine { activity_q: MutTimeQueue, events: Rc>, + // this is a weak reference in order to prevent a reference cycle (see https://doc.rust-lang.org/book/ch15-06-reference-cycles.html) agent_state_transition_logic: Weak>>, } diff --git a/src/simulation/engines/activity_replanning_strategy.rs b/src/simulation/engines/activity_replanning_strategy.rs new file mode 100644 index 0000000..c2bc627 --- /dev/null +++ b/src/simulation/engines/activity_replanning_strategy.rs @@ -0,0 +1,34 @@ +use crate::simulation::wire_types::population::Person; + +trait ActivityReplanningStrategy { + fn is_responsible(&self, agent: &Person) -> bool; + fn replan(&mut self, agent: &Person); +} + +struct DrtPassengerReplanning { + // some fields +} + +impl ActivityReplanningStrategy for DrtPassengerReplanning { + fn is_responsible(&self, agent: &Person) -> bool { + todo!() + } + + fn replan(&mut self, agent: &Person) { + todo!() + } +} + +struct DrtDriverReplanning { + // some fields +} + +impl ActivityReplanningStrategy for DrtDriverReplanning { + fn is_responsible(&self, agent: &Person) -> bool { + todo!() + } + + fn replan(&mut self, agent: &Person) { + todo!() + } +} diff --git a/src/simulation/engines/leg_engine.rs b/src/simulation/engines/leg_engine.rs index eb47fa9..f1a7361 100644 --- a/src/simulation/engines/leg_engine.rs +++ b/src/simulation/engines/leg_engine.rs @@ -21,6 +21,7 @@ pub struct LegEngine { garage: Garage, net_message_broker: NetMessageBroker, events: Rc>, + // this is a weak reference in order to prevent a reference cycle (see https://doc.rust-lang.org/book/ch15-06-reference-cycles.html) agent_state_transition_logic: Weak>>, departure_handler: Vec>, waiting_passengers: IntMap, @@ -102,6 +103,7 @@ impl LegEngine { ) -> Vec { let mut agents = vec![]; for veh in vehicles { + //in case of teleportation, do not publish leave vehicle events if publish_leave_vehicle { self.events .borrow_mut() diff --git a/src/simulation/engines/mod.rs b/src/simulation/engines/mod.rs index 0da37d4..00aef2f 100644 --- a/src/simulation/engines/mod.rs +++ b/src/simulation/engines/mod.rs @@ -7,6 +7,7 @@ use std::cell::RefCell; use std::rc::Rc; pub mod activity_engine; +mod activity_replanning_strategy; pub mod leg_engine; pub mod network_engine; pub mod teleportation_engine; diff --git a/src/simulation/simulation.rs b/src/simulation/simulation.rs index b83c540..4718d01 100644 --- a/src/simulation/simulation.rs +++ b/src/simulation/simulation.rs @@ -110,7 +110,7 @@ where // let mut act_ref = self.activity_engine.borrow_mut(); // let mut leg_ref = self.leg_engine.borrow_mut(); - + // // let mut agents = act_ref.agents(); // agents.extend(leg_ref.agents()); // From ba1acfac35ed909d38368f3be2fa695aa0e552ce Mon Sep 17 00:00:00 2001 From: Paul Heinrich Date: Fri, 8 Nov 2024 10:22:24 +0100 Subject: [PATCH 17/17] comments on mpi communicator --- .../messaging/communication/communicators.rs | 132 +++++++++--------- 1 file changed, 69 insertions(+), 63 deletions(-) diff --git a/src/simulation/messaging/communication/communicators.rs b/src/simulation/messaging/communication/communicators.rs index e7bb583..37c31a6 100644 --- a/src/simulation/messaging/communication/communicators.rs +++ b/src/simulation/messaging/communication/communicators.rs @@ -13,12 +13,12 @@ use tracing::{debug, info, instrument, span, Level}; use crate::simulation::wire_types::messages::{SimMessage, SyncMessage, TravelTimesMessage}; -pub trait Message { - fn serialize(&self) -> Vec; - fn deserialize(data: &[u8]) -> Self; - fn to(&self) -> u32; - fn from(&self) -> u32; -} +// pub trait Message { +// fn serialize(&self) -> Vec; +// fn deserialize(data: &[u8]) -> Self; +// fn to(&self) -> u32; +// fn from(&self) -> u32; +// } pub trait SimCommunicator { fn send_receive_vehicles( @@ -36,13 +36,13 @@ pub trait SimCommunicator { travel_times: HashMap, ) -> Vec; - fn isend_request(&mut self, message: M) - where - M: Message; - - fn irecv_request(&mut self) -> Vec - where - M: Message; + // fn isend_request(&mut self, message: M) + // where + // M: Message; + // + // fn irecv_request(&mut self) -> Vec + // where + // M: Message; fn barrier(&self); @@ -72,19 +72,19 @@ impl SimCommunicator for DummySimCommunicator { vec![TravelTimesMessage::from(travel_times)] } - fn isend_request(&mut self, message: M) - where - M: Message, - { - todo!() - } - - fn irecv_request(&mut self) -> Vec - where - M: Message, - { - todo!() - } + // fn isend_request(&mut self, message: M) + // where + // M: Message, + // { + // todo!() + // } + // + // fn irecv_request(&mut self) -> Vec + // where + // M: Message, + // { + // todo!() + // } fn barrier(&self) { info!("Barrier was called on DummySimCommunicator, which doesn't do anything.") @@ -214,19 +214,19 @@ impl SimCommunicator for ChannelSimCommunicator { result } - fn isend_request(&mut self, message: M) - where - M: Message, - { - todo!() - } - - fn irecv_request(&mut self) -> Vec - where - M: Message, - { - todo!() - } + // fn isend_request(&mut self, message: M) + // where + // M: Message, + // { + // todo!() + // } + // + // fn irecv_request(&mut self) -> Vec + // where + // M: Message, + // { + // todo!() + // } fn barrier(&self) { self.barrier.wait(); @@ -237,13 +237,19 @@ impl SimCommunicator for ChannelSimCommunicator { } } -pub struct MpiSimCommunicator<'data, 'scope, 'send_buffer> +/// We need the send buffer to allow asynchronous communication. More on that can be found here: +/// https://github.com/rsmpi/rsmpi/discussions/190 +/// +/// To put it in a nutshell: Since we don't know when the message is actually sent, we need to store the requests in this struct. +/// Since the requests depend on the buffer, the buffer lifetime (`'send_buffer`) must outlive the request lifetime (`'request`). +/// Thus, the buffer is created before starting the simulation in the controller. +pub struct MpiSimCommunicator<'data, 'request, 'send_buffer> where - 'send_buffer: 'scope, + 'send_buffer: 'request, { pub mpi_communicator: SystemCommunicator, - pub scope: &'data LocalScope<'scope>, - pub requests: &'data mut RequestCollection<'scope, Vec>, + pub scope: &'data LocalScope<'request>, + pub requests: &'data mut RequestCollection<'request, Vec>, pub send_buffer: &'send_buffer Vec>>, pub send_count: u64, } @@ -349,26 +355,26 @@ where messages } - fn isend_request(&mut self, message: M) - where - M: Message, - { - let vec = self.send_buffer[self.send_count as usize].get_or_init(|| message.serialize()); - let req = self - .mpi_communicator - .process_at_rank(message.to() as Rank) - .immediate_send(self.scope, vec); - self.requests.add(req); - self.send_count += 1; - } - - fn irecv_request(&mut self) -> Vec - where - M: Message, - { - let (encoded_msg, _status) = self.mpi_communicator.any_process().receive_vec(); - vec![M::deserialize(&encoded_msg)] - } + // fn isend_request(&mut self, message: M) + // where + // M: Message, + // { + // let vec = self.send_buffer[self.send_count as usize].get_or_init(|| message.serialize()); + // let req = self + // .mpi_communicator + // .process_at_rank(message.to() as Rank) + // .immediate_send(self.scope, vec); + // self.requests.add(req); + // self.send_count += 1; + // } + // + // fn irecv_request(&mut self) -> Vec + // where + // M: Message, + // { + // let (encoded_msg, _status) = self.mpi_communicator.any_process().receive_vec(); + // vec![M::deserialize(&encoded_msg)] + // } fn barrier(&self) { self.mpi_communicator.barrier();