LCOV - code coverage report
Current view: top level - app/src/Dynamic/Policy - DoubleQLearner.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 97 0.0 %
Date: 2023-08-17 16:45:52 Functions: 0 16 0.0 %

          Line data    Source code
       1             : #include "Dynamic/Policy/DoubleQLearner.hpp"
       2             : 
       3             : #include <random>
       4             : 
       5             : #include "Dynamic/Policy/Policy.hpp"
       6             : #include "Dynamic/Policy/QLearner.hpp"
       7             : 
       8             : using namespace std;
       9             : using namespace Dynamic;
      10             : 
      11           0 : DoubleQLearner::PolicyFactory::PolicyFactory(
      12             :     Env::Env&                                     env_,
      13             :     const SUMO::NetworkTAZs&                      sumo_,
      14             :     const Dynamic::SUMOAdapter&                   adapter_,
      15             :     random_device::result_type                    seed,
      16             :     optional<reference_wrapper<QLearner::Logger>> policyLogger_
      17           0 : ):
      18             :     QLearner::Policy::Factory(
      19             :         env_,
      20             :         sumo_,
      21             :         adapter_,
      22             :         seed,
      23             :         policyLogger_
      24           0 :     ) {}
      25             : 
      26           0 : shared_ptr<Dynamic::Policy> DoubleQLearner::PolicyFactory::create(
      27             :     Vehicle::ID id,
      28             :     Time,
      29             :     const Env::TAZ&,
      30             :     const Env::TAZ& toTAZ
      31             : ) {
      32           0 :     auto it = qLearners.find(toTAZ.id);
      33           0 :     if(it == qLearners.end()) {
      34             :         // clang-format off
      35           0 :         it = qLearners.emplace(
      36           0 :             toTAZ.id,
      37           0 :             DoubleQLearner(
      38             :                 env,
      39           0 :                 sumo.network,
      40             :                 adapter,
      41             :                 toTAZ,
      42           0 :                 gen,
      43             :                 policyLogger
      44             :             )
      45           0 :         ).first;
      46             :         // clang-format on
      47             :     }
      48             : 
      49           0 :     QLearner& qLearner = it->second;
      50             : 
      51           0 :     return make_shared<QLearner::Policy>(qLearner, id, gen);
      52             : }
      53             : 
      54           0 : DoubleQLearner::DoubleQLearner(
      55             :     Env::Env&                                     env_,
      56             :     const SUMO::Network&                          network_,
      57             :     const Dynamic::SUMOAdapter&                   adapter_,
      58             :     const Env::TAZ&                               destinationTAZ_,
      59             :     mt19937&                                      gen_,
      60             :     optional<reference_wrapper<QLearner::Logger>> policyLogger_,
      61             :     Reward                                        alpha_,
      62             :     Reward                                        gamma_,
      63             :     Reward                                        xi_,
      64             :     Reward                                        eta_,
      65             :     float                                         epsilon_
      66           0 : ):
      67             :     QLearner(
      68             :         env_,
      69             :         network_,
      70             :         adapter_,
      71             :         destinationTAZ_,
      72             :         policyLogger_,
      73             :         alpha_,
      74             :         gamma_,
      75             :         xi_,
      76             :         eta_,
      77             :         epsilon_
      78             :     ),
      79           0 :     gen(gen_) {
      80           0 : }
      81             : 
      82           0 : [[noreturn]] QLearner::Reward DoubleQLearner::estimateOptimalValue(const State&) const {
      83           0 :     throw logic_error(__PRETTY_FUNCTION__ + string(": not implemented"));
      84             : }
      85             : 
      86           0 : [[noreturn]] QLearner::Reward DoubleQLearner::estimateOptimalFutureValue(const State&, const Action&) const {
      87           0 :     throw logic_error(__PRETTY_FUNCTION__ + string(": not implemented"));
      88             : }
      89             : 
      90           0 : [[noreturn]] QLearner::Reward& DoubleQLearner::Qref(const State&, const Action&) {
      91           0 :     throw logic_error(__PRETTY_FUNCTION__ + string(": not implemented"));
      92             : }
      93             : 
      94           0 : QLearner::Reward DoubleQLearner::Q(const State& s, const Action& a) const {
      95           0 :     return (QA(s, a) + QB(s, a)) / 2.0;
      96             : }
      97             : 
      98           0 : void DoubleQLearner::updateMatrix(const State& s, const Action& a, Reward r) {
      99           0 :     uniform_real_distribution<double> distribution(0.0, 1.0);
     100             : 
     101           0 :     const double x = distribution(gen);
     102           0 :     if(x < 0.5) {
     103           0 :         Reward& qA = QA(s, a);
     104             : 
     105           0 :         Reward qPrev = qA;
     106           0 :         Reward fB    = estimateOptimalFutureValueA(s, a);
     107             : 
     108           0 :         Reward qNew = (r + gamma * fB);
     109             : 
     110           0 :         qA += alpha * (qNew - qA);
     111             : 
     112           0 :         if(policyLogger.has_value()) {
     113           0 :             auto& logger = policyLogger.value().get();
     114           0 :             auto &D = logger.D, &DA = logger.DA;
     115             : 
     116           0 :             const double Delta = qA - qPrev;
     117           0 :             D += Logger::ALPHA_D * (Delta - D);
     118           0 :             DA += Logger::ALPHA_D * (abs(Delta) - DA);
     119             :         }
     120             :     } else {
     121           0 :         Reward& qB = QB(s, a);
     122             : 
     123           0 :         Reward qPrev = qB;
     124           0 :         Reward fA    = estimateOptimalFutureValueB(s, a);
     125             : 
     126           0 :         Reward qNew = (r + gamma * fA);
     127             : 
     128           0 :         qB += alpha * (qNew - qB);
     129             : 
     130           0 :         if(policyLogger.has_value()) {
     131           0 :             auto& logger = policyLogger.value().get();
     132           0 :             auto &D = logger.D, &DA = logger.DA;
     133             : 
     134           0 :             const double Delta = qB - qPrev;
     135           0 :             D += Logger::ALPHA_D * (Delta - D);
     136           0 :             DA += Logger::ALPHA_D * (abs(Delta) - DA);
     137             :         }
     138             :     }
     139           0 : }
     140             : 
     141           0 : QLearner::Reward& DoubleQLearner::QA(const State& s, const Action& a) {
     142           0 :     auto& q = QMatrixA[s];
     143             : 
     144           0 :     auto it = q.find(a);
     145           0 :     if(it != q.end()) return it->second;
     146             : 
     147           0 :     return q[a] = estimateInitialValue(s, a);
     148             : }
     149             : 
     150           0 : QLearner::Reward DoubleQLearner::QA(const State& s, const Action& a) const {
     151           0 :     auto it = QMatrixA.find(s);
     152           0 :     if(it == QMatrixA.end()) return 0.0;
     153             : 
     154           0 :     auto it2 = it->second.find(a);
     155           0 :     if(it2 == it->second.end()) return 0.0;
     156             : 
     157           0 :     return it2->second;
     158             : }
     159             : 
     160           0 : QLearner::Reward& DoubleQLearner::QB(const State& s, const Action& a) {
     161           0 :     auto& q = QMatrixB[s];
     162             : 
     163           0 :     auto it = q.find(a);
     164           0 :     if(it != q.end()) return it->second;
     165             : 
     166           0 :     return q[a] = estimateInitialValue(s, a);
     167             : }
     168             : 
     169           0 : QLearner::Reward DoubleQLearner::QB(const State& s, const Action& a) const {
     170           0 :     auto it = QMatrixB.find(s);
     171           0 :     if(it == QMatrixB.end()) return 0.0;
     172             : 
     173           0 :     auto it2 = it->second.find(a);
     174           0 :     if(it2 == it->second.end()) return 0.0;
     175             : 
     176           0 :     return it2->second;
     177             : }
     178             : 
     179           0 : QLearner::Reward DoubleQLearner::estimateOptimalValueA(const State& s) const {
     180           0 :     vector<Action> actions = s.possibleActions();
     181             : 
     182           0 :     vector<pair<Reward, Action>> actionRewards;
     183           0 :     for(const Action& a: actions) {
     184           0 :         actionRewards.emplace_back(QB(s, a), a);
     185             :     }
     186             : 
     187           0 :     auto [_, a] = *max_element(
     188             :         actionRewards.begin(),
     189             :         actionRewards.end()
     190           0 :     );
     191             : 
     192           0 :     return QA(s, a);
     193             : }
     194             : 
     195           0 : QLearner::Reward DoubleQLearner::estimateOptimalValueB(const State& s) const {
     196           0 :     vector<Action> actions = s.possibleActions();
     197             : 
     198           0 :     vector<pair<Reward, Action>> actionRewards;
     199           0 :     for(const Action& a: actions) {
     200           0 :         actionRewards.emplace_back(QA(s, a), a);
     201             :     }
     202             : 
     203           0 :     auto [_, a] = *max_element(
     204             :         actionRewards.begin(),
     205             :         actionRewards.end()
     206           0 :     );
     207             : 
     208           0 :     return QB(s, a);
     209             : }
     210             : 
     211           0 : QLearner::Reward DoubleQLearner::estimateOptimalFutureValueA(const State& s, const Action& a) const {
     212           0 :     State sNew = s.apply(a);
     213             : 
     214           0 :     return estimateOptimalValueA(sNew);
     215             : }
     216             : 
     217           0 : QLearner::Reward DoubleQLearner::estimateOptimalFutureValueB(const State& s, const Action& a) const {
     218           0 :     State sNew = s.apply(a);
     219             : 
     220           0 :     return estimateOptimalValueB(sNew);
     221             : }

Generated by: LCOV version 1.14