|
| 1 | +# The primal case, with labor mobility, no cross-good congestion, and an Armington (1969) world where each location produces only one good |
| 2 | + |
| 3 | +function model_mobility_armington(optimizer, auxdata) |
| 4 | + |
| 5 | + # Parameters and data |
| 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 | + psigma = (param.sigma - 1) / param.sigma |
| 13 | + Hj = param.Hj |
| 14 | + |
| 15 | + # Model |
| 16 | + model = Model(optimizer) |
| 17 | + set_string_names_on_creation(model, false) |
| 18 | + |
| 19 | + # Variables + bounds |
| 20 | + @variable(model, u, start = 0.0) # Overall utility |
| 21 | + @variable(model, Cjn[1:graph.J, 1:param.N] >= 1e-8, container=Array, start = 1e-6) # Good specific consumption |
| 22 | + @variable(model, Qin[1:graph.ndeg, 1:param.N], container=Array, start = 0.0) # Good specific flow |
| 23 | + @variable(model, 1e-8 <= Lj[1:graph.J] <= 1, container=Array, start = 1 / graph.J) # Total labour |
| 24 | + |
| 25 | + # Parameters: to be updated between solves |
| 26 | + @variable(model, kappa_ex[i = 1:graph.ndeg] in Parameter(i), container=Array) |
| 27 | + set_parameter_value.(kappa_ex, kappa_ex_init) |
| 28 | + |
| 29 | + # Objective |
| 30 | + @objective(model, Max, u) |
| 31 | + |
| 32 | + # Utility constraint (Lj*u <= ... ) |
| 33 | + for j in 1:graph.J |
| 34 | + Cj = sum(Cjn[j, n]^psigma for n in 1:param.N)^(1 / psigma) |
| 35 | + @constraint(model, Lj[j] * u - (Cj / param.alpha)^param.alpha * (Hj[j] / (1 - param.alpha))^(1 - param.alpha) <= -1e-8) |
| 36 | + end |
| 37 | + |
| 38 | + # balanced flow constraints |
| 39 | + @expression(model, Yjn[j=1:graph.J, n=1:param.N], param.Zjn[j, n] * Lj[j]^param.a) |
| 40 | + @constraint(model, Pjn[j in 1:param.J, n in 1:param.N], |
| 41 | + Cjn[j, n] + sum(A[j, i] * Qin[i, n] for i in 1:graph.ndeg) - |
| 42 | + Yjn[j, n] + sum( |
| 43 | + ifelse(Qin[i, n] > 0, Apos[j, i], Aneg[j, i]) * |
| 44 | + abs(Qin[i, n])^(1 + param.beta) / kappa_ex[i] |
| 45 | + for i in 1:graph.ndeg |
| 46 | + ) <= -1e-8 |
| 47 | + ) |
| 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_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[:Cjn] = value.(model_dict[:Cjn]) |
| 65 | + results[:Cj] = dropdims(sum(results[:Cjn] .^ ((param.sigma-1)/param.sigma), dims=2), dims = 2) .^ (param.sigma/(param.sigma-1)) |
| 66 | + results[:Lj] = value.(model_dict[:Lj]) |
| 67 | + results[:Ljn] = (param.Zjn .> 0) .* results[:Lj] |
| 68 | + results[:cj] = ifelse.(results[:Lj] .== 0, 0.0, results[:Cj] ./ results[:Lj]) |
| 69 | + results[:hj] = ifelse.(results[:Lj] .== 0, 0.0, param.Hj ./ results[:Lj]) |
| 70 | + results[:uj] = param.u.(results[:cj], results[:hj]) |
| 71 | + # Prices |
| 72 | + results[:Pjn] = shadow_price.(model_dict[:Pjn]) |
| 73 | + results[:PCj] = dropdims(sum(results[:Pjn] .^ (1-param.sigma), dims=2), dims=2) .^ (1/(1-param.sigma)) |
| 74 | + # Network flows |
| 75 | + results[:Qin] = value.(model_dict[:Qin]) |
| 76 | + results[:Qjkn] = gen_network_flows(results[:Qin], graph, param.N) |
| 77 | + return results |
| 78 | +end |
0 commit comments