Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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
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()));
248std:
249 ostringstream dnp;
250 dnp << (MSNet::getInstance()->getCurrentTimeStep()) << " MSSwarmTrafficLightLogic::decideNextPhase:: " << "tlsid=" << getID() << " congestion_steps=" << congestion_steps;
251 WRITE_MESSAGE(dnp.str());
252#endif
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;
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) {
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.
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.
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
1190void 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
1240void 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
1255std::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:36
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
#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:273
bool isWalkingArea() const
return whether this edge is walking area
Definition MSEdge.h:287
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:614
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:764
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
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.
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.
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()
std::string getName()
MSSOTLPolicyDesirability * getDesirabilityAlgorithm()
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 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.
const LinkVector & getLinksAt(int i) const
Returns the list of links that are controlled by the signals at the given position.
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
static MsgHandler * getMessageInstance()
Returns the instance to add normal messages to.
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
static double rand(SumoRNG *rng=nullptr)
Returns a random real number in [0, 1)
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
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