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