-
Notifications
You must be signed in to change notification settings - Fork 0
/
Project_1.py
229 lines (197 loc) · 8.96 KB
/
Project_1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
import sys
import numpy as np
import math as ma
import csv
def Dijkst(ist,isp,wei):
# Dijkstra algorithm for shortest path in a graph
# ist: index of starting node
# isp: index of stopping node
# wei: weight matrix
# exception handling (start = stop)
if (ist == isp):
shpath = [ist]
return shpath
# initialization
N = len(wei)
Inf = sys.maxint
UnVisited = np.ones(N,int)
cost = np.ones(N)*1.e6
par = -np.ones(N,int)*Inf
# set the source point and get its (unvisited) neighbors
jj = ist
cost[jj] = 0
UnVisited[jj] = 0
tmp = UnVisited*wei[jj,:]
ineigh = np.array(tmp.nonzero()).flatten()
L = np.array(UnVisited.nonzero()).flatten().size
# start Dijkstra algorithm
while (L != 0):
# step 1: update cost of unvisited neighbors,
# compare and (maybe) update
for k in ineigh:
newcost = cost[jj] + wei[jj,k]
if ( newcost < cost[k] ):
cost[k] = newcost
par[k] = jj
# step 2: determine minimum-cost point among UnVisited
# vertices and make this point the new point
icnsdr = np.array(UnVisited.nonzero()).flatten()
cmin,icmin = cost[icnsdr].min(0),cost[icnsdr].argmin(0)
jj = icnsdr[icmin]
# step 3: update "visited"-status and determine neighbors of new point
UnVisited[jj] = 0
tmp = UnVisited*wei[jj,:]
ineigh = np.array(tmp.nonzero()).flatten()
L = np.array(UnVisited.nonzero()).flatten().size
# determine the shortest path
shpath = [isp]
while par[isp] != ist:
shpath.append(par[isp])
isp = par[isp]
shpath.append(ist)
return shpath[::-1]
def calcWei(RX,RY,RA,RB,RV):
# calculate the weight matrix between the points
n = len(RX)
wei = np.zeros((n,n),dtype=float)
m = len(RA)
for i in range(m):
xa = RX[RA[i]-1]
ya = RY[RA[i]-1]
xb = RX[RB[i]-1]
yb = RY[RB[i]-1]
dd = ma.sqrt((xb-xa)**2 + (yb-ya)**2)
tt = dd/RV[i]
wei[RA[i]-1,RB[i]-1] = tt
return wei
def updateWei(wei,c,xi):
# this function is for updating the weights of all segments w_{ij} in the
# network given ta initial weight matrix, an array of number of cars at all
# 58 nodes and a parameter xi
m, n = np.shape(wei)
upwei = wei.copy()
for i in range(m):
for j in range(n):
if (upwei[i, j] != 0):
# if currently there is no weight between node i and j, we cannot
# update the weight w_{ij} since we cannot go straight from i
# to j
upwei[i, j] = wei[i,j]+xi*(c[i]+c[j])/2
# update the weights using the given function upwei[i, j] += ip*(c[i]+c[j])/2
return upwei
def Rome_Network(wei, xi):
# we are going to use this function to calculate the maximum loads at each
# node in the network over the 200 iterations, the five most congested nodes
# and the edges not utilized
n = len(wei)
current_load = np.zeros(n, int) ####################
max_load = np.zeros(n, int) # initialization #
Wei = wei.copy() ####################
U = np.zeros((n, n), int)
# initialise a zero matrix, which will play a role of an indicator matrix,
# i.e, if U[i, j] == 0, it means that there are no cars move from i straight
# to j over the 200 iterations, and by comparing with the initial weight matrix
# we can have a list of edges not utilized
for i in range(1,201):
move = np.round(current_load*0.7)
move[51] = np.round(current_load[51]*0.4)
move = move.astype(int)
# define the list of number of cars move to the next code of each nodes
# in the network, special attention paid to the exit node 52 (since only
# 40% leave at this node), and make the list a list of integers
arrive = np.zeros(n, int)
# initialising the number of cars arrive at each of the 58 nodes
for j in range(n):
if (current_load[j] != 0):
path = Dijkst(j, 51, Wei)
if (len(path) != 1):
arrive[path[1]] += move[j]
U[j, path[1]] += 1
else:
pass
# this for loop updates the list "arrive" and the matrix U after using
# the Dijkstra's algorithm to compute the optimal path to node 52 from
# each node of the network except for node 52
current_load += arrive-move # update the car load at each of the nodes
if i <= 180:
current_load[12] += 20
else:
pass
# this if-statement ensures that 20 cars are injected at the entrance
# node 13 for the 180 minutes
for k in range(n):
if max_load[k] < current_load[k]:
max_load[k] = current_load[k].copy()
else:
pass
# this for loop updates the maximum number of cars each node loads after
# each iteration
Wei = updateWei(wei, current_load, xi)
# use the updateWei function to update the weights of the network after
# updating the car-load of each nodes in the network
most_cong = max_load.argsort()[::-1][:5]
# use argsort() to obtain the indices of the top five nodes based on the
# number of cars total loaded by each node
n_utilized = [] # initiasation of a list of edges not utilized during the iterations
for i in range(n):
for j in range(n):
if U[i, j] == 0 and wei[i, j] != 0:
n_utilized.append([i+1, j+1])
# the for loop is selecting indices i and j such that no cars move straight
# from i to j and there is indeed a path between i and j, then add the path
# [i, j] to the list "n_utilized"
return max_load, most_cong, n_utilized
if __name__ == '__main__':
RomeX = np.empty(0,dtype=float)
RomeY = np.empty(0,dtype=float)
with open('RomeVertices','r') as file:
AAA = csv.reader(file)
for row in AAA:
RomeX = np.concatenate((RomeX,[float(row[1])]))
RomeY = np.concatenate((RomeY,[float(row[2])]))
file.close()
RomeA = np.empty(0,dtype=int)
RomeB = np.empty(0,dtype=int)
RomeV = np.empty(0,dtype=float)
with open('RomeEdges','r') as file:
AAA = csv.reader(file)
for row in AAA:
RomeA = np.concatenate((RomeA,[int(row[0])]))
RomeB = np.concatenate((RomeB,[int(row[1])]))
RomeV = np.concatenate((RomeV,[float(row[2])]))
file.close()
# extract the data from our files and generate RX, RY, RA, RB, RV
wei = calcWei(RomeX,RomeY,RomeA,RomeB,RomeV) # initial weights
max_load_ori, most_cong_ori, n_utilized_ori = Rome_Network(wei, 0.01)
max_load_new, most_cong_new, n_utilized_new = Rome_Network(wei, 0.)
# use our function Rome_Network to calculate the maximum load of each node,
# most congested nodes and not-utilized edges when xi = 0.01 and xi = 0
block_wei = wei.copy()
block_wei[29,:] = np.zeros(58)
block_wei[:,29] = np.zeros(58)
# update the weight matrix when the accident happens and all routes to or
# from node 30 are blocked
max_load_acc,most_cong_acc,_ = Rome_Network(block_wei,0.01)
max_load_most_cong_acc = max_load_acc[most_cong_acc]
# compute the maximum load of the most congested nodes
diff = max_load_acc - max_load_ori
# compute the list of changes in the maximum number of cars loaded of each node
dec_most = diff.argsort()[1]+1
# compute the list of nodes decrease the most in peak value after the accident,
# after intial computation, I found that the first element of this list is
# node 30, but we aim to exclude node 30 from the list, hence we take the
# first six elements after sorting in descending order then the second element of the
# list is our target
inc_most = diff.argsort()[::-1][0]+1
# compute the node increases the most in peak value after the accident
print 'The maximum load for each node over 200 iterations is: ', max_load_ori
print 'The five most congested nodes are: ', most_cong_ori+1
print 'Edges not utilized: ', n_utilized_ori
print 'The maximum load for each node when xi = 0: ', max_load_new
print 'The five most congested nodes when xi = 0: ', most_cong_new+1
print 'Edges not utilized when xi = 0: ', n_utilized_new
print 'After accident, the five most congested nodes are: ', most_cong_acc+1
print 'After accident, the maximum load of the five most congested nodes is: ', max_load_most_cong_acc
print 'After accident, the nodes decrease the most in peak value are: ', dec_most
print 'After accident, the nodes increase the most in peak value are: ', inc_most
# printing our final results