|
| 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