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