MPSGE Overview
February 27, 2026
At its core, the MPSGE.jl package creates a JuMP.jl model with the necessary constraints of a CGE model. Namely: zero profit, income balance, market clearance, and any auxiliary constraints. This appendix gives the mathematical background on how these constraints are created given a model specified by MPSGE.
MPSGE Variables
There are five types of variables in MPSGE: parameters, sectors, commodities, consumers, and auxiliary variables.
Parameters are fixed variables that can be modified between solves.
These are used to introduce exogenous values into the model; a common
example being a tax. MPSGE.jl requires parameters to be explicitly
defined in a @parameter macro. This is in contrast to GAMS
where all non-variable values in a model are considered to be
parameters.
Sectors, or activities, are production activities that convert commodity inputs into commodity outputs. The variable associated with a sector is the activity level of that sector. Sectors are assumed to be initially operating at 100% capacity, which makes the starting level be 1. Each sector corresponds to exactly one production block in the model.
Commodities, or markets, are goods or services that are bought and sold in the economy. The variable associated with a commodity represents the price of the commodity. Initial prices are assumed to be 1. We will discuss the relationship between the price, activity level, and quantity when we discuss production blocks.
Consumers are representative agents with final demands and they supply market with endowments, receive tax revenue, and pay subsidies. The variable associated with a consumer is the total income of the consumer with starting value equal to the initial income level.
Auxiliary variables are used to represent additional economic
concepts not captured by sectors, commodities, or consumers. They can
represent endogenous quantities which are functions of other variables
such as prices and quantities. Auxiliary variables have a default start
value of 0 and are unbounded unless otherwise
specified.
Production Blocks
In MPSGE, we think of each sector as a representative firm. Firms produce output commodities by combining input commodities. The specific inputs and outputs for each sector are defined in a production block. MPSGE takes the information in a production block and generates cost functions (not production functions).
@production(Model, Sector, [Nesting Structure], begin
@output(P_1, Q_1, nest_1)
@input(P_2, Q_2, nest_2)
end)Production blocks define the input and output trees. Non-leaf nodes in these trees are referred to as nests and have an associated elasticity. Leaves are associated with a commodity and are required to include a reference quantity and parent nest. Leaves can optionally include a reference price and taxes.
Specifying Leaves
Leaves are specified using the @input and
@output macros within the begin … end block
within the production macro. The two macros have the same structure, so
we will discuss the input side. The input macro has the form:
@input(P, Q, n, taxes = [Tax(H, tx)], reference_price = rp)Where:
- P is the commodity variable, representing price
- Q is the reference quantity
- n is the parent of this node in the tree
- taxes is an optional keyword, in this case we specify a tax with
value
txpaid to consumerH - reference_price is used to ensure the tax-adjusted price has an initial value of 1
The tax-adjusted price, , for an input with taxes and reference price is given by:
The reference quantity, Q, is also adjusted by the reference price. The corresponding quantity is given by:
For convenience, we will refer to the tax-adjusted price, , as the unit cost function of the leaf.
Inputs/outputs can also be indexed. For a set S we can specify an indexed input using the syntax
@input(P[s=S], Q[s], n)This will create an input for each using the value as the quantity.
Specifying Nests
Nests are specified in an array in the third argument of the
@production macro. There must be exactly two top-level
nests, indicating the roots of the two trees. These are specified using
the syntax
name=elasticity
In MPSGE.jl the names of the top-level nests can be any Julia
expression. MPSGE/GAMS requires the names to be s for the
input tree and t for the output tree, representing
substitution and transformation respectively. Non-root nests must also
specify their parent:
name => parent = elasticity
Non-root nests can also be index. Given a set , we can define
name[s=S] => parent = elasticity[s]
This will create a nest for each .
Building Cost Functions
Each node in the tree has a corresponding quantity and unit cost function. Let N be a non-leaf node in the input tree with elasticity and children, where child has (adjusted) quantity and unit cost function . The quantity of is the sum of its children’s quantities, or
The unit cost function, , of is given by:
Zero Profit
Let and be the unit cost functions for the input/output trees respectively. The profit of the sector is then and the zero profit condition is
Where is the activity level of the sector.
Demand Blocks
Demand blocks in MPSGE specify consumer final demands and endowments. A demand block is structured similarly to a production block, except there is no nesting structure.
@demand(Model, Consumer, begin
@final_demand(P_1, Q_1)
@endowment(P_2, Q_2)
end)The macros @final_demand and @endowment
take a commodity and a quantity. If H is the consumer variable, then the
income balance equation is given by:
Where the first term gives the total value of the endowments and the second term is the tax revenue paid to the consumer. The partial derivative is given by Hotelling’s lemma and represents the compensated demand.
Market Clearing Conditions
MPSGE automatically generates the market clearing conditions. For completeness, we include this condition for a commodity . Let be the sectors with as a netput, be the endowments on , and the consumers demanding . Then the market clearing condition for is given by:
Auxiliary Constraints
Finally, each auxiliary variable gets associated with a constraint. The syntax is given by:
@aux_constraint(Model, A, Constraint)Where A is the auxiliary variable and Constraint is the associated constraint, which is assumed to equal 0. This gets translated into: