pythonsimulationmodelingsimpytraffic-simulation

Create a global dictionary to keep track of iterations


I have created a train simulation in simpy, but to keep a track of the trains ahead, I plan to use a dictionary, where key values can act as 'Signal' status. The keys are basically signal numbers. The preceding trains can check if the next signal is green or vice versa. However, the code seems to be working fine for rest of the signals, but I want to check for Signal 0 and Signal 1 so that the train does not generate or does not depart.

I am not entering the entire code, as it would just make it verbose. It is just to give an idea of what I am trying to do.

Here is the sample code -

signal_dict={}

 def switchSignal(self,signal):
        if signal == 1 or signal == 0:
            signal_dict[signal]= False
            return signal_dict
        else:
            s[signal-1] = False
            return signal_dict


def switchSignal_2(self,signal):
    if signal == 1 or signal == 0:
        signal_dict[signal]= True
        return signal_dict
    else:
        signal_dict[signal-1] = True
        return signal_dict

class Train(object): 
       def __init__(self,xxxx):
       xxxxxxx
       xxxxxxx

    def engagelock(self, car, drivetime,signals): 
        with self.machine.request() as request:
            yield request  
            for signal in range(0,signals):
                switchSignal(self,signal)   
                while signal_dict.get(signal+1) is False :
                    print(f"{now():s} {self.name:s} is waiting for Signal {signal+1} to turn GREEN")
                    yield env.timeout(60)
                else:
                    if isdelay()[0] == True:
                        switchSignal(self,signal)
                        time_delay=round(delay()[0],2)
                        print(f"\n{now():s} {self.name:s} is experiencing a delay of {round((time_delay*10)/60,2)} min at Signal {signal}")
                        print(signal_dict)
                        yield env.timeout(round(time_delay*10,2))
                    switchSignal_2(self,signal)

 def process(self,k):
        here = 'London Old Oak Commons'           
        dest = 'Birmingham Interchange'
        t1=env.now
        print(f"{now():s} {self.name:s} Departed from {here:s}")
        
        drivetime=timeTo(self.accel, self.maxV, d)
        yield env.process(self.engagelock(self.name,drivetime,k))
        yield env.process(self.releaselock(self.name))
        yield env.timeout(drivetime)
        
        print(f"{now():s} {self.name:s} has arrived at {dest:s}, Travelling time {round((env.now-t1)/60,2)} mins")


for i in range(int((stop-start)/timing)):
        print(signal_dict)
        while signal_dict.get(0) is False:
            print(f"Train waiting to depart, congestion ahead!")
            yield env.timeout(60)
        else:
            t = Train(i)
            env.process(t.process(k,timing))
            yield env.timeout(timing)
                
env = simpy.Environment()
env.process(trainGenerator(start=8*3600, stop=12*3600, timing=1500))
env.run()

When I am trying to trace the global dictionary signal_dict, it seems that the train generator is unable to see the updated values in it.

Total number of Signal Blocks 6
Distance Between signalling blocks is 25.17km
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True}
08:00:00 [Train  0] Departed from London Old Oak Commons

08:00:00 [Train  0] is experiencing a delay of 3.37 min at Signal 5
{0: True, 1: True, 2: True, 3: True, 4: False}
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True}
08:05:00 [Train  1] Departed from London Old Oak Commons
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True}
08:10:00 [Train  2] Departed from London Old Oak Commons

08:10:00 [Train  2] is experiencing a delay of 14.46 min at Signal 3
{0: True, 1: True, 2: False, 3: True, 4: True}
{0: True, 1: True, 2: True, 3: True, 4: True, 5: True}

Solution

  • I got this working, instead of a doubly-linked list, I just created a Global Dictionary and kept a flag of the trains for a signal ahead and a signal behind. In this way, every train would check the next signal, if it is red, it would decelerate upto the next signal. The link to the entire project could be found here -

    https://github.com/abhiray92/train_simulation_simpy/blob/main/Simulation.ipynb