LCOV - code coverage report
Current view: top level - src/microsim/traffic_lights - MSSwarmTrafficLightLogic.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 200 411 48.7 %
Date: 2024-05-19 15:37:39 Functions: 15 25 60.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2010-2024 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          32 : MSSwarmTrafficLightLogic::MSSwarmTrafficLightLogic(MSTLLogicControl& tlcontrol, const std::string& id,
      31             :         const std::string& programID, const Phases& phases, int step, SUMOTime delay,
      32          32 :         const Parameterised::Map& parameters) :
      33          32 :     MSSOTLHiLevelTrafficLightLogic(tlcontrol, id, programID, TrafficLightType::SWARM_BASED, phases, step, delay, parameters) {
      34             : 
      35          32 :     std::string pols = getPoliciesParam();
      36          64 :     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          32 :     if (pols.find("platoon") != std::string::npos) {
      44          64 :         addPolicy(new MSSOTLPlatoonPolicy(new MSSOTLPolicy5DFamilyStimulus("PLATOON", parameters), parameters));
      45             :     }
      46          32 :     if (pols.find("phase") != std::string::npos) {
      47          64 :         addPolicy(new MSSOTLPhasePolicy(new MSSOTLPolicy5DFamilyStimulus("PHASE", parameters), parameters));
      48             :     }
      49          32 :     if (pols.find("marching") != std::string::npos) {
      50          64 :         addPolicy(new MSSOTLMarchingPolicy(new MSSOTLPolicy5DFamilyStimulus("MARCHING", parameters), parameters));
      51             :     }
      52          32 :     if (pols.find("congestion") != std::string::npos) {
      53          64 :         addPolicy(new MSSOTLCongestionPolicy(new MSSOTLPolicy5DFamilyStimulus("CONGESTION", parameters), parameters));
      54             :     }
      55             : 
      56          32 :     if (myPolicies.empty()) {
      57           0 :         WRITE_ERROR(TL("NO VALID POLICY LIST READ"));
      58             :     }
      59             : 
      60          32 :     mustChange = false;
      61          32 :     skipEta = false;
      62          32 :     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          32 :     congestion_steps = 0;
      79          96 :     m_useVehicleTypesWeights = getParameter("USE_VEHICLE_TYPES_WEIGHTS", "0") == "1";
      80          32 :     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          32 : }
      84             : 
      85          64 : MSSwarmTrafficLightLogic::~MSSwarmTrafficLightLogic() {
      86          32 :     if (logData && swarmLogFile.is_open()) {
      87           0 :         swarmLogFile.close();
      88             :     }
      89          32 :     for (std::map<std::string, CircularBuffer<double>*>::iterator it = m_meanSpeedHistory.begin();
      90         160 :             it != m_meanSpeedHistory.end(); ++it) {
      91         128 :         delete it->second;
      92             :     }
      93             :     m_meanSpeedHistory.clear();
      94          32 :     for (std::map<std::string, CircularBuffer<double>*>::iterator it = m_derivativeHistory.begin();
      95         160 :             it != m_derivativeHistory.end(); ++it) {
      96         128 :         delete it->second;
      97             :     }
      98             :     m_derivativeHistory.clear();
      99         128 : }
     100             : 
     101         256 : bool MSSwarmTrafficLightLogic::allowLine(MSLane* lane) {
     102             :     //No walking areas
     103         256 :     if (lane->getEdge().isWalkingArea()) {
     104             :         return false;
     105             :     }
     106             :     //No pedestrian crossing
     107         256 :     if (lane->getEdge().isCrossing()) {
     108             :         return false;
     109             :     }
     110             :     //No pedestrian only lanes
     111         256 :     if (lane->getPermissions() == SVC_PEDESTRIAN) {
     112             :         return false;
     113             :     }
     114             :     //No bicycle only lanes
     115         256 :     if (lane->getPermissions() == SVC_BICYCLE) {
     116             :         return false;
     117             :     }
     118             :     //No pedestrian and bicycle only lanes
     119         256 :     if (lane->getPermissions() == (SVC_PEDESTRIAN | SVC_BICYCLE)) {
     120           0 :         return false;
     121             :     }
     122             :     return true;
     123             : }
     124             : 
     125          32 : void MSSwarmTrafficLightLogic::init(NLDetectorBuilder& nb) {
     126          32 :     MSSOTLHiLevelTrafficLightLogic::init(nb);
     127             :     //Setting the startup policy
     128          32 :     choosePolicy(0, 0, 0, 0);
     129             :     //Initializing the random number generator to a time-dependent seed
     130          32 :     srand((int) time(nullptr));
     131             :     //Initializing pheromone maps according to input lanes
     132             :     //For each lane insert a pair into maps
     133          32 :     MSLane* currentLane = nullptr;
     134             : 
     135             : //      Derivative
     136          96 :     const int derivativeHistorySize = StringUtils::toInt(getParameter("PHERO_DERIVATIVE_HISTORY_SIZE", "3"));
     137          96 :     const int meanSpeedHistorySize = StringUtils::toInt(getParameter("PHERO_MEAN_SPEED_HISTORY_SIZE", "3"));
     138          64 :     m_derivativeAlpha = StringUtils::toDouble(getParameter("PHERO_DERIVATIVE_ALPHA", "1"));
     139          32 :     m_losCounter = 0;
     140          64 :     m_losMaxLimit = StringUtils::toInt(getParameter("LOSS_OF_SIGNAL_LIMIT", "10"));
     141             : 
     142             :     int index = 0;
     143          32 :     for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
     144         160 :             laneVector != myLanes.end(); laneVector++) {
     145         256 :         for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
     146             :                 lane++) {
     147         128 :             currentLane = (*lane);
     148         128 :             if (pheromoneInputLanes.find(currentLane->getID()) == pheromoneInputLanes.end()) {
     149         128 :                 laneCheck[currentLane] = false;
     150         128 :                 if (allowLine(currentLane)) {
     151         128 :                     pheromoneInputLanes.insert(MSLaneId_Pheromone(currentLane->getID(), 0.0));
     152             : //                                      Consider the derivative only for the input lane
     153         128 :                     m_meanSpeedHistory.insert(std::make_pair(currentLane->getID(), new CircularBuffer<double>(meanSpeedHistorySize)));
     154         256 :                     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         128 :             m_laneIndexMap[currentLane->getID()].push_back(index++);
     165             :         }
     166             :     }
     167             : 
     168          32 :     LinkVectorVector links = getLinks();
     169         160 :     for (int i = 0; i < (int)links.size(); i++) {
     170         128 :         LinkVector oneLink = getLinksAt(i);
     171         256 :         for (int j = 0; j < (int)oneLink.size(); j++) {
     172         128 :             currentLane = oneLink[j]->getLane();
     173         128 :             if (pheromoneOutputLanes.find(currentLane->getID()) == pheromoneOutputLanes.end()) {
     174         128 :                 laneCheck[currentLane] = false;
     175         128 :                 if (allowLine(currentLane)) {
     176         256 :                     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             :     }
     188             : 
     189          32 :     initScaleFactorDispersionIn((int)pheromoneInputLanes.size());
     190          32 :     initScaleFactorDispersionOut((int)pheromoneOutputLanes.size());
     191             :     //Initializing thresholds for theta evaluations
     192          32 :     lastThetaSensitivityUpdate = MSNet::getInstance()->getCurrentTimeStep();
     193             : 
     194          96 :     WRITE_MESSAGEF(TL("*** Intersection % will run using MSSwarmTrafficLightLogic ***"), getID());
     195          64 :     std::string logFileName = getParameter("SWARMLOG", "");
     196          32 :     logData = logFileName.compare("") != 0;
     197          32 :     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          32 : }
     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       31952 : 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       31952 :     if (getCurrentPhaseDef().isTarget()) {
     241       29504 :         targetLanes = getCurrentPhaseDef().getTargetLaneSet();
     242             :     }
     243             : 
     244       95856 :     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       31952 :     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       31952 :     if (getCurrentPhaseDef().isTransient() && getCurrentPhaseElapsed() < getCurrentPhaseDef().duration) {
     275        1836 :         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       30116 :     if (getCurrentPhaseDef().isCommit()) {
     280             :         //Update learning and forgetting thresholds
     281         306 :         updateSensitivities();
     282         306 :         decidePolicy();
     283         306 :         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       60232 :     return myCurrentPolicy->decideNextPhase(getCurrentPhaseElapsed(), &getCurrentPhaseDef(), getCurrentPhaseIndex(),
     307       60232 :                                             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       31952 : void MSSwarmTrafficLightLogic::updatePheromoneLevels() {
     316             :     //Updating input lanes pheromone: all input lanes without distinction
     317             :     //BETA_NO, GAMMA_NO
     318       31952 :     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       31952 :     updatePheromoneLevels(pheromoneOutputLanes, "PheroOut", getBetaSp(), getGammaSp());
     324             : //    }
     325       31952 : }
     326             : 
     327       63904 : 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      319520 :     for (MSLaneId_PheromoneMap::iterator laneIterator = pheroMap.begin(); laneIterator != pheroMap.end();
     338             :             ++laneIterator) {
     339             :         std::string laneId = laneIterator->first;
     340      255616 :         double oldPhero = laneIterator->second;
     341      766848 :         double maxSpeed = getSensors()->getMaxSpeed(laneId);
     342      511232 :         double meanVehiclesSpeed = getSensors()->meanVehiclesSpeed(laneId);
     343      255616 :         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      255616 :         if (m_meanSpeedHistory.find(laneId) != m_meanSpeedHistory.end()) {
     350             :             //Update the derivative
     351      127808 :             if (updatePheromone) {
     352             :                 double currentDerivative = 0;
     353       83964 :                 m_losCounter = 0;
     354      167928 :                 if (m_meanSpeedHistory[laneId]->size() > 0) {
     355             :                     //Calculate the current derivative mean with the old speed points
     356      670752 :                     for (int i = 0; i < m_meanSpeedHistory[laneId]->size(); ++i)
     357      251412 :                         if (i == 0) {
     358       83964 :                             currentDerivative += fabs(meanVehiclesSpeed - m_meanSpeedHistory[laneId]->at(i));
     359             :                         } else {
     360      167448 :                             currentDerivative += fabs(m_meanSpeedHistory[laneId]->at(i - 1) - m_meanSpeedHistory[laneId]->at(i));
     361             :                         }
     362      167928 :                     currentDerivative /= m_meanSpeedHistory[laneId]->size(); //Non weighted mean
     363             :                 }
     364       83964 :                 m_meanSpeedHistory[laneId]->push_front(meanVehiclesSpeed);
     365             :                 //Check if the current value of the derivative is above the set alpha
     366       83964 :                 if (currentDerivative >= m_derivativeAlpha) {
     367        7228 :                     m_derivativeHistory[laneId]->push_front(currentDerivative);
     368             :                 }
     369      167928 :                 if (m_derivativeHistory[laneId]->size() > 0) {
     370             :                     //Calculate the mean derivative with the old derivative
     371      557464 :                     for (int i = 0; i < m_derivativeHistory[laneId]->size(); ++i) {
     372      207332 :                         derivative += m_derivativeHistory[laneId]->at(i);
     373             :                     }
     374      142800 :                     derivative /= m_derivativeHistory[laneId]->size();
     375             :                 }
     376             :             } else {
     377             :                 //Reset the values if no information is received after a timeout
     378       43844 :                 ++m_losCounter;
     379       43844 :                 if (m_losCounter >= m_losMaxLimit) {
     380       16828 :                     m_derivativeHistory[laneId]->clear();
     381       16828 :                     m_meanSpeedHistory[laneId]->clear();
     382       16828 :                     m_meanSpeedHistory[laneId]->push_front(maxSpeed);
     383             :                 }
     384             :             }
     385             :         }
     386      255616 :         double pheroAdd = MAX2((maxSpeed - meanVehiclesSpeed) * 10 / maxSpeed, 0.0);
     387             : //              Use the derivative only if it has a value
     388      255616 :         if (derivative > 0)
     389             : //              Correct the pheromone value by dividing it for the derivative.
     390             :         {
     391       71400 :             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      255616 :         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      255616 :         phero = MIN2(MAX2(phero, 0.0), getPheroMaxVal());
     413      255616 :         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       63904 : }
     450         306 : void MSSwarmTrafficLightLogic::updateSensitivities() {
     451         306 :     double elapsedTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - lastThetaSensitivityUpdate);
     452         306 :     lastThetaSensitivityUpdate = MSNet::getInstance()->getCurrentTimeStep();
     453             : 
     454             :     //reset of the sensitivity thresholds in case of 0 pheromone on the input lanes
     455         306 :     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         306 :     if (!skipEta || myCurrentPolicy->getName().compare("Congestion") != 0) {
     471         306 :         switch (getReinforcementMode()) {
     472         306 :             case 0:
     473         306 :                 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        1410 :     for (MSSOTLPolicy* const policy : myPolicies) {
     487             :         double newSensitivity;
     488        1128 :         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        1128 :             if (policy == myCurrentPolicy) {    //reward the current policy
     498         282 :                 newSensitivity = policy->getThetaSensitivity() - getLearningCox() * eta;
     499             :             } else
     500             :                 //      punish the other ones
     501             :             {
     502         846 :                 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        1128 :         newSensitivity = MAX2(MIN2(newSensitivity, getThetaMax()), getThetaMin());
     532        1128 :         policy->setThetaSensitivity(newSensitivity);
     533             :     }
     534             : }
     535             : 
     536         314 : double MSSwarmTrafficLightLogic::getPheromoneForInputLanes() {
     537         314 :     if (pheromoneInputLanes.size() == 0) {
     538             :         return 0;
     539             :     }
     540             :     double pheroIn = 0;
     541         314 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneInputLanes.begin();
     542        1570 :             iterator != pheromoneInputLanes.end(); iterator++) {
     543             :         std::string laneId = iterator->first;
     544        1256 :         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         314 :     return pheroIn / (double)pheromoneInputLanes.size();
     558             : }
     559             : 
     560           8 : double MSSwarmTrafficLightLogic::getPheromoneForOutputLanes() {
     561           8 :     if (pheromoneOutputLanes.size() == 0) {
     562             :         return 0;
     563             :     }
     564             :     double pheroOut = 0;
     565           8 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneOutputLanes.begin();
     566          40 :             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          32 :         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           8 :     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           8 : double MSSwarmTrafficLightLogic::getDistanceOfMaxPheroForInputLanes() {
     621           8 :     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           8 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneInputLanes.begin();
     630          40 :             iterator != pheromoneInputLanes.end(); iterator++) {
     631             :         std::string laneId = iterator->first;
     632          32 :         double lanePhero = iterator->second;
     633          32 :         if (counter == 0) {
     634             :             max_phero_val_current = lanePhero;
     635             :             counter++;
     636             :             continue;
     637             :         }
     638          24 :         if (lanePhero > max_phero_val_current) {
     639             :             max_phero_val_old = max_phero_val_current;
     640             :             max_phero_val_current = lanePhero;
     641           6 :             temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + max_phero_val_old) / counter;
     642             :         } else {
     643          18 :             temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + lanePhero) / counter;
     644             :         }
     645             : 
     646          24 :         counter++;
     647             :     }
     648             : 
     649           8 :     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           8 : double MSSwarmTrafficLightLogic::getDistanceOfMaxPheroForOutputLanes() {
     659           8 :     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           8 :     for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneOutputLanes.begin();
     668          40 :             iterator != pheromoneOutputLanes.end(); iterator++) {
     669             :         std::string laneId = iterator->first;
     670          32 :         double lanePhero = iterator->second;
     671          32 :         if (counter == 0) {
     672             :             max_phero_val_current = lanePhero;
     673             :             counter++;
     674             :             continue;
     675             :         }
     676          24 :         if (lanePhero > max_phero_val_current) {
     677             :             max_phero_val_old = max_phero_val_current;
     678             :             max_phero_val_current = lanePhero;
     679          10 :             temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + max_phero_val_old) / counter;
     680             :         } else {
     681          14 :             temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + lanePhero) / counter;
     682             :         }
     683             : 
     684          24 :         counter++;
     685             :     }
     686             : 
     687           8 :     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         306 : 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         306 :     double sampled = RandHelper::rand();
     700         306 :     double changeProb = getChangePlanProbability();
     701             : //      changeProb = changeProb * RAND_MAX;
     702             : 
     703         306 :     if (sampled <= changeProb || mustChange) { // Check for another plan
     704             : 
     705           8 :         double pheroIn = getPheromoneForInputLanes();
     706           8 :         double pheroOut = getPheromoneForOutputLanes();
     707             :         //double dispersionIn = getDispersionForInputLanes(pheroIn);
     708             :         //double dispersionOut = getDispersionForOutputLanes(pheroOut);
     709           8 :         double distancePheroIn = getDistanceOfMaxPheroForInputLanes();
     710           8 :         double distancePheroOut = getDistanceOfMaxPheroForOutputLanes();
     711           8 :         MSSOTLPolicy* oldPolicy = myCurrentPolicy;
     712           8 :         choosePolicy(pheroIn, pheroOut, distancePheroIn, distancePheroOut);
     713           8 :         MSSOTLPolicy* newPolicy = myCurrentPolicy;
     714             : 
     715           8 :         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           8 :         mustChange = false;
     735           8 :         skipEta = false;
     736             :     }
     737         306 : }
     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           0 :         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           0 :         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          40 : void MSSwarmTrafficLightLogic::choosePolicy(double phero_in, double phero_out, double dispersion_in,
    1191             :         double dispersion_out) {
    1192          40 :     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         200 :     for (int i = 0; i < (int)myPolicies.size(); i++) {
    1204         160 :         double stimulus = myPolicies[i]->computeDesirability(phero_in, phero_out, dispersion_in, dispersion_out);
    1205         160 :         double thetaStimulus = pow(stimulus, 2) / (pow(stimulus, 2) + pow(myPolicies[i]->getThetaSensitivity(), 2));
    1206             : 
    1207         160 :         thetaStimuli.push_back(thetaStimulus);
    1208         160 :         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          40 :     for (int i = 0; i < (int)myPolicies.size(); i++) {
    1225          40 :         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          40 :         if (partialSum >= r) {
    1234          40 :             activate(myPolicies[i]);
    1235             :             break;
    1236             :         }
    1237             :     }
    1238             : }
    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 1.14