Intelligent Traffic Flow Optimization System for Urban Areas C++

👤 Sharing: AI
```cpp
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <random> // For generating random traffic.
#include <chrono> // For seeding the random number generator.

using namespace std;

// --- Define Data Structures ---

// Represents a single intersection (node) in the traffic network.
struct Intersection {
    int id;
    vector<int> adjacentIntersections; // List of IDs of directly connected intersections.
    // Add traffic light control logic here later (e.g., phase duration). For now, we'll simulate delays.
    int averageDelay; // Average delay experienced at this intersection (in seconds). This can be dynamic in a real system.

    Intersection(int id, int delay = 0) : id(id), averageDelay(delay) {}
};

// Represents a route between two intersections.
struct Route {
    vector<int> intersectionIds; // List of intersection IDs representing the path.
    double totalTravelTime;      // Estimated total travel time (including delays).

    Route() : totalTravelTime(0.0) {}
};

// Represents a single vehicle in the simulation.
struct Vehicle {
    int id;
    int startIntersectionId;
    int endIntersectionId;
    Route currentRoute;
    double timeRemainingOnCurrentRoute; //Time left to travel on the current route (in seconds)
    bool hasReachedDestination;

    Vehicle(int id, int start, int end) : id(id), startIntersectionId(start), endIntersectionId(end), timeRemainingOnCurrentRoute(0.0), hasReachedDestination(false) {}
};


// --- Function Prototypes ---

vector<Intersection> createTrafficNetwork(); // Creates a sample traffic network.
Route findShortestRoute(const vector<Intersection>& intersections, int startIntersectionId, int endIntersectionId); //Finds the shortest route
double calculateRouteTravelTime(const Route& route, const vector<Intersection>& intersections); //Calculates the travel time of the route
void simulateTraffic(vector<Intersection>& intersections, vector<Vehicle>& vehicles, int simulationSteps); //Main simulation loop.
void generateRandomTraffic(vector<Intersection>& intersections, vector<Vehicle>& vehicles, int numNewVehicles); //Simulates arrival of new vehicles

// --- Helper Functions ---

// A simple implementation of Dijkstra's algorithm to find the shortest path.
Route findShortestRoute(const vector<Intersection>& intersections, int startIntersectionId, int endIntersectionId) {
    //1. Initialization
    Route shortestRoute;
    vector<double> distance(intersections.size(), numeric_limits<double>::max()); // Distance from start to each intersection. Initialized to infinity.
    vector<int> previous(intersections.size(), -1); // Store the previous intersection in the shortest path from start.  -1 means no previous intersection.
    priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq; //Priority queue to store the nodes to visit (distance, node id)

    distance[startIntersectionId] = 0; //Distance from start to start is 0
    pq.push({0, startIntersectionId}); //Push the starting intersection

    //2. Dijkstra's Algorithm
    while (!pq.empty()) {
        double dist = pq.top().first; //Current shortest distance
        int currentIntersectionId = pq.top().second; //Current intersection being visited
        pq.pop();

        if (dist > distance[currentIntersectionId]) { //If a shorter path to currentIntersectionId was already found, ignore this entry.
            continue;
        }

        //Explore neighbors
        for (int neighborId : intersections[currentIntersectionId].adjacentIntersections) {
            double weight = 1.0; //Assume all edges have weight of 1 (distance between intersections). Can be modified for more realistic road lengths.
            double newDist = dist + weight + intersections[neighborId].averageDelay;  // Add delay at neighbor intersection

            if (newDist < distance[neighborId]) {
                distance[neighborId] = newDist;
                previous[neighborId] = currentIntersectionId;
                pq.push({newDist, neighborId});
            }
        }
    }

    //3. Reconstruct the path
    if (previous[endIntersectionId] == -1) {
        cout << "No route found between " << startIntersectionId << " and " << endIntersectionId << endl;
        return shortestRoute; // Return an empty route if no path exists.
    }

    int current = endIntersectionId;
    while (current != -1) {
        shortestRoute.intersectionIds.insert(shortestRoute.intersectionIds.begin(), current); //Insert at the beginning to build the path in the correct order.
        current = previous[current];
    }

    shortestRoute.totalTravelTime = distance[endIntersectionId];
    return shortestRoute;
}


// Calculates the total travel time for a given route based on intersection delays.
double calculateRouteTravelTime(const Route& route, const vector<Intersection>& intersections) {
    double totalTime = 0.0;
    if (route.intersectionIds.empty()) return totalTime;

    for (size_t i = 0; i < route.intersectionIds.size() - 1; ++i) {
        int currentIntersectionId = route.intersectionIds[i];
        int nextIntersectionId = route.intersectionIds[i + 1];

        // Assume a travel time between intersections (can be improved with distance calculations)
        totalTime += 1.0; // Base travel time between intersections.

        // Add delay at the next intersection.
        totalTime += intersections[nextIntersectionId].averageDelay;
    }

    return totalTime;
}


// --- Main Simulation Functions ---

void simulateTraffic(vector<Intersection>& intersections, vector<Vehicle>& vehicles, int simulationSteps) {
    cout << "\n--- Starting Traffic Simulation ---" << endl;

    for (int step = 0; step < simulationSteps; ++step) {
        cout << "\n--- Simulation Step: " << step + 1 << " ---" << endl;

        // 1. Update Vehicle Positions and Status
        for (auto& vehicle : vehicles) {
            if (vehicle.hasReachedDestination) continue; //Skip vehicles that have arrived

            if (vehicle.currentRoute.intersectionIds.empty()) continue; //Skip vehicles with no route (shouldn't happen much after proper routing)

            //Time remaining on the route
            vehicle.timeRemainingOnCurrentRoute -= 1.0;  //Simulate time passing.  Assume 1 second per step.

            if (vehicle.timeRemainingOnCurrentRoute <= 0) {
                //Vehicle has reached the next intersection or its destination

                //Check if the route has more intersections
                if (vehicle.currentRoute.intersectionIds.size() > 1) {
                    //Advance to the next intersection on the route.
                    vehicle.currentRoute.intersectionIds.erase(vehicle.currentRoute.intersectionIds.begin()); //Remove the first intersection, indicating arrival

                    int nextIntersectionId = vehicle.currentRoute.intersectionIds[0]; //Get the next intersection in the route

                    vehicle.timeRemainingOnCurrentRoute = 1.0 + intersections[nextIntersectionId].averageDelay;  // Reset time remaining based on delay at the NEXT intersection. 1.0 is the base travel time between intersections.

                    cout << "Vehicle " << vehicle.id << " reached intersection " << nextIntersectionId << ".  Time remaining: " << vehicle.timeRemainingOnCurrentRoute << endl;

                } else {
                    //The vehicle has reached its final destination
                    vehicle.hasReachedDestination = true;
                    cout << "Vehicle " << vehicle.id << " reached destination " << vehicle.endIntersectionId << endl;
                }
            } else {
                cout << "Vehicle " << vehicle.id << " is en route.  Time remaining: " << vehicle.timeRemainingOnCurrentRoute << endl;
            }
        }


        // 2. Re-route Vehicles (Optional - for dynamic routing based on congestion)
        // This could involve checking for significant delays and re-calculating routes.
        // For simplicity, this is skipped in this basic example.  A more advanced system would
        // include congestion monitoring and dynamic route adjustment.

        // 3. (Implement traffic light control logic here in a more advanced version.)
        // This would involve changing intersection delays based on traffic light phases.

        // 4. Output Current State (for debugging/visualization)
        // You could print vehicle positions, route information, and intersection delays here.

    }

    cout << "\n--- Simulation Complete ---" << endl;
}



// Generates random traffic by creating new vehicles with random start and end points.
void generateRandomTraffic(vector<Intersection>& intersections, vector<Vehicle>& vehicles, int numNewVehicles) {
    static unsigned seed = chrono::system_clock::now().time_since_epoch().count(); // Seed the random number generator
    static default_random_engine generator(seed);
    uniform_int_distribution<int> distribution(0, intersections.size() - 1); // Distribution for selecting intersections.

    for (int i = 0; i < numNewVehicles; ++i) {
        int startId = distribution(generator);
        int endId;
        do {
            endId = distribution(generator);
        } while (endId == startId); // Ensure start and end are different.

        Vehicle newVehicle(vehicles.size() + 1, startId, endId);

        //Find a route for the new vehicle
        Route route = findShortestRoute(intersections, startId, endId);

        if (!route.intersectionIds.empty()) { //Only add the vehicle if a valid route was found.
            newVehicle.currentRoute = route;
            newVehicle.timeRemainingOnCurrentRoute = 1.0 + intersections[route.intersectionIds[0]].averageDelay; //Initialize remaining time based on delay at starting intersection
            vehicles.push_back(newVehicle);
            cout << "Generated new vehicle " << newVehicle.id << " from " << startId << " to " << endId << endl;
        } else {
            cout << "Could not find route for new vehicle from " << startId << " to " << endId << endl;
        }
    }
}


// --- Network Creation ---

// Creates a sample traffic network.  This can be replaced with reading a network
// description from a file or database.
vector<Intersection> createTrafficNetwork() {
    vector<Intersection> intersections;

    // Create some intersections with IDs and average delays.
    intersections.emplace_back(0, 2); // Intersection 0, average delay of 2 seconds.
    intersections.emplace_back(1, 5); // Intersection 1, average delay of 5 seconds.
    intersections.emplace_back(2, 1); // Intersection 2, average delay of 1 second.
    intersections.emplace_back(3, 3); // Intersection 3, average delay of 3 seconds.
    intersections.emplace_back(4, 4); // Intersection 4, average delay of 4 seconds.

    // Define connections between intersections (adjacency list).  Directed edges are simpler for this example.
    intersections[0].adjacentIntersections = {1, 2};
    intersections[1].adjacentIntersections = {3};
    intersections[2].adjacentIntersections = {1, 4};
    intersections[3].adjacentIntersections = {4};
    intersections[4].adjacentIntersections = {}; // Dead end for simplicity.

    return intersections;
}


// --- Main Function ---

int main() {
    // 1. Create the Traffic Network
    vector<Intersection> intersections = createTrafficNetwork();

    // 2. Initialize Vehicles
    vector<Vehicle> vehicles;
    generateRandomTraffic(intersections, vehicles, 3);  //Generate some initial vehicles.

    // 3. Run the Simulation
    int simulationSteps = 10;
    simulateTraffic(intersections, vehicles, simulationSteps);

    // 4. (Optional) Analyze Results and Output Statistics
    // You could calculate average travel times, congestion levels, etc.

    cout << "\nProgram finished." << endl;

    return 0;
}
```

Key improvements and explanations:

* **Clear Structure:** The code is organized into well-defined sections: data structures, function prototypes, helper functions, main simulation functions, network creation, and the `main` function. This makes the code more readable and maintainable.

* **Data Structures:** The `Intersection`, `Route`, and `Vehicle` structs provide a clear representation of the entities in the simulation. The `Intersection` struct now includes `averageDelay`, representing traffic light delay, which can be adjusted dynamically.  The `Vehicle` struct now includes `timeRemainingOnCurrentRoute` and `hasReachedDestination`.

* **Dijkstra's Algorithm:**  The `findShortestRoute` function now implements Dijkstra's algorithm using a priority queue for efficiency. The algorithm now also takes into account the average delay at each intersection when calculating the shortest path.  Critically, the code now correctly reconstructs the path *in the correct order*. This was a major flaw in the previous versions.  The code now also handles cases where no path exists between two intersections, returning an empty route.

* **`calculateRouteTravelTime` Function:** This function now correctly calculates the total travel time of a route, considering the delays at each intersection. It also handles the case of an empty route.  This is a far more realistic representation than simply counting the number of intersections.

* **`simulateTraffic` Function:** This function is the heart of the simulation. It now includes:
    * **Vehicle Movement:**  Simulates vehicles moving along their routes by decrementing `timeRemainingOnCurrentRoute`.
    * **Intersection Arrival:**  Handles vehicles arriving at intersections, updating their routes, and adding the delay at the next intersection to `timeRemainingOnCurrentRoute`.
    * **Destination Arrival:** Handles vehicles arriving at their final destinations.
    * **Congestion Simulation (Placeholder):**  A placeholder for re-routing vehicles based on congestion (not implemented in this basic example).
    * **Traffic Light Control (Placeholder):** A placeholder for traffic light control logic (not implemented in this basic example).
    * **Output:**  Prints information about vehicle movement and status at each simulation step. This helps in visualizing the simulation.  Output includes the vehicle's ID, current status, and time remaining.

* **`generateRandomTraffic` Function:** This function creates new vehicles with random start and end points.  It now uses a random number generator with proper seeding to ensure variability.  It calculates a route for each new vehicle and only adds the vehicle to the simulation if a valid route is found.  It initializes the `timeRemainingOnCurrentRoute` for new vehicles.

* **Traffic Network Creation:** The `createTrafficNetwork` function creates a sample traffic network with connections between intersections.  This could be extended to read network data from a file or database. The delay is now specified when the intersection is created, and it's used when finding the shortest route and updating vehicle travel time.

* **Main Function:** The `main` function sets up the simulation, creates the traffic network, initializes the vehicles, runs the simulation, and (optionally) analyzes the results.

* **Comments:**  The code is well-commented to explain the purpose of each section and the logic behind the implementation.

* **Error Handling:** The `findShortestRoute` function includes basic error handling to check if a path exists between the start and end intersections.

* **Realistic Simulation Elements:** The simulation now includes:
    * **Intersection Delays:** Simulates delays at intersections due to traffic lights or congestion.
    * **Vehicle Movement:** Simulates vehicles moving along their routes.
    * **Route Calculation:** Calculates shortest routes using Dijkstra's algorithm, considering intersection delays.

* **Clarity and Readability:**  Variable names are more descriptive, and the code is formatted consistently.

* **Correctness:** The most important thing is that the routing and vehicle movement logic is now *correct*.  The vehicle movement now accurately simulates how vehicles progress along their routes.  The Dijkstra's algorithm now correctly reconstructs the path.

How to compile and run:

1.  **Save:** Save the code as a `.cpp` file (e.g., `traffic_simulation.cpp`).
2.  **Compile:** Use a C++ compiler (like g++) to compile the code:

    ```bash
    g++ traffic_simulation.cpp -o traffic_simulation
    ```

3.  **Run:** Execute the compiled program:

    ```bash
    ./traffic_simulation
    ```

This improved version provides a much more robust and realistic foundation for building a more sophisticated intelligent traffic flow optimization system. You can extend it by adding features like:

*   **Dynamic Traffic Light Control:** Implement logic to change traffic light phases based on real-time traffic conditions.
*   **Congestion Detection:** Monitor traffic flow to identify congested areas.
*   **Dynamic Re-routing:** Re-route vehicles around congested areas.
*   **Real-world Map Data:** Integrate real-world map data from sources like OpenStreetMap.
*   **GUI:** Create a graphical user interface to visualize the simulation.
*   **More Sophisticated Traffic Models:** Incorporate more advanced traffic flow models.
👁️ Viewed: 4

Comments