LCOV - code coverage report
Current view: top level - app/test - test_Dynamic.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 189 0.0 %
Date: 2023-08-17 16:45:52 Functions: 0 4 0.0 %

          Line data    Source code
       1             : #include <catch2/catch_get_random_seed.hpp>
       2             : #include <catch2/catch_test_macros.hpp>
       3             : #include <catch2/matchers/catch_matchers_floating_point.hpp>
       4             : #include <chrono>
       5             : #include <fstream>
       6             : #include <ios>
       7             : #include <iostream>
       8             : #include <thread>
       9             : 
      10             : #include "Alg/ShortestPath/DijkstraMany.hpp"
      11             : #include "Dynamic/Demand/UniformDemandLoader.hpp"
      12             : #include "Dynamic/Env/Env.hpp"
      13             : #include "Dynamic/Env/Loader.hpp"
      14             : #include "Dynamic/Env/Vehicle.hpp"
      15             : #include "Dynamic/Policy/DoubleQLearner.hpp"
      16             : #include "Dynamic/Policy/PathPolicy.hpp"
      17             : #include "Dynamic/Policy/QLearner.hpp"
      18             : #include "Dynamic/Policy/RandomPolicy.hpp"
      19             : #include "Dynamic/Policy/RewardFunction/RewardFunction.hpp"
      20             : #include "Dynamic/Policy/RewardFunction/RewardFunctionDifference.hpp"
      21             : #include "Dynamic/Policy/RewardFunction/RewardFunctionGreedy.hpp"
      22             : #include "Dynamic/Policy/RewardFunction/RewardFunctionLocal.hpp"
      23             : #include "Log/ProgressLogger.hpp"
      24             : #include "Log/ProgressLoggerTableOStream.hpp"
      25             : #include "Static/Demand.hpp"
      26             : #include "Static/supply/Network.hpp"
      27             : #include "data/SUMO/EdgeData.hpp"
      28             : #include "data/SUMO/NetState.hpp"
      29             : #include "data/SUMO/Routes.hpp"
      30             : #include "data/VISUM/OFormatDemand.hpp"
      31             : 
      32             : using namespace std;
      33             : using Catch::Matchers::WithinRel;
      34             : 
      35             : extern string baseDir;
      36             : extern string benchmarkDir;
      37             : 
      38             : typedef chrono::steady_clock clk;
      39             : 
      40             : const size_t MATRIX_9_10_TOTAL_DEMAND_HOUR = 102731;
      41             : 
      42           0 : TEST_CASE("Dynamic - shortest path", "[dynamic][dynamic-sp][!benchmark]") {
      43           0 :     utils::stringify::stringify<float>::PRECISION  = 3;
      44           0 :     utils::stringify::stringify<double>::PRECISION = 3;
      45             : 
      46           0 :     Log::ProgressLoggerTableOStream logger;
      47             : 
      48             :     // logger << std::fixed << std::setprecision(6);
      49             : 
      50             :     // clang-format off
      51           0 :     Dynamic::Env::Loader<
      52             :         const SUMO::NetworkTAZs &,
      53             :         Dynamic::RewardFunction &
      54           0 :     > loader;
      55             :     // clang-format on
      56             : 
      57             :     // Environment
      58           0 :     shared_ptr<SUMO::Network> sumoNetwork = SUMO::Network::loadFromFile(benchmarkDir + "data/dynaminator-data/porto.net.xml");
      59           0 :     SUMO::TAZs                sumoTAZs    = SUMO::TAZ::loadFromFile(benchmarkDir + "data/dynaminator-data/porto.taz.xml");
      60           0 :     SUMO::NetworkTAZs         sumo{*sumoNetwork, sumoTAZs};
      61             : 
      62           0 :     Dynamic::RewardFunction &rewardFunction = Dynamic::RewardFunctionGreedy::INSTANCE;
      63             : 
      64           0 :     shared_ptr<Dynamic::Env::Env> env = loader.load(sumo, rewardFunction);
      65             : 
      66             :     // loader.adapter.dump();
      67             : 
      68             :     // Demand
      69           0 :     VISUM::OFormatDemand oDemand = VISUM::OFormatDemand::loadFromFile(benchmarkDir + "data/dynaminator-data/matrix.9.0.10.0.2.fma");
      70             :     // clang-format off
      71           0 :     Static::Demand::Loader<
      72             :         const VISUM::OFormatDemand &,
      73             :         const Static::SUMOAdapter &
      74             :     > staticDemandLoader;
      75             :     // clang-format on
      76           0 :     Static::Demand staticDemand = staticDemandLoader.load(
      77             :         oDemand,
      78             :         (Static::SUMOAdapter &)loader.adapter
      79           0 :     );
      80             : 
      81             :     // loader.adapter.dump();
      82             : 
      83             :     // Policy
      84           0 :     Alg::Graph G = env->toGraph();
      85             : 
      86           0 :     vector<Dynamic::Env::Node> startNodes;
      87           0 :     for(const Static::Network::Node &u: staticDemand.getStartNodes()) {
      88           0 :         SUMO::TAZ::ID           fromTAZ     = loader.adapter.toSumoTAZ(u);
      89           0 :         list<SUMO::TAZ::Source> sourcesList = loader.adapter.toTAZEdges(fromTAZ).first;
      90           0 :         for(const SUMO::TAZ::Source &source: sourcesList)
      91           0 :             if(source.weight > 0.0) {
      92           0 :                 Dynamic::Env::Edge::ID edgeID = loader.adapter.toEdge(source.id);
      93           0 :                 Dynamic::Env::Node     nodeID = env->getEdge(edgeID).u;
      94           0 :                 startNodes.push_back(nodeID);
      95             :             }
      96             :     }
      97             : 
      98           0 :     Alg::ShortestPath::DijkstraMany sp;
      99           0 :     sp.solve(G, startNodes);
     100             : 
     101           0 :     Dynamic::PathPolicy::ShortestPathFactory policyFactory(*env, 0);
     102             : 
     103             :     // Demand
     104           0 :     const double SCALE = 0.1;
     105             : 
     106           0 :     Dynamic::UniformDemandLoader demandLoader(SCALE, 0.0, 3600.0, policyFactory, 0);
     107           0 :     Dynamic::Demand              demand = demandLoader.load(staticDemand, *env, loader.adapter).first;
     108             : 
     109           0 :     REQUIRE_THAT(demand.getVehicles().size(), WithinRel(MATRIX_9_10_TOTAL_DEMAND_HOUR * SCALE, 1e-2));
     110             : 
     111             :     // Load demand into environment
     112           0 :     env->addDemand(demand);
     113             : 
     114           0 :     env->initializeTrafficLights(0);
     115             : 
     116           0 :     env->log(logger, 0, 3600, 30);
     117             : 
     118           0 :     SUMO::NetState netState(baseDir + "data/out/netstate.xml", ios_base::out);
     119             : 
     120           0 :     list<thread> threads;
     121           0 :     const size_t MAX_NUMBER_THREADS = 64;
     122             : 
     123             :     // Run simulation
     124             :     // clang-format off
     125           0 :     SUMO::NetState::Timestep::Loader<
     126             :         Dynamic::Env::Env &,
     127             :         const Dynamic::SUMOAdapter &,
     128             :         Dynamic::Time
     129             :     > timestepLoader;
     130             :     // clang-format on
     131             : 
     132           0 :     for(Dynamic::Time t = 0.0; t <= 3600.0; t += 1.0) {
     133           0 :         env->runUntil(t);
     134             : 
     135           0 :         SUMO::NetState::Timestep timestep = timestepLoader.load(*env, loader.adapter, t);
     136             : 
     137             :         // clang-format off
     138           0 :         threads.emplace_back(
     139             :             [&netState](SUMO::NetState::Timestep ts) -> void {
     140             :                 netState << ts;
     141             :             },
     142             :             timestep
     143           0 :         );
     144             :         // clang-format on
     145             : 
     146           0 :         while(threads.size() > MAX_NUMBER_THREADS) {
     147           0 :             threads.front().join();
     148           0 :             threads.pop_front();
     149             :         }
     150             :     }
     151             : 
     152           0 :     while(!threads.empty()) {
     153           0 :         threads.front().join();
     154           0 :         threads.pop_front();
     155             :     }
     156             : 
     157           0 :     env->runUntil(3600.0);
     158             : 
     159             :     // clang-format off
     160           0 :     SUMO::Routes::Loader<
     161             :         const std::list<std::reference_wrapper<const Dynamic::Env::Vehicle>> &,
     162             :         const SUMO::TAZs &,
     163             :         const Dynamic::SUMOAdapter &
     164             :     > routesLoader;
     165             :     // clang-format on
     166             : 
     167           0 :     const Dynamic::Env::Env &envConst = *env;
     168             : 
     169           0 :     SUMO::Routes routes = routesLoader.load(envConst.getVehicles(), sumo.tazs, loader.adapter);
     170             : 
     171           0 :     routes.saveToFile(baseDir + "data/out/sp.rou.xml");
     172           0 : }
     173             : 
     174           0 : void dynamic(Dynamic::RewardFunction &rewardFunction) {
     175           0 :     utils::stringify::stringify<float>::PRECISION  = 3;
     176           0 :     utils::stringify::stringify<double>::PRECISION = 3;
     177             : 
     178           0 :     Log::ProgressLoggerTableOStream logger;
     179             : 
     180             :     // logger << std::fixed << std::setprecision(6);
     181             : 
     182             :     // clang-format off
     183           0 :     Dynamic::Env::Loader<
     184             :         const SUMO::NetworkTAZs &,
     185             :         Dynamic::RewardFunction &
     186           0 :     > loader;
     187             :     // clang-format on
     188             : 
     189             :     // Environment
     190           0 :     shared_ptr<SUMO::Network> sumoNetwork = SUMO::Network::loadFromFile(benchmarkDir + "data/dynaminator-data/porto.net.xml");
     191           0 :     SUMO::TAZs                sumoTAZs    = SUMO::TAZ::loadFromFile(benchmarkDir + "data/dynaminator-data/porto.taz.xml");
     192           0 :     SUMO::NetworkTAZs         sumo{*sumoNetwork, sumoTAZs};
     193             : 
     194           0 :     shared_ptr<Dynamic::Env::Env> env = loader.load(sumo, rewardFunction);
     195             : 
     196             :     // loader.adapter.dump();
     197             : 
     198             :     // Demand
     199           0 :     VISUM::OFormatDemand oDemand = VISUM::OFormatDemand::loadFromFile(benchmarkDir + "data/dynaminator-data/matrix.9.0.10.0.2.fma");
     200             :     // clang-format off
     201           0 :     Static::Demand::Loader<
     202             :         const VISUM::OFormatDemand &,
     203             :         const Static::SUMOAdapter &
     204             :     > staticDemandLoader;
     205             :     // clang-format on
     206           0 :     Static::Demand staticDemand = staticDemandLoader.load(
     207             :         oDemand,
     208             :         (Static::SUMOAdapter &)loader.adapter
     209           0 :     );
     210             : 
     211           0 :     ofstream adapterDumpFile(baseDir + "data/out/adapter-dynamic.dump.txt");
     212           0 :     loader.adapter.dump(adapterDumpFile);
     213             : 
     214           0 :     const double HOUR2SEC = 3600.0;
     215             : 
     216             :     // Policy
     217           0 :     Dynamic::QLearner::Logger policyLogger(0.5);
     218             : 
     219           0 :     std::shared_ptr<Dynamic::Policy::Factory> policyFactory = make_shared<Dynamic::QLearner::Policy::Factory>(
     220           0 :         *env,
     221             :         sumo,
     222             :         loader.adapter,
     223           0 :         0,
     224             :         policyLogger
     225           0 :     );
     226             : 
     227             :     // Demand
     228             :     // clang-format off
     229           0 :     std::vector<std::tuple<float, Dynamic::Time, Dynamic::Time>> demandSpecs = {
     230             :         {0.010,  0,  1},
     231             :         {0.100,  1, 10},
     232             :         {0.200, 10, 30},
     233             :         {0.300, 30, 43},
     234             :         {0.350, 43, 55},
     235             :         {0.375, 55, 75},
     236             :         {0.400, 75, 90},
     237             :         {0.425, 90, 100},
     238             :         {0.450, 100, 200},
     239             : 
     240           0 :     };
     241             :     // clang-format off
     242             : 
     243             :     // double END_SIMULATION = get<2>(demandSpecs.back()) * HOUR2SEC;
     244           0 :     double END_SIMULATION = 105 * HOUR2SEC;
     245             : 
     246           0 :     Dynamic::Vehicle::ID nextID = 0;
     247             :     
     248           0 :     for(auto &[scale, begin, end]: demandSpecs) {
     249           0 :         Dynamic::UniformDemandLoader demandLoader(scale, begin * HOUR2SEC, end * HOUR2SEC, *policyFactory, 0);
     250           0 :         auto p = demandLoader.load(staticDemand, *env, loader.adapter, nextID);
     251           0 :         auto [demand, id] = p;
     252           0 :         nextID = id;
     253           0 :         env->addDemand(demand);
     254             :     }
     255             : 
     256             :     // Load demand into environment
     257             : 
     258           0 :     env->initializeTrafficLights(5);
     259             : 
     260           0 :     env->log(logger, 0, END_SIMULATION, 600, policyLogger);
     261             : 
     262           0 :     env->setDiscardVehicles(true);
     263             : 
     264           0 :     env->setDespawnTime(5*60);
     265             : 
     266           0 :     SUMO::NetState netState(baseDir + "data/out/netstate.xml", ios_base::out);
     267             : 
     268             :     // env->dump(netState, loader.adapter, 0.0, 1.0, 5 * 3600);
     269             : 
     270           0 :     env->dump(netState, loader.adapter, 102 * HOUR2SEC, 0.25, 4 * 2 * HOUR2SEC, true);
     271             : 
     272           0 :     env->runUntil(END_SIMULATION);
     273             : 
     274           0 :     list<reference_wrapper<Dynamic::Env::Vehicle>> vehiclesList = env->getVehicles();
     275             : 
     276             :     // Create edgedata file
     277           0 :     SUMO::EdgeData edgeData;
     278             : 
     279           0 :     SUMO::EdgeData::Interval &interval = edgeData.createInterval(0.0, END_SIMULATION);
     280             : 
     281           0 :     for(const Dynamic::Env::Vehicle &vehicle: vehiclesList) {
     282           0 :         if(vehicle.state != Dynamic::Env::Vehicle::State::STOPPED) continue;
     283             : 
     284           0 :         SUMO::Network::Edge::ID       edgeID = loader.adapter.toSumoEdge(vehicle.position.lane.edge.id);
     285           0 :         SUMO::Network::Edge::Lane::ID laneID = edgeID + "_" + to_string(vehicle.position.lane.index);
     286             : 
     287           0 :         if(!interval.hasEdge(edgeID)) {
     288           0 :             SUMO::EdgeData::Interval::Edge &edge = interval.createEdge(edgeID);
     289           0 :             edge.attributes.setAttribute("hasQueue", true);
     290             :         }
     291             : 
     292           0 :         SUMO::EdgeData::Interval::Edge &edge = interval.getEdge(edgeID);
     293             : 
     294           0 :         if(!edge.hasLane(laneID)) {
     295           0 :             SUMO::EdgeData::Interval::Edge::Lane &lane = edge.createLane(laneID);
     296             : 
     297           0 :             lane.attributes.setAttribute("queueSize", vehicle.position.lane.stopped.size());
     298             :         }
     299             :     }
     300             : 
     301           0 :     edgeData.saveToFile(benchmarkDir + "data/out/edgedata-ql-queues.xml");
     302             : 
     303             :     // policyFactory.dump();
     304             : 
     305             :     // // clang-format off
     306             :     // SUMO::Routes::Loader<
     307             :     //     const std::list<std::reference_wrapper<const Dynamic::Env::Vehicle>> &,
     308             :     //     const SUMO::TAZs &,
     309             :     //     const Dynamic::SUMOAdapter &
     310             :     // > routesLoader;
     311             :     // // clang-format on
     312             : 
     313             :     // const Dynamic::Env::Env &envConst = env;
     314             : 
     315             :     // SUMO::Routes routes = routesLoader.load(envConst.getVehicles(), sumo.tazs, loader.adapter);
     316             : 
     317             :     // routes.saveToFile(baseDir + "data/out/routes-ql.xml");
     318           0 : }
     319             : 
     320           0 : TEST_CASE("Dynamic - Q-learning", "[dynamic][q-learn][!benchmark]") {
     321           0 :     SECTION("w=0.0") {
     322           0 :         Dynamic::RewardFunction &rewardFunction = Dynamic::RewardFunctionGreedy::INSTANCE;
     323           0 :         dynamic(rewardFunction);
     324             :     }
     325           0 :     SECTION("w=0.1") {
     326           0 :         Dynamic::RewardFunctionDifference rewardFunction(0.1);
     327           0 :         dynamic(rewardFunction);
     328             :     }
     329           0 :     SECTION("w=0.5") {
     330           0 :         Dynamic::RewardFunctionDifference rewardFunction(0.5);
     331           0 :         dynamic(rewardFunction);
     332             :     }
     333           0 :     SECTION("w=0.75") {
     334           0 :         Dynamic::RewardFunctionDifference rewardFunction(0.75);
     335           0 :         dynamic(rewardFunction);
     336             :     }
     337           0 :     SECTION("w=0.9") {
     338           0 :         Dynamic::RewardFunctionDifference rewardFunction(0.9);
     339           0 :         dynamic(rewardFunction);
     340             :     }
     341           0 :     SECTION("w=1.0") {
     342           0 :         Dynamic::RewardFunctionDifference rewardFunction(1.0);
     343           0 :         dynamic(rewardFunction);
     344             :     }
     345           0 :     SECTION("w=1.1") {
     346           0 :         Dynamic::RewardFunctionDifference rewardFunction(1.1);
     347           0 :         dynamic(rewardFunction);
     348             :     }
     349           0 : }
     350             : 
     351           0 : TEST_CASE("Dynamic - Q-learners - small", "[dynamic][q-learn-small][!benchmark]") {
     352           0 :     utils::stringify::stringify<float>::PRECISION  = 3;
     353           0 :     utils::stringify::stringify<double>::PRECISION = 3;
     354             : 
     355           0 :     Log::ProgressLoggerTableOStream logger;
     356             : 
     357             :     // logger << std::fixed << std::setprecision(6);
     358             : 
     359             :     // clang-format off
     360           0 :     Dynamic::Env::Loader<
     361             :         const SUMO::NetworkTAZs &,
     362             :         Dynamic::RewardFunction &
     363           0 :     > loader;
     364             :     // clang-format on
     365             : 
     366             :     // Environment
     367           0 :     shared_ptr<SUMO::Network> sumoNetwork = SUMO::Network::loadFromFile(benchmarkDir + "data/dynaminator-data/porto.net.xml");
     368           0 :     SUMO::TAZs                sumoTAZs    = SUMO::TAZ::loadFromFile(benchmarkDir + "data/dynaminator-data/porto.taz.xml");
     369           0 :     SUMO::NetworkTAZs         sumo{*sumoNetwork, sumoTAZs};
     370             : 
     371           0 :     shared_ptr<Dynamic::Env::Env> env = loader.load(sumo, Dynamic::RewardFunctionGreedy::INSTANCE);
     372             : 
     373             :     // loader.adapter.dump();
     374             : 
     375             :     // Demand
     376           0 :     VISUM::OFormatDemand oDemand = VISUM::OFormatDemand::loadFromFile(benchmarkDir + "data/dynaminator-data/matrix.9.0.10.0.2.fma");
     377             :     // clang-format off
     378           0 :     Static::Demand::Loader<
     379             :         const VISUM::OFormatDemand &,
     380             :         const Static::SUMOAdapter &
     381             :     > staticDemandLoader;
     382             :     // clang-format on
     383           0 :     Static::Demand staticDemand = staticDemandLoader.load(
     384             :         oDemand,
     385             :         (Static::SUMOAdapter &)loader.adapter
     386           0 :     );
     387             : 
     388           0 :     ofstream adapterDumpFile(baseDir + "data/out/adapter-dynamic.dump.txt");
     389           0 :     loader.adapter.dump(adapterDumpFile);
     390             : 
     391           0 :     const double HOUR2SEC = 3600.0;
     392             : 
     393             :     // Policy
     394           0 :     Dynamic::QLearner::Logger policyLogger(0.5);
     395             : 
     396           0 :     std::shared_ptr<Dynamic::Policy::Factory> policyFactory = make_shared<Dynamic::QLearner::Policy::Factory>(
     397           0 :         *env,
     398             :         sumo,
     399             :         loader.adapter,
     400           0 :         0,
     401             :         policyLogger
     402           0 :     );
     403             : 
     404             :     // Demand
     405             :     // clang-format off
     406           0 :     std::vector<std::tuple<float, Dynamic::Time, Dynamic::Time>> demandSpecs = {
     407             :         {0.2,  0, 1},
     408           0 :     };
     409             :     // clang-format off
     410             : 
     411           0 :     double END_SIMULATION = get<2>(demandSpecs.back()) * HOUR2SEC;
     412             :     // double END_SIMULATION = 130 * HOUR2SEC;
     413             : 
     414           0 :     Dynamic::Vehicle::ID nextID = 0;
     415             :     
     416           0 :     for(auto &[scale, begin, end]: demandSpecs) {
     417           0 :         Dynamic::UniformDemandLoader demandLoader(scale, begin * HOUR2SEC, end * HOUR2SEC, *policyFactory, 0);
     418           0 :         auto p = demandLoader.load(staticDemand, *env, loader.adapter, nextID);
     419           0 :         auto [demand, id] = p;
     420           0 :         nextID = id;
     421           0 :         env->addDemand(demand);
     422             :     }
     423             : 
     424             :     // Load demand into environment
     425             : 
     426           0 :     env->initializeTrafficLights(0);
     427             : 
     428           0 :     env->log(logger, 0, END_SIMULATION, 600, policyLogger);
     429             : 
     430           0 :     env->runUntil(END_SIMULATION);
     431             : 
     432           0 :     list<reference_wrapper<Dynamic::Env::Vehicle>> vehiclesList = env->getVehicles();
     433             : 
     434             :     // Create edgedata file
     435           0 :     SUMO::EdgeData edgeData;
     436             : 
     437           0 :     SUMO::EdgeData::Interval &interval = edgeData.createInterval(0.0, END_SIMULATION);
     438             : 
     439           0 :     for(const Dynamic::Env::Vehicle &vehicle: vehiclesList) {
     440           0 :         if(vehicle.state != Dynamic::Env::Vehicle::State::STOPPED) continue;
     441             : 
     442           0 :         SUMO::Network::Edge::ID       edgeID = loader.adapter.toSumoEdge(vehicle.position.lane.edge.id);
     443           0 :         SUMO::Network::Edge::Lane::ID laneID = edgeID + "_" + to_string(vehicle.position.lane.index);
     444             : 
     445           0 :         if(!interval.hasEdge(edgeID)) {
     446           0 :             SUMO::EdgeData::Interval::Edge &edge = interval.createEdge(edgeID);
     447           0 :             edge.attributes.setAttribute("hasQueue", true);
     448             :         }
     449             : 
     450           0 :         SUMO::EdgeData::Interval::Edge &edge = interval.getEdge(edgeID);
     451             : 
     452           0 :         if(!edge.hasLane(laneID)) {
     453           0 :             SUMO::EdgeData::Interval::Edge::Lane &lane = edge.createLane(laneID);
     454             : 
     455           0 :             lane.attributes.setAttribute("queueSize", vehicle.position.lane.stopped.size());
     456             :         }
     457             :     }
     458             : 
     459           0 :     edgeData.saveToFile(benchmarkDir + "data/out/edgedata-ql-queues.xml");
     460             : 
     461             :     // policyFactory.dump();
     462             : 
     463             :     // clang-format off
     464           0 :     SUMO::Routes::Loader<
     465             :         const std::list<std::reference_wrapper<const Dynamic::Env::Vehicle>> &,
     466             :         const SUMO::TAZs &,
     467             :         const Dynamic::SUMOAdapter &
     468             :     > routesLoader;
     469             :     // clang-format on
     470             : 
     471           0 :     const Dynamic::Env::Env &envConst = *env;
     472             : 
     473           0 :     SUMO::Routes routes = routesLoader.load(envConst.getVehicles(), sumo.tazs, loader.adapter);
     474             : 
     475           0 :     routes.saveToFile(baseDir + "data/out/routes-ql.xml");
     476           0 : }

Generated by: LCOV version 1.14