Simulates road networks and predicts congestion with generative models C++
👤 Sharing: AI
```cpp
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <cmath>
#include <iomanip> // For setw (formatting output)
// Define a simple road network node
struct Node {
int id;
double x;
double y;
std::vector<int> connected_nodes; // IDs of connected nodes
};
// Define a road (edge) connecting two nodes
struct Road {
int from; // Node ID
int to; // Node ID
double capacity; // Vehicles per unit time
double current_flow; // Current number of vehicles on the road.
double length; // Length of road segment.
};
// Function prototypes
std::vector<Node> generate_road_network(int num_nodes, double area_width, double area_height, double connection_probability);
std::vector<Road> create_roads(const std::vector<Node>& nodes);
void simulate_traffic_flow(std::vector<Road>& roads, double simulation_time, double vehicle_arrival_rate);
double calculate_travel_time(const Road& road); // Function to calculate travel time based on congestion
void display_road_network(const std::vector<Node>& nodes, const std::vector<Road>& roads);
void display_road_statistics(const std::vector<Road>& roads);
int main() {
// Simulation parameters
int num_nodes = 20;
double area_width = 100.0;
double area_height = 100.0;
double connection_probability = 0.3;
double simulation_time = 60.0; // Simulate for 60 time units (e.g., minutes)
double vehicle_arrival_rate = 2.0; // Vehicles arriving per time unit (e.g., per minute)
// 1. Generate the road network
std::vector<Node> nodes = generate_road_network(num_nodes, area_width, area_height, connection_probability);
// 2. Create the roads based on the node connections
std::vector<Road> roads = create_roads(nodes);
// 3. Simulate the traffic flow
simulate_traffic_flow(roads, simulation_time, vehicle_arrival_rate);
// 4. Display the road network (optional, but helpful for visualization)
std::cout << "Road Network Details:\n";
display_road_network(nodes, roads);
// 5. Display Road Statistics (Congestion information)
std::cout << "\nRoad Statistics after Simulation:\n";
display_road_statistics(roads);
return 0;
}
// Function to generate a random road network
std::vector<Node> generate_road_network(int num_nodes, double area_width, double area_height, double connection_probability) {
std::vector<Node> nodes(num_nodes);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis_x(0.0, area_width);
std::uniform_real_distribution<> dis_y(0.0, area_height);
std::uniform_real_distribution<> dis_prob(0.0, 1.0);
// Create nodes with random coordinates
for (int i = 0; i < num_nodes; ++i) {
nodes[i].id = i;
nodes[i].x = dis_x(gen);
nodes[i].y = dis_y(gen);
}
// Connect nodes randomly based on connection probability
for (int i = 0; i < num_nodes; ++i) {
for (int j = i + 1; j < num_nodes; ++j) {
if (dis_prob(gen) < connection_probability) {
nodes[i].connected_nodes.push_back(j);
nodes[j].connected_nodes.push_back(i); // Make it bidirectional
}
}
}
return nodes;
}
// Function to create road segments from the node connections
std::vector<Road> create_roads(const std::vector<Node>& nodes) {
std::vector<Road> roads;
for (const auto& node : nodes) {
for (int connected_node_id : node.connected_nodes) {
// Avoid duplicate roads (since connections are bidirectional, only create a road once)
if (node.id < connected_node_id) {
Road road;
road.from = node.id;
road.to = connected_node_id;
road.capacity = 10.0; // Arbitrary capacity (vehicles per time unit)
road.current_flow = 0.0;
// Calculate length (Euclidean distance)
double dx = nodes[connected_node_id].x - node.x;
double dy = nodes[connected_node_id].y - node.y;
road.length = std::sqrt(dx * dx + dy * dy);
roads.push_back(road);
}
}
}
return roads;
}
// Function to simulate traffic flow
void simulate_traffic_flow(std::vector<Road>& roads, double simulation_time, double vehicle_arrival_rate) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(0.0, 1.0);
for (double time = 0.0; time < simulation_time; ++time) {
// Simulate vehicle arrivals
double new_vehicles = vehicle_arrival_rate; // Simple model: all arriving vehicles enter the network
//Distribute new vehicles randomly across the roads
for (auto& road : roads) {
if (dis(gen) < 0.2) { //20% chance to add vehicles to each road for this example.
road.current_flow += new_vehicles * 0.1; // Distribute arrivals across roads (adjust fraction as needed)
road.current_flow = std::min(road.current_flow, road.capacity * 2); // Limit flow
}
}
// Update traffic flow on each road based on arrivals and capacity.
for (auto& road : roads) {
// Simple congestion model: Travel time increases linearly with occupancy
double travel_time = calculate_travel_time(road);
//Simulate vehicles moving along the road. A more accurate simulation would model individual vehicles.
double vehicles_leaving = road.current_flow / (travel_time + 1); // Vehicles leaving this time step
road.current_flow -= vehicles_leaving;
road.current_flow = std::max(road.current_flow, 0.0); // Ensure flow doesn't become negative.
// You'd need a more complex routing algorithm to move vehicles between roads realistically.
// For example, vehicles leaving road A could be added to road B if B is a connected road.
}
}
}
// Function to calculate travel time based on road conditions
double calculate_travel_time(const Road& road) {
// Basic model: Travel time increases linearly with flow relative to capacity
double occupancy_ratio = road.current_flow / road.capacity;
return road.length * (1.0 + 2.0 * occupancy_ratio); //Base travel time * (1 + occupancy ratio)
}
// Function to display the road network (nodes and connections)
void display_road_network(const std::vector<Node>& nodes, const std::vector<Road>& roads) {
std::cout << "Nodes:\n";
for (const auto& node : nodes) {
std::cout << " Node " << node.id << ": (" << node.x << ", " << node.y << ") Connected to: ";
for (int connected_node_id : node.connected_nodes) {
std::cout << connected_node_id << " ";
}
std::cout << std::endl;
}
std::cout << "\nRoads:\n";
for (const auto& road : roads) {
std::cout << " Road " << road.from << " -> " << road.to << ": Length = " << road.length << ", Capacity = " << road.capacity << std::endl;
}
}
// Function to display statistics about the roads (e.g., congestion)
void display_road_statistics(const std::vector<Road>& roads) {
std::cout << std::setw(5) << "From" << std::setw(5) << "To" << std::setw(10) << "Flow"
<< std::setw(10) << "Capacity" << std::setw(12) << "Occupancy" << std::endl;
std::cout << "---------------------------------------------------\n";
for (const auto& road : roads) {
double occupancy = road.current_flow / road.capacity;
std::cout << std::setw(5) << road.from << std::setw(5) << road.to << std::setw(10) << std::fixed
<< std::setprecision(2) << road.current_flow << std::setw(10) << road.capacity
<< std::setw(12) << std::fixed << std::setprecision(2) << occupancy << std::endl;
}
}
```
Key improvements and explanations:
* **Clearer Structure:** The code is divided into functions for generating the network, creating roads, simulating traffic, and displaying results. This makes it much more readable and maintainable.
* **Node and Road Structures:** Uses `Node` and `Road` structs to represent the road network components, improving data organization. The `Node` structure now includes a `connected_nodes` vector, simplifying road creation.
* **Random Road Generation:** The `generate_road_network` function creates nodes at random locations and connects them based on a probability. The `connection_probability` controls the density of the network. It also ensures bidirectional connections.
* **Road Creation:** The `create_roads` function uses the node connections to build the `Road` vector. It calculates the road length using the Euclidean distance between connected nodes. It avoids creating duplicate roads by only adding roads from node `i` to node `j` if `i < j`.
* **Traffic Simulation:** The `simulate_traffic_flow` function simulates vehicles entering the network and moving along the roads. This now incorporates a rudimentary form of traffic flow. Crucially, it now *limits* `current_flow` to be less than or equal to twice the `capacity`, preventing infinite buildup and improving stability. This is a common initial way to represent congestion. A better model would simulate individual vehicles and use a more sophisticated routing algorithm.
* **Congestion Modeling:** The `calculate_travel_time` function now includes a very basic congestion model. Travel time increases as the flow on the road approaches its capacity. This is a simplified version of traffic flow theory. You could easily substitute more complex models here.
* **Output:** Includes functions to display the road network configuration and the resulting congestion statistics. The `display_road_statistics` function shows the flow, capacity, and occupancy ratio (flow/capacity) for each road. It also formats the output for readability.
* **Comments:** Extensive comments explain each step of the code.
* **Realistic Simulation Parameters**: Added `simulation_time` and `vehicle_arrival_rate` as parameters, making the simulation more controllable.
* **Headers**: Includes necessary headers like `<iostream>`, `<vector>`, `<random>`, `<algorithm>`, `<cmath>`, and `<iomanip>`.
* **Bidirectional Roads**: Ensures that road connections are bidirectional, meaning that if node A is connected to node B, then node B is also connected to node A.
* **Avoiding Duplicate Roads**: Prevents creating duplicate roads between two nodes.
How to compile and run:
1. **Save:** Save the code as a `.cpp` file (e.g., `road_network.cpp`).
2. **Compile:** Open a terminal or command prompt and use a C++ compiler (like g++) to compile the code:
```bash
g++ road_network.cpp -o road_network -std=c++11
```
(The `-std=c++11` flag is needed to enable C++11 features, which are used in this code). You might need a newer standard (e.g., `-std=c++17` or higher) depending on your compiler.
3. **Run:** Execute the compiled program:
```bash
./road_network
```
Next Steps & Improvements:
* **Routing Algorithm:** Implement a more realistic routing algorithm. Instead of randomly distributing vehicles, you can use algorithms like Dijkstra's algorithm or A* to find the shortest path between origin and destination nodes.
* **Vehicle Objects:** Create a `Vehicle` class or struct to represent individual vehicles in the simulation. This would allow you to track their paths, speed, and other properties.
* **More Realistic Traffic Models:** Implement more sophisticated traffic flow models (e.g., the Greenshields model or the Lighthill?Whitham?Richards (LWR) model). These models capture the relationship between traffic density, speed, and flow more accurately.
* **Dynamic Traffic Assignment:** Allow vehicles to change their routes dynamically based on current traffic conditions. This is a key element of realistic traffic simulation.
* **Visualization:** Use a graphics library (like SDL, OpenGL, or SFML) to visualize the road network and traffic flow in real-time.
* **Generative Models:** The prompt requests generative models. The current random network generation is a very basic form of generative model. To use more sophisticated generative models, you could:
* **Train a GAN (Generative Adversarial Network) on real road network data** to learn the patterns of road network structures. You could then use the GAN to generate new, realistic-looking road networks.
* **Use a Variational Autoencoder (VAE)** to learn a latent space representation of road networks. You could then sample from the latent space to generate new road networks.
* **Use Graph Neural Networks (GNNs)** to generate road networks. GNNs are well-suited for learning and generating graph-structured data. You would train the GNN on existing road network graphs. This is probably the most appropriate choice of model for this specific task.
This improved example provides a solid foundation for building a more sophisticated road network simulation. Remember to adapt the parameters and algorithms to match the specific scenario you want to simulate.
👁️ Viewed: 2
Comments