def get_space_time(road_length=100, car_count=20, n_iterations=50, vmax=5, p_slow=0.1, random_state=3): """Convenience Function used to generate the data for the spacetime maps, demonstrating smooth flow at low densities along with the backpropogation of traffic jams at higher densities. Parameters ---------- road_length: int length of road object instantiated by the function car_count: int number of cars on the road object n_iterations: int number of times the system is evolved vmax: int maximum speed of cars on road object p_slow: float probability of random deceleration random_state: int seed used for random number generator object """ style.use('bmh') M1 = v1.Road(L=road_length, car_count=car_count, vmax=vmax, p_slow=p_slow, random_state=random_state) data, top_speeds, avg_speeds = get_data(M1, n_iterations) fig, ax = plt.subplots() plot_space_time_map(data, ax, road_length, n_iterations) ax.xaxis.set_label_position('top') ax.set_xticks([]) ax.set_yticks([]) plt.show()
def plot_setup(): """Function used to illustrate the model using the imshow function""" # a road object is instantiated style.use('bmh') M1 = v1.Road(L=40, car_count=5, vmax=5, p_slow=0., random_state=2) # the system is then evolved 5 times data = get_data(M1, n_iterations=5, flow_rate=True) # axis and figure objects are instantiated. Note that, in order to keep the graph clean, instead of plotting a 40x5 matrix, each iteration of the road is plotted on a seperate axes. This allows greater control in terms of where verything is placed and annotated. fig, ax = plt.subplots(nrows=5, ncols=1, sharex=True, sharey=True) plt.subplots_adjust(bottom=0.3) # the data is returned in the form of a a series of lists within a list. Each nested list is the data for one iteration of the system, which contains the data in a tuple of the form (car.position, car.speed) for count, subset in enumerate(data): road = np.zeros((40)) for car in subset: # the cars are then placed on the 'road' array; note that a 'car' in this case is a tuple of form (car.position, car.speed). The value stored in the array is the speed + 1. Note that the +1 ensures that the speed is not stored as 0 so that when the imshow funciton is used to display the road, the cars with speed = 0 can still be seen road[car[0]] = car[1] + 1 ax[count].annotate(car[1], (car[0], 0), ha='center', va='center') a = ax[count].imshow(road.reshape(-1, 40), aspect='equal', cmap='Wistia') ax[0].set_yticks([]) ax[0].set_xticks([]) ax[0].set_xlabel(r'$Space \longrightarrow$', labelpad=20, fontsize=20) ax[2].set_ylabel(r'$\longleftarrow Time $', labelpad=20, fontsize=20) ax[0].xaxis.set_label_position('top') ax[0].xaxis.tick_top() plt.show()
def test_equi_time_v2(): """Function used to investigate the equilibrium time of a system. Note that the system is defined to be in equilibrium when the average speed remains unchanged for 10 iterations""" n_iterations = 100 vmax = 5 p_slow = 0. random_state = 3 road_lengths = np.arange(100, 1000, 5) densities = [0.05, 0.1, 0.2, 0.5] equi_times = pd.DataFrame(np.zeros( (road_lengths.shape[0], len(densities))), index=road_lengths, columns=densities) for density in densities: for k, length in enumerate(road_lengths): car_count = int(np.ceil(density * length)) avg_speeds = np.zeros(n_iterations) M1 = v1.Road(L=length, car_count=car_count, vmax=vmax, p_slow=p_slow, random_state=random_state) for count, i in enumerate(range(n_iterations)): data_points, avg_speed, top_speed = M1.update() avg_speeds[i] = avg_speed # the system has reached equilibrium if the average speed doesnt change within 5 iterations if i > 5: if np.array_equal(avg_speeds[i - 5:i], np.array([avg_speed for i in range(5)])): equi_time = count break equi_times.loc[length, density] = equi_time style.use('bmh') fig, ax = plt.subplots() colors = ['red', 'limegreen', 'blue', 'black'] for density, c in zip(densities, colors): sns.regplot(x=equi_times.index, y=equi_times[density], color=c, label=r'$\rho = ${}'.format(density), scatter_kws={"s": 2}, line_kws={'lw': 1}) ax.set_xlabel(r'$Road \ Length$', labelpad=10, fontsize=20) ax.set_ylabel(r'$Iterations \ to \ Equilibrium$', labelpad=10, fontsize=20) ax.set_xlim(100, 1000) ax.legend(prop={'size': 20}) plt.show()
def get_animation(road_length=100, car_count=20, vmax=5, p_slow=0.2, random_state=3): """Convenience Function used to generate an animated plot of the setup Parameters ---------- road_length: int length of road object the function instantiates car_count: int number of cars placed on road object vmax: int maximum speed of road p_slow: float probability of random deceleration random_state: int seed used for random number generator object """ M1 = v1.Road(L=road_length, car_count=car_count, vmax=vmax, p_slow=p_slow, random_state=random_state) def animate(i): """Animation function called by FuncAnimation""" # the road object is updated and the data is gathered data_points, avg_speed, top_speed = M1.update() # the data is then stored in its respective lists avg_speeds.append(avg_speed) top_speeds.append(top_speed) data.append(data_points) # the road representation is retrieved. Note that this is what is actually plotted road_rep = M1.road_rep ax[0].clear() road_plot = ax[0].scatter(x, road_rep, marker='s') ax[0].set_ylim(0.25, 1.75) ax[0].set_yticklabels([]) # the average and top speeds are then plotted on a seperate axes avg_plot = ax[1].plot(avg_speeds, c='b', lw=0.5) top_plot = ax[1].plot(top_speeds, c='r', lw=0.5) ax[1].set_ylabel('Speed') ax[1].set_xticklabels([]) ax[1].set_xlim(i - 10, i + 10) return avg_plot, top_plot, style.use('bmh') avg_speeds = [] top_speeds = [] data = [] x = np.arange(0, road_length) y = M1.road_rep fig, ax = plt.subplots(nrows=2, ncols=1) road_plot = ax[0].scatter(x, y, marker='s') ax[0].set_yticklabels([]) top_plot, = ax[1].plot(0, 0, c='r', label='Top Speed') avg_plot, = ax[1].plot(0, 0, c='b', label='Average Speed') ax[1].legend(loc='upper right') ani = FuncAnimation(fig, animate, interval=200) plt.tight_layout() plt.show()