Skip to main content

MPSGE Overview

Mitch Phillipson 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 tx paid to consumer H
  • reference_price is used to ensure the tax-adjusted price has an initial value of 1

The tax-adjusted price, P\bar{P}, for an input with taxes tit_i and reference price rprp is given by:

P=P(1+iti)rp\bar{P} = \frac{P(1+\sum_i t_i)}{rp}

The reference quantity, Q, is also adjusted by the reference price. The corresponding quantity is given by:

Q=Qrp\bar{Q} = Q \cdot rp

For convenience, we will refer to the tax-adjusted price, P\bar{P}, 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 sSs\in S using the value Q[s]Q[s] 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 SS, we can define

name[s=S] => parent = elasticity[s]

This will create a nest for each sSs\in S.

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 σ\sigma and kk children, where child ii has (adjusted) quantity QiQ_i and unit cost function CiC_i. The quantity of NN is the sum of its children’s quantities, or

Q=i=1kQi Q = \sum_{i=1}^k Q_i

The unit cost function, CC, of NN is given by:

C={(i=1kQiQCi1σ)11σif σ1i=1kCiQiQif σ=1 \displaystyle C = \left\{\begin{array}{cl} \displaystyle \left(\sum_{i=1}^k\frac{Q_i}{Q}\cdot C_i^{1-\sigma}\right)^{\frac{1}{1-\sigma}} & \text{if } \sigma \neq 1 \\ \displaystyle \prod_{i=1}^k C_i^{\frac{Q_i}{Q}} & \text{if } \sigma = 1 \end{array}\right.

Zero Profit

Let CC and RR be the unit cost functions for the input/output trees respectively. The profit of the sector is then Π=RC\Pi=R-C and the zero profit condition is

Π=0X-\Pi = 0 \perp X

Where XX 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:

H=iEiPi+jtjQjPjXjΠXjPjH H = \sum_i E_i\cdot P_i + \sum_j t_j\cdot Q_j \cdot P_j \cdot X_j \cdot \frac{\partial \Pi_{X_j}}{\partial \bar{P}_j} \perp H

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 PP. Let XiX_i be the sectors with PP as a netput, EjE_j be the endowments on PP, and HkH_k the consumers demanding PP. Then the market clearing condition for PP is given by:

iXiΠXiP=jEjkHkPP \sum_i X_i\cdot \frac{\partial \Pi_{X_i}}{\partial \bar{P}} = \sum_j E_j - \sum_k \frac{H_k}{P} \perp P

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:

Constraint=0A Constraint = 0 \perp A