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