Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions rust_qsim/src/simulation/network/flow_cap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ impl Flowcap {
/**
Updates the accumulated capacity if the time has advanced.
*/
// TODO: Must know how many vehicles are in the buffer (see updateFastFlowAccumulation)

/// TODO:
/// The capacity of the buffer is the flowcapacityPerTimeStpe
/// Check if the accumalated flow capacity of the buffer is not exceeded.
/// Update flow capacity
pub fn update_capacity(&mut self, now: u32) {
if self.last_update_time < now {
let time_steps: f32 = (now - self.last_update_time) as f32;
Expand Down
96 changes: 82 additions & 14 deletions rust_qsim/src/simulation/network/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,28 @@ impl SimLink {
}
}

/// This method pushes a vehicle directly into the buffer
pub fn push_veh_to_buffer(&mut self, vehicle: InternalVehicle, _now: u32) {
match self {
SimLink::Local(ll) => ll.push_veh_to_buffer(vehicle),
SimLink::In(il) => il.local_link.push_veh_to_buffer(vehicle),
SimLink::Out(_) => {
panic!("Can't push vehicle to buffer on out link")
}
}
}

/// This method pushes a vehicle to the waiting list, which has priority over vehicles in q
pub fn push_veh_to_waiting_list(&mut self, vehicle: InternalVehicle) {
match self {
SimLink::Local(ll) => ll.push_veh_to_waiting_list(vehicle),
SimLink::In(il) => il.local_link.push_veh_to_waiting_list(vehicle),
SimLink::Out(_) => {
panic!("Can't push vehicle to waiting list on out link")
}
}
}

pub fn pop_veh(&mut self) -> InternalVehicle {
match self {
SimLink::Local(ll) => ll.pop_front(),
Expand Down Expand Up @@ -149,6 +171,8 @@ impl SimLink {
pub struct LocalLink {
pub id: Id<Link>,
q: VecDeque<VehicleQEntry>,
buffer: VecDeque<InternalVehicle>,
waiting_list: VecDeque<InternalVehicle>,
length: f64,
free_speed: f32,
storage_cap: StorageCap,
Expand Down Expand Up @@ -183,6 +207,8 @@ impl LocalLink {
LocalLink {
id,
q: VecDeque::new(),
buffer: VecDeque::new(),
waiting_list: VecDeque::new(),
length: 1.0,
free_speed: 1.0,
storage_cap: StorageCap::new(0., 1., 1., 1.0, 7.5),
Expand Down Expand Up @@ -215,6 +241,8 @@ impl LocalLink {
LocalLink {
id,
q: VecDeque::new(),
buffer: VecDeque::new(),
waiting_list: VecDeque::new(),
length,
free_speed,
storage_cap,
Expand All @@ -238,30 +266,70 @@ impl LocalLink {
});
}

pub fn push_veh_to_buffer(&mut self, vehicle: InternalVehicle) {
// self.storage_cap.consume(vehicle.pce);
self.buffer.push_back(vehicle);
}

/// Push a vehicle into the waiting list.
pub fn push_veh_to_waiting_list(&mut self, vehicle: InternalVehicle) {
// self.storage_cap.consume(vehicle.pce);
self.waiting_list.push_back(vehicle);
}

/// This method fills the buffer from two sources with priority:
/// 1) Check if there are vehicles in the waiting list and move them to the buffer.
/// 2) Check if there are vehicles in the queue that have reached their earliest exit time and
/// move them to the buffer.
pub fn do_sim_step(&mut self, now: u32) {
self.update_flow_cap(now);
self.apply_storage_cap_updates();
self.add_waiting_to_buffer();
self.add_queue_to_buffer(now);
}

fn add_queue_to_buffer(&mut self, now: u32) {
while let Some(front) = self.q.front() {
if front.earliest_exit_time <= now {
//TODO check with self.flow_cap.has_capacity();
let veh = self.q.pop_front().unwrap().vehicle;
self.storage_cap.release(veh.pce);
self.buffer.push_back(veh);
} else {
break;
}
}
}

fn add_waiting_to_buffer(&mut self) {
while let Some(veh) = self.waiting_list.pop_front() {
self.buffer.push_back(veh);
}
}

/// This method returns the next/first vehicle from the buffer and removes it from the buffer.
pub fn pop_front(&mut self) -> InternalVehicle {
let veh = self.q.pop_front().unwrap_or_else(|| panic!("There was no vehicle in the queue. Use 'offers_veh' to test if a vehicle is present first."));
self.flow_cap.consume_capacity(veh.vehicle.pce);
self.storage_cap.release(veh.vehicle.pce);
self.stuck_timer.reset();
veh.vehicle
if let Some(veh) = self.buffer.pop_front() {
// self.storage_cap.release(veh.pce);
self.flow_cap.consume_capacity(veh.pce);
self.stuck_timer.reset();
return veh;
}
panic!("There was no vehicle in the buffer.");
}

pub fn update_flow_cap(&mut self, now: u32) {
// increase flow cap if new time step
self.flow_cap.update_capacity(now);
}

/// This method returns the next vehicle that is allowed to leave the connection and checks
/// whether flow capacity is available.
pub fn q_front(&self, now: u32) -> Option<&InternalVehicle> {
// check if we have flow cap left for current time step, otherwise abort
if !self.flow_cap.has_capacity() {
return None;
}

// peek if fist vehicle in queue can leave
if let Some(entry) = self.q.front() {
if entry.earliest_exit_time <= now {
if let Some(entry) = self.buffer.front() {
if self.flow_cap.has_capacity() {
self.stuck_timer.start(now);
return Some(&entry.vehicle);
return Some(entry);
}
}

Expand Down
14 changes: 11 additions & 3 deletions rust_qsim/src/simulation/network/sim_network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,21 @@ impl SimNetworkPartition {
);
});

// If events_publisher is None, this is the start of the route and the vehicle goes
// into the waiting list. `fill_buffer` prioritizes draining waiting_list into buffer.
let is_route_begin = events_publisher.is_none();

if let Some(publisher) = events_publisher {
publisher
.borrow_mut()
.publish_event(now, &Event::new_link_enter(link.id(), &vehicle.id));
}

link.push_veh(vehicle, now);
if is_route_begin {
link.push_veh_to_waiting_list(vehicle);
} else {
link.push_veh(vehicle, now);
}
self.veh_counter += 1;

Self::activate_link(&mut self.active_links, link.id().clone());
Expand Down Expand Up @@ -292,8 +300,8 @@ impl SimNetworkPartition {
active_nodes: &mut IntSet<Id<Node>>,
now: u32,
) -> bool {
link.update_flow_cap(now);
link.apply_storage_cap_updates();
// Move all vehicles that completed their link travel into the buffer.
link.do_sim_step(now);
// the node will only look at the vehicle at the at the top of the queue in the next timestep
// therefore, peek whether vehicles are available for the next timestep.
if link.q_front(now + 1).is_some() {
Expand Down
Loading