Skip to content

Commit 78b9a4d

Browse files
committed
Even more Armington.
1 parent 78e9c0d commit 78b9a4d

2 files changed

Lines changed: 88 additions & 2 deletions

File tree

src/main/optimal_network.jl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,13 @@ function optimal_network(param, graph; I0=nothing, Il=nothing, Iu=nothing, verbo
7373
end
7474
recover_allocation = param.recover_allocation
7575
elseif param.mobility == 1 && param.cong
76-
model = model_mobility_cgc(optimizer, auxdata)
77-
recover_allocation = recover_allocation_mobility_cgc
76+
if all(sum(param.Zjn .> 0, dims = 2) .<= 1) # Armington case
77+
model = model_mobility_cgc_armington(optimizer, auxdata)
78+
recover_allocation = recover_allocation_mobility_cgc_armington
79+
else
80+
model = model_mobility_cgc(optimizer, auxdata)
81+
recover_allocation = recover_allocation_mobility_cgc
82+
end
7883
elseif param.mobility == 0.5 && param.cong
7984
model = model_partial_mobility_cgc(optimizer, auxdata)
8085
recover_allocation = recover_allocation_partial_mobility_cgc
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# The primal case, with mobility and cross-good congestion, and an Armington (1969) world where each location produces only one good
2+
3+
function model_mobility_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+
m = param.m # Vector of weights on each goods flow for aggregate congestion term
13+
psigma = (param.sigma - 1) / param.sigma
14+
beta_nu = (param.beta + 1) / param.nu
15+
16+
# Model
17+
model = Model(optimizer)
18+
set_string_names_on_creation(model, false)
19+
20+
# Variable declarations
21+
@variable(model, u, start = 0.0) # Overall utility
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, cj[1:graph.J] >= 1e-8, container=Array, start = 1e-6) # Overall consumption bundle, including transport costs
24+
@variable(model, Qin_direct[1:graph.ndeg, 1:param.N] >= 1e-8, container=Array, start = 0.0) # Direct aggregate flow
25+
@variable(model, Qin_indirect[1:graph.ndeg, 1:param.N] >= 1e-8, container=Array, start = 0.0) # Indirect aggregate flow
26+
@variable(model, 1e-8 <= Lj[1:graph.J] <= 1, container=Array, start = 1 / graph.J) # Overall labour
27+
28+
# Parameters: to be updated between solves
29+
@variable(model, kappa_ex[i = 1:graph.ndeg] in Parameter(i), container=Array)
30+
set_parameter_value.(kappa_ex, kappa_ex_init)
31+
32+
# Objective
33+
@objective(model, Max, u)
34+
35+
# Utility constraint (Lj*u <= ... )
36+
@constraint(model, Lj .* u - (cj .* Lj / param.alpha) .^ param.alpha .* (param.Hj / (1 - param.alpha)) .^ (1 - param.alpha) .<= -1e-8)
37+
38+
# Create the matrix B_direct (resp. B_indirect) of transport cost along the direction of the edge (resp. in edge opposite direction)
39+
B_direct = @expression(model, ((Qin_direct .^ param.nu) * m) .^ beta_nu ./ kappa_ex)
40+
B_indirect = @expression(model, ((Qin_indirect .^ param.nu) * m) .^ beta_nu ./ kappa_ex)
41+
# Final good constraints
42+
@expression(model, Dj, sum(Djn .^ psigma, dims=2) .^ (1 / psigma))
43+
@constraint(model, cj .* Lj + Apos * B_direct + Aneg * B_indirect - Dj .<= -1e-8)
44+
45+
# Balanced flow constraints
46+
@expression(model, Yjn, param.Zjn .* (Lj .^ param.a))
47+
@constraint(model, Pjn, Djn + A * Qin_direct - A * Qin_indirect - Yjn .<= -1e-8)
48+
49+
# Labor resource constraint
50+
@constraint(model, -1e-8 <= sum(Lj) - 1 <= 1e-8)
51+
52+
return model
53+
end
54+
55+
function recover_allocation_mobility_cgc_armington(model, auxdata)
56+
param = auxdata.param
57+
graph = auxdata.graph
58+
model_dict = model.obj_dict
59+
results = Dict()
60+
61+
results[:welfare] = value(model_dict[:u])
62+
results[:Yjn] = value.(model_dict[:Yjn])
63+
results[:Yj] = dropdims(sum(results[:Yjn], dims=2), dims = 2)
64+
results[:Lj] = value.(model_dict[:Lj])
65+
results[:Ljn] = (param.Zjn .> 0) .* results[:Lj]
66+
results[:Djn] = value.(model_dict[:Djn]) # Consumption per good pre-transport cost
67+
results[:Dj] = dropdims(value.(model_dict[:Dj]), dims = 2)
68+
results[:cj] = value.(model_dict[:cj])
69+
results[:Cj] = results[:cj] .* results[:Lj]
70+
results[:hj] = ifelse.(results[:Lj] .== 0, 0.0, param.Hj ./ results[:Lj])
71+
results[:uj] = param.u.(results[:cj], results[:hj])
72+
# Prices
73+
results[:Pjn] = shadow_price.(model_dict[:Pjn])
74+
results[:PCj] = dropdims(sum(results[:Pjn] .^ (1-param.sigma), dims=2), dims=2) .^ (1/(1-param.sigma))
75+
# Network flows
76+
Qin_direct = value.(model_dict[:Qin_direct])
77+
Qin_indirect = value.(model_dict[:Qin_indirect])
78+
results[:Qin] = ifelse.(Qin_direct .> Qin_indirect, Qin_direct, -Qin_indirect)
79+
results[:Qjkn] = gen_network_flows(results[:Qin], graph, param.N)
80+
return results
81+
end

0 commit comments

Comments
 (0)