This repository provides a curated and documented implementation of the neural-network architectures developed in Wang & Gupta (2025), all built around the mass-conserving perceptron (MCP) as the fundamental computational unit, as illustrated in Figure 1.
Figure 1. A neural-network architecture built from mass-conserving perceptrons.
The original research code was archived at Zenodo; the version presented here has since been streamlined, refactored, and reorganized for improved readability, reproducibility, and reuse, with assistance from OpenAI's ChatGPT (GPT-5.6 Sol and GPT-6.1 Sol, Max intelligence mode).
Note that this repository includes only the results for the Leaf River Basin and is intended primarily for pedagogical and demonstration purposes. Users interested in reproducing or extending the analyses to the CAMELS-US catchments are encouraged to follow the methodology described in Wang & Gupta (2025) and use the scripts provided in the original Zenodo.
Use Python 3.10 and install the dependencies listed in requirements.txt, including NumPy, pandas, PyTorch, and scikit-learn. Run the following command from the repository root:
python -m pip install -r requirements.txtThe example data are provided in 20220527-MDUPLEX-LeafRiver/, the default data directory used by the training and evaluation scripts.
LeafRiverDaily_43YR.txt: daily precipitation (P), potential evapotranspiration (PET), and streamflow (Q), in that column order and all in mm/day.LeafRiverDaily_43YR_Flag.txt: flags identifying the data subsets used for model spin-up, training, selection, and testing.
| Flag | Data subset |
|---|---|
-99999 |
Spin-up |
-1 |
Training |
0 |
Selection |
1 |
Testing |
The data sequence includes three repetitions of water year 1949 for spin-up, followed by the 40-year simulation period covering water years 1949–1988.
Pretrained Leaf River checkpoints are included in the model folders. They can be used for direct evaluation or as starting points for continued training and fine-tuning.
The representative single-node MCP formulation introduced in Wang & Gupta (2024a) used the 7-parameter computational unit
In the present study, we use the corresponding 8-parameter formulation,
referred to in Wang & Gupta (2025) as
The key difference lies in the formulation of the loss gate. In the 7-parameter formulation, the loss gate depends on potential evapotranspiration (PET) at the current time step. In the 8-parameter formulation used in this study, the loss gate additionally depends on the current MCP cell state. Thus, the loss flux can respond jointly to the atmospheric demand represented by PET and to the amount of water currently stored in the MCP state.
The corresponding single-node implementation and pretrained Leaf River checkpoint are provided in:
Miscellaneous/SingleNode-MN
The directory contains:
SingleNode-MN/
├── model_epoch17.pt
├── train_SingleNode_MN.py
└── evaluate_SingleNode_MN.py
To evaluate the pretrained model:
cd Miscellaneous/SingleNode-MN
python evaluate_SingleNode_MN.pyTo continue training from the pretrained checkpoint:
python train_SingleNode_MN.pyThe evaluation script reports model skill for the spin-up, training, selection, and testing periods and saves the corresponding MCP state, flux, and gate diagnostics.
The single-layer experiments investigate a family of parallel MCP networks in which the number of MCP nodes, the treatment of network-level mass conservation, and the degree of internal state information sharing can be systematically varied.
Figure 2 summarizes the five network-level architectural hypotheses considered in Wang & Gupta (2025).
Figure 2. Single-layer MCP network architectures considered in this study. The Distributed-Input (DI) and Distributed-State (DS) formulations conserve mass at the overall network level, whereas DIR, DSR, and MLB progressively relax the network-level mass-conservation constraints.
Five network types are implemented:
| Network type | Paper notation | Input distribution | Output aggregation |
|---|---|---|---|
| Distributed-Input | MNDI(N1) | Positive weights constrained to sum to 1 | Sum of all nodal outputs |
| Distributed-State | MNDS(N1) | Unity input to every node | Positive weights constrained to sum to 1 |
| Distributed-Input-Relaxed | MNDIR(N1) | Positive weights not constrained to sum to 1 | Sum of all nodal outputs |
| Distributed-State-Relaxed | MNDSR(N1) | Unity input to every node | Positive weights not constrained to sum to 1 |
| Machine-Learning Benchmark | MNMLB(N1) | Unconstrained linear mapping with bias | Unconstrained linear mapping with bias |
In the Distributed-Input (DI) formulation, precipitation is partitioned among the parallel MCP nodes using positive weights that sum to one, while the resulting nodal streamflow components are summed to obtain total streamflow.
In contrast, the Distributed-State (DS) formulation sends the full precipitation input to every node and combines the resulting streamflow components using positive output weights that sum to one.
The DIR and DSR formulations relax the corresponding input- and output-side network-level mass-conservation constraints, respectively. The MLB architecture provides the least constrained network-level benchmark by using unconstrained linear mappings with bias terms at both the input and output sides.
The single-layer networks are denoted as:
where
In the experiments reported in Wang & Gupta (2025), we evaluated:
For example,
denotes a single-layer Distributed-State network with three MCP nodes and no internal state information sharing.
For each of the five network types, four information-sharing configurations are considered following the notation used in Table 1 of Wang & Gupta (2025):
| Sharing option | Paper notation | Information available to each node |
|---|---|---|
| None | None |
No state sharing |
| Sharing-Augmented Output | SAO |
States shared with the output gate only |
| Sharing-Augmented Loss | SAL |
States shared with the loss gate only |
| Sharing-Augmented Loss and Output | SALO |
States shared with both output and loss gates |
Combining the five network types with the four information-sharing configurations gives 20 single-layer architectural variants for each value of
Examples include:
-
$MN^{DS}_{None}(N_1)$ : Distributed-State with no information sharing -
$MN^{DS}_{SAO}(N_1)$ : Distributed-State with state information shared at the output gates -
$MN^{DS}_{SAL}(N_1)$ : Distributed-State with state information shared at the loss gates -
$MN^{DS}_{SALO}(N_1)$ : Distributed-State with state information shared at both the output and loss gates
The same None, SAO, SAL, and SALO convention is used for the DI, DIR, DSR, and MLB network families.
The complete single-layer model space consists of:
- 5 network types:
DI,DS,DIR,DSR, andMLB - 4 information-sharing options:
None,SAO,SAL, andSALO - 4 network sizes:
$N_1 = 2, 3, 4, 5$
This gives:
single-layer model configurations.
Each model variant is provided with a training script and a corresponding evaluation script. The filenames identify both the network type and the information-sharing configuration.
For example, to continue training the Machine-Learning Benchmark (MLB) network without internal state sharing:
python train_MLB_None_single_layer.pyTo evaluate the corresponding pretrained model:
python evaluate_MLB_None_single_layer.pySimilarly, DS_SALO refers to a Distributed-State network with information shared at both the output and loss gates, whereas DIR_SAO refers to a Distributed-Input-Relaxed network with state information shared only at the output gates.
The number of MCP nodes,
The evaluation scripts report model skill for the spin-up, training, selection, and testing periods, together with the corresponding MCP state, flux, and gate diagnostics.
The multi-layer experiments extend the MCP network architecture by arranging nodes into two or three successive hidden layers. Based on the results of the single-layer experiments, the multi-layer investigation focuses on the Distributed-State (DS) formulation.
Figure 3 provides a conceptual summary of the multi-layer MCP architectures considered in this study, including the MassConserved, MassRelaxed, and Machine-Learning Benchmark (MLB) formulations.
Figure 3. Conceptual illustration of the multi-layer MCP architectures considered in this study. The three model families differ in how inter-layer and output mappings are constrained: MassConserved uses mass-conserving mappings, MassRelaxed uses positive but mass-relaxed mappings, and MLB uses unconstrained affine mappings.
Three forms of inter-layer and output transformation are investigated, together with corresponding information-sharing variants. The repository therefore contains six multi-layer model families.
The six multi-layer model families are organized as follows:
| No. | Repository folder | Network family | Mapping | Information sharing |
|---|---|---|---|---|
| 1 | MassConserved |
Distributed-State | Mass-conserving | None |
| 2 | MassConserved-InfoShared |
Distributed-State | Mass-conserving | Output + loss gates |
| 3 | MassRelaxed |
Distributed-State-Relaxed | Positive, mass-relaxed | None |
| 4 | MassRelaxed-InfoShared |
Distributed-State-Relaxed | Positive, mass-relaxed | Output + loss gates |
| 5 | ML |
Distributed-State Machine-Learning Benchmark | Unconstrained affine | None |
| 6 | ML-InfoShared |
Distributed-State Machine-Learning Benchmark | Unconstrained affine | Output + loss gates |
The 1st, 3rd, and 5th model families are the non-information-sharing multi-layer networks summarized in Figure 5 of Wang & Gupta (2025):
The 2nd, 4th, and 6th model families are their corresponding Sharing-Augmented Loss and Output (SALO) variants summarized in Figure 9:
The correspondence between the repository folders and the formal paper notation is therefore:
-
MassConserved
$MN^{DS}_{None}(N_1,N_2,N_3)$ -
MassConserved-InfoShared
$MN^{DS}_{SALO}(N_1,N_2,N_3)$ -
MassRelaxed
$MN^{DSR}_{None}(N_1,N_2,N_3)$ -
MassRelaxed-InfoShared
$MN^{DSR}_{SALO}(N_1,N_2,N_3)$ -
ML
$MN^{DS-MLB}_{None}(N_1,N_2,N_3)$ -
ML-InfoShared
$MN^{DS-MLB}_{SALO}(N_1,N_2,N_3)$
For the multi-layer experiments, information sharing is applied to both the output and loss gates. Importantly, information sharing is layer-wise: each node can access the cell states of other nodes within the same layer, but information is not directly shared across different hidden layers.
A multi-layer architecture is denoted as:
where:
-
$N_1$ is the number of MCP nodes in the first hidden layer, -
$N_2$ is the number of MCP nodes in the second hidden layer, -
$N_3$ is the number of MCP nodes in the third hidden layer.
The corresponding repository folder uses the compact notation Lxyz, where x, y, and z represent
For example:
| Folder | Architecture | Interpretation |
|---|---|---|
L110 |
(1, 1, 0) |
Two layers with one MCP node in each layer |
L230 |
(2, 3, 0) |
Two layers with 2 nodes in Layer 1 and 3 nodes in Layer 2 |
L111 |
(1, 1, 1) |
Three layers with one MCP node in each layer |
L231 |
(2, 3, 1) |
Three layers with 2, 3, and 1 nodes |
L333 |
(3, 3, 3) |
Three layers with 3 nodes in every layer |
A value of 0 for
The single-layer architectures are stored separately under MN-Single-Layer/.
For the two-layer networks:
N1 = 1, 2, 3
N2 = 1, 2, 3
N3 = 0
giving:
two-layer architectures.
For the three-layer networks:
N1 = 1, 2, 3
N2 = 1, 2, 3
N3 = 1, 2, 3
giving:
three-layer architectures.
Therefore, each multi-layer model family contains:
architectures.
With six model families, the complete multi-layer model zoo contains:
model configurations.
The 36 architecture folders contained in each family are:
L110 L111 L112 L113
L120 L121 L122 L123
L130 L131 L132 L133
L210 L211 L212 L213
L220 L221 L222 L223
L230 L231 L232 L233
L310 L311 L312 L313
L320 L321 L322 L323
L330 L331 L332 L333
Because information sharing occurs only among nodes within the same hidden layer, sharing does not introduce any additional cross-node information when a layer contains only one node.
This makes the following two architectures special:
L110 = (1, 1, 0)
L111 = (1, 1, 1)
Every active hidden layer in these architectures contains exactly one MCP node. Therefore, there are no additional nodes within a layer from which cell-state information can be shared.
Consequently, for these two architectures, the information-sharing versions are equivalent to their corresponding non-information-sharing versions:
MassConserved-InfoShared/L110 = MassConserved/L110
MassConserved-InfoShared/L111 = MassConserved/L111
MassRelaxed-InfoShared/L110 = MassRelaxed/L110
MassRelaxed-InfoShared/L111 = MassRelaxed/L111
ML-InfoShared/L110 = ML/L110
ML-InfoShared/L111 = ML/L111
Information sharing begins to introduce additional cross-node dependencies only when at least one hidden layer contains two or more MCP nodes.
The multi-layer model zoo is organized as:
MN-Multi-Layers/
├── MassConserved/
├── MassConserved-InfoShared/
├── MassRelaxed/
├── MassRelaxed-InfoShared/
├── ML/
└── ML-InfoShared/
Each of these six folders contains the same set of 36 Lxyz architecture folders.
A typical case is organized as:
MN-Multi-Layers/
└── MassConserved/
└── L330/
├── best_model_epochXXX.pt
├── train_MassConserved_MultiLayer_L330.py
└── evaluate_MassConserved_MultiLayer_L330.py
For example, L330 represents:
which is a two-layer network containing three MCP nodes in the first layer and three MCP nodes in the second layer.
To evaluate the pretrained MassConserved/L330 model:
cd MN-Multi-Layers/MassConserved/L330
python evaluate_MassConserved_MultiLayer_L330.pyTo continue training from the checkpoint stored in the same folder:
python train_MassConserved_MultiLayer_L330.pyBy default, the scripts use the pretrained checkpoint stored in the corresponding Lxyz directory.
The evaluation scripts report model skill for the spin-up, training, selection, and testing periods and save the associated layer-wise discharge, storage, loss, gate, and inter-layer mapping diagnostics.
Several additional benchmark cases are included under Miscellaneous/ to clarify how the relaxed input/output transformations used in the single-layer networks relate to the corresponding multi-layer formulations.
The single-node Distributed-Input-Relaxed (DIR) case,
includes a learnable input weight that is not constrained to equal one. This allows the effective precipitation input supplied to the MCP node to be adjusted relative to the observed precipitation.
The corresponding training and evaluation scripts, together with the pretrained Leaf River checkpoint, are provided in:
Miscellaneous/SingleNode-DIR
The single-node Distributed-State-Relaxed (DSR) case,
retains the direct precipitation input to the MCP node but introduces a learnable output weight that is not constrained to equal one. This allows the nodal discharge to be rescaled when producing the final streamflow estimate.
The corresponding files are provided in:
Miscellaneous/SingleNode-DSR
The single-node Machine-Learning Benchmark (MLB) case,
contains learnable transformations on both the input and output sides, allowing the effective precipitation input and the final streamflow output to be adjusted by the surrounding machine-learning layers.
The corresponding files are provided in:
Miscellaneous/SingleNode-MLB
The definition of the MLB architecture is not identical in the single-layer and multi-layer experiments.
For the single-layer experiments described earlier, the MLB family is denoted as
and includes learnable transformations at both the network input and network output.
In contrast, the multi-layer MLB formulation is constructed from the Distributed-State (DS) architecture and is denoted as
Because the multi-layer MLB family is based on the DS formulation, precipitation is supplied directly to the first-layer MCP nodes with unit input weight. In other words, there is no additional learnable input layer preceding the first MCP layer. The machine-learning flexibility is instead introduced through the unconstrained mappings between MCP layers and at the final network output.
Consequently, the one-layer reductions of the multi-layer MLB formulation are distinct from the MLB models included in the main single-layer model zoo.
For the non-information-sharing case,
the corresponding implementations are:
Miscellaneous/MultiLayer-MLB-L100
Miscellaneous/MultiLayer-MLB-L200
Miscellaneous/MultiLayer-MLB-L300
Miscellaneous/MultiLayer-MLB-L400
Miscellaneous/MultiLayer-MLB-L500
where:
The corresponding Sharing-Augmented Loss and Output (SALO) cases are denoted as
and are provided in:
Miscellaneous/MultiLayer-MLB-L200-SALO
Miscellaneous/MultiLayer-MLB-L300-SALO
Miscellaneous/MultiLayer-MLB-L400-SALO
Miscellaneous/MultiLayer-MLB-L500-SALO
There is no separate L100-SALO case because a single MCP node has no other node within the layer from which state information can be shared. Therefore,
and the L100 non-sharing implementation already represents both cases.
Each directory contains the corresponding pretrained Leaf River checkpoint together with its training and evaluation scripts.
The MA-Sharing/ directory contains information-sharing extensions of four physical-conceptual MCP architectures — MA3, MA4, MA5, and MA6 — originally introduced and evaluated in our previous study, Wang & Gupta (2024b), Towards Interpretable Physical-Conceptual Catchment-Scale Hydrological Modeling Using the Mass-Conserving-Perceptron.
In that earlier work, MA3–MA6 were developed as progressively more complex architectural hypotheses for representing catchment-scale rainfall-runoff dynamics using physically interpretable and mass-conserving MCP units. The architectures differ in how cell states and runoff pathways are organized, ranging from serial soil-moisture/routing representations to structures containing parallel surface, groundwater, channel-routing, and overland-flow pathways.
Building on the cell-state information-sharing framework explored in Wang & Gupta (2025), the implementations provided here augment these original physical-conceptual architectures by allowing gating functions to use information from other internal cell states.
The four architectures differ primarily in the number of cell states and the organization of the associated runoff pathways:
| Model | Main architectural hypothesis |
|---|---|
MA3 |
One flow pathway with two cell states in series: a catchment soil-moisture storage followed by a routing storage |
MA4 |
Two parallel flow pathways representing near-surface runoff and groundwater/baseflow |
MA5 |
Three cell states and two flow pathways, extending MA4 by including explicit surface/channel routing |
MA6 |
Extends MA5 by including an additional overland-flow pathway that can route water directly toward the catchment outlet |
All four architectures retain the physically interpretable storage and flow-path structures developed in Wang & Gupta (2024b).
The versions included in this repository augment the original MA3–MA6 architectures with Sharing-Augmented Loss and Output (SALO) gates.
In the original physical-conceptual formulations, the gating behavior associated with a given MCP state is primarily determined using information local to that state.
In the SALO extensions, both the output gate and the loss gate are additionally allowed to use information from other cell states in the model.
Conceptually:
Original MA model:
state i
├── output gate <- local state information
└── loss gate <- local state information
MA-SALO model:
state i
├── output gate <- local state + information from other cell states
└── loss gate <- local state + information from other cell states
The underlying MA3–MA6 storage and flow-path architectures are retained. The modification concerns the information available to the gating functions rather than the introduction of new hydrologic states or new flow pathways.
This provides a direct way to investigate whether fluxes associated with an individual conceptual storage should depend only on its local state or on a broader representation of the moisture distribution across the model.
Four SALO physical-conceptual cases are included:
| Repository folder | Base architecture | Information sharing |
|---|---|---|
MA3-SALO |
MA3 | Output + loss gates |
MA4-SALO |
MA4 | Output + loss gates |
MA5-SALO |
MA5 | Output + loss gates |
MA6-SALO |
MA6 | Output + loss gates |
The directory is organized as:
MA-Sharing/
├── MA3-SALO/
├── MA4-SALO/
├── MA5-SALO/
└── MA6-SALO/
Each case contains a pretrained Leaf River checkpoint together with its corresponding training and evaluation scripts.
For example, the MA6-SALO directory is organized as:
MA-Sharing/
└── MA6-SALO/
├── model_epoch8.pt
├── train_MA6_SALO.py
└── evaluate_MA6_SALO.py
The exact checkpoint filename may differ among the four cases because each architecture retains its corresponding pretrained model.
For example, to evaluate the pretrained MA6-SALO model:
cd MA-Sharing/MA6-SALO
python evaluate_MA6_SALO.pyTo continue training from the checkpoint stored in the same directory:
python train_MA6_SALO.pyThe same naming convention is used for the remaining architectures:
MA3-SALO
MA4-SALO
MA5-SALO
MA6-SALO
The evaluation scripts report model skill for the spin-up, training, selection, and testing periods and save the associated discharge, storage, routing, loss, and gate diagnostics.
These scripts evaluate pretrained five-node DS networks without retraining or fine-tuning.
The default pruning rule is to compute the learned DS output weights
and prune progressively from the smallest learned output weight. The retained output weights are kept exactly at their pretrained values and are not renormalized after pruning.
python evaluate_Prune_Case1.py --prune_count 1
python evaluate_Prune_Case2_FLOWPATH.py --prune_count 2
python evaluate_Prune_Case2_FULL.py --prune_count 2--prune_count 1 removes the smallest learned flow-path weight; --prune_count 2 removes the two smallest, and so on.
Readers can override the automatic ranking and select any paths directly using 1-based node IDs:
python evaluate_Prune_Case1.py --prune_nodes 2,4
python evaluate_Prune_Case2_FLOWPATH.py --prune_nodes 2,4
python evaluate_Prune_Case2_FULL.py --prune_nodes 2,4Case1: no state sharing; selected direct output flow paths are masked.Case2_FLOWPATH: partial SALO pruning; selected direct output flow paths are masked, but the corresponding cell states remain active in the shared output/loss gates.Case2_FULL: full SALO pruning; selected direct output flow paths are masked and the corresponding source-state interaction rows inweight_b1_yomandweight_b1_ylmare set to zero.
The scripts print the learned output weights and their smallest-to-largest ranking at runtime, and save metrics.csv, output_weights.csv, pruning_configuration.csv, and time-series diagnostics.
Readers should consult the original papers for the formal model names, notation, mathematical definitions, and development of the MCP-based physical-conceptual and neural-network architectures used in this repository.
- Full article: Wang & Gupta (2025)
- DOI: 10.1029/2025WR040178
Wang, Y.-H., & Gupta, H. V. (2025). Using machine learning to discover parsimonious and physically-interpretable representations of catchment-scale rainfall-runoff dynamics. Water Resources Research, 61(12), e2025WR040178. https://doi.org/10.1029/2025WR040178
- Full article: Wang & Gupta (2024a)
- DOI: 10.1029/2023WR036461
Wang, Y.-H., & Gupta, H. V. (2024a). A mass-conserving-perceptron for machine-learning-based modeling of geoscientific systems. Water Resources Research, 60(4), e2023WR036461.
- Full article: Wang & Gupta (2024b)
- DOI: 10.1029/2024WR037224
Wang, Y.-H., & Gupta, H. V. (2024b). Towards interpretable physical-conceptual catchment-scale hydrological modeling using the mass-conserving-perceptron. Water Resources Research, 60(10), e2024WR037224. https://doi.org/10.1029/2024WR037224
This repository provides a consolidated and reproducible collection of MCP neural network variants, including cleaned training and evaluation scripts, checkpoints, and data conventions.
For questions or suggestions, please contact Yuan-Heng Wang, Ph.D. at yhwang0730@gmail.com or yhwang0730@arizona.edu.
This project is licensed under the MIT License.


