API Reference
JuMP.set_lower_boundJuMP.set_start_valueJuMP.set_upper_boundMPSGE._parse_ref_setsMPSGE._strip_nest_elasticityMPSGE._strip_nest_nameMPSGE.build_name_exprMPSGE.build_nest_and_parentMPSGE.build_string_exprMPSGE.cost_functionMPSGE.create_nodesMPSGE.extract_scalarsMPSGE.generate_reportMPSGE.parse_mpsge_ref_setsMPSGE.parse_netputMPSGE.parse_ref_setsMPSGE.production_sectorsMPSGE.revenue_functionMPSGE.sectorsMPSGE.sectorsMPSGE.solve!MPSGE.@auxiliariesMPSGE.@auxiliaryMPSGE.@commoditiesMPSGE.@commodityMPSGE.@consumerMPSGE.@consumersMPSGE.@demandMPSGE.@endowmentMPSGE.@final_demandMPSGE.@inputMPSGE.@outputMPSGE.@parameterMPSGE.@parametersMPSGE.@productionMPSGE.@sectorMPSGE.@sectors
JuMP.set_lower_bound — Methodset_lower_bound(X::MPSGEScalarVariable, val::Real)Set the lower bound of an MPSGE variable. This is an extension of the JuMP function set_lower_bound.
JuMP.set_start_value — Methodset_start_value(X::MPSGEScalarVariable, val::Real)Set the staring value of an MPSGE variable. This is an extension of the JuMP function set_start_value.
JuMP.set_upper_bound — Methodset_upper_bound(X::MPSGEScalarVariable, val::Real)Set the upper bound of an MPSGE variable. This is an extension of the JuMP function set_upper_bound.
MPSGE._parse_ref_sets — Method_parse_ref_sets(error_fn::Function, expr::Expr)Called by parse_ref_sets to extract the index variables, index sets, and all indices from an expression of the form Y[r, :a, i=I].
Performs checks to interpret the expressions.
Adapted from JuMP.
MPSGE._strip_nest_elasticity — Method_strip_nest_elasticity(nest)Strips the elasticity from a nest expression. Handles either,
s = σ, root nodesva => s = σ, child nodes
MPSGE._strip_nest_name — Method_strip_nest_name(nest)Strips the name and parent from a nest expression. Handles either,
s = σ, root nodes (child iss, parent ismissing)va => s = σ, child nodes (child isva, parent iss)
MPSGE.build_name_expr — Methodbuild_name_expr(name::Union{Symbol,Nothing}, index_vars::Vector, kwargs::Dict{Symbol,Any})Builds an expression that represents the name of a reference set, including the index variables.
Adapted from JuMP, however the JuMP version returns a String where as this returns a usuable object, like a Sector.
MPSGE.build_nest_and_parent — Methodbuild_nest_and_parent(nest_arg::Expr, source)Return an expression that evaluates to
((Nest, nest base name), (Parent, parent base name))MPSGE.build_string_expr — Methodbuild_string_expr(name::Union{Symbol,Nothing}, index_vars::Vector, kwargs::Dict{Symbol,Any})Builds a string expression that represents the name of a reference set, including the index variables.
Adapted from the JuMP build_name_expr.
MPSGE.cost_function — Methodcost_function(S::ScalarSector; virtual = false)
cost_function(S::ScalarSector, nest::Symbol; virtual = false)Return a vector of cost functions for the given sector and nest. If nest is not provided return the cost function for input tree.
nest is the symbol representing the nest. This can also be the name of a commodity.
If virtual is true, return the virtual cost functions.
MPSGE.create_nodes — Methodcreate_nodes(generated_nodes::Vector{Any})Given a vector of generated nodes, create the nodes and two required trees.
Returns
(nodes::Dict{Symbol, MPSGE.Node}, root_nodes::Vector{MPSGE.Node})MPSGE.extract_scalars — Methodextract_scalarsTakes a variable and extracts it the sub-variables.
MPSGE.generate_report — Methodgenerate_report(M::MPSGEModel)Returns a dataframe with three columns, the variable, the value and the margin. The product of the value and the marge should be zero, if not the model has a specification error.
This function is useful for debugging models that fail a calibrated benchmark. If the model fails the benchmark, look for non-zero margins in this report, as they will reveal the error.
MPSGE.parse_mpsge_ref_sets — Methodparse_mpsge_ref_sets(error_fn::Function, index_vars, index_sets, all_indices, arg::Expr)Builds the three vectors index_vars, index_sets, and all_indices from an expression arg that is part of a reference set.
Expressions of the form i=S, i∈S, and i in S are interpreted as index variables, and will set up variables to create an indexed object.
Otherwise expressions are escaped and treated as scalars.
MPSGE.parse_netput — Methodparse_netput(error_fn::Function, netput_arg::Any)Main code that goes in the macro
Return
(netput, parent nest)MPSGE.parse_ref_sets — Methodparse_ref_sets(error_fn::Function, expr::Expr)Given an expression of the form Y[r, :a, i=I] extract four components:
name: the name of the reference set, in this caseY.index_vars: a vector of index variables, in this case[:i]. In this case, onlyiis an index variable, whilerand:aare not as they do not have and=.indices: an expression representing the Cartesian product of the index sets, in this example it's onlyI.all_indices: a vector of all indices, in this case[:r, :(:a), :i].
This is used in macros.
MPSGE.production_sectors — Methodproduction_sectors(m::MPSGEModel)Return all sectors that have a corresponding production block. These are coming from a dictionary, so order is not guaranteed.
This is primarily used when generating constraints.
MPSGE.revenue_function — Methodrevenue_function(S::ScalarSector; virtual = false)
revenue_function(S::ScalarSector, nest::Symbol; virtual = false)Return a vector of revenue functions for the given sector and nest. If nest is not provided return the revenue function for input tree.
nest is the symbol representing the nest. This can also be the name of a commodity.
If virtual is true, return the virtual revenue functions.
MPSGE.sectors — Methodsectors(C::Commodity)Return only the sectors that have the input commodity in their production block.
This is an optimization in building the model as the structure is very sparse iterating over all sectors is expensive.
MPSGE.sectors — Methodsectors(m::MPSGEModel)Return all sectors in a model
MPSGE.solve! — Methodsolve!(m::abstract_mpsge_model; keywords)
Function to solve the model. Triggers the build if the model hasn't been built yet.Example
julia> solve!(m, cumulative_iteration_limit=0)MPSGE.@auxiliaries — Macro@auxiliaries(model, args...)Adds multiple @auxiliary to a model.
The model must be the first argument, and multiple auxiliaries can be added in a begin ... end block, one auxiliary per line.
Example
julia> M = MPSGEModel()
julia> I = [:a,:b]
julia> @auxiliaries(M, begin
X[i=I]
Y[i=I,j=I], (description = "This is an indexed variable")
Z, (description = "Scalar variable")
end)MPSGE.@auxiliary — Macro@auxiliary(model, X, kwargs...)
@auxiliary(model, X[I], kwargs...)
@auxiliary(model, X[i=I], kwargs...)Create a auxiliary in the model with name X, index I, and index name i with arguments kwargs.
Arguments
model: An isntance ofMPSGEModel.- The auxiliary
Xcan be instantiated in a several ways.Xcreates a scalar auxiliary- If
Iis a defined array, thenX[I]creates an indexed auxiliary with
I.- If
Iis a defined array, thenX[i=I]creates an indexed auxiliary with
Iand variable index namedi.
If you want to create an index auxiliary it is highly recommended to use the syntax from (3) with better name for i, For example X[goods=I], this will get the index name to goods which will be displayed when printing the model. For example creating a variable using
@auxiliary(M, X[goods=I], description = "Auxiliary with indexed variables")will allow the auxiliary to be printed as
X[goods] -- Auxiliary with indexed variablesAdditionally, multi-indexed auxiliaries can be created by using the syntax X[regions = R, goods = G].
Optional Arguments
description: Set a description on a variable.start: Set the starting value of the variable Default 0.0lower_bound: Set the lower bound of the variable. Default-Inf.upper_bound: Set the upper bound of the variable. DefaultInf.
Examples
using MPSGE
R = Symbol.(:r, 1:5)
G = Symbol.(:g, 1:5)
M = MPSGEModel()
@auxiliary(M, X[region=R, goods=G], description="Auxiliary with indexed variables")By default auxiliary variables start at 0 with no lower or upper bounds. These can be set after variable creating using set_start_value, set_lower_bound, and set_upper_bound.
MPSGE.@commodities — Macro@commodities(model, args...)Adds multiple @commodity to a model.
The model must be the first argument, and multiple commodities can be added in a begin ... end block, one commodity per line.
Example
julia> M = MPSGEModel()
julia> I = [:a,:b]
julia> @commodities(M, begin
X[i=I]
Y[i=I,j=I], (description = "This is an indexed variable")
Z, (description = "Scalar variable")
end)MPSGE.@commodity — Macro@commodity(model, C, kwargs...)
@commodity(model, C[I], kwargs...)
@commodity(model, C[i=I], kwargs...)Create a commodity in the model with name C, index I, and index name i with arguments kwargs.
Arguments
model: An isntance ofMPSGEModel.- The commodity
Ccan be instantiated in a several ways.Ccreates a scalar commodity- If
Iis a defined array, thenC[I]creates an indexed commodity with
I.- If
Iis a defined array, thenC[i=I]creates an indexed commodity with
Iand variable index namedi.
If you want to create an index commodity it is highly recommended to use the syntax from (3) with better name for i, For example C[goods=I], this will get the index name to goods which will be displayed when printing the model. For example creating a variable using
@commodity(M, C[goods=I], description = "Commodity with indexed variables")will allow the commodity to be printed as
C[goods] -- Commodity with indexed variablesAdditionally, multi-indexed commoditys can be created by using the syntax C[regions = R, goods = G].
Optional Arguments
description: Set a description on a variable.start: Set the starting value of the variable Default 1.0lower_bound: Set the lower bound of the variable. Default 0.upper_bound: Set the upper bound of the variable. DefaultInf.
Examples
using MPSGE
R = Symbol.(:r, 1:5)
G = Symbol.(:g, 1:5)
M = MPSGEModel()
@commodity(M, C[region=R, goods=G], description="Commodity with indexed variables")MPSGE.@consumer — Macro@consumer(model, H, kwargs...)
@consumer(model, H[I], kwargs...)
@consumer(model, H[i=I], kwargs...)Create a consumer in the model with name H, index I, and index name i with arguments kwargs.
Arguments
model: An isntance ofMPSGEModel.- The consumer
Hcan be instantiated in a several ways.Hcreates a scalar consumer- If
Iis a defined array, thenH[I]creates an indexed consumer with
I.- If
Iis a defined array, thenH[i=I]creates an indexed consumer with
Iand variable index namedi.
If you want to create an index consumer it is highly recommended to use the syntax from (3) with better name for i, For example H[goods=I], this will get the index name to goods which will be displayed when printing the model. For example creating a variable using
@consumer(M, H[goods=I], description = "Consumer with indexed variables")will allow the consumer to be printed as
H[goods] -- Consumer with indexed variablesAdditionally, multi-indexed consumers can be created by using the syntax H[regions = R, goods = G].
Optional Arguments
description: Set a description on a variable.start: Set the starting value of the variable Default 1.0lower_bound: Set the lower bound of the variable. Default 0.upper_bound: Set the upper bound of the variable. DefaultInf.
Examples
using MPSGE
R = Symbol.(:r, 1:5)
G = Symbol.(:g, 1:5)
M = MPSGEModel()
@consumer(M, H[region=R, goods=G], description="Consumer with indexed variables")MPSGE.@consumers — Macro@consumers(model, args...)Adds multiple @consumer to a model.
The model must be the first argument, and multiple consumers can be added in a begin ... end block, one consumer per line.
Example
julia> M = MPSGEModel()
julia> I = [:a,:b]
julia> @consumers(M, begin
X[i=I]
Y[i=I,j=I], (description = "This is an indexed variable")
Z, (description = "Scalar variable")
end)MPSGE.@demand — Macro@demand(model, comsumer, demand_netputs; elasticity = 1)Define a demand for a consumer in the model with given demand_netputs where the final_demands have an elasticity of substitution elasticity.
consumer
The consumer can take the following forms:
X, ifXis a scalar consumer.X[i=I,j=J,...]if the consumer is indexed. IndexingX[i=I, :j]if:jis an element of the second index ofX.X[i=I, j]ifjis defined outside the demand block, for example in aforloop.
For an indexed consumer it is required that an index is provided when iterating over an array. For example,
julia> I = [:a,:b]
julia> @consumer(M, X[i=I])
julia> demand(M, X[I], ...) # This is not allowed and will error.
julia> demand(M, X[i=I], ...) # This is required behavior.
julia> for i in I
demand(M, X[i], ...) # This is allowed.
enddemand_netputs
A demand netput is either a @final_demand or an @endowment. The netputs get wrapped in a begin ... end block and each netput must be on its own line. For examples creating netputs, see the netput documentation and the examples below.
Netputs can use indices initialized in the consumer, but can not use them as a new index. For example, if we have X[i=I] in the demand block, we can use @final_demand(PX[i],...) but not @final_demand(PX[i=I],...). The latter will error.
Examples
We demonstrate three ways to define a demand block.
julia> M = MPSGEModel();
julia> I = [:a,:b]
julia> @parameters(M, begin
elas[i=I,j=J], 4
T[i=I], .1
end)
julia> @commodities(M, begin
PX
PY
PL[i=I]
PK
end);
julia> @consumers(M, begin
X
Y[i=I, j=J]
Z[i=I]
end);
julia> @demand(M, X, begin
@final_demand(PX, 10, t)
@endowment(PL, 5, s)
@endowment(PK, 5, s)
end);
julia> @demand(M, Y[i=I,j=J], [s=2, t=1, begin
@final_demand(PY, 15, t, reference_price = 2)
@endowment(PX, 3, s)
@endowment(PL[ii=I], 4, va[ii])
@endowment(PK, 6, va[i])
end, elasticity = 2);
julia> for i in I
@demand(M, Z[i], begin
@final_demand(PK, 20, t)
@endowment(PL[i], 2, s)
end)
endMPSGE.@endowment — Macro@endowment(commodity, quantity, nest, kwargs...)This macro is soley used within a @demand block to define the endowments for a consumer.
Required Arguments
commodity- A commodity. This can either be a scalarCor indexedC[i=R].quantity- Either a number or expression.
Examples
@endowment(C, 1)
@endowment(C[i=R], 1)
@endowment(C[i=R], quantity[i])MPSGE.@final_demand — Macro@final_demand(commodity, quantity, nest, kwargs...)This macro is soley used within a @demand block to define the final demands for a consumer.
Required Arguments
commodity- A commodity. This can either be a scalarCor indexedC[i=R].quantity- Either a number or expression.
Keyword Arguments
reference_price=1Set the reference price of a commodity.
Examples
@final_demand(C, 1)
@final_demand(C[i=R], 1)
@final_demand(C[i=R], quantity[i])
@final_demand(C[i=R], quantity[i], reference_price = price[i])MPSGE.@input — Macro@input(commodity, quantity, nest, kwargs...)This macro is soley used within a @production block to define the inputs for a sector.
Required Arguments
commodity- A commodity. This can either be a scalarCor indexedC[i=R].quantity- Either a number or expression.nest- The parent nest of the input.
Keyword Arguments
taxesassociate a tax to the commodity. The syntaxtaxes = [Tax(RA, .1), Tax(GOVT, .3)]defines two taxes, one associated the consumerRAand another withGOVT. In this example the values are fixed, but they can also be parameters.reference_price=1Set the reference price of a commodity.
Examples
@input(C, 1, nest, taxes = [Tax(RA, .1), Tax(GOVT, .3)])
@input(C[i=R], 1, nest)
@input(C[i=R], quantity[i], nest[i])
@input(C[i=R], quantity[i], nest[i], reference_price = price[i])
@input(C[i=R], quantity[i], nest[i], taxes = [Tax(RA, tax[i]), Tax(GOVT, .5)])MPSGE.@output — Macro@output(commodity, quantity, nest, kwargs...)This macro is soley used within a @production block to define the outputs for a sector.
Required Arguments
commodity- A commodity. This can either be a scalarCor indexedC[i=R].quantity- Either a number or expression.nest- The parent nest of the output.
Keyword Arguments
taxesassociate a tax to the commodity. The syntaxtaxes = [Tax(RA, .1), Tax(GOVT, .3)]defines two taxes, one associated the consumerRAand another withGOVT. In this example the values are fixed, but they can also be parameters.reference_price=1Set the reference price of a commodity.
Examples
@output(C, 1, nest, taxes = [Tax(RA, .1), Tax(GOVT, .3)])
@output(C[i=R], 1, nest)
@output(C[i=R], quantity[i], nest[i])
@output(C[i=R], quantity[i], nest[i], reference_price = price[i])
@output(C[i=R], quantity[i], nest[i], taxes = [Tax(RA, tax[i]), Tax(GOVT, .5)])MPSGE.@parameter — Macro@parameter(model, expr, value, kwargs...)Add a parameter to the model described by expr with initial value value and keyword arguments kwargs....
Required Arguments
modelis the MPSGE modelexpran expression that describes the name and index of the parameter. See the examples belowvalueThe initial value of the parameter.
Keyword Arguments
descriptionA string describing the parameter.
Examples
Non-Indexed Parameters
using MPSGE
M = MPSGEModel()
initial_value = 10
@parameter(M, X, 1)
@parameter(M, Y, initial_value, description="A parameter")Indexed Parameters
using MPSGE
M = MPSGEModel()
R = 1:5
S = 1:3
one_dimension = Dict(r => 2*r for r in R)
two_dimension = Dict((r,s) => r+s for r in R, s in S)
@parameter(M, X[r=R], 1, description = "example") # Index `R` and value 1 with a description
@parameter(M, Y[R, S], 1) # Indices `R` and `S` and value 1.
@parameter(M, Z[r=R], one_dimension[r]) # Index `R` and values `one_dimension[r]`.
@parameter(M, W[r=R, s=S], two_dimension[r, s]) # Indices `R` and `S` and values `two_dimension[r, s]`.MPSGE.@parameters — Macro@parameters(model, args...)Adds multiple parameters to model at once, in the same fashion as the @parameter macro.
The model must be the first argument, and multiple parameters can be added on multiple lines wrapped in a begin ... end block.
The macro returns a tuple containing the parameters that were defined.
Example
using MPSGE
model = MPSGEModel();
@parameters(model, begin
x, 1
y[i = 1:2], i, (description = "y parameter")
end)MPSGE.@production — Macro@production(model, sector, nestings, netputs)Define a production for the sector in the model with given nestings and netputs.
sector
The sector can take the following forms:
X, ifXis a scalar sector.X[i=I,j=J,...]if the sector is indexed. IndexingX[i=I, :j]if:jis an element of the second index ofX.X[i=I, j]ifjis defined outside the production block, for example in aforloop.
For an indexed sector it is required that an index is provided when iterating over an array. For example,
julia> I = [:a,:b]
julia> @sector(M, X[i=I])
julia> @production(M, X[I], ...) # This is not allowed and will error.
julia> @production(M, X[i=I], ...) # This is required behavior.
julia> for i in I
@production(M, X[i], ...) # This is allowed.
endnestings
This is where the nesting structure is defined and the associated elasticities. At minimum you must declare at least two nests and elasticities, one for the elasticity of substitution (input) and one for the elasticity of transformation (output), by convention these are denoted s and t respectively, although any identifier may be used. As a minimal example, [s=1, t=0] will set the s nest to have an elasticity of 1 and the t nest 0.
Additional nests must have a parent nest, which is defined by the => operator. For example, if you want a nest below s called va with an elasticity of 2, this is created with [s=1, t=0, va=>s=2]. The va points at its parent nest s and the elasticity follows. Nestings can be arbitrarily deep, for example
[s=1, t=0, va=>s=2, dm=>s=1, d=>dm=2]will have two nests, va and dm, below s and one below dm, namely d.
Non-root nests can also be indexed. For example, if I=[:a,:b], we can created an indexed nest with [s=1, t=0, va[i=I]=>s=2]. This will create a nest va for each element of I with an elasticity of 2.
Finally, elasticities can be either numbers, parameters, or a defined expression. For example, all of the following define nestings if the sectors and parameters are defined:
julia> V = Dict(:a => 1, :b => 2)
julia> I = [:a,:b]
julia> J = [:c, :d]
julia> @production(M, X, [s=1,t=0, va[i=I]=> s = V[i], ...)
julia> @production(M, X[i=I], [s = V[i], t=0, va=>s=V[i]], ...)
julia> @production(M, X[i=I], [s = 0, t=0, va[ii=I, j=J] => s = V[ii]],...)netputs
A netput is either an @input or an @output. The netputs get wrapped in a begin ... end block and each netput must be on its own line. For examples creating netputs, see the netput documentation and the examples below.
Netputs can use indices initialized in the sector, but can not use them as a new index. For example, if we have X[i=I] in the production block, we can use @input(PX[i],...) but not @input(PX[i=I],...). The latter will error.
Examples
We demonstrate three ways to define a production block.
julia> M = MPSGEModel();
julia> I = [:a,:b]
julia> @parameters(M, begin
elas[i=I,j=J], 4
T[i=I], .1
end)
julia> @sectors(M, begin
X
Y[i=I, j=J]
Z[i=I]
end);
julia> @commodities(M, begin
PX
PY
PL[i=I]
PK
end);
julia> @consumer(M, RA);
julia> @production(M, X, [s=1,t=0], begin
@output(PX, 10, t)
@input(PL, 5, s)
@input(PK, 5, s)
end);
julia> @production(M, Y[i=I,j=J], [s=2, t=1, va[ii=I]=>s=elas[i,ii]], begin
@output(PY, 15, t)
@input(PX, 3, s)
@input(PL[ii=I], 4, va[ii], taxes = [Tax(RA, .5)])
@input(PK, 6, va[i])
end);
julia> for i in I
@production(M, Z[i], [s=1, t=0], begin
@output(PK, 20, t)
@input(PL[i], 2, s, taxes = [Tax(RA, T[i])])
end)
endMPSGE.@sector — Macro@sector(model, S, kwargs...)
@sector(model, S[I], kwargs...)
@sector(model, S[i=I], kwargs...)Create a sector in the model with name S, index I, and index name i with arguments kwargs.
Arguments
model: An isntance ofMPSGEModel.- The sector
Scan be instantiated in a several ways.Screates a scalar sector- If
Iis a defined array, thenS[I]creates an indexed sector with
I.- If
Iis a defined array, thenS[i=I]creates an indexed sector with
Iand variable index namedi.
If you want to create an index sector it is highly recommended to use the syntax from (3) with better name for i, For example S[goods=I], this will set the index name to goods which will be displayed when printing the model. For example creating a variable using
@sector(M, S[goods=I], description = "Sector with indexed variables")will allow the sector to be printed as
S[goods] -- Sector with indexed variablesAdditionally, multi-indexed sectors can be created by using the syntax S[regions = R, goods = G].
Optional Arguments
description: Set a description on a variable.start: Set the starting value of the variable Default 1.0lower_bound: Set the lower bound of the variable. Default 0.upper_bound: Set the upper bound of the variable. DefaultInf.
Examples
using MPSGE
R = Symbol.(:r, 1:5)
G = Symbol.(:g, 1:5)
M = MPSGEModel()
@sector(M, S[region=R, goods=G], description="Sector with indexed variables", start = 1.5)MPSGE.@sectors — Macro@sectors(model, args...)Adds multiple @sector to a model.
The model must be the first argument, and multiple sectors can be added in a begin ... end block, one sector per line.
Example
julia> M = MPSGEModel()
julia> I = [:a,:b]
julia> @sectors(M, begin
X[i=I]
Y[i=I,j=I], (description = "This is an indexed variable")
Z, (description = "Scalar variable")
end)