Skip to main content

February 2026 Updates

Mitch Phillipson February 28, 2026


This month I have been focused on MPSGE and I have updates about both the paper and news about a new MPSGE feature.

Paper

I am working with Eli Lazarus on finalizing revisions for the MPSGE paper. We have made significant progress and are in the final stages of the revisions.

As part of the revisions, I wrote two long examples. One details an example comparing MPSGE.jl, MPSGE/GAMS, and the algebraic MCP formulation in Julia/JuMP. The second example is a more abstract overview of MPSGE.jl. It provides a description of each of the variable types, general syntax for production/demand blocks, a breakdown of how to create nestings, and a formula for constructing the cost functions from the production blocks.

MPSGE Updates

I have been working with Ed Balistreri’s student Suraiya Binte Ali, helping her learn Julia and MPSGE.jl. This past week she approached me with a potential bug in MPSGE. I helped her raise an issue on the MPSGE.jl GitHub repository, this link has all the details about the issue and the fix. I’ll summarize the issue here and then show off what this inspired and how it led to a new feature in MPSGE.jl.

Every node in the production tree has an associated cost function. Rather than storing the explicit function at each node, MPSGE.jl creates an intermediate variable that stores the value of the cost function at each node. This variable is used in all the relevant equations and constraints. The issue was that this variable is tied to the cost function, but updating the start value of a different variable (like price) did not trigger an update to the cost function variable. This meant that if you updated the price variable, the cost function variable would not update and the model would be inconsistent.

This issue only occurred using set_start_value after the definition of the production blocks. And it really impacted verification of the benchmark with cumulative_iteration_limit=0. Any non-zero value for the iteration limit would trigger an update to the cost function variable. I modified the set_start_value function to properly update the cost function variable when necessary. The pull request is awaiting review and should be merged soon.

New MPSGE.jl Feature - cost function depth

This issue inspired a change to how MPSGE generates and displays cost functions. Currently, cost functions have a virtual=true attribute. This uses the cost function variable in the equations, which simplifies this display. For example:

zero_profit(X, virtual=true)

displays:

5 _[7] - 2 _[8]

This is helpful if you are familiar with the structure of MPSGE, but it is not very informative. The _[7] and _[8] are the cost function variables. The names are automatically generated by JuMP. The first modification was naming these variables in a more informative way. For example, this would be a much better display:

5 ucf(X, :s) - 2 ucf(X, :t)

The ucf stands for unit_cost_function. You can view this using

unit_cost_function(X, :s)

which will display:

+(0) + (((0.6 * ((((0.6666666666666666 * (((1 * ((0.5 PX) ^ -1)) ^ -1) ^ -2)) + (0.3333333333333333 * ((PY) ^ -2))) ^ -0.5) ^ 1)) + (0.4 PY)) ^ 1)

While this display is useful, it is the unit cost function for the input side of the X sector, it’s very complex. It would be better view the unit cost function with a specified depth. For example, if we specify a depth of 1, we would get:

+(0) + ((0.6 ucf(X, :va) + 0.4 PY) ^ 1)

This is far more clear than the previous display. A user familiar with MCP formulations of CGE models can recognize this as a CES function with elasticity of substitution 0. The code to generate this display is:

unit_cost_function(X, :s, depth=1)

We can also specify a depth of 2, which gives us:

+(0) + (((0.6 * ((((0.6666666666666666 * (ucf(X, :d) ^ -2)) + (0.3333333333333333 * ((PY) ^ -2))) ^ -0.5) ^ 1)) + (0.4 PY)) ^ 1)

You can see the difference if you view

unit_cost_function(X, :va, depth = 1)

which gives us:

+(0) + (((0.6666666666666666 * (ucf(X, :d) ^ -2)) + (0.3333333333333333 * ((PY) ^ -2))) ^ -0.5)

You should be able to see the substitution that occurred to generate the depth 2 display.

My goal with MPSGE.jl is to eliminate the need for users to construct the explicit algebraic MCP formulation of the model. I am going to continue to add features so that users can simply extract the relevant information from the MPSGE model. This new feature is a step in that direction.

These features are not yet available publicly. They will be included in the next release of MPSGE.jl, which should be in March. To get the fastest notification of this release, star the MPSGE.jl GitHub repository. This way you will get a notification as soon as the release is published.