Skip to content

Commit ee7f720

Browse files
committed
Update to reflect changes.
1 parent ac00971 commit ee7f720

1 file changed

Lines changed: 95 additions & 123 deletions

File tree

src/main/nodes.jl

Lines changed: 95 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,103 @@
11

22
"""
3-
add_node(param, graph, x, y, neighbors) -> Dict, Dict
3+
add_node(graph, x, y, neighbors) -> Dict
44
5-
Add a node in position (x,y) and list of neighbors. The new node is given an index J+1.
5+
Add a node in position (x,y) and list of neighbors. The new node is given an index J+1. Returns an updated `graph` object.
66
77
# Arguments
8-
- `param::Dict`: Dict that contains the model's parameters, or `nothing` to only update graph
98
- `graph::Dict`: Dict that contains the underlying graph (created by create_graph())
109
- `x::Float64`: x coordinate of the new node (any real number)
1110
- `y::Float64`: y coordinate of the new node (any real number)
1211
- `neighbors::Vector{Int64}`: Vector of nodes to which it is connected (1 x n list of node indices between 1 and J, where n is an arbitrary # of neighbors)
1312
14-
The cost matrices `delta_tau` and `delta_i` are parametrized as a function of Euclidean distance between nodes.
15-
16-
Returns the updated `graph` and `param` objects (`param` is affected too because the variable `Zjn`, `Lj`, `Hj` and others are reset to a uniform dist.)
13+
# Notes
14+
The cost matrices `delta_tau` and `delta_i` are parametrized as a function of Euclidean distance between nodes.
15+
The new node is given population 1e-6 and productivity equal to the minimum productivity in the graph.
1716
"""
18-
function add_node(param, graph, x, y, neighbors)
17+
function add_node(graph, x, y, neighbors)
1918

20-
graph = dict_to_namedtuple(graph)
19+
if graph isa Dict
20+
graph_new = copy(dict)
21+
else
22+
graph_new = Dict(pairs(namedtuple))
23+
end
2124

2225
# Check validity of neighbors list
23-
if any(neighbors .!= floor.(neighbors)) || any(neighbors .< 1) || any(neighbors .> graph.J)
24-
error("neighbors should be a list of integers between 1 and $(graph.J).")
26+
if any(neighbors .!= floor.(neighbors)) || any(neighbors .< 1) || any(neighbors .> graph[:J])
27+
error("neighbors should be a list of integers between 1 and $(graph[:J]).")
2528
end
26-
Jnew = graph.J + 1
29+
Jnew = graph[:J] + 1
2730

2831
# Add node
29-
nodes = [graph.nodes; [neighbors]]
30-
new_x = [graph.x; x]
31-
new_y = [graph.y; y]
32+
nodes = [graph[:nodes]; [neighbors]]
33+
new_x = [graph[:x]; x]
34+
new_y = [graph[:y]; y]
3235

3336
# Add new node to neighbors' neighbors
3437
# And update adjacency and cost matrices
3538
adjacency = zeros(Jnew, Jnew)
36-
adjacency[1:graph.J, 1:graph.J] = graph.adjacency
39+
adjacency[1:graph[:J], 1:graph[:J]] = graph[:adjacency]
3740

3841
delta_tau = zeros(Jnew, Jnew)
39-
delta_tau[1:graph.J, 1:graph.J] = graph.delta_tau
42+
delta_tau[1:graph[:J], 1:graph[:J]] = graph[:delta_tau]
4043

4144
delta_i = zeros(Jnew, Jnew)
42-
delta_i[1:graph.J, 1:graph.J] = graph.delta_i
45+
delta_i[1:graph[:J], 1:graph[:J]] = graph[:delta_i]
4346

4447
for i in neighbors
4548
nodes[i] = [nodes[i]; Jnew]
4649
distance = sqrt((new_x[i] - x)^2 + (new_y[i] - y)^2)
4750

4851
# Adjacency
49-
adjacency[i, Jnew] = 1
50-
adjacency[Jnew, i] = 1
52+
adjacency[i, Jnew] = adjacency[Jnew, i] = 1
5153

5254
# Travel cost: delta_tau
53-
delta_tau[i, Jnew] = distance
54-
delta_tau[Jnew, i] = distance
55+
delta_tau[i, Jnew] = delta_tau[Jnew, i] = distance
5556

5657
# Building cost: delta_i
57-
delta_i[i, Jnew] = distance
58-
delta_i[Jnew, i] = distance
58+
delta_i[i, Jnew] = delta_i[Jnew, i] = distance
5959
end
6060

6161
# Update number of degrees of liberty for Ijk
6262
ndeg = sum(tril(adjacency)) # nb of degrees of liberty in adjacency matrix
6363

64-
# Return new graph structure
65-
graph_new = Dict(
66-
:J => Jnew,
67-
:x => new_x,
68-
:y => new_y,
69-
:nodes => nodes,
70-
:adjacency => adjacency,
71-
:delta_i => delta_i,
72-
:delta_tau => delta_tau,
73-
:ndeg => ndeg
74-
)
75-
76-
if param !== nothing
77-
# Now, update the param structure
78-
if param isa Dict
79-
param_new = copy(param)
80-
else
81-
param_new = Dict(pairs(param))
82-
end
83-
if haskey(param, :J)
84-
param_new[:J] = Jnew
85-
end
86-
if haskey(param, :Lj)
87-
param_new[:Lj] = ones(Jnew) / Jnew
88-
end
89-
if haskey(param, :Hj)
90-
param_new[:Hj] = ones(Jnew)
91-
end
92-
if haskey(param, :hj)
93-
param_new[:hj] = param[:Hj] ./ param[:Lj]
94-
end
95-
if haskey(param, :omegaj)
96-
param_new[:omegaj] = ones(Jnew)
97-
end
98-
if haskey(param, :Zjn)
99-
param_new[:Zjn] = ones(Jnew, param[:N])
100-
end
101-
102-
return param_new, graph_new
64+
# Update graph structure
65+
graph_new[:J] = Jnew
66+
graph_new[:x] = new_x
67+
graph_new[:y] = new_y
68+
graph_new[:nodes] = nodes
69+
graph_new[:adjacency] = adjacency
70+
graph_new[:delta_i] = delta_i
71+
graph_new[:delta_tau] = delta_tau
72+
graph_new[:ndeg] = ndeg
73+
74+
# Update other parameters if they exist
75+
if haskey(graph, :Lj)
76+
graph_new[:Lj] = [graph[:Lj]; 1e-6] # ones(Jnew) / Jnew
77+
end
78+
if haskey(graph, :Hj)
79+
graph_new[:Hj] = [graph[:Hj]; 1e-6] # ones(Jnew)
80+
end
81+
if haskey(graph, :hj)
82+
graph_new[:hj] = graph_new[:Hj] ./ graph_new[:Lj]
83+
end
84+
if haskey(graph, :omegaj)
85+
graph_new[:omegaj] = [graph_new[:omegaj]; 1e-6] # ones(Jnew)
86+
end
87+
if haskey(graph, :Zjn)
88+
Zjn = fill(minimum(graph[:Zjn]), Jnew, size(graph[:Zjn], 2))
89+
Zjn[1:graph[:J], :] = graph[:Zjn]
90+
graph_new[:Zjn] = Zjn # ones(Jnew, size(graph[:Zjn], 2))
91+
end
92+
if haskey(graph, :region)
93+
closest_node = find_node(graph, x, y)
94+
closest_region = graph[:region][closest_node]
95+
graph_new[:region] = [graph[:region]; closest_region]
10396
end
10497

10598
return graph_new
10699
end
107100

108-
109-
# Please note that in Julia, we use `Dict` to represent structures as in Matlab. The keys of the `Dict` are strings that correspond to the field names in the Matlab structure. Also, the `tril` function is not built-in in Julia, you may need to use a package like `LinearAlgebra` to use it.
110-
111101
"""
112102
find_node(graph, x, y) -> Int64
113103
@@ -124,97 +114,79 @@ function find_node(graph, x, y)
124114
return id
125115
end
126116

127-
128-
129117
"""
130-
remove_node(param, graph, i) -> updated_param, updated_graph
118+
remove_node(graph, i) -> Dict
131119
132-
Removes node i from the graph.
120+
Removes node i from the graph, returning an updated `graph` object.
133121
134122
# Arguments
135-
- `param::Dict`: Dict that contains the model's parameters, or `nothing` to only update graph
136123
- `graph::Dict`: Dict that contains the underlying graph (created by create_graph())
137-
- `i::Int64`: index of the mode to be removed (integer between 1 and graph.J)
138-
139-
Returns the updated graph and param objects (param is affected too because the variable Zjn, Lj, Hj and others are changed).
124+
- `i::Int64`: index of the mode to be removed (integer between 1 and graph[:J])
140125
"""
141-
function remove_node(param, graph, i)
126+
function remove_node(graph, i)
142127

143128
if graph isa Dict
144129
graph_new = copy(dict)
145130
else
146131
graph_new = Dict(pairs(namedtuple))
147132
end
148-
graph = dict_to_namedtuple(graph)
149133

150-
if i < 1 || i > graph.J || i != floor(i)
151-
error("remove_node: node i should be an integer between 1 and $(graph.J).")
134+
if i < 1 || i > graph[:J] || i != floor(i)
135+
error("remove_node: node i should be an integer between 1 and $(graph[:J]).")
152136
end
153137

154-
Jnew = graph.J - 1
138+
Jnew = graph[:J] - 1
155139

156140
graph_new[:J] = Jnew
157-
graph_new[:x] = deleteat!(copy(graph.x), i)
158-
graph_new[:y] = deleteat!(copy(graph.y), i)
159-
graph_new[:nodes] = deleteat!(copy(graph.nodes), i)
160-
161-
nodes = graph_new[:nodes]
141+
graph_new[:x] = deleteat!(copy(graph[:x]), i)
142+
graph_new[:y] = deleteat!(copy(graph[:y]), i)
143+
nodes = deleteat!(copy(graph[:nodes]), i)
162144
for k in 1:Jnew
163-
node_k = filter(x -> x != i, nodes[k]) # nodes[k][nodes[k] .!= i]
145+
node_k = filter(x -> x != i, nodes[k])
164146
nodes[k] = ifelse.(node_k .> i, node_k .- 1, node_k) # reindex nodes k > i to k-1
165147
end
148+
graph_new[:nodes] = nodes # Assign the modified nodes to graph_new
166149

167150
# Rebuild adjacency matrix, delta_i and delta_tau
168-
graph_new[:adjacency] = [graph.adjacency[1:i-1, 1:i-1] graph.adjacency[1:i-1, i+1:end];
169-
graph.adjacency[i+1:end, 1:i-1] graph.adjacency[i+1:end, i+1:end]]
151+
graph_new[:adjacency] = [graph[:adjacency][1:i-1, 1:i-1] graph[:adjacency][1:i-1, i+1:end];
152+
graph[:adjacency][i+1:end, 1:i-1] graph[:adjacency][i+1:end, i+1:end]]
170153

171-
graph_new[:delta_i] = [graph.delta_i[1:i-1, 1:i-1] graph.delta_i[1:i-1, i+1:end];
172-
graph.delta_i[i+1:end, 1:i-1] graph.delta_i[i+1:end, i+1:end]]
154+
graph_new[:delta_i] = [graph[:delta_i][1:i-1, 1:i-1] graph[:delta_i][1:i-1, i+1:end];
155+
graph[:delta_i][i+1:end, 1:i-1] graph[:delta_i][i+1:end, i+1:end]]
173156

174-
graph_new[:delta_tau] = [graph.delta_tau[1:i-1, 1:i-1] graph.delta_tau[1:i-1, i+1:end];
175-
graph.delta_tau[i+1:end, 1:i-1] graph.delta_tau[i+1:end, i+1:end]]
157+
graph_new[:delta_tau] = [graph[:delta_tau][1:i-1, 1:i-1] graph[:delta_tau][1:i-1, i+1:end];
158+
graph[:delta_tau][i+1:end, 1:i-1] graph[:delta_tau][i+1:end, i+1:end]]
176159

177160
if haskey(graph, :across_obstacle)
178-
graph_new[:across_obstacle] = [graph.across_obstacle[1:i-1, 1:i-1] graph.across_obstacle[1:i-1, i+1:end];
179-
graph.across_obstacle[i+1:end, 1:i-1] graph.across_obstacle[i+1:end, i+1:end]]
161+
graph_new[:across_obstacle] = [graph[:across_obstacle][1:i-1, 1:i-1] graph[:across_obstacle][1:i-1, i+1:end];
162+
graph[:across_obstacle][i+1:end, 1:i-1] graph[:across_obstacle][i+1:end, i+1:end]]
180163
end
181164

182165
if haskey(graph, :along_obstacle)
183-
graph_new[:along_obstacle] = [graph.along_obstacle[1:i-1, 1:i-1] graph.along_obstacle[1:i-1, i+1:end];
184-
graph.along_obstacle[i+1:end, 1:i-1] graph.along_obstacle[i+1:end, i+1:end]]
166+
graph_new[:along_obstacle] = [graph[:along_obstacle][1:i-1, 1:i-1] graph[:along_obstacle][1:i-1, i+1:end];
167+
graph[:along_obstacle][i+1:end, 1:i-1] graph[:along_obstacle][i+1:end, i+1:end]]
185168
end
186169

187170
graph_new[:ndeg] = sum(tril(graph_new[:adjacency]))
188171

189-
if graph.region !== nothing
190-
graph_new[:region] = deleteat!(copy(graph.region), i)
191-
end
192-
193-
if param !== nothing
194-
# Now, update the param structure
195-
if param isa Dict
196-
param_new = copy(param)
197-
else
198-
param_new = Dict(pairs(param))
199-
end
200-
param_new[:J] = Jnew
201-
if haskey(param, :Lj)
202-
param_new[:Lj] = deleteat!(copy(param[:Lj]), i)
203-
end
204-
if haskey(param, :Hj)
205-
param_new[:Hj] = deleteat!(copy(param[:Hj]), i)
206-
end
207-
if haskey(param, :hj)
208-
param_new[:hj] = deleteat!(copy(param[:hj]), i)
209-
end
210-
if haskey(param, :omegaj)
211-
param_new[:omegaj] = deleteat!(copy(param[:omegaj]), i)
212-
end
213-
if haskey(param, :Zjn)
214-
param_new[:Zjn] = vcat(param[:Zjn][1:i-1, :], param[:Zjn][i+1:end, :])
215-
end
216-
217-
return param_new, graph_new
172+
# Update other parameters if they exist
173+
if haskey(graph, :Lj)
174+
graph_new[:Lj] = deleteat!(copy(graph[:Lj]), i)
175+
end
176+
if haskey(graph, :Hj)
177+
graph_new[:Hj] = deleteat!(copy(graph[:Hj]), i)
178+
end
179+
if haskey(graph, :hj)
180+
graph_new[:hj] = deleteat!(copy(graph[:hj]), i)
181+
end
182+
if haskey(graph, :omegaj)
183+
graph_new[:omegaj] = deleteat!(copy(graph[:omegaj]), i)
184+
end
185+
if haskey(graph, :Zjn)
186+
graph_new[:Zjn] = vcat(graph[:Zjn][1:i-1, :], graph[:Zjn][i+1:end, :])
187+
end
188+
if haskey(graph, :region)
189+
graph_new[:region] = deleteat!(copy(graph[:region]), i)
218190
end
219191

220192
return graph_new

0 commit comments

Comments
 (0)