LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSSwarmTrafficLightLogic.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 49.1 % 411 202
Test Date: 2025-11-14 15:59:05 Functions: 60.0 % 25 15

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2010-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MSSwarmTrafficLightLogic.cpp
      15              : /// @author  Gianfilippo Slager
      16              : /// @author  Federico Caselli
      17              : /// @date    Mar 2010
      18              : ///
      19              : // The class for Swarm-based logics
      20              : /****************************************************************************/
      21              : 
      22              : #include <microsim/MSEdge.h>
      23              : #include "MSSwarmTrafficLightLogic.h"
      24              : //#define SWARM_DEBUG
      25              : //#define ANALYSIS_DEBUG
      26              : 
      27              : // ===========================================================================
      28              : // method definitions
      29              : // ===========================================================================
      30           16 : MSSwarmTrafficLightLogic::MSSwarmTrafficLightLogic(MSTLLogicControl& tlcontrol, const std::string& id,
      31              :         const std::string& programID, const Phases& phases, int step, SUMOTime delay,
      32           16 :         const Parameterised::Map& parameters) :
      33           16 :     MSSOTLHiLevelTrafficLightLogic(tlcontrol, id, programID, TrafficLightType::SWARM_BASED, phases, step, delay, parameters) {
      34              : 
      35           16 :     std::string pols = getPoliciesParam();
      36           32 :     pols = StringUtils::to_lower_case(pols);
      37              : #ifdef SWARM_DEBUG
      38              :     std::ostringstream str;
      39              :     str << "policies: " << pols;
      40              :     WRITE_MESSAGE(str.str());
      41              : #endif
      42              : 
      43           16 :     if (pols.find("platoon") != std::string::npos) {
      44           32 :         addPolicy(new MSSOTLPlatoonPolicy(new MSSOTLPolicy5DFamilyStimulus("PLATOON", parameters), parameters));
      45              :     }
      46           16 :     if (pols.find("phase") != std::string::npos) {
      47           32 :         addPolicy(new MSSOTLPhasePolicy(new MSSOTLPolicy5DFamilyStimulus("PHASE", parameters), parameters));
      48              :     }
      49           16 :     if (pols.find("marching") != std::string::npos) {
      50           32 :         addPolicy(new MSSOTLMarchingPolicy(new MSSOTLPolicy5DFamilyStimulus("MARCHING", parameters), parameters));
      51              :     }
      52           16 :     if (pols.find("congestion") != std::string::npos) {
      53           32 :         addPolicy(new MSSOTLCongestionPolicy(new MSSOTLPolicy5DFamilyStimulus("CONGESTION", parameters), parameters));
      54              :     }
      55              : 
      56           16 :     if (myPolicies.empty()) {
      57            0 :         WRITE_ERROR(TL("NO VALID POLICY LIST READ"));
      58              :     }
      59              : 
      60           16 :     mustChange = false;
      61           16 :     skipEta = false;
      62           16 :     gotTargetLane = false;
      63              : 
      64              : #ifdef SWARM_DEBUG
      65              :     std::ostringstream d_str;
      66              :     d_str << getMaxCongestionDuration();
      67              :     vector<MSSOTLPolicy*> policies = myPolicies;
      68              : 
      69              :     WRITE_MESSAGE("getMaxCongestionDuration " + d_str.str());
      70              :     for (int i = 0; i < policies.size(); i++) {
      71              :         MSSOTLPolicy* policy = policies[i];
      72              :         MSSOTLPolicyDesirability* stim = policy->getDesirabilityAlgorithm();
      73              :         std::ostringstream _str;
      74              :         _str << policy->getName() << stim->getMessage() << " getThetaSensitivity " << policy->getThetaSensitivity() << " .";
      75              :         WRITE_MESSAGE(_str.str());
      76              :     }
      77              : #endif
      78           16 :     congestion_steps = 0;
      79           32 :     m_useVehicleTypesWeights = getParameter("USE_VEHICLE_TYPES_WEIGHTS", "0") == "1";
      80           16 :     if (m_useVehicleTypesWeights && pols.find("phase") == std::string::npos) {
      81            0 :         WRITE_ERROR(TL("VEHICLE TYPES WEIGHT only works with phase policy, which is missing"));
      82              :     }
      83           16 : }
      84              : 
      85           32 : MSSwarmTrafficLightLogic::~MSSwarmTrafficLightLogic() {
      86           16 :     if (logData && swarmLogFile.is_open()) {
      87            0 :         swarmLogFile.close();
      88              :     }
      89           16 :     for (std::map<std::string, CircularBuffer<double>*>::iterator it = m_meanSpeedHistory.begin();
      90           80 :             it != m_meanSpeedHistory.end(); ++it) {
      91           64 :         delete it->second;
      92              :     }
      93              :     m_meanSpeedHistory.clear();
      94           16 :     for (std::map<std::string, CircularBuffer<double>*>::iterator it = m_derivativeHistory.begin();
      95           80 :             it != m_derivativeHistory.end(); ++it) {
      96           64 :         delete it->second;
      97              :     }
      98              :     m_derivativeHistory.clear();
      99           64 : }
     100              : 
     101          128 : bool MSSwarmTrafficLightLogic::allowLine(MSLane* lane) {
     102              :     //No walking areas
     103          128 :     if (lane->getEdge().isWalkingArea()) {
     104              :         return false;
     105              :     }
     106              :     //No pedestrian crossing
     107          128 :     if (lane->getEdge().isCrossing()) {
     108              :         return false;
     109              :     }
     110              :     //No pedestrian only lanes
     111          128 :     if (lane->getPermissions() == SVC_PEDESTRIAN) {
     112              :         return false;
     113              :     }
     114              :     //No bicycle only lanes
     115          128 :     if (lane->getPermissions() == SVC_BICYCLE) {
     116              :         return false;
     117              :     }
     118              :     //No pedestrian and bicycle only lanes
     119          128 :     if (lane->getPermissions() == (SVC_PEDESTRIAN | SVC_BICYCLE)) {
     120            0 :         return false;
     121              :     }
     122              :     return true;
     123              : }
     124              : 
     125           16 : void MSSwarmTrafficLightLogic::init(NLDetectorBuilder& nb) {
     126           16 :     MSSOTLHiLevelTrafficLightLogic::init(nb);
     127              :     //Setting the startup policy
     128           16 :     choosePolicy(0, 0, 0, 0);
     129              :     //Initializing the random number generator to a time-dependent seed
     130           16 :     srand((int) time(nullptr));
     131              :     //Initializing pheromone maps according to input lanes
     132              :     //For each lane insert a pair into maps
     133           16 :     MSLane* currentLane = nullptr;
     134              : 
     135              : //      Derivative
     136           32 :     const int derivativeHistorySize = StringUtils::toInt(getParameter("PHERO_DERIVATIVE_HISTORY_SIZE", "3"));
     137           32 :     const int meanSpeedHistorySize = StringUtils::toInt(getParameter("PHERO_MEAN_SPEED_HISTORY_SIZE", "3"));
     138           32 :     m_derivativeAlpha = StringUtils::toDouble(getParameter("PHERO_DERIVATIVE_ALPHA", "1"));
     139           16 :     m_losCounter = 0;
     140           32 :     m_losMaxLimit = StringUtils::toInt(getParameter("LOSS_OF_SIGNAL_LIMIT", "10"));
     141              : 
     142              :     int index = 0;
     143           16 :     for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
     144           80 :             laneVector != myLanes.end(); laneVector++) {
     145          128 :         for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
     146              :                 lane++) {
     147           64 :             currentLane = (*lane);
     148           64 :             if (pheromoneInputLanes.find(currentLane->getID()) == pheromoneInputLanes.end()) {
     149           64 :                 laneCheck[currentLane] = false;
     150           64 :                 if (allowLine(currentLane)) {
     151           64 :                     pheromoneInputLanes.insert(MSLaneId_Pheromone(currentLane->getID(), 0.0));
     152              : //                                      Consider the derivative only for the input lane
     153           64 :                     m_meanSpeedHistory.insert(std::make_pair(currentLane->getID(), new CircularBuffer<double>(meanSpeedHistorySize)));
     154          128 :                     m_derivativeHistory.insert(std::make_pair(currentLane->getID(), new CircularBuffer<double>(derivativeHistorySize)));
     155              : #ifdef ANALYSIS_DEBUG
     156              :                     WRITE_MESSAGE("MSSwarmTrafficLightLogic::init Intersection " + getID() + " pheromoneInputLanes adding " + currentLane->getID());
     157              : #endif
     158              :                 } else {
     159              : #ifdef ANALYSIS_DEBUG
     160              :                     WRITE_MESSAGEF(TL("MSSwarmTrafficLightLogic::init Intersection % pheromoneInputLanes: lane % not allowed"), getID(), currentLane->getID());
     161              : #endif
     162              :                 }
     163              :             }
     164           64 :             m_laneIndexMap[currentLane->getID()].push_back(index++);
     165              :         }
     166              :     }
     167              : 
     168           16 :     LinkVectorVector links = getLinks();
     169           80 :     for (int i = 0; i < (int)links.size(); i++) {
     170           64 :         LinkVector oneLink = getLinksAt(i);
     171          128 :         for (int j = 0; j < (int)oneLink.size(); j++) {
     172           64 :             currentLane = oneLink[j]->getLane();
     173           64 :             if (pheromoneOutputLanes.find(currentLane->getID()) == pheromoneOutputLanes.end()) {
     174           64 :                 laneCheck[currentLane] = false;
     175           64 :                 if (allowLine(currentLane)) {
     176          128 :                     pheromoneOutputLanes.insert(MSLaneId_Pheromone(currentLane->getID(), 0.0));
     177              : #ifdef ANALYSIS_DEBUG
     178              :                     WRITE_MESSAGE("MSSwarmTrafficLightLogic::init Intersection " + getID() + " pheromoneOutputLanes adding " + currentLane->getID());
     179              : #endif
     180              :                 } else {
     181              : #ifdef ANALYSIS_DEBUG
     182              :                     WRITE_MESSAGEF(TL("MSSwarmTrafficLightLogic::init Intersection % pheromoneOutputLanes lane % not allowed"), getID(), currentLane->getID());
     183              : #endif
     184              :                 }
     185              :             }
     186              :         }
     187           64 :     }
     188              : 
     189           16 :     initScaleFactorDispersionIn((int)pheromoneInputLanes.size());
     190           16 :     initScaleFactorDispersionOut((int)pheromoneOutputLanes.size());
     191              :     //Initializing thresholds for theta evaluations
     192           16 :     lastThetaSensitivityUpdate = MSNet::getInstance()->getCurrentTimeStep();
     193              : 
     194           48 :     WRITE_MESSAGEF(TL("*** Intersection % will run using MSSwarmTrafficLightLogic ***"), getID());
     195           32 :     std::string logFileName = getParameter("SWARMLOG", "");
     196           16 :     logData = logFileName.compare("") != 0;
     197           16 :     if (logData) {
     198            0 :         swarmLogFile.open(logFileName.c_str(), std::ios::out | std::ios::binary);
     199              :     }
     200              : //      Log the initial state
     201              : #ifdef ANALYSIS_DEBUG
     202              :     WRITE_MESSAGEF(TL("TL % time 0 Policy: % (pheroIn= 0 ,pheroOut= 0 ) OldPolicy: % ."), getID(), myCurrentPolicy->getName(), myCurrentPolicy->getName());
     203              : //      ostringstream maplog;
     204              : //      for(map<string, vector<int> >::const_iterator mIt = m_laneIndexMap.begin();mIt != m_laneIndexMap.end();++mIt)
     205              : //      {
     206              : //              maplog << mIt->first <<'[';
     207              : //              for(vector<int>::const_iterator vIt = mIt->second.begin();vIt != mIt->second.end();++vIt)
     208              : //                      maplog<<*vIt<<", ";
     209              : //              maplog << "] ";
     210              : //      }
     211              : //      WRITE_MESSAGE("Map content " + maplog.str());
     212              : #endif
     213           16 : }
     214              : 
     215            0 : void MSSwarmTrafficLightLogic::resetPheromone() {
     216              :     //input
     217            0 :     for (MSLaneId_PheromoneMap::iterator laneIterator = pheromoneInputLanes.begin();
     218            0 :             laneIterator != pheromoneInputLanes.end(); laneIterator++) {
     219              :         std::string laneId = laneIterator->first;
     220            0 :         pheromoneInputLanes[laneId] = 0;
     221              :     }
     222              :     //output
     223            0 :     for (MSLaneId_PheromoneMap::iterator laneIterator = pheromoneOutputLanes.begin();
     224            0 :             laneIterator != pheromoneOutputLanes.end(); laneIterator++) {
     225              :         std::string laneId = laneIterator->first;
     226            0 :         pheromoneOutputLanes[laneId] = 0;
     227              :     }
     228            0 : }
     229              : 
     230        15976 : int MSSwarmTrafficLightLogic::decideNextPhase() {
     231              : 
     232              : #ifdef SWARM_DEBUG
     233              :     MsgHandler::getMessageInstance()->inform("\n" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic decideNextPhase()");
     234              :     std::ostringstream dnp;
     235              :     dnp << (MSNet::getInstance()->getCurrentTimeStep()) << " MSSwarmTrafficLightLogic::decideNextPhase:: " << "tlsid=" << getID() << " getCurrentPhaseDef().getState()=" << getCurrentPhaseDef().getState() << " is commit?" << getCurrentPhaseDef().isCommit();
     236              :     MsgHandler::getMessageInstance()->inform(dnp.str());
     237              : #endif
     238              :     // if we're congested, it should be wise to reset and recalculate the pheromone levels after X steps
     239              : 
     240        15976 :     if (getCurrentPhaseDef().isTarget()) {
     241        14752 :         targetLanes = getCurrentPhaseDef().getTargetLaneSet();
     242              :     }
     243              : 
     244        47928 :     if (myCurrentPolicy->getName().compare("Congestion") == 0 && getCurrentPhaseDef().isCommit()) {
     245            0 :         congestion_steps += 1;  //STEPS2TIME(getCurrentPhaseDef().duration);
     246              : #ifdef SWARM_DEBUG
     247              :         WRITE_MESSAGEF("\n% MSSwarmTrafficLightLogic decideNextPhase()", time2string(MSNet::getInstance()->getCurrentTimeStep()));
     248              : std:
     249              :         ostringstream dnp;
     250              :         dnp << (MSNet::getInstance()->getCurrentTimeStep()) << " MSSwarmTrafficLightLogic::decideNextPhase:: " << "tlsid=" << getID() << " congestion_steps=" << congestion_steps;
     251              :         WRITE_MESSAGE(dnp.str());
     252              : #endif
     253            0 :         if (congestion_steps >= getMaxCongestionDuration()) {
     254            0 :             resetPheromone();
     255            0 :             congestion_steps = 0;
     256            0 :             mustChange = true;
     257            0 :             if (getReinforcementMode() != 0) {
     258            0 :                 skipEta = true;
     259              :             }
     260              : #ifdef SWARM_DEBUG
     261              :             WRITE_MESSAGEF("\n% MSSwarmTrafficLightLogic decideNextPhase()", time2string(MSNet::getInstance()->getCurrentTimeStep()));
     262              :             std::ostringstream dnp;
     263              :             dnp << (MSNet::getInstance()->getCurrentTimeStep()) << " MSSwarmTrafficLightLogic::decideNextPhase:: " << "tlsid=" << getID() << " max congestion reached, congestion_steps=" << congestion_steps;
     264              :             WRITE_MESSAGE(dnp.str());
     265              : #endif
     266              :         }
     267              :     }
     268              : 
     269              :     //Update pheromone levels
     270        15976 :     updatePheromoneLevels();
     271              : 
     272              :     /* Since we changed the behaviour of computeReturnTime() in order to update pheromone levels every step
     273              :      * it is now mandatory to check if the duration of a transient phase is elapsed or not*/
     274        15976 :     if (getCurrentPhaseDef().isTransient() && getCurrentPhaseElapsed() < getCurrentPhaseDef().duration) {
     275          918 :         return getCurrentPhaseIndex();
     276              :     }
     277              : 
     278              :     //Decide the current policy according to pheromone levels. this should be done only at the end of a chain, before selecting the new one
     279        15058 :     if (getCurrentPhaseDef().isCommit()) {
     280              :         //Update learning and forgetting thresholds
     281          153 :         updateSensitivities();
     282          153 :         decidePolicy();
     283          153 :         gotTargetLane = false;
     284              :     }
     285              : 
     286              : //    double phero =0;
     287              : //      if(getCurrentPhaseDef().isDecisional())
     288              : //      {
     289              : //    for(LaneIdVector::const_iterator it = targetLanes.begin(); it != targetLanes.end(); ++it)
     290              : //    {
     291              : //      string name = (*it);
     292              : //      phero +=pheromoneInputLanes[name];
     293              : //    }
     294              : //    phero /= targetLanes.size() == 0 ? 1 : targetLanes.size();
     295              : //    if(getCurrentPhaseElapsed() >= getCurrentPhaseDef().minDuration)
     296              : //      if(abs(phero-pheroBegin) <= 2)
     297              : //        return getCurrentPhaseIndex() + 1;
     298              : //      }
     299              : #ifdef SWARM_DEBUG
     300              :     std::ostringstream str;
     301              :     str << "tlsID=" << getID() << " currentPolicyname=" + myCurrentPolicy->getName();
     302              :     WRITE_MESSAGE(str.str());
     303              : #endif
     304              : 
     305              :     //Execute current policy. congestion "policy" must maintain the commit phase, and that must be an all-red one
     306        30116 :     return myCurrentPolicy->decideNextPhase(getCurrentPhaseElapsed(), &getCurrentPhaseDef(), getCurrentPhaseIndex(),
     307        30116 :                                             getPhaseIndexWithMaxCTS(), isThresholdPassed(), isPushButtonPressed(), countVehicles(getCurrentPhaseDef()));
     308              : //      int newStep =myCurrentPolicy->decideNextPhase(getCurrentPhaseElapsed(), &getCurrentPhaseDef(), getCurrentPhaseIndex(),
     309              : //                getPhaseIndexWithMaxCTS(), isThresholdPassed(), isPushButtonPressed(), countVehicles(getCurrentPhaseDef()));
     310              : //      if(newStep != myStep)
     311              : //        pheroBegin = phero;
     312              : //      return newStep;
     313              : }
     314              : 
     315        15976 : void MSSwarmTrafficLightLogic::updatePheromoneLevels() {
     316              :     //Updating input lanes pheromone: all input lanes without distinction
     317              :     //BETA_NO, GAMMA_NO
     318        15976 :     updatePheromoneLevels(pheromoneInputLanes, "PheroIn", getBetaNo(), getGammaNo());
     319              : 
     320              :     //BETA_SP, GAMMA_SP
     321              :     //Updating output lanes pheromone: only input lanes currently having green light. Pheromone for non green lanes is "freezed"
     322              : //    if (getCurrentPhaseDef().isDecisional()) {
     323        15976 :     updatePheromoneLevels(pheromoneOutputLanes, "PheroOut", getBetaSp(), getGammaSp());
     324              : //    }
     325        15976 : }
     326              : 
     327        31952 : void MSSwarmTrafficLightLogic::updatePheromoneLevels(MSLaneId_PheromoneMap& pheroMap, std::string logString,
     328              :         const double beta, const double gamma) {
     329              :     //  ANALYSIS_DBG(
     330              : #ifdef SWARM_DEBUG
     331              :     std::ostringstream _str;
     332              :     _str << logString << " Lanes " << pheroMap.size() << " TL " << getID() << " .";
     333              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::updatePheromoneLevels:: " + _str.str());
     334              : #else
     335              :     UNUSED_PARAMETER(logString);
     336              : #endif
     337       159760 :     for (MSLaneId_PheromoneMap::iterator laneIterator = pheroMap.begin(); laneIterator != pheroMap.end();
     338              :             ++laneIterator) {
     339              :         std::string laneId = laneIterator->first;
     340       127808 :         double oldPhero = laneIterator->second;
     341       383424 :         double maxSpeed = getSensors()->getMaxSpeed(laneId);
     342       255616 :         double meanVehiclesSpeed = getSensors()->meanVehiclesSpeed(laneId);
     343       127808 :         bool updatePheromone = (meanVehiclesSpeed > -1);
     344              :         //              double pheroAdd = getSensors()->countVehicles(laneId);
     345              : 
     346              :         //derivative
     347              :         double derivative = 0;
     348              :         //If i need to use the derivative for the lane
     349       127808 :         if (m_meanSpeedHistory.find(laneId) != m_meanSpeedHistory.end()) {
     350              :             //Update the derivative
     351        63904 :             if (updatePheromone) {
     352              :                 double currentDerivative = 0;
     353        41982 :                 m_losCounter = 0;
     354        83964 :                 if (m_meanSpeedHistory[laneId]->size() > 0) {
     355              :                     //Calculate the current derivative mean with the old speed points
     356       335376 :                     for (int i = 0; i < m_meanSpeedHistory[laneId]->size(); ++i)
     357       125706 :                         if (i == 0) {
     358        41982 :                             currentDerivative += fabs(meanVehiclesSpeed - m_meanSpeedHistory[laneId]->at(i));
     359              :                         } else {
     360        83724 :                             currentDerivative += fabs(m_meanSpeedHistory[laneId]->at(i - 1) - m_meanSpeedHistory[laneId]->at(i));
     361              :                         }
     362        83964 :                     currentDerivative /= m_meanSpeedHistory[laneId]->size(); //Non weighted mean
     363              :                 }
     364        41982 :                 m_meanSpeedHistory[laneId]->push_front(meanVehiclesSpeed);
     365              :                 //Check if the current value of the derivative is above the set alpha
     366        41982 :                 if (currentDerivative >= m_derivativeAlpha) {
     367         3614 :                     m_derivativeHistory[laneId]->push_front(currentDerivative);
     368              :                 }
     369        83964 :                 if (m_derivativeHistory[laneId]->size() > 0) {
     370              :                     //Calculate the mean derivative with the old derivative
     371       278732 :                     for (int i = 0; i < m_derivativeHistory[laneId]->size(); ++i) {
     372       103666 :                         derivative += m_derivativeHistory[laneId]->at(i);
     373              :                     }
     374        71400 :                     derivative /= m_derivativeHistory[laneId]->size();
     375              :                 }
     376              :             } else {
     377              :                 //Reset the values if no information is received after a timeout
     378        21922 :                 ++m_losCounter;
     379        21922 :                 if (m_losCounter >= m_losMaxLimit) {
     380         8414 :                     m_derivativeHistory[laneId]->clear();
     381         8414 :                     m_meanSpeedHistory[laneId]->clear();
     382         8414 :                     m_meanSpeedHistory[laneId]->push_front(maxSpeed);
     383              :                 }
     384              :             }
     385              :         }
     386       127808 :         double pheroAdd = MAX2((maxSpeed - meanVehiclesSpeed) * 10 / maxSpeed, 0.0);
     387              : //              Use the derivative only if it has a value
     388       127808 :         if (derivative > 0)
     389              : //              Correct the pheromone value by dividing it for the derivative.
     390              :         {
     391        35700 :             pheroAdd /= MAX2(derivative, m_derivativeAlpha);
     392              :         }
     393              : //    pheroAdd /= max(derivative, 1.0);
     394              : #ifdef ANALYSIS_DEBUG
     395              :         if (updatePheromone) {
     396              :             std::ostringstream oss;
     397              :             oss << time2string(MSNet::getInstance()->getCurrentTimeStep()) << " l " << laneId;
     398              :             oss << " der " << derivative << " phero " << pheroAdd << " maxS " << maxSpeed << " meanS " << meanVehiclesSpeed;
     399              :             WRITE_MESSAGE(oss.str())
     400              :         }
     401              : #endif
     402              : 
     403              :         // Evaporation + current contribute
     404       127808 :         double phero = beta * oldPhero + gamma * pheroAdd * updatePheromone;
     405              : #ifdef ANALYSIS_DEBUG
     406              :         if (phero > 10) {
     407              :             std::ostringstream i_str;
     408              :             i_str << "MSSwarmTrafficLightLogic::updatePheromoneLevels " << logString << " > 10. Value: " << phero;
     409              :             WRITE_MESSAGE(i_str.str())
     410              :         }
     411              : #endif
     412       127808 :         phero = MIN2(MAX2(phero, 0.0), getPheroMaxVal());
     413       127808 :         pheroMap[laneId] = phero;
     414              : #ifdef ANALYSIS_DEBUG
     415              :         //              DBG(
     416              :         std::ostringstream i_str;
     417              :         //                                      i_str << " oldPheroIn " << oldPheroIn
     418              :         //                                              << " inMeanVehiclesSpeed " << meanVehiclesSpeed
     419              :         //                                              << " pheroInAdd " << pheroAdd * updatePheromoneIn
     420              :         //                                              << " pheroInEvaporated " << oldPheroIn-oldPheroIn*getBetaNo()
     421              :         //                                              << " pheroInDeposited " << getGammaNo() * pheroAdd * updatePheromoneIn
     422              :         //                                              <<" newPheroIn "<<pheromoneInputLanes[laneId]
     423              :         //                                              << " inLane "<< laneId<<" ID "<< getID() <<" .";
     424              :         i_str << " op " << oldPhero << " ms " << meanVehiclesSpeed << " p " << pheroAdd* updatePheromone <<
     425              :               " pe " << oldPhero - oldPhero* beta << " pd " << gamma* pheroAdd* updatePheromone << " np " <<
     426              :               pheroMap[laneId] << " l " << laneId << " ID " << getID() << " c " << getSensors()->countVehicles(laneId) << " s " << getLaneLightState(laneId) << " .";
     427              :         if (m_pheroLevelLog[laneId] != i_str.str()) {
     428              :             m_pheroLevelLog[laneId] = i_str.str();
     429              :             WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::updatePheromoneLevels:: " + logString + i_str.str());
     430              :         }
     431              : #endif
     432              : #ifdef SWARM_DEBUG
     433              :         std::ostringstream str;
     434              :         str << time2string(MSNet::getInstance()->getCurrentTimeStep()) << " MSSwarmTrafficLightLogic::countSensors:: lane " << laneId << " passedVeh " << getCountSensors()->getPassedVeh(laneId, false);
     435              :         WRITE_MESSAGE(str.str());
     436              : #endif
     437              : //              int vehicles = getSensors()->countVehicles(laneId);
     438              : //              double pheroIn = getBetaNo() * oldPheroIn + // Evaporation
     439              : //              getGammaNo() * vehicles;
     440              : //              DBG(
     441              : //              std::ostringstream i_str;
     442              : //              i_str << " vehicles " << getSensors()->countVehicles(laneId)<<" pheromoneInputLanes "<<pheromoneInputLanes[laneId] << " lane "<< laneId<<" ID "<<  getID() <<" .";
     443              : //              MsgHandler::getMessageInstance()->inform(time2string(MSNet::getInstance()->getCurrentTimeStep()) +" MSSwarmTrafficLightLogic::updatePheromoneLevels:: PheroIn"+i_str.str());
     444              : //              )
     445              : //
     446              : //      pheroIn = MIN2(MAX2(pheroIn, 0.0), getPheroMaxVal());
     447              : //              pheromoneInputLanes[laneId] = pheroIn;
     448              :     }
     449        31952 : }
     450          153 : void MSSwarmTrafficLightLogic::updateSensitivities() {
     451          153 :     double elapsedTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - lastThetaSensitivityUpdate);
     452          153 :     lastThetaSensitivityUpdate = MSNet::getInstance()->getCurrentTimeStep();
     453              : 
     454              :     //reset of the sensitivity thresholds in case of 0 pheromone on the input lanes
     455          153 :     if (getPheromoneForInputLanes() == 0) {
     456            0 :         for (MSSOTLPolicy* const policy : myPolicies) {
     457            0 :             policy->setThetaSensitivity(getThetaInit());
     458              : //                      ANALYSIS_DBG(
     459              : #ifdef SWARM_DEBUG
     460              :             std::ostringstream phero_str;
     461              :             phero_str << "Policy " << policy->getName() << " sensitivity reset to " << policy->getThetaSensitivity() << " due to evaporated input pheromone.";
     462              :             WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::updateSensitivities::" + phero_str.str());
     463              : #endif
     464              :         }
     465              :         return;
     466              :     }
     467              : 
     468              :     double eta = -1.;
     469              :     // If skipEta it means that we've had Congestion for too much time. Forcing forgetting.
     470          153 :     if (!skipEta || myCurrentPolicy->getName().compare("Congestion") != 0) {
     471          153 :         switch (getReinforcementMode()) {
     472          153 :             case 0:
     473          153 :                 if (elapsedTime == STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())) {
     474              :                     return;     //we don't want to reinforce the policy selected at the beginning of the simulation since it's time-based
     475              :                 }
     476              :                 eta = elapsedTime;
     477              :                 break;
     478            0 :             case 1:
     479            0 :                 eta = calculateEtaDiff();
     480            0 :                 break;
     481            0 :             case 2:
     482            0 :                 eta = calculateEtaRatio();
     483            0 :                 break;
     484              :         }
     485              :     }
     486          705 :     for (MSSOTLPolicy* const policy : myPolicies) {
     487              :         double newSensitivity;
     488          564 :         if (eta < 0) {       //bad performance
     489            0 :             if (policy == myCurrentPolicy) { // punish the current policy
     490            0 :                 newSensitivity = policy->getThetaSensitivity() + getForgettingCox() * (-eta);
     491              :             } else
     492              :                 // reward the other ones
     493              :             {
     494            0 :                 newSensitivity = policy->getThetaSensitivity() - getLearningCox() * (-eta);
     495              :             }
     496              :         } else {        //good performance
     497          564 :             if (policy == myCurrentPolicy) {    //reward the current policy
     498          141 :                 newSensitivity = policy->getThetaSensitivity() - getLearningCox() * eta;
     499              :             } else
     500              :                 //      punish the other ones
     501              :             {
     502          423 :                 newSensitivity = policy->getThetaSensitivity() + getForgettingCox() * eta;
     503              :             }
     504              :         }
     505              : //                      ANALYSIS_DBG(
     506              : #ifdef SWARM_DEBUG
     507              :         std::ostringstream lf;
     508              :         std::ostringstream phero_str;
     509              :         if (getReinforcementMode() == 0) {
     510              :             if (policy == currentPolicy) {
     511              :                 lf << " ,LearningCox " << getLearningCox() << " ,LCox*Time " << getLearningCox() * elapsedTime;
     512              :             } else {
     513              :                 lf << " ,ForgettingCox " << getForgettingCox() << " ,FCox*Time " << getForgettingCox() * elapsedTime;
     514              :             }
     515              : 
     516              :             phero_str << " policy " << policy->getName() << " newSensitivity " << newSensitivity << " ,pol.Sensitivity " << policy->getThetaSensitivity() << " ,elapsedTime " << elapsedTime << lf.str() << " NEWERSensitivity= " << max(min(newSensitivity, getThetaMax()), getThetaMin()) << " ID " << getID() << " .";
     517              :         } else {
     518              :             if (policy == currentPolicy && eta > 0) {
     519              :                 lf << " ,LearningCox " << getLearningCox() << " ,LCox*Eta " << getLearningCox() * eta;
     520              :             } else if (policy == currentPolicy && eta < 0) {
     521              :                 lf << " ,ForgettingCox " << getForgettingCox() << " ,FCox*Eta " << getForgettingCox() * eta;
     522              :             } else if (eta > 0) {
     523              :                 lf << " ,ForgettingCox " << getForgettingCox() << " ,FCox*Eta " << getForgettingCox() * eta;
     524              :             } else if (eta < 0) {
     525              :                 lf << " ,LearningCox " << getLearningCox() << " ,LCox*Eta " << getLearningCox() * eta;
     526              :             }
     527              :             phero_str << " policy " << policy->getName() << " newSensitivity " << newSensitivity << " ,pol.Sensitivity " << policy->getThetaSensitivity() << " ,eta " << eta << " ,carsIn " << carsIn << " ,inTarget " << inTarget << " ,notTarget " << notTarget << " ,carsOut " << carsOut << lf.str() << " NEWERSensitivity= " << max(min(newSensitivity, getThetaMax()), getThetaMin()) << " ID " << getID() << " .";
     528              :         }
     529              :         WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::updateSensitivities::" + phero_str.str());
     530              : #endif
     531          564 :         newSensitivity = MAX2(MIN2(newSensitivity, getThetaMax()), getThetaMin());
     532          564 :         policy->setThetaSensitivity(newSensitivity);
     533              :     }
     534              : }
     535              : 
     536          157 : double MSSwarmTrafficLightLogic::getPheromoneForInputLanes() {
     537          157 :     if (pheromoneInputLanes.size() == 0) {
     538              :         return 0;
     539              :     }
     540              :     double pheroIn = 0;
     541          157 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneInputLanes.begin();
     542          785 :             iterator != pheromoneInputLanes.end(); iterator++) {
     543              :         std::string laneId = iterator->first;
     544          628 :         pheroIn += iterator->second;
     545              : #ifdef SWARM_DEBUG
     546              :         std::ostringstream phero_str;
     547              :         phero_str << " lane " << iterator->first << " pheromoneIN  " << iterator->second << " id " << getID() << " .";
     548              :         WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::getPheromoneForInputLanes::" + phero_str.str());
     549              : #endif
     550              :     }
     551              : 
     552              : #ifdef SWARM_DEBUG
     553              :     std::ostringstream o_str;
     554              :     o_str << " TOTpheromoneIN  " << pheroIn << " return  " << pheroIn / pheromoneInputLanes.size() << getID() << " .";
     555              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::getPheromoneForInputLanes::" + o_str.str());
     556              : #endif
     557          157 :     return pheroIn / (double)pheromoneInputLanes.size();
     558              : }
     559              : 
     560            4 : double MSSwarmTrafficLightLogic::getPheromoneForOutputLanes() {
     561            4 :     if (pheromoneOutputLanes.size() == 0) {
     562              :         return 0;
     563              :     }
     564              :     double pheroOut = 0;
     565            4 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneOutputLanes.begin();
     566           20 :             iterator != pheromoneOutputLanes.end(); iterator++) {
     567              : #ifdef SWARM_DEBUG
     568              :         std::ostringstream phero_str;
     569              :         phero_str << " lane " << iterator->first << " pheromoneOUT  " << iterator->second << " id " << getID() << " .";
     570              :         WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::getPheromoneForOutputLanes::" + phero_str.str());
     571              : #endif
     572           16 :         pheroOut += iterator->second;
     573              :     }
     574              : #ifdef SWARM_DEBUG
     575              :     std::ostringstream o_str;
     576              :     o_str << " TOTpheromoneOUT  " << pheroOut << " return  " << pheroOut / pheromoneOutputLanes.size() << " id " << getID() << " .";
     577              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::getPheromoneForOutputLanes::" + o_str.str());
     578              : #endif
     579            4 :     return pheroOut / (double)pheromoneOutputLanes.size();
     580              : }
     581              : 
     582            0 : double MSSwarmTrafficLightLogic::getDispersionForInputLanes(double average_phero_in) {
     583            0 :     if (pheromoneInputLanes.size() == 0) {
     584              :         return 0;
     585              :     }
     586              :     double sum = 0;
     587            0 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneInputLanes.begin();
     588            0 :             iterator != pheromoneInputLanes.end(); iterator++) {
     589              :         std::string laneId = iterator->first;
     590            0 :         sum += pow(iterator->second - average_phero_in, 2);
     591              :     }
     592              : 
     593            0 :     double result = sqrt(sum / (double)pheromoneInputLanes.size()) * getScaleFactorDispersionIn();
     594              : #ifdef SWARM_DEBUG
     595              :     ostringstream so_str;
     596              :     so_str << " dispersionIn " << result;
     597              :     WRITE_MESSAGE("MSSwarmTrafficLightLogic::getDispersionForInputLanes::" + so_str.str());
     598              : #endif
     599            0 :     return result;
     600              : }
     601              : 
     602            0 : double MSSwarmTrafficLightLogic::getDispersionForOutputLanes(double average_phero_out) {
     603            0 :     if (pheromoneOutputLanes.size() == 0) {
     604              :         return 0;
     605              :     }
     606              :     double sum = 0;
     607            0 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneOutputLanes.begin();
     608            0 :             iterator != pheromoneOutputLanes.end(); iterator++) {
     609            0 :         sum += pow(iterator->second - average_phero_out, 2);
     610              :     }
     611              : 
     612            0 :     double result = sqrt(sum / (double)pheromoneOutputLanes.size()) * getScaleFactorDispersionOut();
     613              : #ifdef SWARM_DEBUG
     614              :     ostringstream so_str;
     615              :     so_str << " dispersionOut " << result;
     616              :     WRITE_MESSAGE("MSSwarmTrafficLightLogic::getDispersionForOutputLanes::" + so_str.str());
     617              : #endif
     618            0 :     return result;
     619              : }
     620            4 : double MSSwarmTrafficLightLogic::getDistanceOfMaxPheroForInputLanes() {
     621            4 :     if (pheromoneInputLanes.size() == 0) {
     622              :         return 0;
     623              :     }
     624              :     double max_phero_val_current = 0;
     625              :     double max_phero_val_old = 0;
     626              :     double temp_avg_other_lanes = 0;
     627              :     std::string laneId_max;
     628              :     int counter = 0;
     629            4 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneInputLanes.begin();
     630           20 :             iterator != pheromoneInputLanes.end(); iterator++) {
     631              :         std::string laneId = iterator->first;
     632           16 :         double lanePhero = iterator->second;
     633           16 :         if (counter == 0) {
     634              :             max_phero_val_current = lanePhero;
     635              :             counter++;
     636              :             continue;
     637              :         }
     638           12 :         if (lanePhero > max_phero_val_current) {
     639              :             max_phero_val_old = max_phero_val_current;
     640              :             max_phero_val_current = lanePhero;
     641            3 :             temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + max_phero_val_old) / counter;
     642              :         } else {
     643            9 :             temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + lanePhero) / counter;
     644              :         }
     645              : 
     646           12 :         counter++;
     647              :     }
     648              : 
     649            4 :     double result = max_phero_val_current - temp_avg_other_lanes;
     650              : #ifdef SWARM_DEBUG
     651              :     ostringstream so_str;
     652              :     so_str << " currentMaxPhero " << max_phero_val_current << " lane " << laneId_max << " avgOtherLanes " << temp_avg_other_lanes << " distance " << result;
     653              :     WRITE_MESSAGE("MSSwarmTrafficLightLogic::getDistanceOfMaxPheroForInputLanes::" + so_str.str());
     654              : #endif
     655              :     return result;
     656              : }
     657              : 
     658            4 : double MSSwarmTrafficLightLogic::getDistanceOfMaxPheroForOutputLanes() {
     659            4 :     if (pheromoneOutputLanes.size() == 0) {
     660              :         return 0;
     661              :     }
     662              :     double max_phero_val_current = 0;
     663              :     double max_phero_val_old = 0;
     664              :     double temp_avg_other_lanes = 0;
     665              :     std::string laneId_max;
     666              :     int counter = 0;
     667            4 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneOutputLanes.begin();
     668           20 :             iterator != pheromoneOutputLanes.end(); iterator++) {
     669              :         std::string laneId = iterator->first;
     670           16 :         double lanePhero = iterator->second;
     671           16 :         if (counter == 0) {
     672              :             max_phero_val_current = lanePhero;
     673              :             counter++;
     674              :             continue;
     675              :         }
     676           12 :         if (lanePhero > max_phero_val_current) {
     677              :             max_phero_val_old = max_phero_val_current;
     678              :             max_phero_val_current = lanePhero;
     679            5 :             temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + max_phero_val_old) / counter;
     680              :         } else {
     681            7 :             temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + lanePhero) / counter;
     682              :         }
     683              : 
     684           12 :         counter++;
     685              :     }
     686              : 
     687            4 :     double result = max_phero_val_current - temp_avg_other_lanes;
     688              : #ifdef SWARM_DEBUG
     689              :     ostringstream so_str;
     690              :     so_str << " currentMaxPhero " << max_phero_val_current << " lane " << laneId_max << " avgOtherLanes " << temp_avg_other_lanes << " distance " << result;
     691              :     WRITE_MESSAGE("MSSwarmTrafficLightLogic::getDistanceOfMaxPheroForOutputLanes::" + so_str.str());
     692              : #endif
     693              :     return result;
     694              : }
     695          153 : void MSSwarmTrafficLightLogic::decidePolicy() {
     696              : //      MSSOTLPolicy* currentPolicy = myCurrentPolicy;
     697              :     // Decide if it is the case to check for another plan
     698              : //      double sampled = (double) RandHelper::rand(RAND_MAX);
     699          153 :     double sampled = RandHelper::rand();
     700          153 :     double changeProb = getChangePlanProbability();
     701              : //      changeProb = changeProb * RAND_MAX;
     702              : 
     703          153 :     if (sampled <= changeProb || mustChange) { // Check for another plan
     704              : 
     705            4 :         double pheroIn = getPheromoneForInputLanes();
     706            4 :         double pheroOut = getPheromoneForOutputLanes();
     707              :         //double dispersionIn = getDispersionForInputLanes(pheroIn);
     708              :         //double dispersionOut = getDispersionForOutputLanes(pheroOut);
     709            4 :         double distancePheroIn = getDistanceOfMaxPheroForInputLanes();
     710            4 :         double distancePheroOut = getDistanceOfMaxPheroForOutputLanes();
     711            4 :         MSSOTLPolicy* oldPolicy = myCurrentPolicy;
     712            4 :         choosePolicy(pheroIn, pheroOut, distancePheroIn, distancePheroOut);
     713            4 :         MSSOTLPolicy* newPolicy = myCurrentPolicy;
     714              : 
     715            4 :         if (newPolicy != oldPolicy) {
     716              : #ifdef ANALYSIS_DEBUG
     717              :             SUMOTime step = MSNet::getInstance()->getCurrentTimeStep();
     718              :             std::ostringstream phero_str;
     719              :             phero_str << " (pheroIn= " << pheroIn << " ,pheroOut= " << pheroOut << " )";
     720              :             WRITE_MESSAGE("TL " + getID() + " time=" + time2string(step) + " Policy: " + newPolicy->getName() + phero_str.str() + " OldPolicy: " + oldPolicy->getName() + " id " + getID() + " .");
     721              : #endif
     722            0 :             if (oldPolicy->getName().compare("Congestion") == 0) {
     723            0 :                 congestion_steps = 0;
     724              :             }
     725              :         } else { //debug purpose only
     726              : #ifdef ANALYSIS_DEBUG
     727              :             std::ostringstream phero_str;
     728              :             phero_str << " (pheroIn= " << pheroIn << " ,pheroOut= " << pheroOut << " )";
     729              :             SUMOTime step = MSNet::getInstance()->getCurrentTimeStep();
     730              :             WRITE_MESSAGE("TL " + getID() + " time=" + time2string(step) + " Policy: Nochanges" + phero_str.str() + " OldPolicy: " + oldPolicy->getName() + " id " + getID() + " .");
     731              : #endif
     732              :         }
     733              : 
     734            4 :         mustChange = false;
     735            4 :         skipEta = false;
     736              :     }
     737          153 : }
     738              : 
     739            0 : double MSSwarmTrafficLightLogic::calculatePhi(int factor) {
     740            0 :     if (factor == 0) {
     741              :         return 1;
     742              :     }
     743            0 :     if (factor == 1) {
     744              :         return 0.2;
     745              :     } else {
     746            0 :         return 1 - (1 / ((double) factor));
     747              :     }
     748              : }
     749              : 
     750            0 : double MSSwarmTrafficLightLogic::calculateEtaDiff() {
     751              : 
     752            0 :     MSLane* currentLane = nullptr;
     753            0 :     int count = 0, minIn = 0, minOut = 0, toSub, tmp;
     754              :     bool inInit = true, outInit = true;
     755              :     double eta, normalized, diff, phi, delta;
     756              :     LaneIdVector toReset;
     757              : 
     758            0 :     carsIn = 0;
     759            0 :     carsOut = 0;
     760            0 :     inTarget = 0;
     761            0 :     notTarget = 0;
     762              : 
     763              :     MSSOTLE2Sensors* sensors = (MSSOTLE2Sensors*) getCountSensors();
     764              : 
     765              :     // Search the incoming lane to get the count of the vehicles passed. [IN]
     766            0 :     for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
     767            0 :             laneVector != myLanes.end(); laneVector++) {
     768            0 :         for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
     769              :                 lane++) {
     770            0 :             currentLane = (*lane);
     771              : 
     772              :             // Map to avoid check the lane for every possible direction
     773            0 :             if (laneCheck[currentLane] == false) {
     774              :                 // Get the vehicles passed from this lane.
     775            0 :                 count = sensors->getPassedVeh(currentLane->getID(), false);
     776              : 
     777              : #ifdef SWARM_DEBUG
     778              :                 std::ostringstream cars_str;
     779              :                 cars_str << "Lane " << currentLane->getID() << ": vehicles entered - " << count;
     780              :                 WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + cars_str.str());
     781              : #endif
     782              : 
     783              :                 // Increment the global count of the cars passed through the tl
     784            0 :                 carsIn += count;
     785              :                 // Set to true to skip similar lane since there's just one sensor
     786            0 :                 laneCheck[currentLane] = true;
     787              :             }
     788              :         }
     789              :     }
     790              : 
     791              :     // Search the outgoing lane to get the count of the vehicles passed. [OUT]
     792              :     // We use the links to get the respective lane id.
     793            0 :     for (MSTrafficLightLogic::LinkVectorVector::const_iterator linkVector = myLinks.begin();
     794            0 :             linkVector != myLinks.end(); linkVector++) {
     795            0 :         for (MSTrafficLightLogic::LinkVector::const_iterator link = linkVector->begin(); link != linkVector->end();
     796              :                 link++) {
     797            0 :             currentLane = (*link)->getLane();
     798              : 
     799              :             // Map to avoid check the lane for every possible direction
     800            0 :             if (laneCheck[currentLane] == false) {
     801              :                 // Get the vehicles passed from this lane.
     802            0 :                 count = sensors->getPassedVeh(currentLane->getID(), true);
     803              : 
     804              : #ifdef SWARM_DEBUG
     805              :                 std::ostringstream cars_str;
     806              :                 cars_str << "Lane " << currentLane->getID() << ": vehicles gone out- " << count;
     807              :                 WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + cars_str.str());
     808              : #endif
     809              : 
     810              :                 // Increment the global count of the cars passed through the tl
     811            0 :                 carsOut += count;
     812              : 
     813              :                 // Since there's no output target lanes we check here the minimum number of
     814              :                 // cars passed though the tl. This ahs to be done to all the output lanes since cars can go
     815              :                 // in any direction from a target lane. If a direction isn't reachable the sensor count will be 0.
     816              :                 // This is done to update the sensorCount value in order to don't make it grow too much.
     817            0 :                 if (count != 0) {
     818            0 :                     toReset.push_back(currentLane->getID());
     819            0 :                     if (outInit) {
     820            0 :                         minOut = count;
     821              :                         outInit = false;
     822            0 :                     } else if (count <= minOut) {
     823            0 :                         minOut = count;
     824              :                     }
     825              :                 }
     826              :                 // Set to true to skip similar lane since there's just one sensor
     827            0 :                 laneCheck[currentLane] = true;
     828              :             }
     829              :         }
     830              :     }
     831              :     // Reset the map to check again all the lane on the next commit.
     832            0 :     resetLaneCheck();
     833              : 
     834              :     // We retrieve the minimum number of cars passed from the target lanes.
     835            0 :     for (LaneIdVector::const_iterator laneId = targetLanes.begin(); laneId < targetLanes.end(); laneId++) {
     836              :         std::string lane = (*laneId);
     837            0 :         tmp = sensors->getPassedVeh(lane, false);
     838            0 :         inTarget += tmp;
     839            0 :         if (inInit && tmp != 0) {
     840            0 :             minIn = tmp;
     841              :             inInit = false;
     842              :         }
     843            0 :         if (tmp < minIn && tmp != 0) {
     844            0 :             minIn = tmp;
     845              :         }
     846            0 :         if (tmp != 0) {
     847            0 :             toReset.push_back(lane);
     848              :         }
     849              : #ifdef SWARM_DEBUG
     850              :         std::ostringstream cars_str;
     851              :         cars_str << "Lane " << lane << " passed: " << tmp;
     852              :         WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + cars_str.str());
     853              : #endif
     854              :     }
     855              : 
     856              :     // The cars not on a target lane counted as in.
     857            0 :     notTarget = carsIn - inTarget;
     858              : 
     859              :     // Calculate the min beetween the min number of cars entered the tl (minIn) and the
     860              :     // ones that have exit the tl (minOut)
     861            0 :     toSub = std::min(minIn, minOut);
     862              : 
     863              :     // Subtract the value to all the sensor on the target lanes.
     864            0 :     while (!toReset.empty()) {
     865              :         std::string laneId = toReset.back();
     866              :         toReset.pop_back();
     867            0 :         sensors->subtractPassedVeh(laneId, toSub);
     868              :     }
     869              : 
     870              :     //Normalized to 1
     871            0 :     diff = inTarget - carsOut;
     872            0 :     normalized = diff / inTarget;
     873              : 
     874              :     // Analize difference to return an appropriate eta to reinforce/forget the policies.
     875              : 
     876              : #ifdef SWARM_DEBUG
     877              :     std::ostringstream final_str;
     878              :     final_str << "Total cars in lanes: " << carsIn << " Total cars out: " << carsOut << " Difference: " << diff << " Pure eta: " << normalized;
     879              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + final_str.str());
     880              :     std::ostringstream eta_str;
     881              :     eta_str << "IN:" << inTarget << " OUT:" << carsOut << " R:" << notTarget;
     882              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + eta_str.str());
     883              :     std::ostringstream eta_str;
     884              :     eta_str << "Min found:" << toSub << " MinIn:" << minIn << " MinOut:" << minOut;
     885              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + eta_str.str());
     886              : #endif
     887              :     // IN > OUT
     888            0 :     if (inTarget > carsOut) {
     889            0 :         if (carsOut == 0) {
     890              :             // We're in Congestion but not for long so we don't do nothing. When we reach max steps for
     891              :             // Congestion the evaluation of eta is skipped and we force a forget of the policy
     892            0 :             if (myCurrentPolicy->getName().compare("Congestion") == 0) {
     893              :                 eta = 0;
     894              :             }
     895              :             // vehicles aren't going out and we've additional vehicle on a red lane. We set
     896              :             // eta to -1 to forget
     897              :             else {
     898              :                 eta = -1;
     899              :             }
     900              :         } else {
     901              :             // Forget - Amplify to R
     902            0 :             phi = calculatePhi(notTarget);
     903            0 :             eta = (-normalized * (1 / phi));
     904            0 :             if (eta < -1.0) {
     905              :                 eta = -1.0;
     906              :             }
     907              :         }
     908              :     }
     909              : 
     910              :     // IN = OUT
     911            0 :     else if (inTarget == carsOut) {
     912              :         // Can't say nothing
     913            0 :         if (inTarget == 0) {
     914              :             eta = 0;
     915              :         }
     916              : 
     917              :         // Reinforce - Attenuate to R
     918              :         // Normalized = 0 --> use delta = 1-1/IN
     919              :         else {
     920            0 :             delta = calculatePhi(inTarget);
     921            0 :             phi = calculatePhi(notTarget);
     922            0 :             eta = delta * phi;
     923            0 :             if (eta > 1.0) {
     924              :                 eta = 1.0;
     925              :             }
     926              :         }
     927              :     }
     928              : 
     929              :     // IN < OUT
     930              :     else {
     931              :         // Can't say nothing
     932            0 :         if (inTarget == 0) {
     933              :             eta = 0;
     934              :         }
     935              : 
     936              :         // Reinforce - Attenuate to R
     937              :         else {
     938            0 :             phi = calculatePhi(notTarget);
     939            0 :             diff = inTarget - carsOut;
     940            0 :             normalized = diff / carsOut;
     941            0 :             eta = normalized * phi;
     942            0 :             if (eta > 1.0) {
     943              :                 eta = 1.0;
     944              :             }
     945              :         }
     946              :     }
     947              : 
     948              : #ifdef SWARM_DEBUG
     949              :     std::ostringstream eta_str;
     950              :     eta_str << "Eta Normalized: " << eta;
     951              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + eta_str.str());
     952              : #endif
     953            0 :     return eta;
     954            0 : }
     955              : 
     956            0 : double MSSwarmTrafficLightLogic::calculateEtaRatio() {
     957            0 :     MSLane* currentLane = nullptr;
     958            0 :     int count = 0, minIn = 0, minOut = 0, toSub, tmp;
     959              :     bool inInit = true, outInit = true;
     960              :     double eta, ratio, phi, normalized, delta;
     961              :     LaneIdVector toReset;
     962              : 
     963            0 :     carsIn = 0;
     964            0 :     carsOut = 0;
     965            0 :     inTarget = 0;
     966            0 :     notTarget = 0;
     967              : 
     968              :     MSSOTLE2Sensors* sensors = (MSSOTLE2Sensors*) getCountSensors();
     969              : 
     970              :     // Search the incoming lane to get the count of the vehicles passed. [IN]
     971            0 :     for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
     972            0 :             laneVector != myLanes.end(); laneVector++) {
     973            0 :         for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
     974              :                 lane++) {
     975            0 :             currentLane = (*lane);
     976              : 
     977              :             // Map to avoid check the lane for every possible direction
     978            0 :             if (laneCheck[currentLane] == false) {
     979              :                 // Get the vehicles passed from this lane.
     980            0 :                 count = sensors->getPassedVeh(currentLane->getID(), false);
     981              : 
     982              : #ifdef SWARM_DEBUG
     983              :                 std::ostringstream cars_str;
     984              :                 cars_str << "Lane " << currentLane->getID() << ": vehicles entered - " << count;
     985              :                 WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + cars_str.str());
     986              : #endif
     987              : 
     988              :                 // Increment the global count of the cars passed through the tl
     989            0 :                 carsIn += count;
     990              :                 // Set to true to skip similar lane since there's just one sensor
     991            0 :                 laneCheck[currentLane] = true;
     992              :             }
     993              :         }
     994              :     }
     995              : 
     996              :     // Search the outgoing lane to get the count of the vehicles passed. [OUT]
     997              :     // We use the links to get the respective lane id.
     998            0 :     for (MSTrafficLightLogic::LinkVectorVector::const_iterator linkVector = myLinks.begin();
     999            0 :             linkVector != myLinks.end(); linkVector++) {
    1000            0 :         for (MSTrafficLightLogic::LinkVector::const_iterator link = linkVector->begin(); link != linkVector->end();
    1001              :                 link++) {
    1002            0 :             currentLane = (*link)->getLane();
    1003              : 
    1004              :             // Map to avoid check the lane for every possible direction
    1005            0 :             if (laneCheck[currentLane] == false) {
    1006              :                 // Get the vehicles passed from this lane.
    1007            0 :                 count = sensors->getPassedVeh(currentLane->getID(), true);
    1008              : 
    1009              : #ifdef SWARM_DEBUG
    1010              :                 std::ostringstream cars_str;
    1011              :                 cars_str << "Lane " << currentLane->getID() << ": vehicles gone out- " << count;
    1012              :                 WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + cars_str.str());
    1013              : #endif
    1014              :                 // Increment the global count of the cars passed through the tl
    1015            0 :                 carsOut += count;
    1016              : 
    1017              :                 // Since there's no output target lanes we check here the minimum number of
    1018              :                 // cars passed though the tl. This has to be done to all the output lanes since cars can go
    1019              :                 // in any direction from a target lane. If a direction isn't reachable the sensor count will be 0.
    1020              :                 // This is done to update the sensorCount value in order to don't make it grow too much.
    1021            0 :                 if (count != 0) {
    1022            0 :                     toReset.push_back(currentLane->getID());
    1023            0 :                     if (outInit) {
    1024            0 :                         minOut = count;
    1025              :                         outInit = false;
    1026            0 :                     } else if (count <= minOut) {
    1027            0 :                         minOut = count;
    1028              :                     }
    1029              :                 }
    1030              : 
    1031              :                 // Set to true to skip similar lane since there's just one sensor
    1032            0 :                 laneCheck[currentLane] = true;
    1033              :             }
    1034              :         }
    1035              :     }
    1036              :     // Reset the map to check again all the lane on the next commit.
    1037            0 :     resetLaneCheck();
    1038              : 
    1039              :     // We retrieve the minimum number of cars passed from the target lanes.
    1040            0 :     for (LaneIdVector::const_iterator laneId = targetLanes.begin(); laneId < targetLanes.end(); laneId++) {
    1041              :         std::string lane = (*laneId);
    1042            0 :         tmp = sensors->getPassedVeh(lane, false);
    1043            0 :         inTarget += tmp;
    1044            0 :         if (inInit && tmp != 0) {
    1045            0 :             minIn = tmp;
    1046              :             inInit = false;
    1047              :         }
    1048            0 :         if (tmp < minIn && tmp != 0) {
    1049            0 :             minIn = tmp;
    1050              :         }
    1051            0 :         if (tmp != 0) {
    1052            0 :             toReset.push_back(lane);
    1053              :         }
    1054              : #ifdef SWARM_DEBUG
    1055              :         std::ostringstream cars_str;
    1056              :         cars_str << "Lane " << lane << " passed: " << tmp;
    1057              :         WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + cars_str.str());
    1058              : #endif
    1059              :     }
    1060              : 
    1061              :     // The cars not on a target lane counted as in.
    1062            0 :     notTarget = carsIn - inTarget;
    1063              : 
    1064              :     // Calculate the min beetween the min number of cars entered the tl (minIn) and the
    1065              :     // ones that have exit the tl (minOut)
    1066            0 :     toSub = std::min(minIn, minOut);
    1067              : 
    1068              :     // Subtract the value to all the sensor on the target lanes.
    1069            0 :     while (!toReset.empty()) {
    1070              :         std::string laneId = toReset.back();
    1071              :         toReset.pop_back();
    1072            0 :         sensors->subtractPassedVeh(laneId, toSub);
    1073              :     }
    1074              : 
    1075              :     //Normalized to 1
    1076            0 :     if (carsOut != 0) {
    1077            0 :         ratio = ((double) inTarget) / carsOut;
    1078            0 :         normalized = ratio / (inTarget + carsOut);
    1079              :     } else {
    1080              :         ratio = std::numeric_limits<double>::infinity();
    1081              :         normalized = std::numeric_limits<double>::infinity();
    1082              :     }
    1083              : 
    1084              : #ifdef SWARM_DEBUG
    1085              :     std::ostringstream final_str;
    1086              :     final_str << "Total cars in lanes: " << carsIn << " Total cars out: " << carsOut << " Ratio: " << ratio << " Pure eta: " << normalized;
    1087              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + final_str.str());
    1088              :     std::ostringstream eta_str;
    1089              :     eta_str << "IN:" << inTarget << ". OUT:" << carsOut << " R:" << notTarget;
    1090              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + eta_str.str());
    1091              :     std::ostringstream eta_str;
    1092              :     eta_str << "Min found:" << toSub << ". MinIn:" << minIn << " MinOut:" << minOut;
    1093              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + eta_str.str());
    1094              : #endif
    1095              :     // Analize ratio to return an appropriate eta to reinforce/forget the policies.
    1096              : 
    1097              :     // IN > OUT
    1098            0 :     if (inTarget > carsOut) {
    1099            0 :         if (carsOut == 0) {
    1100              :             // we're in Congestion but not for long so we don't do nothing. When we reach max steps for
    1101              :             // Congestion the evaluation of eta is skipped and we force a forget of the policy
    1102            0 :             if (myCurrentPolicy->getName().compare("Congestion") == 0) {
    1103              :                 eta = 0;
    1104              :             }
    1105              :             // vehicles aren't going out and we've additional vehicle on a red lane. We set
    1106              :             // eta to -1 to forget
    1107              :             else {
    1108              :                 eta = -1;
    1109              :             }
    1110              :         } else {
    1111              :             // Forget according to the ratio. Amplify due to the cars in the red lanes
    1112            0 :             phi = calculatePhi(notTarget);
    1113            0 :             eta = (-(normalized) * (1 / phi));
    1114            0 :             if (eta < -1.0) {
    1115              :                 eta = -1.0;
    1116              :             }
    1117              :         }
    1118              :     }
    1119              :     // IN = OUT
    1120            0 :     else if (inTarget == carsOut) {
    1121              :         // We can't say nothing.
    1122            0 :         if (inTarget == 0) {
    1123              :             eta = 0;
    1124              :         }
    1125              :         // Reinforce - Attenuate to R
    1126              :         // same number of vehicles that are getting IN is getting OUT
    1127              :         // Normalized = 1/TOT ---> change to delta = 1-1/IN
    1128              :         else {
    1129            0 :             delta = calculatePhi(inTarget);
    1130            0 :             phi = calculatePhi(notTarget);
    1131            0 :             eta = delta * phi;
    1132            0 :             if (eta > 1.0) {
    1133              :                 eta = 1.0;
    1134              :             }
    1135              :         }
    1136              :     }
    1137              :     // IN < OUT
    1138              :     else {
    1139              :         // We can't say nothing.
    1140            0 :         if (inTarget == 0) {
    1141              :             eta = 0;
    1142              :         }
    1143              : 
    1144              :         // There was a queue and now cars are getting over it
    1145              :         // There're vehicles on the red lanes (R)
    1146              :         // We reinforce and attenuate according to R
    1147              :         else {
    1148            0 :             phi = calculatePhi(notTarget);
    1149            0 :             eta = (normalized) * phi;
    1150            0 :             if (eta > 1.0) {
    1151              :                 eta = 1.0;
    1152              :             }
    1153              :         }
    1154              :     }
    1155              : 
    1156              : #ifdef SWARM_DEBUG
    1157              :     std::ostringstream eta_str;
    1158              :     eta_str << "Eta Normalized: " << eta << ".";
    1159              :     WRITE_MESSAGE(time2string(MSNet::getInstance()->getCurrentTimeStep()) + " MSSwarmTrafficLightLogic::calculateEta::" + eta_str.str());
    1160              : #endif
    1161            0 :     return eta;
    1162              : 
    1163            0 : }
    1164              : 
    1165            0 : void MSSwarmTrafficLightLogic::resetLaneCheck() {
    1166              : 
    1167            0 :     MSLane* currentLane = nullptr;
    1168              : 
    1169              :     // reset both the input and the output lanes.
    1170            0 :     for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
    1171            0 :             laneVector != myLanes.end(); laneVector++) {
    1172              : 
    1173            0 :         for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
    1174              :                 lane++) {
    1175            0 :             currentLane = (*lane);
    1176            0 :             laneCheck[currentLane] = false;
    1177              :         }
    1178              :     }
    1179              : 
    1180            0 :     for (MSTrafficLightLogic::LinkVectorVector::const_iterator linkVector = myLinks.begin();
    1181            0 :             linkVector != myLinks.end(); linkVector++) {
    1182            0 :         for (MSTrafficLightLogic::LinkVector::const_iterator link = linkVector->begin(); link != linkVector->end();
    1183              :                 link++) {
    1184            0 :             currentLane = (*link)->getLane();
    1185            0 :             laneCheck[currentLane] = false;
    1186              :         }
    1187              :     }
    1188            0 : }
    1189              : 
    1190           20 : void MSSwarmTrafficLightLogic::choosePolicy(double phero_in, double phero_out, double dispersion_in,
    1191              :         double dispersion_out) {
    1192           20 :     if (m_useVehicleTypesWeights) {
    1193            0 :         for (std::vector<MSSOTLPolicy*>::iterator it = myPolicies.begin(); it != myPolicies.end(); ++it) {
    1194            0 :             if (it.operator * ()->getName() == "Phase") {
    1195            0 :                 activate(*it);
    1196              :                 return;
    1197              :             }
    1198              :         }
    1199              :     }
    1200              :     std::vector<double> thetaStimuli;
    1201              :     double thetaSum = 0.0;
    1202              :     // Compute stimulus for each policy
    1203          100 :     for (int i = 0; i < (int)myPolicies.size(); i++) {
    1204           80 :         double stimulus = myPolicies[i]->computeDesirability(phero_in, phero_out, dispersion_in, dispersion_out);
    1205           80 :         double thetaStimulus = pow(stimulus, 2) / (pow(stimulus, 2) + pow(myPolicies[i]->getThetaSensitivity(), 2));
    1206              : 
    1207           80 :         thetaStimuli.push_back(thetaStimulus);
    1208           80 :         thetaSum += thetaStimulus;
    1209              : 
    1210              : //              ANALYSIS_DBG(
    1211              : #ifdef SWARM_DEBUG
    1212              :         ostringstream so_str;
    1213              :         so_str << " policy " << myPolicies[i]->getName() << " stimulus " << stimulus << " pow(stimulus,2) " << pow(stimulus, 2) << " pow(Threshold,2) " << pow(myPolicies[i]->getThetaSensitivity(), 2) << " thetaStimulus " << thetaStimulus << " thetaSum " << thetaSum << " TL " << getID();
    1214              :         WRITE_MESSAGE("MSSwarmTrafficLightLogic::choosePolicy::" + so_str.str());
    1215              : #endif
    1216              :     }
    1217              : 
    1218              :     // Compute a random value between 0 and the sum of the thetaSum
    1219              : //      double r = RandHelper::rand(RAND_MAX);
    1220              : //      r = r / RAND_MAX * thetaSum;
    1221              :     double r = RandHelper::rand((double)thetaSum);
    1222              : 
    1223              :     double partialSum = 0;
    1224           20 :     for (int i = 0; i < (int)myPolicies.size(); i++) {
    1225           20 :         partialSum += thetaStimuli[i];
    1226              : 
    1227              : //              ANALYSIS_DBG(
    1228              : #ifdef SWARM_DEBUG
    1229              :         ostringstream aao_str;
    1230              :         aao_str << " policy " << myPolicies[i]->getName() << " partialSum " << partialSum << " thetaStimuls " << thetaStimuli[i] << " r " << r << " TL " << getID();
    1231              :         WRITE_MESSAGE("MSSwarmTrafficLightLogic::choosePolicy::" + aao_str.str());
    1232              : #endif
    1233           20 :         if (partialSum >= r) {
    1234           20 :             activate(myPolicies[i]);
    1235              :             break;
    1236              :         }
    1237              :     }
    1238           20 : }
    1239              : 
    1240            0 : void MSSwarmTrafficLightLogic::choosePolicy(double phero_in, double phero_out) {
    1241            0 :     choosePolicy(phero_in, phero_out, 0, 0);
    1242            0 : }
    1243              : 
    1244              : //never called...
    1245            0 : bool MSSwarmTrafficLightLogic::canRelease() {
    1246              : #ifdef SWARM_DEBUG
    1247              :     std::ostringstream phero_str;
    1248              :     phero_str << "getCurrentPhaseElapsed()=" << time2string(getCurrentPhaseElapsed()) << " isThresholdPassed()=" << isThresholdPassed() << " currentPhase=" << (&getCurrentPhaseDef())->getState() << " countVehicles()=" << countVehicles(getCurrentPhaseDef());
    1249              :     WRITE_MESSAGE("MSSwamTrafficLightLogic::canRelease(): " + phero_str.str());
    1250              : #endif
    1251            0 :     return myCurrentPolicy->canRelease(getCurrentPhaseElapsed(), isThresholdPassed(), isPushButtonPressed(), &getCurrentPhaseDef(),
    1252            0 :                                        countVehicles(getCurrentPhaseDef()));
    1253              : }
    1254              : 
    1255            0 : std::string MSSwarmTrafficLightLogic::getLaneLightState(const std::string& laneId) {
    1256            0 :     std::string laneState = "";
    1257            0 :     if (m_laneIndexMap.find(laneId) != m_laneIndexMap.end()) {
    1258            0 :         std::string state = getCurrentPhaseDef().getState();
    1259            0 :         for (std::vector<int>::const_iterator it = m_laneIndexMap[laneId].begin(); it != m_laneIndexMap[laneId].end(); ++it) {
    1260            0 :             laneState += state[*it];
    1261              :         }
    1262              :     }
    1263            0 :     return laneState;
    1264              : }
        

Generated by: LCOV version 2.0-1