Eclipse SUMO - Simulation of Urban MObility
MSSwarmTrafficLightLogic.cpp
Go to the documentation of this file.
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 /****************************************************************************/
19 // The class for Swarm-based logics
20 /****************************************************************************/
21 
22 #include <microsim/MSEdge.h>
24 //#define SWARM_DEBUG
25 //#define ANALYSIS_DEBUG
26 
27 // ===========================================================================
28 // method definitions
29 // ===========================================================================
31  const std::string& programID, const Phases& phases, int step, SUMOTime delay,
32  const Parameterised::Map& parameters) :
33  MSSOTLHiLevelTrafficLightLogic(tlcontrol, id, programID, TrafficLightType::SWARM_BASED, phases, step, delay, parameters) {
34 
35  std::string pols = getPoliciesParam();
36  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  if (pols.find("platoon") != std::string::npos) {
44  addPolicy(new MSSOTLPlatoonPolicy(new MSSOTLPolicy5DFamilyStimulus("PLATOON", parameters), parameters));
45  }
46  if (pols.find("phase") != std::string::npos) {
47  addPolicy(new MSSOTLPhasePolicy(new MSSOTLPolicy5DFamilyStimulus("PHASE", parameters), parameters));
48  }
49  if (pols.find("marching") != std::string::npos) {
50  addPolicy(new MSSOTLMarchingPolicy(new MSSOTLPolicy5DFamilyStimulus("MARCHING", parameters), parameters));
51  }
52  if (pols.find("congestion") != std::string::npos) {
53  addPolicy(new MSSOTLCongestionPolicy(new MSSOTLPolicy5DFamilyStimulus("CONGESTION", parameters), parameters));
54  }
55 
56  if (myPolicies.empty()) {
57  WRITE_ERROR(TL("NO VALID POLICY LIST READ"));
58  }
59 
60  mustChange = false;
61  skipEta = false;
62  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];
73  std::ostringstream _str;
74  _str << policy->getName() << stim->getMessage() << " getThetaSensitivity " << policy->getThetaSensitivity() << " .";
75  WRITE_MESSAGE(_str.str());
76  }
77 #endif
78  congestion_steps = 0;
79  m_useVehicleTypesWeights = getParameter("USE_VEHICLE_TYPES_WEIGHTS", "0") == "1";
80  if (m_useVehicleTypesWeights && pols.find("phase") == std::string::npos) {
81  WRITE_ERROR(TL("VEHICLE TYPES WEIGHT only works with phase policy, which is missing"));
82  }
83 }
84 
86  if (logData && swarmLogFile.is_open()) {
87  swarmLogFile.close();
88  }
89  for (std::map<std::string, CircularBuffer<double>*>::iterator it = m_meanSpeedHistory.begin();
90  it != m_meanSpeedHistory.end(); ++it) {
91  delete it->second;
92  }
93  m_meanSpeedHistory.clear();
94  for (std::map<std::string, CircularBuffer<double>*>::iterator it = m_derivativeHistory.begin();
95  it != m_derivativeHistory.end(); ++it) {
96  delete it->second;
97  }
98  m_derivativeHistory.clear();
99 }
100 
102  //No walking areas
103  if (lane->getEdge().isWalkingArea()) {
104  return false;
105  }
106  //No pedestrian crossing
107  if (lane->getEdge().isCrossing()) {
108  return false;
109  }
110  //No pedestrian only lanes
111  if (lane->getPermissions() == SVC_PEDESTRIAN) {
112  return false;
113  }
114  //No bicycle only lanes
115  if (lane->getPermissions() == SVC_BICYCLE) {
116  return false;
117  }
118  //No pedestrian and bicycle only lanes
119  if (lane->getPermissions() == (SVC_PEDESTRIAN | SVC_BICYCLE)) {
120  return false;
121  }
122  return true;
123 }
124 
127  //Setting the startup policy
128  choosePolicy(0, 0, 0, 0);
129  //Initializing the random number generator to a time-dependent seed
130  srand((int) time(nullptr));
131  //Initializing pheromone maps according to input lanes
132  //For each lane insert a pair into maps
133  MSLane* currentLane = nullptr;
134 
135 // Derivative
136  const int derivativeHistorySize = StringUtils::toInt(getParameter("PHERO_DERIVATIVE_HISTORY_SIZE", "3"));
137  const int meanSpeedHistorySize = StringUtils::toInt(getParameter("PHERO_MEAN_SPEED_HISTORY_SIZE", "3"));
138  m_derivativeAlpha = StringUtils::toDouble(getParameter("PHERO_DERIVATIVE_ALPHA", "1"));
139  m_losCounter = 0;
140  m_losMaxLimit = StringUtils::toInt(getParameter("LOSS_OF_SIGNAL_LIMIT", "10"));
141 
142  int index = 0;
143  for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
144  laneVector != myLanes.end(); laneVector++) {
145  for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
146  lane++) {
147  currentLane = (*lane);
148  if (pheromoneInputLanes.find(currentLane->getID()) == pheromoneInputLanes.end()) {
149  laneCheck[currentLane] = false;
150  if (allowLine(currentLane)) {
151  pheromoneInputLanes.insert(MSLaneId_Pheromone(currentLane->getID(), 0.0));
152 // Consider the derivative only for the input lane
153  m_meanSpeedHistory.insert(std::make_pair(currentLane->getID(), new CircularBuffer<double>(meanSpeedHistorySize)));
154  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  m_laneIndexMap[currentLane->getID()].push_back(index++);
165  }
166  }
167 
168  LinkVectorVector links = getLinks();
169  for (int i = 0; i < (int)links.size(); i++) {
170  LinkVector oneLink = getLinksAt(i);
171  for (int j = 0; j < (int)oneLink.size(); j++) {
172  currentLane = oneLink[j]->getLane();
173  if (pheromoneOutputLanes.find(currentLane->getID()) == pheromoneOutputLanes.end()) {
174  laneCheck[currentLane] = false;
175  if (allowLine(currentLane)) {
176  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 
191  //Initializing thresholds for theta evaluations
193 
194  WRITE_MESSAGEF(TL("*** Intersection % will run using MSSwarmTrafficLightLogic ***"), getID());
195  std::string logFileName = getParameter("SWARMLOG", "");
196  logData = logFileName.compare("") != 0;
197  if (logData) {
198  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 }
214 
216  //input
217  for (MSLaneId_PheromoneMap::iterator laneIterator = pheromoneInputLanes.begin();
218  laneIterator != pheromoneInputLanes.end(); laneIterator++) {
219  std::string laneId = laneIterator->first;
220  pheromoneInputLanes[laneId] = 0;
221  }
222  //output
223  for (MSLaneId_PheromoneMap::iterator laneIterator = pheromoneOutputLanes.begin();
224  laneIterator != pheromoneOutputLanes.end(); laneIterator++) {
225  std::string laneId = laneIterator->first;
226  pheromoneOutputLanes[laneId] = 0;
227  }
228 }
229 
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();
237 #endif
238  // if we're congested, it should be wise to reset and recalculate the pheromone levels after X steps
239 
240  if (getCurrentPhaseDef().isTarget()) {
242  }
243 
244  if (myCurrentPolicy->getName().compare("Congestion") == 0 && getCurrentPhaseDef().isCommit()) {
245  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
254  resetPheromone();
255  congestion_steps = 0;
256  mustChange = true;
257  if (getReinforcementMode() != 0) {
258  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
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  if (getCurrentPhaseDef().isTransient() && getCurrentPhaseElapsed() < getCurrentPhaseDef().duration) {
275  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  if (getCurrentPhaseDef().isCommit()) {
280  //Update learning and forgetting thresholds
282  decidePolicy();
283  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
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 
316  //Updating input lanes pheromone: all input lanes without distinction
317  //BETA_NO, GAMMA_NO
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()) {
324 // }
325 }
326 
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  for (MSLaneId_PheromoneMap::iterator laneIterator = pheroMap.begin(); laneIterator != pheroMap.end();
338  ++laneIterator) {
339  std::string laneId = laneIterator->first;
340  double oldPhero = laneIterator->second;
341  double maxSpeed = getSensors()->getMaxSpeed(laneId);
342  double meanVehiclesSpeed = getSensors()->meanVehiclesSpeed(laneId);
343  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  if (m_meanSpeedHistory.find(laneId) != m_meanSpeedHistory.end()) {
350  //Update the derivative
351  if (updatePheromone) {
352  double currentDerivative = 0;
353  m_losCounter = 0;
354  if (m_meanSpeedHistory[laneId]->size() > 0) {
355  //Calculate the current derivative mean with the old speed points
356  for (int i = 0; i < m_meanSpeedHistory[laneId]->size(); ++i)
357  if (i == 0) {
358  currentDerivative += fabs(meanVehiclesSpeed - m_meanSpeedHistory[laneId]->at(i));
359  } else {
360  currentDerivative += fabs(m_meanSpeedHistory[laneId]->at(i - 1) - m_meanSpeedHistory[laneId]->at(i));
361  }
362  currentDerivative /= m_meanSpeedHistory[laneId]->size(); //Non weighted mean
363  }
364  m_meanSpeedHistory[laneId]->push_front(meanVehiclesSpeed);
365  //Check if the current value of the derivative is above the set alpha
366  if (currentDerivative >= m_derivativeAlpha) {
367  m_derivativeHistory[laneId]->push_front(currentDerivative);
368  }
369  if (m_derivativeHistory[laneId]->size() > 0) {
370  //Calculate the mean derivative with the old derivative
371  for (int i = 0; i < m_derivativeHistory[laneId]->size(); ++i) {
372  derivative += m_derivativeHistory[laneId]->at(i);
373  }
374  derivative /= m_derivativeHistory[laneId]->size();
375  }
376  } else {
377  //Reset the values if no information is received after a timeout
378  ++m_losCounter;
379  if (m_losCounter >= m_losMaxLimit) {
380  m_derivativeHistory[laneId]->clear();
381  m_meanSpeedHistory[laneId]->clear();
382  m_meanSpeedHistory[laneId]->push_front(maxSpeed);
383  }
384  }
385  }
386  double pheroAdd = MAX2((maxSpeed - meanVehiclesSpeed) * 10 / maxSpeed, 0.0);
387 // Use the derivative only if it has a value
388  if (derivative > 0)
389 // Correct the pheromone value by dividing it for the derivative.
390  {
391  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  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  phero = MIN2(MAX2(phero, 0.0), getPheroMaxVal());
413  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 }
451  double elapsedTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep() - lastThetaSensitivityUpdate);
453 
454  //reset of the sensitivity thresholds in case of 0 pheromone on the input lanes
455  if (getPheromoneForInputLanes() == 0) {
456  for (MSSOTLPolicy* const policy : myPolicies) {
457  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  if (!skipEta || myCurrentPolicy->getName().compare("Congestion") != 0) {
471  switch (getReinforcementMode()) {
472  case 0:
473  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  case 1:
479  eta = calculateEtaDiff();
480  break;
481  case 2:
482  eta = calculateEtaRatio();
483  break;
484  }
485  }
486  for (MSSOTLPolicy* const policy : myPolicies) {
487  double newSensitivity;
488  if (eta < 0) { //bad performance
489  if (policy == myCurrentPolicy) { // punish the current policy
490  newSensitivity = policy->getThetaSensitivity() + getForgettingCox() * (-eta);
491  } else
492  // reward the other ones
493  {
494  newSensitivity = policy->getThetaSensitivity() - getLearningCox() * (-eta);
495  }
496  } else { //good performance
497  if (policy == myCurrentPolicy) { //reward the current policy
498  newSensitivity = policy->getThetaSensitivity() - getLearningCox() * eta;
499  } else
500  // punish the other ones
501  {
502  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  newSensitivity = MAX2(MIN2(newSensitivity, getThetaMax()), getThetaMin());
532  policy->setThetaSensitivity(newSensitivity);
533  }
534 }
535 
537  if (pheromoneInputLanes.size() == 0) {
538  return 0;
539  }
540  double pheroIn = 0;
541  for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneInputLanes.begin();
542  iterator != pheromoneInputLanes.end(); iterator++) {
543  std::string laneId = iterator->first;
544  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  return pheroIn / (double)pheromoneInputLanes.size();
558 }
559 
561  if (pheromoneOutputLanes.size() == 0) {
562  return 0;
563  }
564  double pheroOut = 0;
565  for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneOutputLanes.begin();
566  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  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  return pheroOut / (double)pheromoneOutputLanes.size();
580 }
581 
583  if (pheromoneInputLanes.size() == 0) {
584  return 0;
585  }
586  double sum = 0;
587  for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneInputLanes.begin();
588  iterator != pheromoneInputLanes.end(); iterator++) {
589  std::string laneId = iterator->first;
590  sum += pow(iterator->second - average_phero_in, 2);
591  }
592 
593  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  return result;
600 }
601 
603  if (pheromoneOutputLanes.size() == 0) {
604  return 0;
605  }
606  double sum = 0;
607  for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneOutputLanes.begin();
608  iterator != pheromoneOutputLanes.end(); iterator++) {
609  sum += pow(iterator->second - average_phero_out, 2);
610  }
611 
612  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  return result;
619 }
621  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  for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneInputLanes.begin();
630  iterator != pheromoneInputLanes.end(); iterator++) {
631  std::string laneId = iterator->first;
632  double lanePhero = iterator->second;
633  if (counter == 0) {
634  max_phero_val_current = lanePhero;
635  counter++;
636  continue;
637  }
638  if (lanePhero > max_phero_val_current) {
639  max_phero_val_old = max_phero_val_current;
640  max_phero_val_current = lanePhero;
641  temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + max_phero_val_old) / counter;
642  } else {
643  temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + lanePhero) / counter;
644  }
645 
646  counter++;
647  }
648 
649  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 
659  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  for (MSLaneId_PheromoneMap::const_iterator iterator = pheromoneOutputLanes.begin();
668  iterator != pheromoneOutputLanes.end(); iterator++) {
669  std::string laneId = iterator->first;
670  double lanePhero = iterator->second;
671  if (counter == 0) {
672  max_phero_val_current = lanePhero;
673  counter++;
674  continue;
675  }
676  if (lanePhero > max_phero_val_current) {
677  max_phero_val_old = max_phero_val_current;
678  max_phero_val_current = lanePhero;
679  temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + max_phero_val_old) / counter;
680  } else {
681  temp_avg_other_lanes = (temp_avg_other_lanes * (counter - 1) + lanePhero) / counter;
682  }
683 
684  counter++;
685  }
686 
687  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 }
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  double sampled = RandHelper::rand();
700  double changeProb = getChangePlanProbability();
701 // changeProb = changeProb * RAND_MAX;
702 
703  if (sampled <= changeProb || mustChange) { // Check for another plan
704 
705  double pheroIn = getPheromoneForInputLanes();
706  double pheroOut = getPheromoneForOutputLanes();
707  //double dispersionIn = getDispersionForInputLanes(pheroIn);
708  //double dispersionOut = getDispersionForOutputLanes(pheroOut);
709  double distancePheroIn = getDistanceOfMaxPheroForInputLanes();
710  double distancePheroOut = getDistanceOfMaxPheroForOutputLanes();
711  MSSOTLPolicy* oldPolicy = myCurrentPolicy;
712  choosePolicy(pheroIn, pheroOut, distancePheroIn, distancePheroOut);
713  MSSOTLPolicy* newPolicy = myCurrentPolicy;
714 
715  if (newPolicy != oldPolicy) {
716 #ifdef ANALYSIS_DEBUG
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  if (oldPolicy->getName().compare("Congestion") == 0) {
723  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 << " )";
730  WRITE_MESSAGE("TL " + getID() + " time=" + time2string(step) + " Policy: Nochanges" + phero_str.str() + " OldPolicy: " + oldPolicy->getName() + " id " + getID() + " .");
731 #endif
732  }
733 
734  mustChange = false;
735  skipEta = false;
736  }
737 }
738 
740  if (factor == 0) {
741  return 1;
742  }
743  if (factor == 1) {
744  return 0.2;
745  } else {
746  return 1 - (1 / ((double) factor));
747  }
748 }
749 
751 
752  MSLane* currentLane = nullptr;
753  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  carsIn = 0;
759  carsOut = 0;
760  inTarget = 0;
761  notTarget = 0;
762 
764 
765  // Search the incoming lane to get the count of the vehicles passed. [IN]
766  for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
767  laneVector != myLanes.end(); laneVector++) {
768  for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
769  lane++) {
770  currentLane = (*lane);
771 
772  // Map to avoid check the lane for every possible direction
773  if (laneCheck[currentLane] == false) {
774  // Get the vehicles passed from this lane.
775  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  carsIn += count;
785  // Set to true to skip similar lane since there's just one sensor
786  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  for (MSTrafficLightLogic::LinkVectorVector::const_iterator linkVector = myLinks.begin();
794  linkVector != myLinks.end(); linkVector++) {
795  for (MSTrafficLightLogic::LinkVector::const_iterator link = linkVector->begin(); link != linkVector->end();
796  link++) {
797  currentLane = (*link)->getLane();
798 
799  // Map to avoid check the lane for every possible direction
800  if (laneCheck[currentLane] == false) {
801  // Get the vehicles passed from this lane.
802  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  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  if (count != 0) {
818  toReset.push_back(currentLane->getID());
819  if (outInit) {
820  minOut = count;
821  outInit = false;
822  } else if (count <= minOut) {
823  minOut = count;
824  }
825  }
826  // Set to true to skip similar lane since there's just one sensor
827  laneCheck[currentLane] = true;
828  }
829  }
830  }
831  // Reset the map to check again all the lane on the next commit.
832  resetLaneCheck();
833 
834  // We retrieve the minimum number of cars passed from the target lanes.
835  for (LaneIdVector::const_iterator laneId = targetLanes.begin(); laneId < targetLanes.end(); laneId++) {
836  std::string lane = (*laneId);
837  tmp = sensors->getPassedVeh(lane, false);
838  inTarget += tmp;
839  if (inInit && tmp != 0) {
840  minIn = tmp;
841  inInit = false;
842  }
843  if (tmp < minIn && tmp != 0) {
844  minIn = tmp;
845  }
846  if (tmp != 0) {
847  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.
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  toSub = std::min(minIn, minOut);
862 
863  // Subtract the value to all the sensor on the target lanes.
864  while (!toReset.empty()) {
865  std::string laneId = toReset.back();
866  toReset.pop_back();
867  sensors->subtractPassedVeh(laneId, toSub);
868  }
869 
870  //Normalized to 1
871  diff = inTarget - carsOut;
872  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  if (inTarget > carsOut) {
889  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  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  phi = calculatePhi(notTarget);
903  eta = (-normalized * (1 / phi));
904  if (eta < -1.0) {
905  eta = -1.0;
906  }
907  }
908  }
909 
910  // IN = OUT
911  else if (inTarget == carsOut) {
912  // Can't say nothing
913  if (inTarget == 0) {
914  eta = 0;
915  }
916 
917  // Reinforce - Attenuate to R
918  // Normalized = 0 --> use delta = 1-1/IN
919  else {
920  delta = calculatePhi(inTarget);
921  phi = calculatePhi(notTarget);
922  eta = delta * phi;
923  if (eta > 1.0) {
924  eta = 1.0;
925  }
926  }
927  }
928 
929  // IN < OUT
930  else {
931  // Can't say nothing
932  if (inTarget == 0) {
933  eta = 0;
934  }
935 
936  // Reinforce - Attenuate to R
937  else {
938  phi = calculatePhi(notTarget);
939  diff = inTarget - carsOut;
940  normalized = diff / carsOut;
941  eta = normalized * phi;
942  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  return eta;
954 }
955 
957  MSLane* currentLane = nullptr;
958  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  carsIn = 0;
964  carsOut = 0;
965  inTarget = 0;
966  notTarget = 0;
967 
969 
970  // Search the incoming lane to get the count of the vehicles passed. [IN]
971  for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
972  laneVector != myLanes.end(); laneVector++) {
973  for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
974  lane++) {
975  currentLane = (*lane);
976 
977  // Map to avoid check the lane for every possible direction
978  if (laneCheck[currentLane] == false) {
979  // Get the vehicles passed from this lane.
980  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  carsIn += count;
990  // Set to true to skip similar lane since there's just one sensor
991  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  for (MSTrafficLightLogic::LinkVectorVector::const_iterator linkVector = myLinks.begin();
999  linkVector != myLinks.end(); linkVector++) {
1000  for (MSTrafficLightLogic::LinkVector::const_iterator link = linkVector->begin(); link != linkVector->end();
1001  link++) {
1002  currentLane = (*link)->getLane();
1003 
1004  // Map to avoid check the lane for every possible direction
1005  if (laneCheck[currentLane] == false) {
1006  // Get the vehicles passed from this lane.
1007  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  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  if (count != 0) {
1022  toReset.push_back(currentLane->getID());
1023  if (outInit) {
1024  minOut = count;
1025  outInit = false;
1026  } else if (count <= minOut) {
1027  minOut = count;
1028  }
1029  }
1030 
1031  // Set to true to skip similar lane since there's just one sensor
1032  laneCheck[currentLane] = true;
1033  }
1034  }
1035  }
1036  // Reset the map to check again all the lane on the next commit.
1037  resetLaneCheck();
1038 
1039  // We retrieve the minimum number of cars passed from the target lanes.
1040  for (LaneIdVector::const_iterator laneId = targetLanes.begin(); laneId < targetLanes.end(); laneId++) {
1041  std::string lane = (*laneId);
1042  tmp = sensors->getPassedVeh(lane, false);
1043  inTarget += tmp;
1044  if (inInit && tmp != 0) {
1045  minIn = tmp;
1046  inInit = false;
1047  }
1048  if (tmp < minIn && tmp != 0) {
1049  minIn = tmp;
1050  }
1051  if (tmp != 0) {
1052  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.
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  toSub = std::min(minIn, minOut);
1067 
1068  // Subtract the value to all the sensor on the target lanes.
1069  while (!toReset.empty()) {
1070  std::string laneId = toReset.back();
1071  toReset.pop_back();
1072  sensors->subtractPassedVeh(laneId, toSub);
1073  }
1074 
1075  //Normalized to 1
1076  if (carsOut != 0) {
1077  ratio = ((double) inTarget) / carsOut;
1078  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  if (inTarget > carsOut) {
1099  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  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  phi = calculatePhi(notTarget);
1113  eta = (-(normalized) * (1 / phi));
1114  if (eta < -1.0) {
1115  eta = -1.0;
1116  }
1117  }
1118  }
1119  // IN = OUT
1120  else if (inTarget == carsOut) {
1121  // We can't say nothing.
1122  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  delta = calculatePhi(inTarget);
1130  phi = calculatePhi(notTarget);
1131  eta = delta * phi;
1132  if (eta > 1.0) {
1133  eta = 1.0;
1134  }
1135  }
1136  }
1137  // IN < OUT
1138  else {
1139  // We can't say nothing.
1140  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  phi = calculatePhi(notTarget);
1149  eta = (normalized) * phi;
1150  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  return eta;
1162 
1163 }
1164 
1166 
1167  MSLane* currentLane = nullptr;
1168 
1169  // reset both the input and the output lanes.
1170  for (MSTrafficLightLogic::LaneVectorVector::const_iterator laneVector = myLanes.begin();
1171  laneVector != myLanes.end(); laneVector++) {
1172 
1173  for (MSTrafficLightLogic::LaneVector::const_iterator lane = laneVector->begin(); lane != laneVector->end();
1174  lane++) {
1175  currentLane = (*lane);
1176  laneCheck[currentLane] = false;
1177  }
1178  }
1179 
1180  for (MSTrafficLightLogic::LinkVectorVector::const_iterator linkVector = myLinks.begin();
1181  linkVector != myLinks.end(); linkVector++) {
1182  for (MSTrafficLightLogic::LinkVector::const_iterator link = linkVector->begin(); link != linkVector->end();
1183  link++) {
1184  currentLane = (*link)->getLane();
1185  laneCheck[currentLane] = false;
1186  }
1187  }
1188 }
1189 
1190 void MSSwarmTrafficLightLogic::choosePolicy(double phero_in, double phero_out, double dispersion_in,
1191  double dispersion_out) {
1193  for (std::vector<MSSOTLPolicy*>::iterator it = myPolicies.begin(); it != myPolicies.end(); ++it) {
1194  if (it.operator * ()->getName() == "Phase") {
1195  activate(*it);
1196  return;
1197  }
1198  }
1199  }
1200  std::vector<double> thetaStimuli;
1201  double thetaSum = 0.0;
1202  // Compute stimulus for each policy
1203  for (int i = 0; i < (int)myPolicies.size(); i++) {
1204  double stimulus = myPolicies[i]->computeDesirability(phero_in, phero_out, dispersion_in, dispersion_out);
1205  double thetaStimulus = pow(stimulus, 2) / (pow(stimulus, 2) + pow(myPolicies[i]->getThetaSensitivity(), 2));
1206 
1207  thetaStimuli.push_back(thetaStimulus);
1208  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  for (int i = 0; i < (int)myPolicies.size(); i++) {
1225  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  if (partialSum >= r) {
1234  activate(myPolicies[i]);
1235  break;
1236  }
1237  }
1238 }
1239 
1240 void MSSwarmTrafficLightLogic::choosePolicy(double phero_in, double phero_out) {
1241  choosePolicy(phero_in, phero_out, 0, 0);
1242 }
1243 
1244 //never called...
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
1253 }
1254 
1255 std::string MSSwarmTrafficLightLogic::getLaneLightState(const std::string& laneId) {
1256  std::string laneState = "";
1257  if (m_laneIndexMap.find(laneId) != m_laneIndexMap.end()) {
1258  std::string state = getCurrentPhaseDef().getState();
1259  for (std::vector<int>::const_iterator it = m_laneIndexMap[laneId].begin(); it != m_laneIndexMap[laneId].end(); ++it) {
1260  laneState += state[*it];
1261  }
1262  }
1263  return laneState;
1264 }
long long int SUMOTime
Definition: GUI.h:35
std::map< std::string, double > MSLaneId_PheromoneMap
std::pair< std::string, double > MSLaneId_Pheromone
std::vector< std::string > LaneIdVector
#define WRITE_MESSAGEF(...)
Definition: MsgHandler.h:298
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:297
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define TL(string)
Definition: MsgHandler.h:315
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_PEDESTRIAN
pedestrian
TrafficLightType
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
bool isCrossing() const
return whether this edge is a pedestrian crossing
Definition: MSEdge.h:270
bool isWalkingArea() const
return whether this edge is walking area
Definition: MSEdge.h:284
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
SVCPermissions getPermissions() const
Returns the vehicle class permissions for this lane.
Definition: MSLane.h:606
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:756
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
const std::string & getState() const
Returns the state within this phase.
const std::vector< std::string > & getTargetLaneSet() const
Class for low-level congestion policy.
void subtractPassedVeh(std::string laneId, int passed)
int getPassedVeh(std::string laneId, bool out)
A self-organizing high-level traffic light logic.
std::vector< MSSOTLPolicy * > myPolicies
void init(NLDetectorBuilder &nb)
Initialises the tls.
Class for low-level marching policy.
Class for low-level phase policy.
Class for low-level platoon policy.
This class determines the desirability algorithm of a MSSOTLPolicy when used in combination with a hi...
virtual std::string getMessage()=0
Class for a low-level policy.
Definition: MSSOTLPolicy.h:61
MSSOTLPolicyDesirability * getDesirabilityAlgorithm()
Definition: MSSOTLPolicy.h:117
virtual bool canRelease(SUMOTime elapsed, bool thresholdPassed, bool pushButtonPressed, const MSPhaseDefinition *stage, int vehicleCount)=0
virtual int decideNextPhase(SUMOTime elapsed, const MSPhaseDefinition *stage, int currentPhaseIndex, int phaseMaxCTS, bool thresholdPassed, bool pushButtonPressed, int vehicleCount)
virtual double getThetaSensitivity()
Definition: MSSOTLPolicy.h:108
std::string getName()
Definition: MSSOTLPolicy.h:114
virtual double meanVehiclesSpeed(MSLane *lane)=0
virtual double getMaxSpeed(std::string laneId)=0
virtual int countVehicles(MSLane *lane)=0
MSSOTLE2Sensors * getCountSensors()
Return the sensors that count the passage of vehicles in and out of the tl.
int countVehicles(MSPhaseDefinition phase)
int getCurrentPhaseIndex() const override
Returns the current index within the program.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const override
gets a parameter
const MSPhaseDefinition & getCurrentPhaseDef() const override
Returns the definition of the current phase.
MSLaneId_PheromoneMap pheromoneOutputLanes
This pheromone is an indicator of congestion on output lanes. Its levels refer to the average speed o...
bool mustChange
When true, indicates that the current policy MUST be changed. It's used to force the exit from the co...
bool allowLine(MSLane *)
Check if a lane is allowed to be added to the maps pheromoneInputLanes and pheromoneOutputLanes Contr...
bool gotTargetLane
When true indicates that we've already acquired the target lanes for this particular phase.
MSSwarmTrafficLightLogic(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, const Phases &phases, int step, SUMOTime delay, const Parameterised::Map &parameters)
Constructor without sensors passed.
void updatePheromoneLevels()
Update pheromone levels Pheromone on input lanes is costantly updated Pheromone follows a discrete-ti...
void choosePolicy(double phero_in, double phero_out, double dispersion_in, double dispersion_out)
void initScaleFactorDispersionIn(int lanes_in)
LaneIdVector targetLanes
A copy of the target lanes of this phase.
double getDispersionForOutputLanes(double average_phero_out)
bool skipEta
When true indicates that we can skip the evaluation of eta since we've a congestion policy that is la...
double calculateEtaDiff()
Method that should calculate the valor of eta a coefficient to evaluate the current policy's work....
std::map< std::string, CircularBuffer< double > * > m_meanSpeedHistory
double getDispersionForInputLanes(double average_phero_in)
std::map< std::string, CircularBuffer< double > * > m_derivativeHistory
void resetPheromone()
Resets pheromone levels.
MSLaneId_PheromoneMap pheromoneInputLanes
This pheronome is an indicator of congestion on input lanes. Its levels refer to the average speed of...
std::string getLaneLightState(const std::string &laneId)
void initScaleFactorDispersionOut(int lanes_out)
std::map< std::string, std::vector< int > > m_laneIndexMap
void decidePolicy()
Decide the current policy according to pheromone levels The decision reflects on currentPolicy value.
LaneCheckMap laneCheck
Map to check if a lane was already controlled during the elaboration of eta.
double calculatePhi(int factor)
Method that should calculate the valor of phi a coefficient to amplify/attenuate eta based on a facto...
void init(NLDetectorBuilder &nb)
Initialises the tls with sensors on incoming and outgoing lanes Sensors are built in the simulation a...
A class that stores and controls tls and switching of their programs.
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
LaneVectorVector myLanes
The list of LaneVectors; each vector contains the incoming lanes that belong to the same link index.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
std::vector< LinkVector > LinkVectorVector
Definition of a list that holds lists of links that do have the same attribute.
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
LinkVectorVector myLinks
The list of LinkVectors; each vector contains the links that belong to the same link index.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:154
static MsgHandler * getMessageInstance()
Returns the instance to add normal messages to.
Definition: MsgHandler.cpp:66
Builds detectors for microsim.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
std::map< std::string, std::string > Map
parameters map
Definition: Parameterised.h:45
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.cpp:94
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
Definition: StringUtils.cpp:79
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
Definition: json.hpp:4471