├── 01:22 Elevator Simulation.py ├── 01:22 Game of Life.py ├── 01:24 Host Pathogen Model.py ├── 01:26 Forest Fire.py ├── 02:19 Traffic Simulation Final.ipynb ├── 02:21 Dynamics of Networks.py ├── 03:05 PageRank.py ├── 03:09 Disease Spread.py ├── 03:16 Monte Carlo Simulation Introduction 2.py ├── 03:16 Monte Carlo Simulation Introduction.py ├── 03:21 Ising Simulation.py ├── 03:22 Network Simulation.ipynb ├── 04:03 Ising Simulation II.py ├── 04:04 Random walks.py ├── 04:12 Parameter finding.py └── 04:26 Community Algorithm.ipynb /01:22 Elevator Simulation.py: -------------------------------------------------------------------------------- 1 | import random as rd 2 | import numpy as np 3 | import itertools 4 | 5 | rd.seed(1) 6 | 7 | 8 | class Passenger(): 9 | """ 10 | Passengers are initiated with a starting and ending floor and 11 | the waittime attribute is used to evaluate elevator performance. 12 | It represents total waiting and travel time. 13 | """ 14 | def __init__(self, desired_floor, starting_floor): 15 | self.desired_floor = desired_floor 16 | self.starting_floor = starting_floor 17 | self.waittime = 0 18 | 19 | 20 | 21 | class Elevator(): 22 | """ 23 | Elevators are initiated with a maximum capacity. Current and 24 | next floor are used to track elevator movement and the moving 25 | attribute determines when the elevator is stopping. 26 | The elevator keeps track of the passengers inside it, but not the 27 | global waiting list. 28 | """ 29 | def __init__(self, max_capacity): 30 | self.max_capacity = max_capacity 31 | self.current_capacity = 0 32 | 33 | self.current_floor = 0 34 | self.next_floor = 0 35 | 36 | self.moving = False # True == moving 37 | self.passenger_list = [] 38 | 39 | 40 | 41 | def get_next_floor(self, passenger_list): 42 | """ 43 | Assigns as the next floor the first passenger's 44 | desired floor. 45 | """ 46 | self.next_floor = passenger_list[0].desired_floor 47 | 48 | def get_next_passenger(self, waiting_list): 49 | """ 50 | Sets elevators next floor to a waiting passenger's 51 | starting floor when passenger list is empty. 52 | """ 53 | self.next_floor = waiting_list[0].starting_floor 54 | 55 | def move(self): 56 | """ 57 | Moves the elevator closer to the desired floor of the 58 | first passenger. Once it reaches that floor, self.moving 59 | is set to False. This is for time tracking and unloading. 60 | """ 61 | if self.next_floor > self.current_floor: 62 | self.current_floor += 1 63 | elif self.next_floor < self.current_floor: 64 | self.current_floor -= 1 65 | else: 66 | self.moving = False 67 | 68 | 69 | class Building(): 70 | """ 71 | Buildings are initiated with a number of floors. They keep track 72 | of the global waitlist and the total runtime, passed from passengers 73 | who have finished their journey (self.finished_passengers). 74 | """ 75 | def __init__(self, floors): 76 | self.floors = floors 77 | self.waiting_list = [] 78 | self.finished_passengers = [] 79 | self.total_runtime = 0 80 | 81 | 82 | def spawn_passengers(self, num_of_passengers): 83 | """ 84 | Creates passengers with random starting and desired floors, 85 | ensuring that those are not the same. Appends them to the 86 | global waiting list and finishes by sorting the waiting list. 87 | """ 88 | for _ in range(num_of_passengers): 89 | starting = rd.randint(0, self.floors) 90 | desired = rd.choice([x for x in range(self.floors) if x != starting]) 91 | 92 | self.waiting_list.append(Passenger(starting, desired)) 93 | self.waiting_list = sorted(self.waiting_list, key=lambda x: x.starting_floor) 94 | 95 | 96 | def unload_elevator(self, elevator, waiting_list_on_current_floor): 97 | """ 98 | Drops of passengers on their desired floor by adding them to the 99 | finished_passenger list and picks up new, waiting passengers. 100 | Sets moving back to True. 101 | Ensures that the maximum capacity is not surpassed. 102 | """ 103 | #p is used to represent passengers in all code 104 | for i, p in enumerate(elevator.passenger_list): 105 | if p.desired_floor == elevator.current_floor: 106 | self.finished_passengers.append(elevator.passenger_list.pop(i)) 107 | elevator.current_capacity -= 1 108 | 109 | entered_elevator = [] 110 | for p in waiting_list_on_current_floor: 111 | if elevator.current_capacity < elevator.max_capacity: 112 | elevator.passenger_list.append(p) 113 | entered_elevator.append(p) 114 | elevator.current_capacity += 1 115 | 116 | self.waiting_list = [p for p in self.waiting_list if p not in entered_elevator] 117 | self.moving = True 118 | 119 | 120 | def update_time(self, elevator, time): 121 | """ 122 | Updates each unfinished person's time counter by a set time. 123 | """ 124 | for p in itertools.chain(self.waiting_list, elevator.passenger_list): 125 | p.waittime += time 126 | 127 | 128 | 129 | def run_elevator_simulation(self, sim_size, capacity, walking = False): 130 | """ 131 | META FUNCTION 132 | This function performs the full elevator run. If walking 133 | is set to True, passengers with less than or equal to 4 floors to go will 134 | take the stairs instead of the elevator. 135 | 136 | It spawns passengers and performs elevator movements. Moving 1 floor is 137 | the base unit of time and takes 1. Stopping takes 3 and walking 138 | stairs also takes 3 units of time. 139 | """ 140 | elevator = Elevator(capacity) 141 | self.spawn_passengers(sim_size) 142 | 143 | if walking == True: 144 | # people take 3x as long to walk, as the elevator takes 145 | # to move a single floor. 146 | for i, p in enumerate(self.waiting_list): 147 | distance = abs(p.desired_floor - p.starting_floor) 148 | if distance <= 4: 149 | p.waittime = distance * 3 150 | self.finished_passengers.append(self.waiting_list.pop(i)) 151 | 152 | 153 | while len(self.waiting_list) != 0 or len(elevator.passenger_list) != 0: 154 | #uncomment print statements below to track elevator movement 155 | # print("# of waiting: ", len(self.waiting_list)) 156 | # print("# of passengers: ", len(elevator.passenger_list)) 157 | # print("# of finished: ", len(self.finished_passengers)) 158 | # print("I'm on floor %d." %elevator.current_floor) 159 | # print("-------------------") 160 | # for p in self.waiting_list: 161 | # print (p.starting_floor, p.desired_floor) 162 | 163 | 164 | if elevator.moving == False: 165 | # time steps are added whenever the elevator stops to unload 166 | # big elevators take longer 167 | if elevator.max_capacity >= 15: 168 | self.update_time(elevator, 5) 169 | else: 170 | self.update_time(elevator, 3) 171 | # determines who's waiting on the current floor & adds them 172 | # to the elevator/drops off current passengers 173 | waiting_list_on_current_floor = [p for p in self.waiting_list 174 | if p.starting_floor == elevator.current_floor] 175 | self.unload_elevator(elevator, waiting_list_on_current_floor) 176 | # print("Currently holding %d passengers." %elevator.current_capacity) 177 | 178 | 179 | if len(elevator.passenger_list) == 0 and len(self.waiting_list) != 0: 180 | # if there's no more passengers in the elevator, pick up new ones 181 | # move elevator 1 floor 182 | elevator.get_next_passenger(self.waiting_list) 183 | elevator.move() 184 | self.update_time(elevator, 1) 185 | 186 | if len(elevator.passenger_list) != 0: 187 | elevator.get_next_floor(elevator.passenger_list) 188 | elevator.move() 189 | self.update_time(elevator, 1) 190 | 191 | 192 | # print ("I have moved all passengers!") 193 | for p in self.finished_passengers: 194 | self.total_runtime += p.waittime 195 | 196 | # print ("Average runtime is %d units." %(self.total_runtime/sim_size)) 197 | return (self.total_runtime/sim_size) 198 | 199 | 200 | def reset_simulation(self): 201 | """ 202 | Clear runtime variables. 203 | """ 204 | self.finished_passengers = [] 205 | self.total_runtime = 0 206 | 207 | 208 | Judy_the_House = Building(20) 209 | Judy_the_House.run_elevator_simulation(180, 7) 210 | Judy_the_House.reset_simulation() -------------------------------------------------------------------------------- /01:22 Game of Life.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib 3 | matplotlib.use("TkAgg") 4 | from matplotlib import pyplot as plt 5 | import pylab as pl 6 | 7 | n = 100 # size of space: n x n 8 | 9 | def p_param(val = 0.1): 10 | global p 11 | 12 | p = float(val) 13 | return p 14 | 15 | def initialize(): 16 | global config, nextconfig, density 17 | density = [] 18 | config = pl.zeros([n, n]) 19 | for x in range(n): 20 | for y in range(n): 21 | config[x, y] = 1 if pl.random() < p else 0 22 | nextconfig = pl.zeros([n, n]) 23 | 24 | def observe(): 25 | global config, nextconfig 26 | pl.cla() 27 | pl.subplot(1,2,1) 28 | pl.imshow(config, vmin = 0, vmax = 1, cmap = pl.cm.binary) 29 | pl.subplot(1,2,2) 30 | pl.plot(density) 31 | 32 | #Game of Life 33 | def update(): 34 | global config, nextconfig, density 35 | for x in range(n): 36 | for y in range(n): 37 | count = 0 38 | for dx in [-1, 0, 1]: 39 | for dy in [-1, 0, 1]: 40 | count += config[(x + dx) % n, (y + dy) % n] 41 | if config[x, y] == 0: 42 | nextconfig[x, y] = 1 if count == 3 else 0 43 | if config[x, y] == 1: 44 | nextconfig[x, y] = 1 if (count == 3) or (count == 2) else 0 45 | density.append(np.mean(config.ravel())) 46 | config, nextconfig = nextconfig, config 47 | 48 | # #Panic simulation 49 | # def update(): 50 | # global config, nextconfig, density 51 | # for x in range(n): 52 | # for y in range(n): 53 | # count = 0 54 | # for dx in [-1, 0, 1]: 55 | # for dy in [-1, 0, 1]: 56 | # count += config[(x + dx) % n, (y + dy) % n] 57 | # nextconfig[x, y] = 1 if count >= 4 else 0 58 | # density.append(np.mean(config.ravel())) 59 | # config, nextconfig = nextconfig, config 60 | 61 | 62 | import pycxsimulator 63 | pycxsimulator.GUI(parameterSetters=[p_param]).start(func=[initialize, observe, update]) -------------------------------------------------------------------------------- /01:24 Host Pathogen Model.py: -------------------------------------------------------------------------------- 1 | # Simple CA simulator in Python 2 | # 3 | # *** Hosts & Pathogens *** 4 | # 5 | # Copyright 2008-2012 Hiroki Sayama 6 | # sayama@binghamton.edu 7 | 8 | # Modified to run with Python 3 9 | 10 | import matplotlib 11 | matplotlib.use('TkAgg') 12 | 13 | import pylab as PL 14 | import random as RD 15 | import scipy as SP 16 | import numpy as NP 17 | 18 | RD.seed() 19 | 20 | width = 50 21 | height = 50 22 | sim_size = width * height 23 | 24 | def param_init(P_init = 0.01): 25 | global initProb 26 | initProb = float(P_init) 27 | return initProb 28 | 29 | def param_infection(R_inf = 0.85): 30 | global infectionRate 31 | infectionRate = float(R_inf) 32 | return infectionRate 33 | 34 | def param_growth(R_growth = 0.15): 35 | global regrowthRate 36 | regrowthRate = float(R_growth) 37 | return regrowthRate 38 | 39 | def init(): 40 | global time, config, nextConfig, healthy_density, sick_density 41 | healthy_density, sick_density = [], [] 42 | time = 0 43 | 44 | config = SP.zeros([height, width]) 45 | for x in range(width): 46 | for y in range(height): 47 | if RD.random() < initProb: 48 | state = 2 49 | else: 50 | state = 1 51 | config[y, x] = state 52 | 53 | nextConfig = SP.zeros([height, width]) 54 | 55 | def draw(): 56 | PL.cla() 57 | PL.subplot(1,2,1) 58 | PL.pcolor(config, vmin = 0, vmax = 2, cmap = PL.cm.jet) 59 | PL.axis('image') 60 | PL.title('t = ' + str(time)) 61 | PL.subplot(1,2,2) 62 | PL.plot(healthy_density, 'g-', sick_density, 'r-') 63 | 64 | 65 | def step(): 66 | ''' 67 | 0 represents dead (blue) 68 | 1 represents alive (green) 69 | 2 represents infected (red) 70 | ''' 71 | global time, config, nextConfig 72 | 73 | time += 1 74 | 75 | for x in range(width): 76 | for y in range(height): 77 | state = config[y, x] 78 | if state == 0: 79 | for dx in range(-1, 2): 80 | for dy in range(-1, 2): 81 | if config[(y+dy)%height, (x+dx)%width] == 1: 82 | if RD.random() < regrowthRate: 83 | state = 1 84 | elif state == 1: 85 | for dx in range(-1, 2): 86 | for dy in range(-1, 2): 87 | if config[(y+dy)%height, (x+dx)%width] == 2: 88 | if RD.random() < infectionRate: 89 | state = 2 90 | else: 91 | state = 0 92 | 93 | nextConfig[y, x] = state 94 | healthy_individuals = NP.count_nonzero(config.ravel() == 1) 95 | sick_individuals = NP.count_nonzero(config.ravel() == 2) 96 | healthy_density.append(healthy_individuals/sim_size) 97 | sick_density.append(sick_individuals/sim_size) 98 | 99 | config, nextConfig = nextConfig, config 100 | 101 | import pycxsimulator 102 | pycxsimulator.GUI(parameterSetters=[param_init, param_infection, param_growth]).start(func=[init,draw,step]) 103 | 104 | def f(x): 105 | return 28*x**9 - 224*x**8 + 700*x**7 - 1120*x**6 + 980*x**5 - 448*x**4 + 84*x**3 106 | 107 | x = NP.linspace(0,1, 100) 108 | y = [f(x) for x in x] 109 | PL.plot(x, y, 'b-', x, x, 'r-') 110 | PL.show() 111 | -------------------------------------------------------------------------------- /01:26 Forest Fire.py: -------------------------------------------------------------------------------- 1 | # Simple CA simulator in Python 2 | # 3 | # *** Forest fire *** 4 | # 5 | # Copyright 2008-2012 Hiroki Sayama 6 | # sayama@binghamton.edu 7 | 8 | # Modified to run with Python 3 9 | 10 | import matplotlib 11 | matplotlib.use('TkAgg') 12 | 13 | import pylab as PL 14 | import random as RD 15 | import scipy as SP 16 | import numpy as NP 17 | from matplotlib.pyplot import cm 18 | 19 | RD.seed() 20 | 21 | width = 100 22 | height = 100 23 | initProb_default = 0.4 24 | empty, tree, fire, char = range(4) 25 | 26 | def param_init(tree_prob = initProb_default): 27 | global initProb 28 | initProb = float(tree_prob) 29 | return initProb 30 | 31 | def init(): 32 | global time, config, nextConfig, burnt_area 33 | 34 | time = 0 35 | burnt_area = [] 36 | 37 | config = SP.zeros([height, width]) 38 | for x in range(width): 39 | for y in range(height): 40 | if RD.random() < initProb: 41 | state = tree 42 | else: 43 | state = empty 44 | config[y, x] = state 45 | config[height//2, width//2] = fire 46 | 47 | nextConfig = SP.zeros([height, width]) 48 | 49 | def draw(): 50 | PL.cla() 51 | PL.subplot(1,2,1) 52 | PL.pcolor(config, vmin = 0, vmax = 3, cmap = PL.cm.binary) 53 | PL.axis('image') 54 | PL.title('t = ' + str(time)) 55 | PL.subplot(1,2,2) 56 | PL.ylim(0,1) 57 | PL.plot(burnt_area, 'b-') 58 | 59 | def step(): 60 | global time, config, nextConfig 61 | 62 | time += 1 63 | 64 | for x in range(width): 65 | for y in range(height): 66 | state = config[y, x] 67 | if state == fire: 68 | state = char 69 | elif state == tree: 70 | for dx in range(-1, 2): 71 | for dy in range(-1, 2): 72 | if config[(y+dy)%height, (x+dx)%width] == fire: 73 | state = fire 74 | nextConfig[y, x] = state 75 | burnt = NP.count_nonzero(config.ravel() == 3) 76 | alive = NP.count_nonzero(config.ravel() == 1) 77 | burnt_area.append( burnt/(burnt + alive)) 78 | 79 | config, nextConfig = nextConfig, config 80 | 81 | # import pycxsimulator 82 | # pycxsimulator.GUI(parameterSetters=[param_init]).start(func=[init,draw,step]) 83 | 84 | def f(x): 85 | return x**4 + 4*x**3*(1-x) + 4*x**2*(1-x)**2 86 | 87 | # x = NP.linspace(0,1, 100) 88 | # y = [f(x) for x in x] 89 | # PL.plot(x, y, 'b-', x, x, 'r-') 90 | # PL.show() 91 | 92 | runs = 10 93 | time_steps = 200 94 | probabilites = [0.3, 0.38, 0.4, 0.42, 0.5] 95 | total_burnt_area = NP.zeros((runs, len(probabilites), time_steps)) 96 | 97 | for r in range(runs): 98 | print("RUN:", r) 99 | j = 0 100 | for prob in probabilites: 101 | global initProb 102 | initProb = prob 103 | init() 104 | for i in range(time_steps): 105 | step() 106 | 107 | print (NP.shape(burnt_area)) 108 | print (NP.shape(total_burnt_area)) 109 | total_burnt_area[r, j, :] = burnt_area 110 | j+=1 111 | 112 | mean_burnt_area = NP.mean(total_burnt_area, axis=0) 113 | print (NP.shape(mean_burnt_area)) 114 | 115 | x = range(0,time_steps) 116 | color = cm.rainbow(NP.linspace(0,1, len(probabilites))) 117 | 118 | for y, col in zip(range(0, len(probabilites)), color): 119 | PL.plot(x, mean_burnt_area[y,:], c = col) 120 | 121 | PL.xlabel("Time") 122 | PL.ylabel("Fraction of forest burnt") 123 | PL.legend(['Initial density = 0.3','Initial density = 0.38', 124 | 'Initial density = 0.4','Initial density = 0.42', 125 | 'Initial density = 0.5']) 126 | PL.show() 127 | -------------------------------------------------------------------------------- /02:19 Traffic Simulation Final.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "

Traffic Simulation\n", 8 | "\n", 9 | "
Michelle Hackl\n", 10 | "
CS166 - Prof. Sheffler\n", 11 | "\n", 12 | "-----------" 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "### Part 1 - Traffic Jams on a Circular Road\n", 20 | "Implement the single lane, variable speed traffic model described in Nagel, K.,\n", 21 | "Schreckenberg, M. (1992).\n", 22 | "- Write well-structured and well-documented Python code to implement the model described in the paper.\n", 23 | "- Visualize the state of this model over time, to show how traffic jams can appear when traffic density is high enough.\n", 24 | "- Analyze how the overall average traffic flow rate varies with traffic density and present your results in your report." 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "### Part 2 - Multi-lane Highways\n", 32 | "Implement the 2-lane, symmetric, uni-directional, variable speed model in Rickert, M., et al. (1996).\n", 33 | "\n", 34 | "- A description, in your report, of how this model works. What are the assumptions, parameters, and update rules of the model? Do not just copy and paste from the paper. Explain the cellular automaton in your own words and as clearly as possible.\n", 35 | "- Write well-structured and well-documented Python code to implement the model described in the paper.\n", 36 | "- Visualize the state of this model over time, to show the typical traffic patterns that can emerge. Your results will again depend on traffic density.\n", 37 | "- Analyze how much more traffic can flow through a multi-lane road, compare to a single lane road, at the same traffic density. Present your results in your report." 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "### Part 3 - General Discussion\n", 45 | "- How much more traffic can flow through a 2-lane road compared to a 1-lane road at the same traffic density? What about roads with more than 2 lanes? Either model 3 or more lanes and report on your results, or predict how much larger the traffic flow through a 3+ lane road will be compared to a 1-lane road at the same traffic density.\n", 46 | "- How applicable is this model to traffic in your city? Write a short paragraph and motivate why the model is suited to traffic in your city (or why it is not)." 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 2, 52 | "metadata": { 53 | "collapsed": true 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "#general reference made to this code:\n", 58 | "#https://gist.github.com/xmichaelx/2a3b45ba589296da73ef\n", 59 | "\n", 60 | "import numpy as np \n", 61 | "import pylab as pl\n", 62 | "import random as rd\n", 63 | "import copy\n", 64 | "\n", 65 | "class TrafficSimulation():\n", 66 | " \"\"\"N-lane traffic simulation based on Rickert et al. (1996)\n", 67 | " and the original Nagel & Schreckenberg (1992) model.\n", 68 | " \"\"\"\n", 69 | " def __init__(self, len_road = 100, density = 0.01, max_vel = 5, \n", 70 | " prob_slowing = 0.5, prob_lane_change = 0.8, lanes = 1):\n", 71 | " self.len_road = len_road\n", 72 | " self.density = density\n", 73 | " self.max_vel = max_vel\n", 74 | " self.prob_slowing = prob_slowing\n", 75 | " self.prob_lane_change = prob_lane_change\n", 76 | " self.lanes = lanes\n", 77 | "\n", 78 | " self.car_counter = 0\n", 79 | " self.flow_counter = 0\n", 80 | " self.time_counter = 0\n", 81 | "\n", 82 | " self.config = []\n", 83 | " self.next_config = []\n", 84 | "\n", 85 | "\n", 86 | " def initialize(self):\n", 87 | " \"\"\"\n", 88 | " Sets up the initial state based on density & length and\n", 89 | " initiates the global car count.\n", 90 | " \"\"\"\n", 91 | " for _ in range(self.lanes):\n", 92 | " self.config.append(pl.zeros([self.len_road], dtype=int))\n", 93 | " self.next_config.append(pl.zeros([self.len_road], dtype=int))\n", 94 | "\n", 95 | " for lane in self.config:\n", 96 | " lane.fill(-1)\n", 97 | " for lane in self.next_config:\n", 98 | " lane.fill(-1)\n", 99 | "\n", 100 | " for state in self.config:\n", 101 | " indexes = np.random.choice(range(0, self.len_road),\n", 102 | " size = int(self.density * self.len_road),\n", 103 | " replace = False)\n", 104 | " state[indexes] = self.max_vel\n", 105 | "\n", 106 | " self.car_counter = self.count_cars()\n", 107 | "\n", 108 | "\n", 109 | " def lane_change(self):\n", 110 | " \"\"\"\n", 111 | " Checks for lane changes and moves cars between lanes.\n", 112 | " Rules:\n", 113 | " IF v > gap\n", 114 | " AND v_o + 1 are empty AND empty behind >= vmax\n", 115 | " AND IF rd.rand < probability of switching\n", 116 | " THEN switch.\n", 117 | " \"\"\"\n", 118 | " for lane_index, lane in enumerate(self.config):\n", 119 | " for spot in range(self.len_road):\n", 120 | " if lane[spot] != -1: #if car\n", 121 | " switch = False #if car will switch lane\n", 122 | " vel = lane[spot]\n", 123 | "\n", 124 | " gap = 0 #rule 1 - check ahead \n", 125 | " looked_ahead = 0\n", 126 | "\n", 127 | " while looked_ahead <= (self.max_vel):\n", 128 | " if lane[(spot + gap + 1) % self.len_road] < 0:\n", 129 | " gap += 1\n", 130 | " else:\n", 131 | " break\n", 132 | " looked_ahead += 1\n", 133 | "\n", 134 | " if gap < vel: #rule 1 - if no space ahead, switch\n", 135 | " switch = True\n", 136 | "\n", 137 | " #rule 2 - define neighbors\n", 138 | " right_neighbor = self.config[(lane_index + 1) % self.lanes]\n", 139 | " left_neighbor = self.config[(lane_index - 1) % self.lanes]\n", 140 | "\n", 141 | " if switch: #rule 2 - if planning on switching\n", 142 | " switch_right = False \n", 143 | " switch_left = False\n", 144 | " #rule 2 - check for free lanes\n", 145 | " if self.neighbor_free(right_neighbor, spot, vel):\n", 146 | " switch_right = True\n", 147 | " if self.neighbor_free(left_neighbor, spot, vel):\n", 148 | " switch_left = True\n", 149 | "\n", 150 | " #rule 3 - if less than random switching \n", 151 | " #probability, switch lanes\n", 152 | " if rd.random() < self.prob_lane_change:\n", 153 | " self.switch_lanes(lane_index, spot, vel, switch_right, switch_left)\n", 154 | " else:\n", 155 | " self.next_config[lane_index][spot] = vel\n", 156 | "\n", 157 | " #if we're not switching the car, then we\n", 158 | " else: #have to write it back into it's own lane\n", 159 | " self.next_config[lane_index][spot] = vel\n", 160 | "\n", 161 | " # self.state_difference() \n", 162 | " self.config = copy.deepcopy(self.next_config) #update config and resetnext_config state\n", 163 | " for lane in self.next_config: \n", 164 | " lane.fill(-1)\n", 165 | "\n", 166 | "\n", 167 | " def neighbor_free(self, neighbor, cur_spot, vel):\n", 168 | " \"\"\"\n", 169 | " Takes in a lane, neighboring lane, current spot of the car\n", 170 | " and it's velocity and checks if the neighboring lane has\n", 171 | " enough space for the car. Returns True if so, else False.\n", 172 | " \"\"\"\n", 173 | " free = True\n", 174 | "\n", 175 | " gap = 0 \n", 176 | " check_back = -1 * self.max_vel #distance to check in the back and front\n", 177 | " check_front = vel\n", 178 | "\n", 179 | " for index in range(check_back, check_front + 1):\n", 180 | " if neighbor[(cur_spot + index) % self.len_road] < 0:\n", 181 | " pass\n", 182 | " else:\n", 183 | " free = False\n", 184 | " break\n", 185 | "\n", 186 | " return free\n", 187 | "\n", 188 | "\n", 189 | " def switch_lanes(self, lane_index, spot, vel, right, left):\n", 190 | " \"\"\"\n", 191 | " Determines if cars will be switched to the right or\n", 192 | " left lane and updates the next_config state.\n", 193 | " Because I am updating into the next_config state, some-\n", 194 | " times cars want to switch into the same spot from two sides.\n", 195 | " Here, earlier update cars (left lane) get priority over \n", 196 | " those from the right lane.\n", 197 | " \"\"\"\n", 198 | " #checking free slots in the config\n", 199 | " #and the next_config lanes.\n", 200 | " if self.next_config[(lane_index + 1) % self.lanes][spot] == -1:\n", 201 | " right_taken = False\n", 202 | " else: right_taken = True \n", 203 | "\n", 204 | " if self.next_config[(lane_index - 1) % self.lanes][spot] == -1:\n", 205 | " left_taken = False\n", 206 | " else: left_taken = True\n", 207 | " #if both lanes free, pick randomly\n", 208 | " if (right and left) and not right_taken and not left_taken: \n", 209 | " if rd.random() < 0.5:\n", 210 | " self.next_config[(lane_index + 1) % self.lanes][spot] = vel\n", 211 | " else:\n", 212 | " self.next_config[(lane_index - 1) % self.lanes][spot] = vel\n", 213 | " \n", 214 | " elif right and not right_taken: #else, pick right or left as free\n", 215 | " self.next_config[(lane_index + 1) % self.lanes][spot] = vel\n", 216 | " elif left and not left_taken:\n", 217 | " self.next_config[(lane_index - 1) % self.lanes][spot] = vel\n", 218 | "\n", 219 | " else: #if neither, keep car in lane\n", 220 | " self.next_config[lane_index][spot] = vel \n", 221 | "\n", 222 | "\n", 223 | " def update_speed(self):\n", 224 | " \"\"\"\n", 225 | " Iterates over array and updates all cars' speeds.\n", 226 | " Rules: \n", 227 | " IF v != vmax THEN v+=1\n", 228 | " IF v > gap THEN v=gap\n", 229 | " IF V>0 AND rand

gap: #rule 2 - reduce speed to gap\n", 251 | " vel = max(gap, 0)\n", 252 | "\n", 253 | " #rule 3 - randomness\n", 254 | " vel = max(vel - 1, 0) if rd.random() < self.prob_slowing else vel \n", 255 | "\n", 256 | " lane[spot] = vel #update speeds\n", 257 | "\n", 258 | "\n", 259 | " def move_cars(self):\n", 260 | " \"\"\"\n", 261 | " Moves cars forward and updates the config states.\n", 262 | " Creates a deep copy of the next_config state and \n", 263 | " then clears it after moving all cars.\n", 264 | " \"\"\"\n", 265 | " for lane, next_lane in zip(self.config, self.next_config):\n", 266 | " for spot in range(0, self.len_road):\n", 267 | " if lane[spot] != -1: #if car\n", 268 | " distance = lane[spot]\n", 269 | "\n", 270 | " next_lane[int(spot + distance) % self.len_road] = lane[spot]\n", 271 | "\n", 272 | " self.config = copy.deepcopy(self.next_config)\n", 273 | " for lane in self.next_config:\n", 274 | " lane.fill(-1)\n", 275 | "\n", 276 | "\n", 277 | " def count_flow(self):\n", 278 | " \"\"\"\n", 279 | " Counts the number of cars that will leave the simulation \n", 280 | " in the following step and updates the time counter.\n", 281 | " \"\"\"\n", 282 | " for lane in self.config:\n", 283 | " for k in range(-1 * self.max_vel, 0): #check last max_vel slots\n", 284 | " if lane[k] >= abs(k): #count if car will move outside lane\n", 285 | " self.flow_counter += 1\n", 286 | "\n", 287 | " self.time_counter += 1 #add one time step\n", 288 | "\n", 289 | "\n", 290 | " def count_cars(self):\n", 291 | " \"\"\"\n", 292 | " Counts the number of cars in the simulation to make\n", 293 | " sure I am not loosing any to a separate dimension \n", 294 | " along the way...\n", 295 | " \"\"\"\n", 296 | " car_num = 0\n", 297 | " for lane in self.config:\n", 298 | " car_num += sum([1 if spot != -1 else 0 for spot in lane]) \n", 299 | "\n", 300 | " return car_num\n", 301 | "\n", 302 | "\n", 303 | " def display(self, message = None):\n", 304 | " \"\"\"\n", 305 | " Visualizes the self.config states as a string printout.\n", 306 | " \"\"\"\n", 307 | " if message:\n", 308 | " print(message) #for debugging\n", 309 | "\n", 310 | " for lane in self.config:\n", 311 | " string = ''.join(['.' if x == -1 else str(x) for x in lane])\n", 312 | " print(string)\n", 313 | "\n", 314 | "\n", 315 | " def state_difference(self):\n", 316 | " \"\"\"\n", 317 | " Function to aid debugging (shows where changes have)\n", 318 | " ocurred between states. Use before updating next_config.\n", 319 | " \"\"\"\n", 320 | " state_dif = np.isclose(self.config, self.next_config)\n", 321 | " for lane in state_dif:\n", 322 | " string = ''.join(['.' if x == True else \"X\" for x in lane])\n", 323 | " print (string)\n", 324 | "\n", 325 | "\n", 326 | " def run(self, runs = 10, display = False):\n", 327 | " \"\"\" Runs simulation r times. \"\"\"\n", 328 | " for r in range(runs):\n", 329 | " self.simulate(display = display)\n", 330 | "\n", 331 | "\n", 332 | " def simulate(self, display = True):\n", 333 | " \"\"\"\n", 334 | " Updates the simulation by a single step. Checks for lane changes,\n", 335 | " then updates all car speeds and finally moves cars after\n", 336 | " displaying the state (if display == True).\n", 337 | " \"\"\"\n", 338 | " self.lane_change()\n", 339 | " self.update_speed()\n", 340 | "\n", 341 | " if display: #show speeds before updating!\n", 342 | " self.display()\n", 343 | "\n", 344 | " self.count_flow() #collect metrics before moving cars\n", 345 | "\n", 346 | " self.move_cars() \n", 347 | "\n", 348 | " if self.count_cars() != self.car_counter:\n", 349 | " print(\"We lost some cars during the run!\")\n" 350 | ] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "execution_count": null, 355 | "metadata": {}, 356 | "outputs": [], 357 | "source": [ 358 | "#-------------------------------------------\n", 359 | "# TESTING\n", 360 | "#-------------------------------------------\n", 361 | "\n", 362 | "CountryRoad = TrafficSimulation(len_road = 80, density = 0.15, max_vel = 5,\n", 363 | " prob_slowing = 0.5, prob_lane_change = 0.8, lanes = 1)\n", 364 | "CountryRoad.initialize()\n", 365 | "CountryRoad.run(5, display=True)\n" 366 | ] 367 | }, 368 | { 369 | "cell_type": "code", 370 | "execution_count": 137, 371 | "metadata": {}, 372 | "outputs": [], 373 | "source": [ 374 | "#-------------------------------------------\n", 375 | "# PLOTTING FUNCTION\n", 376 | "#-------------------------------------------\n", 377 | "import sys\n", 378 | "\n", 379 | "def display_flow_graph(len_road = 300, prob_slowing = 0.5, prob_lane_change = 0.8, lanes = [1],\n", 380 | " runs = 5, densities = np.linspace(0.05, 0.3, 20), col = ['k'], steps = 500,\n", 381 | " display_runs = True, display_avgline = False, display_CI = False):\n", 382 | " \"\"\"\n", 383 | " Generates the traffic flow graph as described by Rickert et al. (1996).\n", 384 | " Lanes need to be passed as a list of desired lengths to simulate and plot.\n", 385 | " Colors are passed to match the number of lanes to simulate.\n", 386 | " \n", 387 | " Optional arguments:\n", 388 | " display_runs = plot individual runs as single dots\n", 389 | " display_avgline = average over all runs and plot the resulting line\n", 390 | " display_CI = calculate 95% confidence intervals and display on the graph\n", 391 | " \n", 392 | " The function returns the axis object. This allows for titles or optional\n", 393 | " arguments to be added after running the function without loosing the plot.\n", 394 | " \"\"\"\n", 395 | " #instantiate plotting\n", 396 | " fig = pl.figure()\n", 397 | " ax = fig.add_subplot(111)\n", 398 | " \n", 399 | " if len(lanes) != len(col):\n", 400 | " print (\"Please provide more colors!\")\n", 401 | " return\n", 402 | " \n", 403 | " # to track completion of the simulation, counts\n", 404 | " # total number of simulation steps for plotting\n", 405 | " total_runs = (runs * steps * len(densities) * len(lanes)) # +\n", 406 | " #display_avgline * line_runs * len(densities) * len(lanes))\n", 407 | " finished_runs = 0\n", 408 | " \n", 409 | " for index, lane in enumerate(lanes):\n", 410 | "\n", 411 | " flow_total = np.zeros((runs, len(densities)))\n", 412 | " flow_total_line = np.zeros((len(densities)))\n", 413 | " \n", 414 | " #running trials and collecting average flow rate over x runs\n", 415 | " for r in range(runs):\n", 416 | " j = 0\n", 417 | " for rho in densities:\n", 418 | " Sim = TrafficSimulation(len_road = len_road, prob_slowing = prob_slowing,\n", 419 | " prob_lane_change = prob_lane_change, lanes = lane)\n", 420 | " Sim.density = rho\n", 421 | " Sim.initialize()\n", 422 | "\n", 423 | " Sim.run(steps)\n", 424 | " finished_runs += steps\n", 425 | " \n", 426 | " #displays completion percentage as an updating single-line print\n", 427 | " sys.stdout.write(\"\\r\" + str(\"Completed: {0:.1f}%\".format(float(finished_runs)/total_runs*100)))\n", 428 | " sys.stdout.flush()\n", 429 | "\n", 430 | " flow_total[r,j] = float(Sim.flow_counter) / float(Sim.time_counter)\n", 431 | " j += 1\n", 432 | "\n", 433 | " #show individuals points on the plot for each run\n", 434 | " if display_runs:\n", 435 | " for q in range(0, runs):\n", 436 | " ax.scatter(densities, flow_total[q,:], s=6, c=col[index], marker='o', alpha=0.4)\n", 437 | " \n", 438 | " #display averaged line over all runs\n", 439 | " if display_avgline:\n", 440 | " flow_total_line = np.mean(flow_total, axis=0)\n", 441 | " ax.plot(densities, flow_total_line, c=col[index], label=\"{0:.0f}-lane road\".format(lane))\n", 442 | " \n", 443 | " if display_CI:\n", 444 | " #getting descriptive stats to plot confidence intervals\n", 445 | " flow_mean = np.mean(flow_total, axis=0)\n", 446 | " flow_stdev = np.std(flow_total, axis=0)\n", 447 | " flow_upper_bound = [flow_mean[i] + 1.96*flow_stdev[i] for i in range(len(densities))]\n", 448 | " flow_lower_bound = [flow_mean[i] - 1.96*flow_stdev[i] for i in range(len(densities))]\n", 449 | " #plotting CIs\n", 450 | " ax.plot(densities, flow_upper_bound, c=col[index], alpha=0.3)\n", 451 | " ax.plot(densities, flow_lower_bound, c=col[index], alpha=0.3)\n", 452 | " \n", 453 | " ax.legend()\n", 454 | " ax.set_xlabel(\"Density\")\n", 455 | " ax.set_ylabel(\"Flow\")\n", 456 | " \n", 457 | " return ax" 458 | ] 459 | }, 460 | { 461 | "cell_type": "markdown", 462 | "metadata": {}, 463 | "source": [ 464 | "---\n", 465 | "### Part 1 - Traffic Jams on a Circular Road\n", 466 | "** Parameters **\n", 467 | "\n", 468 | "The single-lane model takes the following input parameters: length of the highway, initial density of cars (unchanging since it is a closed-loop system), a maximum velocity at which cars are allowed to travel and a probability of slowing down randomly. This parameter was introduced by Nagel & Schreckenberg (1992) to make the system non-deterministic and more accurately model real world traffic behavior (default 50%). This could represent both overly attentive behavior, when for example a driver breaks before the car in front of her slows down, or careless behavior, where a driver paying little attention to the road does not keep a constant speed or takes a few seconds to speed up after moving out of a traffic jam.\n", 469 | "\n", 470 | "** The Model **\n", 471 | "\n", 472 | "The below display shows traffic jams building on the single-lane, circular model when density is high. Below I analyze traffic flow of this model, which peaks at around 0.35 cars per update step (second) when density is at 0.08. Note that the standard deviation is highest around the infliction point of a density of 0.08." 473 | ] 474 | }, 475 | { 476 | "cell_type": "code", 477 | "execution_count": 123, 478 | "metadata": {}, 479 | "outputs": [ 480 | { 481 | "name": "stdout", 482 | "output_type": "stream", 483 | "text": [ 484 | "....5........0.02...4......1.04....1.0.04........3...0.0.1..02..02...3\n", 485 | "..4......2...0.0..2.....3...00....1.01.0....4.......00.0..1.0..00..3..\n", 486 | "4.....4....1.1.1....3......000.....01.00........3...00.1...01..00.....\n", 487 | "....4.....1.0.0.2......2...000.....1.001...........001..1..1.1.00.....\n", 488 | "........1..00.0...3......0.001......001.1..........01.2..1..1.000.....\n", 489 | ".........1.01.1......2...1.01.1.....00.1.2.........0.2..0.2..0000.....\n", 490 | "..........01.1.2.......2..01.0.1....01..1..3.......1...00...00001.....\n", 491 | "..........0.0.1..2.......00.01..1...1.1..2....4.....2..00...0000.1....\n", 492 | "..........1.0..2...2.....01.0.1..1...0.2...2......3...000...0001..2...\n", 493 | "...........01....3...2...0.01..1..1..1...2...3.......0001...000.2...3.\n", 494 | ".3.........0.1......2..0.1.0.2..2..2..2....3....3....001.2..001...2...\n", 495 | "....3......1..2.......01..00...2..1..2..2.....4....0.01.1..001.1....2.\n", 496 | "3......4....1...3.....1.1.00.....0.2...2..3.......00.1.0.1.01.1.1.....\n", 497 | "...3.......0.1.....2...0.001.....0...3...3...3....00..01..01.0.0.1....\n", 498 | "......4....0..1......0.0.01.1....0......2...2...0.01..1.1.0.00.1..2...\n", 499 | "..........00...2.....0.0.0.1.1...0........3...0.0.0.1..0.00.00..2...2.\n", 500 | "3.........00.....3...1.0.0..0.1..0...........00.1.1..1.0.01.00....2...\n", 501 | "...4......01........1.00.0..0..0.1...........01..0.2..00.1.001......2.\n", 502 | "3......1..0.2........001.1..0..1..2..........1.1.0...001..001.2.......\n", 503 | "...3....1.1...2......00.1.1.0...1...2.........0.01...01.1.00.1..3.....\n", 504 | "......2..1.2....2....01..0.01....2....3.......0.0.2..0.1.000..2....3..\n", 505 | "4.......0.2..2....1..0.1.1.1.1.....3.....3....0.0...01..0000....3.....\n", 506 | "....3...1...2..3...0.1..1.0.0.2.......4.....0.1.1...1.1.0000.......3..\n", 507 | "4......1.2....3...01..2..01.1...2.........1.0..0.2...0.00000..........\n", 508 | "....2...2..3.....01.1...01.1.2....3........01..0...1.0.00000..........\n", 509 | "......3...3...2..0.0.1..1.0.2..2.....4.....0.0.1....01.00000..........\n", 510 | ".........2...1..01.1..1..01...1..2.......1.1.0..1...1.000000..........\n", 511 | "...........2..1.1.1.2..1.1.1...1...2......0.00...2...0000001..........\n", 512 | ".............0.1.0.2..1.0.0.1...2....2....0.00.....1.000001.1.........\n", 513 | ".............0..01...1.01.0..2....3....2..1.00......000000.1.1........\n", 514 | ".............1..0.1...01.01....3.....3...1.001......000000..0.1.......\n", 515 | "..............0.0..1..1.01.1......4.....1.000.1.....000001..1..1......\n", 516 | "..............0.1...2..01.1.1.........1..0000..1....00001.1..1..1.....\n", 517 | "..............0..2....01.0.1.2.........1.0001...1...0001.1.2..1..1....\n", 518 | "..............1....1..1.01..1..2........0001.1...2..000.0.2..0.2..2...\n" 519 | ] 520 | } 521 | ], 522 | "source": [ 523 | "#-------------------------------------------\n", 524 | "# PART 1 - SINGLE LANE ROAD\n", 525 | "#-------------------------------------------\n", 526 | "\n", 527 | "# Show traffic jams at high density\n", 528 | "Highway = TrafficSimulation(len_road = 70, density = 0.3, max_vel = 5,\n", 529 | " prob_slowing = 0.5, prob_lane_change = 0.8, lanes = 1)\n", 530 | "Highway.initialize()\n", 531 | "Highway.run(35, display=True)" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": 144, 537 | "metadata": {}, 538 | "outputs": [ 539 | { 540 | "name": "stdout", 541 | "output_type": "stream", 542 | "text": [ 543 | "Completed: 100.0%" 544 | ] 545 | }, 546 | { 547 | "data": { 548 | "image/png": "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\nYII=\n", 549 | "text/plain": [ 550 | "" 551 | ] 552 | }, 553 | "metadata": {}, 554 | "output_type": "display_data" 555 | } 556 | ], 557 | "source": [ 558 | "# Plot the density of the simulation\n", 559 | "plot = display_flow_graph(runs = 8, steps = 800, display_runs = True, display_avgline = True, display_CI = True)\n", 560 | "pl.title(\"Single-lane traffic flow with 95% CI\")\n", 561 | "pl.show()" 562 | ] 563 | }, 564 | { 565 | "cell_type": "markdown", 566 | "metadata": {}, 567 | "source": [ 568 | "### Part 2 - Multi-lane Highways\n", 569 | "**Description and update rules**\n", 570 | "\n", 571 | "The above code can be expanded to an n-lane, circular highway that wraps around on either side (essentially a taurus), by passing in a lane argument. While this seems unrepresentative of the real world a first, it could represent cars leaving and joining the highway in a real world scenario. In addition to the standard movement and speed update rules:\n", 572 | "- IF velocity != maximum speed THEN insrease velocity by 1\n", 573 | "- IF velocity > than the gap in front THEN velocity equals the gap \n", 574 | "- IF velocity > 0 AND probability of randomly slowing down is met THEN reduce velocity by 1\n", 575 | " \n", 576 | "cars on the 2-lane road first check if they are going to have to slow down on the next step. If there is a car in front of them, they attempt to change lanes based on the following rules:\n", 577 | "- IF velocity of car > gap in front of it\n", 578 | "- AND there is max_vel space behind and velocity + 1 space in front on the neighboring lane (I have combined these two rules into a single sweep, since either condition not being met would prevent lane switching regardless of the other)\n", 579 | "- AND IF the probability of switching is met,\n", 580 | "- THEN the car will switch lanes.\n", 581 | "\n", 582 | "In addition to these basic rules, on the n-lane model cars can switch either left or right. In the code above, I check availability on both lanes if switching is initiated and if both are free, a lane is chosen at random. This creates symmetric switching conditions. Due to the order of updates in the array, the switch_lanes function gives priority to cars switching right over those switching left in *extreme corner cases (this happens so rarely, the error only showed up on one out of ~50 runs)* where two cars from different lanes happen to try to switch into the exact same spot. After switching, cars are updated and moved just like in the single-lane model.\n", 583 | "\n", 584 | "The density-flow plot below shows that with an additional lane, we can increase traffic flow up to 0.375, being able to move slighly more than twice the cars (since density is now a function of the average over 2 lanes), than we would with just a single lane. This suggests that the lane change model actually allows for smoother traffic flow than two single lanes would, side by side. The curve also declines more slowly with increased density, showing that the average movement speed of cars stays higher on a 2-lane compared to a 1-lane highway, and traffic jams form less and resolve faster by allowing lane changes.\n", 585 | "\n", 586 | "**Parameters**\n", 587 | "\n", 588 | "The multi-lane model consists of the same parameters as described above for the single-lane model, with the addition of a lane change probability (default 80%). If cars switch lanes with 100% probability when space is free, this leads to tail-gating behavior that can be broken if cars sometimes do not switch. This reflects real world behavior since cars there do not always switch lanes when possible or when seeing that the car in front of them is already indicating that they plan a lane change (a time step that our simulation cannot represent, but can be approximated with the lange change probability parameter)." 589 | ] 590 | }, 591 | { 592 | "cell_type": "code", 593 | "execution_count": 145, 594 | "metadata": {}, 595 | "outputs": [ 596 | { 597 | "name": "stdout", 598 | "output_type": "stream", 599 | "text": [ 600 | "Completed: 100.0%" 601 | ] 602 | }, 603 | { 604 | "data": { 605 | "image/png": "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\npZTyyv8Abc2FKOXRY10AAAAASUVORK5CYII=\n", 606 | "text/plain": [ 607 | "" 608 | ] 609 | }, 610 | "metadata": {}, 611 | "output_type": "display_data" 612 | } 613 | ], 614 | "source": [ 615 | "#-------------------------------------------\n", 616 | "# QUESTION 2 - TWO-LANE\n", 617 | "#-------------------------------------------\n", 618 | "\n", 619 | "# Show behavior of 2-lane system\n", 620 | "plot2 = display_flow_graph(runs = 6, steps = 900, lanes = [1,2], col = ['k', 'maroon'],\n", 621 | " display_runs = True, display_avgline = True, display_CI = False)\n", 622 | "pl.title(\"Traffic flow comparison single to double-lane road\")\n", 623 | "pl.show()" 624 | ] 625 | }, 626 | { 627 | "cell_type": "markdown", 628 | "metadata": {}, 629 | "source": [ 630 | "### Part 3 - General Discussion\n", 631 | "\n", 632 | "**Multi-lane comparison**\n", 633 | "\n", 634 | "The below plot shows that there is sidnificant increase in traffic flow when increasing the number of lanes from one to two and allowing cars to move around traffic jams. It also demonstrates, however, that further increase in lanes does not significantly increase the traffic flow at critical density. The only marginal advantage that a n-lane (in our graph 10-lane) highway has over the standard 2-lane road is that it maintains slightly higher flow rates as density increases. In a real world scenario, where we would expect traffic to be added to the highway only from one side (all cars have to enter and leave on the right side), we might actually expect a 10-lane model to perform significantly worse on average traffic flow, since there would be a higher density in the first few lanes that leads to excessive traffic jams. The world's largest highway supports an impressive 11 lanes, but solves the traffic jam problem by combining from smaller roads and splitting into smaller roads before allowing cars to move off. The middle piece of this highway could actually be modelled fairly accurately by my simulation.\n", 635 | "\n", 636 | "** Traffic in Buenos Aires** \n", 637 | "\n", 638 | "Given the many small roads and grid-like structure of Buenos Aires traffic, the traffic model could only accurately reflect traffic in the 1-lane model. As such, it is moderately well-suited to model traffic, but could be greatly improved by random obstacles (eg. taxi drivers stopping, people crossing the road away from pedestrian walks, angry protesters, potholes causing cars to slow down, etc.). \n", 639 | "\n", 640 | "**Good Driver Behavior**\n", 641 | "\n", 642 | "In part 3.2 I am modelling \"good driver behavior\" by reducing the probability of randomly slowing down from 50% to 10%. This could reflect extremely attentive driving or drivers using their cruise control on the highway, preventing them from slowing down randomly (I personally drive this way on the highway and find it to make for a very smooth driving experience). As the plot shows, this good driver behavior significantly increases the average traffic flow by a factor of two, and the decrease as density increases is minimized. It also reduces the difference between single, two, and ten-lane highways to a minimum, suggesting that if people do not slow down randomly, we could grealt increase the traffic flow of our streets regardless of size and traffic jams would occur less frequently/be resolved faster." 643 | ] 644 | }, 645 | { 646 | "cell_type": "code", 647 | "execution_count": 146, 648 | "metadata": {}, 649 | "outputs": [ 650 | { 651 | "name": "stdout", 652 | "output_type": "stream", 653 | "text": [ 654 | "Completed: 100.0%" 655 | ] 656 | }, 657 | { 658 | "data": { 659 | "image/png": "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\n", 660 | "text/plain": [ 661 | "" 662 | ] 663 | }, 664 | "metadata": {}, 665 | "output_type": "display_data" 666 | } 667 | ], 668 | "source": [ 669 | "#-------------------------------------------\n", 670 | "# QUESTION 3.1 - N-LANE\n", 671 | "#-------------------------------------------\n", 672 | "\n", 673 | "# Assuming \"good\" driver behavior where drivers barely \n", 674 | "# ever slow down randomly\n", 675 | "plot3 = display_flow_graph(lanes = [1,2,3,4,10], runs = 4, steps = 1200, col = ['k', 'maroon', 'navy', 'g', 'coral'],\n", 676 | " display_runs = True, display_avgline = True, display_CI = False)\n", 677 | "pl.title(\"Traffic flow comparison by number of lanes\")\n", 678 | "pl.show()" 679 | ] 680 | }, 681 | { 682 | "cell_type": "code", 683 | "execution_count": 149, 684 | "metadata": {}, 685 | "outputs": [ 686 | { 687 | "name": "stdout", 688 | "output_type": "stream", 689 | "text": [ 690 | "Completed: 100.0%" 691 | ] 692 | }, 693 | { 694 | "data": { 695 | "image/png": "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\n", 696 | "text/plain": [ 697 | "" 698 | ] 699 | }, 700 | "metadata": {}, 701 | "output_type": "display_data" 702 | } 703 | ], 704 | "source": [ 705 | "#-------------------------------------------\n", 706 | "# QUESTION 3.2 - GOOD DRIVER BEHAVIOR\n", 707 | "#-------------------------------------------\n", 708 | "\n", 709 | "# Assuming \"good\" driver behavior where drivers barely \n", 710 | "# ever slow down randomly (eg. cruise control)\n", 711 | "plot4 = display_flow_graph(prob_slowing = 0.1, prob_lane_change = 0.8, runs = 5, steps = 600,\n", 712 | " lanes = [1, 2, 10], col = ['k', 'maroon', 'coral'],\n", 713 | " display_runs = True, display_avgline = True, display_CI = False)\n", 714 | "pl.title(\"Traffic flow under 'good' driver behavior\")\n", 715 | "pl.show()" 716 | ] 717 | }, 718 | { 719 | "cell_type": "markdown", 720 | "metadata": { 721 | "collapsed": true 722 | }, 723 | "source": [ 724 | "### Future Work\n", 725 | "On top of the extensions already suggested in class or by the original work of Rickert, M., et al. (1996), I would suggest that little modifications are needed to accurately model traffic flow on any high-way like system. The chosen parameters have proven up to the task of being compared against real world rods. Section 3.2, however, suggests that small modifications to driver behavior (eg. more active use of cruise control) could greatly increase higway efficiency. This hypothesis could be tested on a test track and, if it proves robust, taken onto real world highways by, for example, reminding people to use cruise control (the effectiveness of such reminders is topic of different research). This simple modification suggests that self-driving cars might not be the only modification able to improve our driving behavior significantly (at least with regards to highways)." 726 | ] 727 | } 728 | ], 729 | "metadata": { 730 | "kernelspec": { 731 | "display_name": "Python 3", 732 | "language": "python", 733 | "name": "python3" 734 | }, 735 | "language_info": { 736 | "codemirror_mode": { 737 | "name": "ipython", 738 | "version": 2 739 | }, 740 | "file_extension": ".py", 741 | "mimetype": "text/x-python", 742 | "name": "python", 743 | "nbconvert_exporter": "python", 744 | "pygments_lexer": "ipython2", 745 | "version": "2.7.14" 746 | } 747 | }, 748 | "nbformat": 4, 749 | "nbformat_minor": 2 750 | } 751 | -------------------------------------------------------------------------------- /02:21 Dynamics of Networks.py: -------------------------------------------------------------------------------- 1 | import matplotlib 2 | matplotlib.use('TkAgg') 3 | from pylab import * 4 | import networkx as nx 5 | import random as rd 6 | import numpy as np 7 | 8 | #------------------------- 9 | # WATTS-STROGATZ MODEL 10 | # grid structure 11 | #------------------------- 12 | 13 | # num_nodes = 30 # number of nodes 14 | 15 | # def initialize(n = num_nodes): 16 | # global g 17 | # g = nx.Graph() 18 | # #determining how many nodes to plot and the grid 19 | # #dimensions for a nice rectangular grid 20 | # width = np.ceil(np.sqrt(n)) 21 | # height = np.floor(np.sqrt(n)) 22 | # n = width * height 23 | 24 | # for i in range(int(n)): 25 | # if not (i < width): 26 | # g.add_edge(i, i - width) #adds vertical connections 27 | 28 | # if i % width != 0: 29 | # g.add_edge(i, i - 1) #adds horizontal connections 30 | 31 | # g.pos = nx.spring_layout(g) 32 | # g.count = 0 33 | 34 | # def observe(): 35 | # global g 36 | # cla() 37 | # nx.draw(g, pos = g.pos) 38 | # plt.show() 39 | 40 | # def update(): 41 | # global g 42 | # g.count += 1 43 | # if g.count % 20 == 0: # rewiring once in every 20 steps 44 | # nds = list(g.nodes) 45 | # i = rd.choice(nds) 46 | # if g.degree[i] > 0: 47 | # g.remove_edge(i, rd.choice(list(g.neighbors(i)))) 48 | # nds.remove(i) 49 | # for j in g.neighbors(i): 50 | # nds.remove(j) 51 | # g.add_edge(i, rd.choice(nds)) 52 | 53 | # # simulation of node movement 54 | # g.pos = nx.spring_layout(g, pos = g.pos, iterations = 5) 55 | 56 | # import pycxsimulator 57 | # pycxsimulator.GUI().start(func=[initialize, observe, update]) 58 | 59 | #------------------------- 60 | # BARABASI-ALBERT MODEL 61 | # 62 | #------------------------- 63 | 64 | m0 = 5 # number of nodes in initial condition 65 | m = 5 # number of edges per new node 66 | 67 | def initialize(): 68 | global g 69 | g = nx.complete_graph(m0) 70 | g.pos = nx.spring_layout(g) 71 | g.count = 0 72 | 73 | def observe(): 74 | global g 75 | cla() 76 | nx.draw(g, pos = g.pos) 77 | 78 | def pref_select(nds): 79 | global g 80 | r = uniform(0, sum(g.degree(i) for i in nds)) 81 | x=0 82 | for i in nds: 83 | x += g.degree[i] 84 | if r <= x: 85 | return i 86 | 87 | def update(): 88 | global g 89 | g.count += 1 90 | if g.count % 20 == 0: # network growth once in every 20 steps 91 | nds = list(g.nodes) 92 | newcomer = max(nds) + 1 93 | for i in range(m): 94 | j = pref_select(nds) 95 | g.add_edge(newcomer, j) 96 | nds.remove(j) 97 | g.pos[newcomer] = (0, 0) 98 | 99 | # simulation of node movement 100 | g.pos = nx.spring_layout(g, pos = g.pos, iterations = 5) 101 | 102 | import pycxsimulator 103 | pycxsimulator.GUI().start(func=[initialize, observe, update]) 104 | -------------------------------------------------------------------------------- /03:05 PageRank.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import random as rd 5 | 6 | 7 | #---------------------------- 8 | # SIMULATING THE SURFER 9 | #---------------------------- 10 | def generate_graph(): 11 | ''' 12 | Generates our graph and initiates the visits attribute to 0. 13 | ''' 14 | g = nx.erdos_renyi_graph(30, 0.05, directed=True, seed=123) 15 | for node in g.nodes: 16 | g.nodes[node]['visits'] = 0 17 | 18 | return g 19 | 20 | def calculate_page_rank(g, n): 21 | ''' 22 | Updates the pagerank attribute for each node and also 23 | generates a pagerank dict that can be passed into the 24 | calculate_difference() function. 25 | ''' 26 | page_rank = [] 27 | for i in g.nodes(): 28 | score = g.nodes[i]['visits'] / n 29 | 30 | g.nodes[i]['pagerank'] = score 31 | page_rank.append(score) 32 | 33 | return g, page_rank 34 | 35 | def calculate_difference(g, ranking): 36 | ''' 37 | Get the difference between our current ranking and 38 | the real one (networkx-generated). 39 | ''' 40 | page_rank_dict = nx.pagerank(g) 41 | page_rank = [page_rank_dict[k] for k in range(len(page_rank_dict))] 42 | 43 | error = 0 44 | 45 | for real, approx in zip(page_rank, ranking): 46 | error += abs(real - approx) 47 | 48 | return error 49 | 50 | 51 | def surfer(g = generate_graph(), alpha = 0.85, N = 1000): 52 | ''' 53 | Does an N-step random walk over the graph and then returns the 54 | error between the predicted page rank and the actual page rank 55 | every 10 iterations. 56 | ''' 57 | x = [] 58 | error_y = [] 59 | 60 | surfer_loc = rd.choice(list(g.nodes)) #pick random starting node 61 | g.nodes[surfer_loc]['visits'] += 1 62 | 63 | for n in range(1, N): 64 | neighbors = [n for n in g.neighbors(surfer_loc)] 65 | #if no neighbor or > alpha 66 | #jump to random other page 67 | if np.random.uniform() > alpha or neighbors == []: 68 | surfer_loc = rd.choice(list(g.nodes)) 69 | g.nodes[surfer_loc]['visits'] += 1 70 | else: #move to neighbor node normally 71 | surfer_loc = rd.choice(neighbors) 72 | g.nodes[surfer_loc]['visits'] += 1 73 | 74 | if n % 10 == 0: 75 | g, cur_rank = calculate_page_rank(g, n) 76 | error = calculate_difference(g, cur_rank) 77 | 78 | x.append(n) 79 | error_y.append(error) 80 | 81 | return g, x, error_y 82 | 83 | #---------------------------- 84 | # PLOT ERROR REDUCTION 85 | #---------------------------- 86 | 87 | final_graph, x, y = surfer() 88 | # plt.plot(x, y) 89 | # plt.xlabel("Number of steps") 90 | # plt.ylabel("Error") 91 | # plt.show() 92 | 93 | 94 | #---------------------------- 95 | # PLOTTING PAGE RANK BY COLOR 96 | #---------------------------- 97 | _, rankings = calculate_page_rank(final_graph, 1000) 98 | page_rankings = nx.pagerank(final_graph) 99 | page_rankings = [v for k, v in page_rankings.items()] 100 | 101 | plt.figure() 102 | plt.subplot(1,2,1) 103 | plt.title("Page Rank") 104 | nx.draw(final_graph, cmap=plt.get_cmap('Reds'), pos=nx.kamada_kawai_layout(final_graph), 105 | node_color=page_rankings) 106 | 107 | plt.subplot(1,2,2) 108 | plt.title("Random Walk") 109 | nx.draw(final_graph, cmap=plt.get_cmap('Reds'), pos=nx.kamada_kawai_layout(final_graph), 110 | node_color=rankings) 111 | 112 | plt.show() 113 | 114 | -------------------------------------------------------------------------------- /03:09 Disease Spread.py: -------------------------------------------------------------------------------- 1 | import matplotlib 2 | matplotlib.use('TkAgg') 3 | from pylab import * 4 | import networkx as nx 5 | import random as rd 6 | 7 | #---------------------- 8 | # PART 1 9 | # SIS Model 10 | #---------------------- 11 | 12 | n = 200 #nodes 13 | p_e = 0.05 #connection probability 14 | p_i = 0.04 # infection probability 15 | p_r = 0.5 # recovery probability 16 | 17 | def initialize(): 18 | global g 19 | g = nx.erdos_renyi_graph(n, p_e) 20 | g.pos = nx.spring_layout(g) 21 | for i in g.nodes: 22 | g.nodes[i]['state'] = 1 if random() < .5 else 0 23 | 24 | def observe(): 25 | global g 26 | cla() 27 | nx.draw(g, vmin = 0, vmax = 1, 28 | node_color = [g.nodes[i]['state'] for i in g.nodes], 29 | pos = g.pos) 30 | 31 | def update(): 32 | ''' 33 | Updated to account for simultaneous updating. 34 | ''' 35 | global g 36 | all_nodes = list(g.nodes) 37 | 38 | for node in all_nodes: 39 | if g.nodes[node]['state'] == 0: # if susceptible 40 | neighbors = list(g.neighbors(node)) 41 | for neig in neighbors: 42 | if g.nodes[neig]['state'] == 1: # if randomly chosen neighbor is infected 43 | g.nodes[neig]['state'] = 1 if random() < p_i else 0 44 | else: # if node is already infected 45 | g.nodes[neig]['state'] = 0 if random() < p_r else 1 46 | 47 | 48 | import pycxsimulator 49 | pycxsimulator.GUI().start(func=[initialize, observe, update]) 50 | 51 | 52 | 53 | #-------------------------------- 54 | # PART 2 55 | # Friends of Friends Effect 56 | #-------------------------------- 57 | 58 | # p_i = 0.04 # infection probability 59 | # p_r = 0.5 # recovery probability 60 | # n = 1000 # we want 1000 nodes, ~20.000 connections 61 | 62 | # def avg_degree(g, n): 63 | # ''' 64 | # Calculates the average degree of a graph g 65 | # with n nodes. Edges*2/nodes 66 | # ''' 67 | # total_edges = len(list(g.edges)) 68 | # avg_degr = total_edges * 2/ n 69 | 70 | # print ("Total edges in the graph: ", total_edges) 71 | # print ("Average degree: ", avg_degr) 72 | 73 | # return avg_degr 74 | 75 | 76 | # def avg_neighbor_degree(g): 77 | # ''' 78 | # Iterates through all edges in the graph and all their attached 79 | # nodes and calculates the average node degree. 80 | # ''' 81 | # node_counter = 0 82 | # total_degree = 0 83 | 84 | # for edge in g.edges(): 85 | # for neighbor in edge: 86 | # total_degree += len(g.edges(neighbor)) 87 | # node_counter += 1 88 | 89 | # avg_neighbor_degr = total_degree/node_counter 90 | # print ("Average neighbor degree: ", avg_neighbor_degr) 91 | # return avg_neighbor_degr 92 | 93 | 94 | # def generate_graph(graph_type='erdos'): 95 | # if graph_type == "erdos": 96 | # g = nx.erdos_renyi_graph(n, 0.04) #edges = (n chose 2) * p_e 97 | # elif graph_type == "watts": 98 | # g = nx.watts_strogatz_graph(n, 40, 0.3) #each node is connected to k neighbors (40) 99 | # elif graph_type == "barabasi": 100 | # g = nx.barabasi_albert_graph(n, 20) #m = number of connections for each new node 101 | # else: #m = ~20-21 generates 20k edges 102 | # print("Couldn't recognize your graph type!") 103 | 104 | # _ = avg_degree(g, n) #check average degree 105 | # _ = avg_neighbor_degree(g) #returns avg degree of all neighbors 106 | 107 | 108 | # generate_graph("erdos") 109 | # generate_graph("watts") 110 | # generate_graph("barabasi") 111 | -------------------------------------------------------------------------------- /03:16 Monte Carlo Simulation Introduction 2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random as rd 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | #------------------------------- 7 | # GAMBLER'S RUIN 8 | #------------------------------- 9 | # Simulate the gambler's ruin problem with different upper bounds on 10 | # the iteration count. 11 | # a) how does this bias average game duration? 12 | # b) How does this bias sample variance? 13 | #--------------------------------------------------------------------- 14 | 15 | def gamble(): 16 | if rd.uniform(0,1) < 0.5: 17 | return 1 18 | else: 19 | return -1 20 | 21 | def simulate(runs, time_lim, plot=False): 22 | len_game = [] 23 | 24 | for r in range(runs): 25 | gamblers_money = 100 26 | house_money = 2000 27 | 28 | for t in range(time_lim): 29 | if (gamblers_money > 0) & (house_money > 0): 30 | game_return = gamble() 31 | gamblers_money += game_return 32 | house_money -= game_return 33 | total_time = t 34 | else: 35 | total_time = t 36 | break 37 | 38 | len_game.append(total_time) 39 | 40 | var = np.var(len_game) 41 | mean = np.mean(len_game) 42 | 43 | if plot: 44 | plt.hist(len_game) 45 | plt.title("Gambles until bankrupcy with %d samples" %runs) 46 | plt.xlabel("Game durations at a time limit of %d rounds. \n Mean: %.3g; Var: %.3g" 47 | %(time_lim, mean, var)) 48 | plt.show() 49 | 50 | 51 | simulate(100, 1000, plot=True) 52 | 53 | 54 | -------------------------------------------------------------------------------- /03:16 Monte Carlo Simulation Introduction.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random as rd 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | #------------------------------- 7 | # BIASED COIN - RANDOM WALK 8 | #------------------------------- 9 | # Use a biased coin (P(H)=0.6, P(T)=0.4) to simulate a walk of 30 10 | # steps. If the coin comes up heads, take a step to the right, tails 11 | # one to the left. 12 | # a) plot a sample path 13 | # b) histogram for 200 walks 14 | # c) sample mean and variance (simulated & exact values) 15 | #--------------------------------------------------------------------- 16 | 17 | def biased_coin_flip(p_heads): 18 | if rd.uniform(0,1) < p_heads: 19 | return -1 20 | else: 21 | return 1 22 | 23 | 24 | def plot_sample_path(p_heads): 25 | steps = range(0,31) 26 | sample_locations = [] 27 | cur_loc = 0 28 | 29 | for step in steps: 30 | direction = biased_coin_flip(p_heads) 31 | cur_loc += direction 32 | sample_locations.append(cur_loc) 33 | 34 | plt.plot(steps, sample_locations) 35 | plt.xlabel("Number of Steps Taken") 36 | plt.ylabel("Location (negative numbers are to the right)") 37 | plt.ylim(-20,15) 38 | plt.show() 39 | 40 | 41 | def simulate_rand_walks(runs, p_heads, bins = 10, plot = False): 42 | steps = range(0,31) 43 | final_locations = [] 44 | 45 | for r in range(runs): 46 | cur_loc = 0 47 | for step in steps: 48 | cur_loc += biased_coin_flip(p_heads) 49 | final_locations.append(cur_loc) 50 | 51 | if plot: 52 | plt.hist(final_locations, bins = bins) 53 | plt.suptitle("Random walks of %d samples" %runs) 54 | plt.show() 55 | 56 | mean = np.mean(final_locations) 57 | variance = np.var(final_locations) 58 | print ("The sample mean is %f. The variance is %f." 59 | %(mean, variance)) 60 | 61 | 62 | # plot_sample_path(0.6) 63 | simulate_rand_walks(200, 0.4, plot = True) 64 | simulate_rand_walks(100000, 0.4, bins = 15, plot = True) 65 | 66 | -------------------------------------------------------------------------------- /03:21 Ising Simulation.py: -------------------------------------------------------------------------------- 1 | import matplotlib 2 | matplotlib.use('TkAgg') 3 | 4 | import pylab as plt 5 | import random as rd 6 | import scipy as sp 7 | import numpy as np 8 | from matplotlib.pyplot import cm 9 | 10 | rd.seed() 11 | 12 | n = 100 13 | 14 | class Magnet(): 15 | """ 16 | Description 17 | """ 18 | 19 | def __init__(self, T, size = 100): 20 | self.size = size 21 | self.temp = T 22 | 23 | self.config = sp.zeros([size, size]) 24 | self.time = 0 25 | self.magnetized_frac = [] 26 | 27 | 28 | def initialize(self): 29 | """ 30 | Randomly initializes the magnet's state and 31 | resets counting/plotting variables. 32 | """ 33 | self.time = 0 34 | self.config = sp.zeros([self.size, self.size]) 35 | self.magnetized_frac = [] 36 | 37 | for x in range(self.size): 38 | for y in range(self.size): 39 | 40 | if rd.random() < 0.5: 41 | state = -1 42 | else: 43 | state = 1 44 | 45 | self.config[y, x] = state 46 | 47 | def step(self): 48 | """ 49 | Updates the magnet and records the current magnetization. 50 | """ 51 | 52 | i, j = np.random.choice(range(self.size), 2) 53 | cell_val = self.config[i,j] 54 | neighbors = [self.config[(i-1)%self.size, j], 55 | self.config[i, (j-1)%self.size], 56 | self.config[(i+1)%self.size, j], 57 | self.config[i, (j+1)%self.size]] 58 | 59 | energy = (cell_val * -1) * sum([n * cell_val for n in neighbors]) 60 | 61 | if rd.uniform(0, 1) < min(1, np.exp(2 * energy / self.temp)): 62 | cell_val = cell_val * -1 63 | 64 | self.config[i,j] = cell_val 65 | 66 | if self.time % 10 == 0: #records state every 20 steps 67 | self.magnetized_frac.append(np.mean(self.config)) 68 | 69 | self.time += 1 70 | 71 | 72 | def run(self, r): 73 | for _ in range(r): 74 | self.step() 75 | 76 | def draw(self): 77 | """ 78 | Visualizes the current state. 79 | """ 80 | plt.cla() 81 | plt.subplot(1,2,1) 82 | plt.pcolor(self.config, vmin = -1, vmax = 1, cmap = cm.coolwarm) 83 | plt.title('time = ' + str(self.time) + "steps Temperature: " + str(self.temp)) 84 | plt.subplot(1,2,2) 85 | plt.ylim(-1,1) 86 | plt.plot(self.magnetized_frac, 'b-') 87 | plt.show() 88 | 89 | 90 | # print ("Test run! ") 91 | # for temp in [1, 2, 3, 4, 5]: 92 | # test_magnet = Magnet(T = temp, size = 10) 93 | # test_magnet.initialize() 94 | # test_magnet.run(100000) 95 | # test_magnet.draw() 96 | 97 | """ 98 | For each of the T values above, plot a histogram over 99 | the average magnetization of the final state. 100 | You will need to run the simulation about 100 times 101 | for each T, to get enough data for your histogram. 102 | """ 103 | print("Starting now") 104 | for temp in [1, 2, 3, 4, 5]: 105 | final_magnetization = [] 106 | print ("Current temp: " + str(temp)) 107 | 108 | for run in range(30): 109 | magnet = Magnet(T = temp, size = 20) 110 | magnet.initialize() 111 | magnet.run(30000) 112 | final_magnetization.append(magnet.magnetized_frac[-1]) 113 | 114 | plt.subplot(1,5,temp) 115 | plt.title("T = " + str(temp)) 116 | plt.xlim(-1, 1) 117 | plt.hist(final_magnetization) 118 | 119 | plt.suptitle("Final magnetizations with different values of T") 120 | plt.show() 121 | 122 | -------------------------------------------------------------------------------- /04:03 Ising Simulation II.py: -------------------------------------------------------------------------------- 1 | import matplotlib 2 | matplotlib.use('TkAgg') 3 | 4 | import pylab as plt 5 | import random as rd 6 | import scipy as sp 7 | import numpy as np 8 | from matplotlib.pyplot import cm 9 | 10 | rd.seed() 11 | 12 | 13 | class Magnet(): 14 | """ 15 | Description 16 | """ 17 | J = 6.34369e-21 # Interaction constant for iron [Joule] 18 | kB = 1.38065e-23 # Boltzmann constant [Joule / Kelvin] 19 | 20 | def __init__(self, T, size = 100): 21 | self.size = size 22 | self.temp = float(T) 23 | 24 | self.config = sp.zeros([size, size]) 25 | self.time = 0 26 | 27 | 28 | def initialize(self): 29 | """ 30 | Randomly initializes the magnet's state and 31 | resets counting/plotting variables. 32 | """ 33 | self.time = 0 34 | self.config = sp.random.choice([-1, +1], size=(self.size, self.size)) 35 | self.magnetized_frac = [] 36 | 37 | 38 | def change_temperature(self, T): 39 | self.temp = float(T) 40 | 41 | 42 | def step(self): 43 | """ 44 | Updates the magnet and records the current magnetization. 45 | """ 46 | i, j = sp.random.randint(self.size, size=2) 47 | cell = self.config[i,j] 48 | 49 | # Change in energy from current state to next state 50 | delta_E = 2 * self.J * cell * ( 51 | self.config[(i + 1) % self.size, j] + 52 | self.config[(i - 1) % self.size, j] + 53 | self.config[i, (j + 1) % self.size] + 54 | self.config[i, (j - 1) % self.size]) 55 | 56 | # Log probability of changing state 57 | log_p = - delta_E / (self.temp * self.kB) 58 | 59 | if sp.log(sp.random.uniform(0, 1)) < log_p: 60 | self.config[i,j] = cell * -1 61 | 62 | if self.time % 100 == 0: #records state every 20 steps 63 | self.magnetized_frac.append(np.mean(self.config)) 64 | 65 | self.time += 1 66 | 67 | 68 | def run(self, r): 69 | for _ in range(r): 70 | self.step() 71 | 72 | def draw(self): 73 | """ 74 | Visualizes the current state. 75 | """ 76 | plt.cla() 77 | plt.subplot(1,2,1) 78 | plt.pcolor(self.config, vmin = -1, vmax = 1, cmap = cm.coolwarm) 79 | plt.title('time = ' + str(self.time) + "steps Temperature: " + str(self.temp)) 80 | plt.subplot(1,2,2) 81 | plt.ylim(-1,1) 82 | plt.plot(self.magnetized_frac, 'b-') 83 | plt.show() 84 | 85 | 86 | print ("Test run! ") 87 | for temp in [1, 1043, 2000]: 88 | test_magnet = Magnet(T = temp, size = 5) 89 | test_magnet.initialize() 90 | test_magnet.run(300000) 91 | print (test_magnet.config) 92 | # test_magnet.draw() 93 | 94 | """ 95 | Histogram for simulation. 96 | """ 97 | 98 | # final_magnetization = [] 99 | # magnet = Magnet(T = 1, size = 20) 100 | 101 | # for _ in range(60): 102 | # magnet.initialize() 103 | # magnet.run(50000) 104 | # final_magnetization.append(magnet.magnetized_frac[-1]) 105 | # # magnet.draw() 106 | 107 | # plt.xlim(-1, 1) 108 | # plt.hist(final_magnetization) 109 | # plt.show() 110 | 111 | """ 112 | Histogram for simulation using annealing. 113 | """ 114 | 115 | plt.clf() 116 | final_magnetization = [] 117 | 118 | for _ in range(60): 119 | magnet = Magnet(T = 2000, size = 20) 120 | magnet.initialize() 121 | T = 2000 122 | 123 | while T > 2: 124 | magnet.change_temperature(T) 125 | magnet.run(50) 126 | T -= 1 127 | 128 | final_magnetization.append(magnet.magnetized_frac[-1]) 129 | 130 | plt.title("Simulation with Annealing") 131 | plt.xlim(-1, 1) 132 | plt.hist(final_magnetization) 133 | plt.show() 134 | 135 | -------------------------------------------------------------------------------- /04:04 Random walks.py: -------------------------------------------------------------------------------- 1 | import random as rd 2 | import numpy as np 3 | import pylab as plt 4 | 5 | """ 6 | ------------------------------------------------------------------ 7 | EXERCISE 1: Write a random walk. 8 | ------------------------------------------------------------------ 9 | """ 10 | 11 | def random_walk_1d(steps, bias = 0): 12 | X = 0 13 | for _ in range(steps): 14 | dx = rd.choice([-1+bias, 1+bias]) 15 | X += dx 16 | return X 17 | 18 | 19 | # #without bias 20 | # dist_rand_walk = [] 21 | # for _ in range(500): 22 | # dist_rand_walk.append(random_walk_1d(100)) 23 | 24 | # plt.hist(dist_rand_walk) 25 | # plt.show() 26 | 27 | # #with bias 28 | # dist_rand_walk = [] 29 | # for _ in range(500): 30 | # dist_rand_walk.append(random_walk_1d(100, 0.1)) 31 | 32 | # plt.hist(dist_rand_walk) 33 | # plt.show() 34 | 35 | """ 36 | ------------------------------------------------------------------ 37 | EXERCISE 2: Write an unbiased random walk with obstacles. 38 | a) reflection barrier at x = -4 (bounce off) 39 | b) partial block at x = 6 (0.25 chance of passing through) 40 | ------------------------------------------------------------------ 41 | """ 42 | def rw_obstacles(steps, barrier = -4, block = 6): 43 | """ 44 | Note: barriers would overwrite blocks, since they 45 | can never be passed. 46 | """ 47 | if barrier == block: 48 | print("Don't do that!") 49 | return 50 | 51 | X = 0 52 | for _ in range(steps): 53 | dx = rd.choice([-1, 1]) 54 | 55 | if X == block: 56 | if X > 0: 57 | if rd.uniform(0,1) < 0.25: 58 | X += 1 59 | else: 60 | X -= 1 61 | else: 62 | if rd.uniform(0,1) < 0.25: 63 | X -= 1 64 | else: 65 | X += 1 66 | #barrier (either on right or left side) 67 | elif X == barrier: 68 | if X > 0: 69 | X -= 1 70 | else: 71 | X += 1 72 | else: 73 | X += dx 74 | 75 | return X 76 | 77 | # #random walk with obstacles at default 78 | # dist_rand_walk = [] 79 | # for _ in range(10000): 80 | # dist_rand_walk.append(rw_obstacles(100)) 81 | 82 | # plt.hist(dist_rand_walk, bins=15) 83 | # plt.show() 84 | 85 | # #random walk with obstacles at 10 and 2 86 | # dist_rand_walk = [] 87 | # for _ in range(10000): 88 | # dist_rand_walk.append(rw_obstacles(100, 10, 2)) 89 | 90 | # plt.hist(dist_rand_walk, bins=20) 91 | # plt.show() 92 | 93 | 94 | """ 95 | ------------------------------------------------------------------ 96 | EXERCISE 3: Simulate a random walk in 2 continuous dimensions. 97 | 1) Start at origin. 98 | 2) Choose a direction from 0 to 360 degrees. 99 | 3) Choose step size according to a Gaussian (0, sigma) 100 | 4) Advance in that direction and continue. 101 | 102 | Take Sigma^2 to be 0.5, 1, 2 and evaluate the effect. 103 | Take n to be 20, 400, 1600 and evaluate the effect. 104 | Plot one typical path for n=1600. 105 | Show density plots for several walkers. 106 | ------------------------------------------------------------------ 107 | """ 108 | def contin_walk(steps, sigma = 1, history=False): 109 | #1) start at origin 110 | X, Y = 0, 0 111 | 112 | if history: 113 | x_hist, y_hist = [], [] 114 | 115 | for _ in range(steps): 116 | 117 | #2-3) choose direction and step size 118 | (dX, dY) = np.random.normal(0, np.sqrt(sigma), 2) 119 | 120 | #4) advance in direction 121 | X += dX 122 | Y += dY 123 | 124 | if history: 125 | x_hist.append(X) 126 | y_hist.append(Y) 127 | 128 | if history: 129 | return(x_hist, y_hist) 130 | else: 131 | return(X, Y) 132 | 133 | 134 | # #plotting a single random walk 135 | # x_loc, y_loc = contin_walk(1600, history=True) 136 | # plt.plot(x_loc, y_loc, linewidth = 0.4) 137 | # plt.show() 138 | 139 | # #plotting different types of walkers 140 | # steps = [20, 400, 1600] 141 | # sigma = [0.5, 1, 2] 142 | 143 | # sigma_marker = ['blue', 'green', 'red'] 144 | 145 | # for m, step in enumerate(steps): 146 | # for n, sig in enumerate(sigma): 147 | # x_loc, y_loc = [], [] 148 | # for _ in range(150): 149 | # (x_new, y_new) = contin_walk(step, sig) 150 | # x_loc.append(x_new) 151 | # y_loc.append(y_new) 152 | # plt.scatter(x_loc, y_loc, color = sigma_marker[n], alpha = 0.3, 153 | # s = 4, label=str(sig)) 154 | # plt.legend(["Sigma 0.5", "Sigma 1", "Sigma 2"]) 155 | # plt.title("Steps: %d" %(step)) 156 | # plt.xlim(-100, 100) 157 | # plt.ylim(-100, 100) 158 | # plt.show() 159 | 160 | 161 | """ 162 | ------------------------------------------------------------------ 163 | EXERCISE 4: Diffusion in a plane with a hole. 164 | 165 | Starting at the origin, carry out a random walk over a 40x40 plane. 166 | Assume there is a square hole whose boundaries are (13,7), (14,7), 167 | (14,8) and (13,8). Walks that reach the hole (or it's boundary) 168 | are absorbed. 169 | Show the distribution of final positions for walks of various steps 170 | and the fraction that enters the hole. 171 | ------------------------------------------------------------------ 172 | """ 173 | def rw_contin_hole(n_walkers, steps, hole_x = (0,20), hole_y=(0,20)): 174 | """ 175 | This simply modifies the original model with a hole. 176 | Now returns only the final state, since we don't need 177 | the history for a histogram (funny, isn't it?) 178 | """ 179 | #1) start at origin 180 | X_final, Y_final = [], [] 181 | walkers_in_hole = 0 182 | hole_len = abs(hole_x[0] - hole_x[1]) 183 | hole_wid = abs(hole_y[0] - hole_y[1]) 184 | 185 | for walker in range(0, n_walkers): 186 | X, Y = 0, 0 187 | 188 | for _ in range(0, steps): 189 | 190 | # choose direction and step size 191 | (dX, dY) = np.random.normal(0, 1, 2) 192 | 193 | # advance in direction 194 | X += dX 195 | Y += dY 196 | 197 | #make sure our walkers don't run off 198 | if X > 20: 199 | X = 20 200 | elif X < -20: 201 | X = -20 202 | if Y > 20: 203 | Y = 20 204 | elif Y < -20: 205 | Y = -20 206 | 207 | #check if they disappear in the hole! 208 | if ((X > hole_x[0]) and (X hole_y[0]) and (Y < hole_y[1])): 210 | walkers_in_hole += 1 211 | X, Y = np.mean(hole_x)+rd.uniform(0,hole_len//3), np.mean(hole_y)+rd.uniform(0,hole_wid//3) 212 | break 213 | 214 | X_final.append(X) 215 | Y_final.append(Y) 216 | lost_walkers = walkers_in_hole/float(n_walkers) 217 | 218 | return(X_final, Y_final, lost_walkers) 219 | 220 | n = 100 221 | s = 100000 222 | 223 | fig, ax = plt.subplots(1) 224 | 225 | X, Y, lost_walkers = rw_contin_hole(n, s, (13,14), (7,8)) 226 | plt.title(f'After {s} steps, with {n} walkers, we lost {100*lost_walkers:.1f} percent.') 227 | plt.scatter(X,Y, s = 5) 228 | plt.xlim(-20, 20) 229 | plt.ylim(-20, 20) 230 | plt.show() 231 | -------------------------------------------------------------------------------- /04:12 Parameter finding.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | # Data (hard coded) 7 | Dx = [1.0, 2.0] # We actually don’t need the x values 8 | Dy = [30.0, 40.0] 9 | 10 | # Model , horizontal line , y(x) = m 11 | def y(x, theta): 12 | return theta[0] 13 | 14 | # Chi Squared 15 | def chi2(Dx, Dy, theta): 16 | s = 0.0 17 | for i in range(len(Dx)): 18 | s += (y(Dx[i], theta) - Dy[i])**2 19 | 20 | return s/len(Dx) 21 | 22 | # Likelihood function 23 | def P(Dx, Dy, theta): 24 | return (-chi2(Dx, Dy, theta)) 25 | 26 | 27 | # Initial guess for model parameters 28 | theta_cur = [-3.0] 29 | P_cur = P(Dx, Dy, theta_cur) 30 | chain = [] # Array to save the MCMC chain 31 | 32 | 33 | # Do 5000 generations 34 | for _ in range(5000): 35 | 36 | # Randomly draw new_prop theta 37 | theta_prop = [theta + 0.1 * np.random.randn() for theta in theta_cur] 38 | P_prop = P(Dx, Dy, theta_prop) 39 | 40 | # Calculate likelihood ratio 41 | ratio = math.exp(P_prop - P_cur) 42 | 43 | # Decide if to accept the new theta values 44 | if ratio > np.random.rand(): 45 | theta_cur = theta_prop 46 | P_cur = P_prop 47 | 48 | # Save_cur theta value in chain 49 | chain.append(theta_cur[0]) 50 | 51 | 52 | # Plot the result 53 | plt.plot(chain) 54 | plt.show() 55 | 56 | 57 | """ 58 | Using a more complicated model, this process 59 | looks almost exactly the same: 60 | """ 61 | 62 | # # Read in data 63 | # Dx=[] 64 | # Dy=[] 65 | 66 | # for line in open("temp.txt"): 67 | # rows = line.split(" ") 68 | # Dx.append(float(rows[0])) 69 | # Dy.append(float(rows[1])) 70 | 71 | # # Model 72 | # def y(x,theta): 73 | # return theta[0]+theta[1]* math.sin(2.* math.pi/24.*x+theta[2]) 74 | 75 | # # Chi Squared 76 | # def chi2(Dx, Dy, theta): 77 | # s = 0. 78 | # for i in range(len(Dx)): 79 | # s += (y(Dx[i],theta)Dy[i])**2 80 | # return s/len(Dx) 81 | 82 | # # Likelihood function 83 | # def P(Dx, Dy, theta): 84 | # return -chi2(Dx,Dy,theta) 85 | 86 | # # Initial guess for model parameters 87 | # theta_cur = [0.,0.,0.] 88 | # P_current = P(Dx,Dy,theta_cur) 89 | # chain = [] 90 | 91 | # for i in range(10000): 92 | # theta_prop = [theta+0.1* numpy.random.randn() for theta in theta_cur] 93 | # P_prop = P(Dx,Dy,theta_prop) 94 | # ratio = math.exp(P_prop - P_cur) 95 | 96 | # if ratio > numpy.random.rand(): 97 | # theta_cur = theta_prop 98 | # P_cur = P_prop 99 | 100 | # if i>=5000: # save chain only after burnin 101 | # chain.append(theta_cur) 102 | 103 | 104 | # # Calculate average: 105 | # theta_avg = [0.,0.,0.] 106 | # for theta in chain: 107 | # for i in range(3): 108 | # theta avg[i] += theta[i] 109 | 110 | # for i in range(3): 111 | # theta_avg[i] /= len(chain) 112 | 113 | # # Calculate model y 114 | # My = [] 115 | # for x in Dx: 116 | # My.append(y(x,theta avg)) 117 | 118 | # plt.plot(Dx, Dy, "ro") 119 | # plt.plot(Dx, My, ".") 120 | # plt.show() --------------------------------------------------------------------------------