JuMP.set_lower_bound
JuMP.set_start_value
JuMP.set_upper_bound
MPSGE._parse_ref_sets
MPSGE._strip_nest_elasticity
MPSGE._strip_nest_name
MPSGE.build_name_expr
MPSGE.build_nest_and_parent
MPSGE.build_string_expr
MPSGE.cost_function
MPSGE.create_nodes
MPSGE.extract_scalars
MPSGE.generate_report
MPSGE.parse_mpsge_ref_sets
MPSGE.parse_netput
MPSGE.parse_ref_sets
MPSGE.production_sectors
MPSGE.revenue_function
MPSGE.sectors
MPSGE.sectors
MPSGE.solve!
MPSGE.@auxiliaries
MPSGE.@auxiliary
MPSGE.@commodities
MPSGE.@commodity
MPSGE.@consumer
MPSGE.@consumers
MPSGE.@demand
MPSGE.@endowment
MPSGE.@final_demand
MPSGE.@input
MPSGE.@output
MPSGE.@parameter
MPSGE.@parameters
MPSGE.@production
MPSGE.@sector
MPSGE.@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_scalars
Takes 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.
Different input types are handled differently.
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, onlyi
is an index variable, whiler
and:a
are 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
X
can be instantiated in a several ways.X
creates a scalar auxiliary- If
I
is a defined array, thenX[I]
creates an indexed auxiliary with
I
.- If
I
is a defined array, thenX[i=I]
creates an indexed auxiliary with
I
and 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 variables
Additionally, 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
C
can be instantiated in a several ways.C
creates a scalar commodity- If
I
is a defined array, thenC[I]
creates an indexed commodity with
I
.- If
I
is a defined array, thenC[i=I]
creates an indexed commodity with
I
and 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 variables
Additionally, 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
H
can be instantiated in a several ways.H
creates a scalar consumer- If
I
is a defined array, thenH[I]
creates an indexed consumer with
I
.- If
I
is a defined array, thenH[i=I]
creates an indexed consumer with
I
and 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 variables
Additionally, 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, consumer, demand_flow_block, kwargs...)
Example
@demand(M, CONS, begin
@final_demand(X, 10)
@endowment(Y, 5)
@endowment(Z, 10)
end)
MPSGE.@endowment
— Macro@endowment(commodity, quantity, kwargs...)
MPSGE.@final_demand
— Macro@final_demand(commodity, quantity, kwargs...)
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 scalarC
or indexedC[i=R]
.quantity
- Either a number or expression.nest
- The parent nest of the input.
Keyword Arguments
taxes
associate a tax to the commodity. The syntaxtaxes = [Tax(RA, .1), Tax(GOVT, .3)]
defines two taxes, one associated the consumerRA
and another withGOVT
. In this example the values are fixed, but they can also be parameters.reference_price=1
Set 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 scalarC
or indexedC[i=R]
.quantity
- Either a number or expression.nest
- The parent nest of the output.
Keyword Arguments
taxes
associate a tax to the commodity. The syntaxtaxes = [Tax(RA, .1), Tax(GOVT, .3)]
defines two taxes, one associated the consumerRA
and another withGOVT
. In this example the values are fixed, but they can also be parameters.reference_price=1
Set 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
model
is the MPSGE modelexpr
an expression that describes the name and index of the parameter. See the examples belowvalue
The initial value of the parameter.
Keyword Arguments
description
A 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
, ifX
is a scalar sector.X[i=I,j=J,...]
if the sector is indexed. IndexingX[i=I, :j]
if:j
is an element of the second index ofX
.X[i=I, j]
ifj
is defined outside the production block, for example in afor
loop.
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.
end
nestings
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)
end
MPSGE.@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
S
can be instantiated in a several ways.S
creates a scalar sector- If
I
is a defined array, thenS[I]
creates an indexed sector with
I
.- If
I
is a defined array, thenS[i=I]
creates an indexed sector with
I
and 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 variables
Additionally, 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)