Architecture#

CGE-Core v0.8 separates six concerns:

  1. economic model definitions;

  2. benchmark data and calibration;

  3. model-owned closure and policy metadata;

  4. counterfactual workflow;

  5. numerical result interfaces; and

  6. solver resolution.

The public interface is deliberately smaller than the implementation. The four bundled model families present a similar modelling workflow, but v0.8 does not force them through one internal implementation when their economics or validation requirements differ.

Practitioner-first public architecture#

        flowchart TB
    U["Practitioner"]

    subgraph PUBLIC["Practitioner entry points"]
      G["SimpleCGE · StandardCGE · CamCGE"]
      I["IFPRICGE"]
    end

    subgraph GENERIC["Generic Simple / Standard / CAMCGE path"]
      GW["Scientific workflow<br/>CGE → Equilibrium → Scenario → Result"]
      MD["Model definition + ModelSpec"]
      CE["CoreEngine<br/>model-declared policy"]
      PY["PyCGE<br/>instance · mutation · rollback · solve bookkeeping"]
    end

    subgraph IFPRI["IFPRI-specific path"]
      IW["IFPRI workflow<br/>IFPRIEquilibrium → IFPRIScenario → IFPRIResult"]
      IM["IFPRI calibration · closure<br/>named scenario builders"]
    end

    subgraph NUM["Shared numerical boundary"]
      P["Pyomo model"]
      SR["cge_core.solver<br/>backend resolution"]
      N["Supported NLP backend<br/>Ipopt · cyipopt · COIN/ipoptnl"]
    end

    U --> G
    U --> I

    G --> GW
    GW --> MD
    MD --> CE
    CE --> PY
    PY --> P

    I --> IW
    IW --> IM
    IM --> P

    P --> SR
    SR --> N

    classDef public fill:#eef4ff,stroke:#4f6fad,stroke-width:2px,color:#172033;
    classDef generic fill:#f6f2ff,stroke:#7252b8,stroke-width:1.5px,color:#172033;
    classDef ifpri fill:#edf8f4,stroke:#3c806b,stroke-width:1.5px,color:#172033;
    classDef numerical fill:#fff7e8,stroke:#9a6b22,stroke-width:1.5px,color:#172033;
    class U,G,I public;
    class GW,MD,CE,PY generic;
    class IW,IM ifpri;
    class P,SR,N numerical;

    

Use the mouse wheel or a trackpad pinch gesture to zoom, drag to pan, or select to inspect the diagram in full screen.

Mermaid source

Download the .mmd source

flowchart TB
    U["Practitioner"]

    subgraph PUBLIC["Practitioner entry points"]
      G["SimpleCGE · StandardCGE · CamCGE"]
      I["IFPRICGE"]
    end

    subgraph GENERIC["Generic Simple / Standard / CAMCGE path"]
      GW["Scientific workflow<br/>CGE → Equilibrium → Scenario → Result"]
      MD["Model definition + ModelSpec"]
      CE["CoreEngine<br/>model-declared policy"]
      PY["PyCGE<br/>instance · mutation · rollback · solve bookkeeping"]
    end

    subgraph IFPRI["IFPRI-specific path"]
      IW["IFPRI workflow<br/>IFPRIEquilibrium → IFPRIScenario → IFPRIResult"]
      IM["IFPRI calibration · closure<br/>named scenario builders"]
    end

    subgraph NUM["Shared numerical boundary"]
      P["Pyomo model"]
      SR["cge_core.solver<br/>backend resolution"]
      N["Supported NLP backend<br/>Ipopt · cyipopt · COIN/ipoptnl"]
    end

    U --> G
    U --> I

    G --> GW
    GW --> MD
    MD --> CE
    CE --> PY
    PY --> P

    I --> IW
    IW --> IM
    IM --> P

    P --> SR
    SR --> N

    classDef public fill:#eef4ff,stroke:#4f6fad,stroke-width:2px,color:#172033;
    classDef generic fill:#f6f2ff,stroke:#7252b8,stroke-width:1.5px,color:#172033;
    classDef ifpri fill:#edf8f4,stroke:#3c806b,stroke-width:1.5px,color:#172033;
    classDef numerical fill:#fff7e8,stroke:#9a6b22,stroke-width:1.5px,color:#172033;
    class U,G,I public;
    class GW,MD,CE,PY generic;
    class IW,IM ifpri;
    class P,SR,N numerical;

For the Hosoe Simple, Hosoe Standard, and CAMCGE families, the modeller sees the generic scientific lifecycle:

StandardCGE.example()
        │
        └── solve()
              ↓
         Equilibrium
              │
              ├── scenario("A") → tariff/endowment/... → solve() → Result A
              │
              └── scenario("B") → tariff/endowment/... → solve() → Result B

Result A.compare(Equilibrium)
Result A.compare(Result B)

SimpleCGE, StandardCGE, and CamCGE configure this lifecycle with their own model definition and ModelSpec. Their canonical closure is therefore model-owned even though the surrounding workflow is shared.

IFPRICGE deliberately follows a parallel path. It exposes the same benchmark → scenario → solve → inspect idea through IFPRIEquilibrium, IFPRIScenario, and IFPRIResult, while retaining IFPRI-specific calibration, named policy scenarios, and macro-closure machinery. It does not pass through the generic CGE / CoreEngine workflow merely for architectural symmetry.

For the generic Simple/Standard/CAMCGE path, a scenario owns one independent clone of the calibrated benchmark. The benchmark remains protected, and solved results expose immutable numerical snapshots for ordinary inspection. IFPRI provides its own result objects over its model-specific solved states.

Generic workflow and the retained PyCGE engine#

The generic v0.8 path has three distinct software layers:

  1. CGE Equilibrium Scenario Result is the scientific workflow layer;

  2. CoreEngine is the CGE-Core policy adapter; and

  3. PyCGE is the retained lower-level engine mechanics.

        flowchart TB
    USER["Model façade / advanced user"]

    subgraph DEF["Model-specific definition and policy"]
      MODEL["Economic model definition<br/>sets · parameters · variables · equations"]
      SPEC["ModelSpec<br/>closure metadata · protection<br/>semantic shocks · required data"]
      DATA["SAM / packaged model data"]
    end

    subgraph WF["Generic scientific workflow"]
      CGE["CGE"]
      EQ["Equilibrium<br/>protected benchmark + snapshot"]
      SC["Scenario<br/>one independent model clone"]
      RES["Result<br/>immutable numerical snapshot"]
    end

    subgraph ENG["Engine layers"]
      CORE["CoreEngine<br/>ModelSpec-driven policy"]
      PYCGE["PyCGE<br/>instance construction · mutation<br/>undo/rollback · solve bookkeeping"]
    end

    subgraph RUN["Numerical runtime"]
      PYOMO["Pyomo ConcreteModel"]
      SOLVER["cge_core.solver<br/>resolve supported backend"]
      NLP["NLP backend<br/>Ipopt · cyipopt · COIN/ipoptnl"]
    end

    USER --> CGE
    MODEL --> CGE
    SPEC --> CGE
    DATA --> CGE

    CGE --> CORE
    SPEC --> CORE
    CORE --> PYCGE
    PYCGE --> PYOMO
    PYOMO --> SOLVER
    SOLVER --> NLP
    NLP --> EQ

    EQ --> SC
    SC --> PYCGE
    NLP --> RES

    classDef model fill:#edf8f4,stroke:#3c806b,stroke-width:1.5px,color:#172033;
    classDef workflow fill:#eef4ff,stroke:#4f6fad,stroke-width:1.5px,color:#172033;
    classDef engine fill:#f6f2ff,stroke:#7252b8,stroke-width:1.5px,color:#172033;
    classDef runtime fill:#fff7e8,stroke:#9a6b22,stroke-width:1.5px,color:#172033;
    class MODEL,SPEC,DATA model;
    class CGE,EQ,SC,RES workflow;
    class CORE,PYCGE engine;
    class PYOMO,SOLVER,NLP runtime;

    
Mermaid source

Download the .mmd source

flowchart TB
    USER["Model façade / advanced user"]

    subgraph DEF["Model-specific definition and policy"]
      MODEL["Economic model definition<br/>sets · parameters · variables · equations"]
      SPEC["ModelSpec<br/>closure metadata · protection<br/>semantic shocks · required data"]
      DATA["SAM / packaged model data"]
    end

    subgraph WF["Generic scientific workflow"]
      CGE["CGE"]
      EQ["Equilibrium<br/>protected benchmark + snapshot"]
      SC["Scenario<br/>one independent model clone"]
      RES["Result<br/>immutable numerical snapshot"]
    end

    subgraph ENG["Engine layers"]
      CORE["CoreEngine<br/>ModelSpec-driven policy"]
      PYCGE["PyCGE<br/>instance construction · mutation<br/>undo/rollback · solve bookkeeping"]
    end

    subgraph RUN["Numerical runtime"]
      PYOMO["Pyomo ConcreteModel"]
      SOLVER["cge_core.solver<br/>resolve supported backend"]
      NLP["NLP backend<br/>Ipopt · cyipopt · COIN/ipoptnl"]
    end

    USER --> CGE
    MODEL --> CGE
    SPEC --> CGE
    DATA --> CGE

    CGE --> CORE
    SPEC --> CORE
    CORE --> PYCGE
    PYCGE --> PYOMO
    PYOMO --> SOLVER
    SOLVER --> NLP
    NLP --> EQ

    EQ --> SC
    SC --> PYCGE
    NLP --> RES

    classDef model fill:#edf8f4,stroke:#3c806b,stroke-width:1.5px,color:#172033;
    classDef workflow fill:#eef4ff,stroke:#4f6fad,stroke-width:1.5px,color:#172033;
    classDef engine fill:#f6f2ff,stroke:#7252b8,stroke-width:1.5px,color:#172033;
    classDef runtime fill:#fff7e8,stroke:#9a6b22,stroke-width:1.5px,color:#172033;
    class MODEL,SPEC,DATA model;
    class CGE,EQ,SC,RES workflow;
    class CORE,PYCGE engine;
    class PYOMO,SOLVER,NLP runtime;

ModelSpec#

ModelSpec carries model-specific software policy that should not be guessed from component names: default closure metadata, protected benchmark components, semantic policy shocks, and required data declarations. Economic equations remain in the model-definition modules.

CoreEngine#

CoreEngine is intentionally small. It subclasses PyCGE and changes the protection policy so benchmark/base protection comes from ModelSpec rather than historical naming rules such as a trailing 0.

PyCGE#

The retained lower-level engine owns the mature mechanics used by the generic workflow: instance construction, mutation, undo/rollback, solver execution, and result bookkeeping. Advanced users can still import it intentionally with:

from cge_core import PyCGE

The practitioner façades do not rewrite validated economic algebra. They configure and call the appropriate model-specific implementation while hiding routine framework plumbing.

Solver boundary#

Ordinary code calls .solve() rather than managing solver installation or PATH state. cge_core.solver resolves a supported nonlinear backend and is shared by the generic and IFPRI paths. It prefers a usable system Ipopt, then a working cyipopt, and otherwise can prepare the packaged COIN/Ipopt NL route used through Pyomo.

The architecture therefore separates an economic modelling decision from the numerical backend used to solve it.

Model-family boundaries#

Family

v0.8 public path

Closure

Hosoe Simple

Generic CGE Equilibrium Scenario Result

Model-owned canonical closure

Hosoe Standard

Generic CGE Equilibrium Scenario Result

Model-owned canonical closure

CAMCGE

Generic CGE Equilibrium Scenario Result

CAMCGE-specific closure

IFPRI Standard

IFPRI-specific equilibrium/scenario/result adapter

IFPRI-specific closure and named scenarios

The project therefore shares practitioner semantics without pretending there is one universal CGE equation template or one mandatory internal workflow.

Experimental authoring boundary#

The optional authoring tools live only under cge_core.experimental:

  • cge_core.experimental.authoring adapts functional Python models; and

  • cge_core.experimental.spec implements the deterministic .cge.md specification.

They are intentionally outside the main bundled-model pipeline. Experimental authoring can evolve before 1.0 without forcing the validated Hosoe, CAMCGE, or IFPRI implementations to be rewritten around it.

The Standard CGE in economic blocks#

Block

Main role

Production and factors

Firms combine factors and intermediate inputs

Household

Factor income finances consumption, saving, and direct taxes

Government

Tax revenue finances government demand and saving

Investment

Domestic and foreign saving finance investment demand

Armington trade

Imports and domestic goods form composite supply

CET transformation

Output is allocated between domestic and export markets

Market clearing

Commodity and factor markets balance

External balance

Export receipts and foreign saving finance imports

Closure

A price anchor and independent equilibrium conditions complete the system

Trace economics to implementation#

Economic concept

Theory

Detailed equations

Public workflow

Production

Production and Factor Demand

The Standard CGE Model (stdcge)

StandardCGE.example().solve()

Final demand

Households, Government and Investment

The Standard CGE Model (stdcge)

result inspection

Trade

International Trade

The Standard CGE Model (stdcge)

scenario.tariff(...)

Closure / Walras’ law

Closure, Numeraire and Walras’ Law

Modelling workflow

model-owned for bundled models

SAM loading

Social Accounting Matrix

Modelling workflow

StandardCGE.from_sam(...)

Policy simulation

Your first policy simulation

Modelling workflow

benchmark → scenario → result

IFPRI scenarios

IFPRI Standard CGE

IFPRI Standard CGE replication

IFPRICGE.synthetic().solve()

Advanced engine inspection

Advanced PyCGE API

Modelling workflow

.raw / PyCGE

The intended reading path is:

economic meaning → equation → practitioner workflow → lower-level implementation only when needed.