Skip to content

Commit 60d9fc6

Browse files
committed
The Armington case with cross-good congestion.
1 parent d831260 commit 60d9fc6

2 files changed

Lines changed: 86 additions & 2 deletions

File tree

src/main/optimal_network.jl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,13 @@ function optimal_network(param, graph; I0=nothing, Il=nothing, Iu=nothing, verbo
7979
model = model_partial_mobility_cgc(optimizer, auxdata)
8080
recover_allocation = recover_allocation_partial_mobility_cgc
8181
elseif param.mobility == 0 && param.cong
82-
model = model_fixed_cgc(optimizer, auxdata)
83-
recover_allocation = recover_allocation_fixed_cgc
82+
if all(sum(param.Zjn .> 0, dims = 2) .<= 1) # Armington case
83+
model = model_fixed_cgc_armington(optimizer, auxdata)
84+
recover_allocation = recover_allocation_fixed_cgc_armington
85+
else
86+
model = model_fixed_cgc(optimizer, auxdata)
87+
recover_allocation = recover_allocation_fixed_cgc
88+
end
8489
elseif param.mobility == 1 && !param.cong
8590
model = model_mobility(optimizer, auxdata)
8691
recover_allocation = recover_allocation_mobility
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# The primal case, no mobility, with cross-good congestion, and an Armington (1969) world where each location produces only one good
2+
3+
function model_fixed_cgc_armington(optimizer, auxdata)
4+
5+
# Extract parameters
6+
param = auxdata.param
7+
graph = auxdata.graph
8+
kappa_ex_init = auxdata.kappa_ex
9+
A = auxdata.edges.A
10+
Apos = auxdata.edges.Apos
11+
Aneg = auxdata.edges.Aneg
12+
Lj = param.Lj
13+
m = param.m # 1:param.N: Vector of weights on each goods flow for aggregate congestion term
14+
psigma = (param.sigma - 1) / param.sigma
15+
beta_nu = (param.beta + 1) / param.nu
16+
17+
# Model
18+
model = Model(optimizer)
19+
set_string_names_on_creation(model, false)
20+
21+
# Variables
22+
@variable(model, Djn[1:graph.J, 1:param.N] >= 1e-8, container=Array, start = 1e-6) # Consumption per good pre-transport cost (Dj)
23+
@variable(model, Qin_direct[1:graph.ndeg, 1:param.N] >= 1e-8, container=Array, start = 0.0) # Direct aggregate flow
24+
@variable(model, Qin_indirect[1:graph.ndeg, 1:param.N] >= 1e-8, container=Array, start = 0.0) # Indirect aggregate flow
25+
@variable(model, cj[1:graph.J] >= 1e-8, container=Array, start = 1e-6) # Overall consumption bundle, including transport costs
26+
27+
# Parameters: to be updated between solves
28+
@variable(model, kappa_ex[i = 1:graph.ndeg] in Parameter(i), container=Array)
29+
set_parameter_value.(kappa_ex, kappa_ex_init)
30+
31+
# Defining Utility Funcion: from cj + parameters (by operator overloading)
32+
@expression(model, uj, ((cj / param.alpha) .^ param.alpha .* (param.hj / (1-param.alpha)) .^ (1-param.alpha)) .^ (1-param.rho) / (1-param.rho))
33+
@expression(model, U, sum(param.omegaj .* Lj .* uj)) # Overall Utility
34+
@objective(model, Max, U)
35+
36+
# Create the matrix B_direct (resp. B_indirect) of transport cost along the direction of the edge (resp. in edge opposite direction)
37+
B_direct = @expression(model, ((Qin_direct .^ param.nu) * m) .^ beta_nu ./ kappa_ex)
38+
B_indirect = @expression(model, ((Qin_indirect .^ param.nu) * m) .^ beta_nu ./ kappa_ex)
39+
# Final good constraints
40+
@expression(model, Dj, sum(Djn .^ psigma, dims=2) .^ (1 / psigma))
41+
@constraint(model, cj .* Lj + Apos * B_direct + Aneg * B_indirect - Dj .<= -1e-8)
42+
43+
# Balanced flow constraints
44+
Yjn = param.Zjn .* Lj .^ param.a
45+
@constraint(model, Pjn, Djn + A * Qin_direct - A * Qin_indirect - Yjn .<= -1e-8)
46+
47+
return model
48+
end
49+
50+
function recover_allocation_fixed_cgc_armington(model, auxdata)
51+
param = auxdata.param
52+
graph = auxdata.graph
53+
model_dict = model.obj_dict
54+
results = Dict()
55+
# Production: Fixed because just one good is produced by each location
56+
Yj = dropdims(sum(param.Zjn, dims = 2) .* param.Lj .^ param.a, dims = 2)
57+
WY = param.Zjn .> 0
58+
59+
results[:welfare] = value(model_dict[:U])
60+
results[:Yjn] = WY .* Yj
61+
results[:Yj] = Yj
62+
results[:Ljn] = WY .* param.Lj
63+
results[:Lj] = param.Lj
64+
results[:Djn] = value.(model_dict[:Djn]) # Consumption per good pre-transport cost
65+
results[:Dj] = dropdims(value.(model_dict[:Dj]), dims = 2)
66+
results[:cj] = value.(model_dict[:cj])
67+
results[:Cj] = results[:cj] .* param.Lj
68+
results[:hj] = ifelse.(results[:Lj] .== 0, 0.0, param.Hj ./ results[:Lj])
69+
results[:uj] = value.(model_dict[:uj])
70+
# Prices
71+
results[:Pjn] = shadow_price.(model_dict[:Pjn])
72+
results[:PCj] = dropdims(sum(results[:Pjn] .^ (1-param.sigma), dims=2), dims = 2) .^ (1/(1-param.sigma))
73+
# Network flows
74+
Qin_direct = value.(model_dict[:Qin_direct])
75+
Qin_indirect = value.(model_dict[:Qin_indirect])
76+
results[:Qin] = max.(Qin_direct, Qin_indirect) - min.(Qin_direct, Qin_indirect)
77+
results[:Qjkn] = gen_network_flows(results[:Qin], graph, param.N)
78+
return results
79+
end

0 commit comments

Comments
 (0)