def get_arriving_clusters_from_positions(self, vehicle_positions, outgoing_edges, IDs): arrivals = self.get_arrival_times(vehicle_positions) tally = {} arriving_cluster_info = {} arriving_clusters = ClusterSequence() for vehID, arrival, outgoing_edge in zip(IDs, arrivals, outgoing_edges): bucket = arrival // self.sampling_interval try: tally[bucket] += 1 arriving_cluster_info[bucket * self.sampling_interval].append( VehicleInfo(vehID, arrival, outgoing_edge)) except KeyError: tally[bucket] = 1 arriving_cluster_info[bucket * self.sampling_interval] = [ VehicleInfo(vehID, arrival, outgoing_edge) ] for bucket, count in tally.items(): arriving_clusters.insort( Cluster(count=count, arrival=bucket * self.sampling_interval, departure=(bucket + 1) * self.sampling_interval)) return arriving_clusters, arriving_cluster_info
def get_queued_clusters_from_positions(self, vehicle_positions, outgoing_edges, IDs): arrival_times = self.get_arrival_times(vehicle_positions) queued_clusters = ClusterSequence() queued_cluster_info = {} queue_length = len(arrival_times) queue_arrival = 0 queue_duration = queue_length / self.saturation_flow_rate queue_departure = self.round_to_delta(queue_arrival + queue_duration) queue_cluster = Cluster(count=queue_length, arrival=queue_arrival, departure=queue_departure) queued_clusters.insort(queue_cluster, merge=True) for vehID, arrival, outgoing_edge in zip(IDs, arrival_times, outgoing_edges): try: queued_cluster_info[queue_arrival].append( VehicleInfo(vehID, arrival, outgoing_edge)) except KeyError: queued_cluster_info[queue_arrival] = [ VehicleInfo(vehID, arrival, outgoing_edge) ] return queued_clusters, queued_cluster_info
def construct_outflow(self, inflow, phase_sequence, start_times): curr_cluster = ScheduleStatus({phase: 0 for phase in inflow}) outflow = ClusterSequence() for phase, start in zip(phase_sequence, start_times): next_cluster = inflow[phase][curr_cluster[phase]] outflow.append( Cluster(count=next_cluster.count, arrival=start, departure=start + next_cluster.duration)) curr_cluster.schedule_in_place(phase) return outflow
def get_arriving_clusters(self, arrivals): tally = {} arriving_clusters = ClusterSequence() for arrival in arrivals: bucket = arrival // self.sampling_interval try: tally[bucket] += 1 except KeyError: tally[bucket] = 1 for bucket, count in tally.items(): arriving_clusters.insort( Cluster(count=count, arrival=bucket * self.sampling_interval, departure=(bucket + 1) * self.sampling_interval)) return arriving_clusters
def __init__(self, phases, inflow=None, cluster_info=None): self.inflow = {phase: ClusterSequence() for phase in phases} if inflow is None else inflow self.cluster_info = {phase: {} for phase in phases } if cluster_info is None else cluster_info self.phases = sorted(phases)
def road_to_phase(self, edgeID, roadflow, turn_proportions): inflow = {} turns_by_phase = {} turns_from_edge = [ turn for turn in turn_proportions if turn['incoming_edge'] == edgeID ] for turn in turns_from_edge: phase = turn['phase'] try: turns_by_phase[phase] = min( turns_by_phase[phase] + turn['probability'], 1) except KeyError: turns_by_phase[phase] = min(turn['probability'], 1) inflow[phase] = ClusterSequence() for cluster in roadflow: for phase, ratio in turns_by_phase.items(): split = cluster.expected_proportion(ratio, self.min_cluster_size) if split: inflow[phase].insort(split, merge=True) return inflow
def publish_results(self, inflow, outflow, phase_sequence, road_ratio): outflow_by_edge = {} curr_cluster = {phase: 0 for phase in inflow} for outgoing_cluster, phase in zip(outflow, phase_sequence): original_cluster = inflow[phase][curr_cluster[phase]] curr_cluster[phase] += 1 for incoming_edge, split_ratio in road_ratio[phase][ original_cluster.arrival].items(): turns_from_edge = self._get_normalized_turn_ratios( incoming_edge, phase) for turn in turns_from_edge: outgoing_edge = turn['outgoing_edge'] turn_probability = turn['probability'] outflow_to_edge = outgoing_cluster.expected_proportion( split_ratio * turn_probability, self.min_cluster_size) if outflow_to_edge: try: outflow_by_edge[outgoing_edge].insort( outflow_to_edge, merge=True) except KeyError: outflow_by_edge[outgoing_edge] = ClusterSequence( [outflow_to_edge]) else: pass with self.shared_lock: self.publish_directory.clear() for edge, outflow in outflow_by_edge.items(): self.publish_directory[edge] = outflow self.shared_results_directory[self.id] = self.publish_directory
def get_inflow_from_roadflow(self, roadflow, phases, turn_proportions): # Warning: road_to_phase doesn't return edge_inflow for every phase # Only for phases relevant to the edge inflow = {phase: ClusterSequence() for phase in phases} road_count = {} for edge, edge_roadflow in roadflow.items(): if edge_roadflow: edge_inflow = self.road_to_phase(edge, edge_roadflow, turn_proportions) for phase, clusters in edge_inflow.items(): inflow[phase] = inflow[phase].merge(clusters) if phase not in road_count: road_count[phase] = {} for cluster in clusters: if cluster.arrival not in road_count[phase]: road_count[phase][cluster.arrival] = {} try: road_count[phase][ cluster.arrival][edge] += cluster.count except KeyError: road_count[phase][ cluster.arrival][edge] = cluster.count return inflow, road_count
def get_feasible_control_flow(self, inflow, curr_phase, curr_phase_duration, curr_time, road_ratio): outflow = ClusterSequence() phase_sequence = [] phase_duration = [] updated_inflow = {phase: ClusterSequence() for phase in inflow} updated_road_ratio = {phase: {} for phase in inflow} violation_time = None tmp_curr_phase = curr_phase tmp_curr_phase_duration = curr_phase_duration tmp_curr_time = curr_time tmp_inflow = { phase: sequence.copy() for phase, sequence in inflow.items() } while violation_time != float('inf'): violation_time = float('inf') tmp_outflow, tmp_phase_sequence, tmp_phase_duration = self.scheduler.schedule( tmp_inflow, tmp_curr_phase, tmp_curr_phase_duration, tmp_curr_time) curr_index = 0 for cluster, phase, duration in zip(tmp_outflow, tmp_phase_sequence, tmp_phase_duration): cluster_from_inflow = tmp_inflow[phase][0] if duration > self.Gmax[phase]: violation_time = cluster.departure - (duration - self.Gmax[phase]) if violation_time < cluster.arrival: if curr_index == 0: violation_time = tmp_curr_time else: previous_cluster = tmp_outflow[curr_index - 1] violation_time = previous_cluster.departure unviolated_outflow, violated_outflow = cluster.split( violation_time, self.min_cluster_size) unviolated_ratio = 1 - (violated_outflow.count / cluster.count) unviolated_inflow, violated_inflow = cluster_from_inflow.split_by_ratio( unviolated_ratio, self.min_cluster_size) tmp_inflow[phase].set(0, violated_inflow) road_ratio[phase][violated_inflow.arrival] = road_ratio[ phase][cluster_from_inflow.arrival] if unviolated_outflow: outflow.append(unviolated_outflow) phase_sequence.append(phase) phase_duration.append(self.Gmax[phase]) updated_inflow[phase].append(unviolated_inflow) updated_road_ratio[phase][ unviolated_inflow.arrival] = road_ratio[phase][ cluster_from_inflow.arrival] tmp_curr_time = violation_time + self.Y[phase] tmp_curr_phase = self.get_next_phase(phase) tmp_curr_phase_duration = 0 break else: outflow.append(cluster) phase_sequence.append(phase) phase_duration.append(duration) scheduled_cluster = tmp_inflow[phase].pop(0) if scheduled_cluster: updated_inflow[phase].append(scheduled_cluster) updated_road_ratio[phase][ scheduled_cluster.arrival] = deepcopy( road_ratio[phase][cluster_from_inflow.arrival]) curr_index += 1 return outflow, phase_sequence, phase_duration, updated_inflow, updated_road_ratio