Balancing Agriculture, Households, and Industry
Water is the one resource that every sector needs and no sector can replace. Farms need it to feed people, households need it to keep people alive, and factories turn it into the tax revenue that pays for tomorrow’s infrastructure. When a drought arrives, every cubic meter given to one sector is taken from another.
In this article we formulate a concrete water allocation problem as a 20-turn dynamic optimization, solve it numerically with Python, and visualize the result with a single combined figure that includes two 3D plots.
1. Problem Statement
A region receives a limited amount of water $W_t$ in each turn $t = 0, 1, \dots, 19$. The planner splits it among three sectors:
$$
\alpha_t^{\mathrm{agr}} + \alpha_t^{\mathrm{dom}} + \alpha_t^{\mathrm{ind}} = 1, \qquad \alpha_t^{\bullet} \ge 0 .
$$
The goal is to maximize the sum of the final population and the final asset value:
$$
\max_ ; J = P_{20} + w , A_{20}, \qquad w = 1 .
$$
Here $P$ is the population in thousands of people and $A$ is the asset value in millions of USD.
2. Mathematical Model
2.1 Water supply
The base supply drops sharply in a drought centered on turn 9. Infrastructure built from past tax revenue reduces leakage and raises the effective supply:
$$
W_t^{\mathrm{base}} = W_0\left(1 - 0.55, e^{-\left(\frac{t-9}{3}\right)^2}\right), \qquad
W_t = W_t^{\mathrm{base}}\left(1 + \eta_{\max}\frac{A_t}{A_t + A_{1/2}}\right).
$$
2.2 Satisfaction ratios
The water delivered to each sector is $W_t^{\mathrm{agr}} = \alpha_t^{\mathrm{agr}} W_t$, and similarly for the other two. The demand is proportional to the population, with per-capita coefficients $q_a$ and $q_d$:
$$
r_t^{\mathrm{agr}} = \frac{W_t^{\mathrm{agr}}}{q_a P_t}, \qquad
r_t^{\mathrm{dom}} = \frac{W_t^{\mathrm{dom}}}{q_d P_t}.
$$
The satisfaction level is a smooth version of $\min(1, r)$, which keeps the objective differentiable for gradient-based optimization:
$$
s(r) = 1 - \frac{1}{\beta}\log!\left(1 + e^{\beta (1-r)}\right).
$$
2.3 Population dynamics
Water shortage raises mortality, and a food shortage also suppresses births. The logistic factor represents the carrying capacity $K$:
$$
m_t = m_0 + m_d,(1 - s_t^{\mathrm{dom}})^2 + m_a,(1 - s_t^{\mathrm{agr}})^2,
$$
$$
P_{t+1} = P_t\left[1 + b, s_t^{\mathrm{agr}} s_t^{\mathrm{dom}}\left(1 - \frac{P_t}{K}\right) - m_t\right].
$$
2.4 Industry, tax revenue, and assets
Industrial output saturates with industrial water and scales with the square root of the workforce. A fraction $\kappa$ of the output is collected as tax and reinvested, while assets depreciate at rate $\delta$:
$$
Y_t = Y_{\max}\left(1 - e^{-W_t^{\mathrm{ind}}/k_i}\right)\sqrt{\frac{P_t}{P_0}}, \qquad
A_{t+1} = (1-\delta)A_t + \kappa Y_t .
$$
This creates the central trade-off. Industrial water increases future assets and future water efficiency, while household and agricultural water keeps people alive and growing.
2.5 Concrete example
| Symbol | Value | Meaning |
|---|---|---|
| $P_0$, $A_0$ | 100, 200 | Initial population (thousand) and asset value (million USD) |
| $W_0$ | 85 | Base water supply per turn |
| $q_a$, $q_d$ | 0.50, 0.30 | Per-capita agricultural and domestic demand |
| $K$, $b$ | 260, 0.09 | Carrying capacity and birth coefficient |
| $m_0, m_d, m_a$ | 0.010, 0.25, 0.20 | Mortality coefficients |
| $Y_{\max}$, $k_i$ | 60, 25 | Industrial output scale and saturation constant |
| $\kappa$, $\delta$ | 0.5, 0.03 | Reinvestment rate and depreciation |
| $\eta_{\max}$, $A_{1/2}$ | 0.4, 400 | Infrastructure efficiency gain |
3. Solution Approach
We compare five policies:
- Equal split, with one third of the water to each sector.
- Agriculture first, with shares (0.60, 0.30, 0.10).
- Industry first, with shares (0.25, 0.20, 0.55).
- Best constant, found by a grid search over all fixed allocations.
- Optimized (dynamic), where the allocation can change every turn.
The dynamic policy has $20 \times 3 = 60$ logits $z_t$, mapped to valid shares by a softmax:
$$
\alpha_t^{k} = \frac{e^{z_t^{k}}}{\sum_{j} e^{z_t^{j}}} .
$$
The softmax removes the simplex constraint, so we can use L-BFGS-B directly. Because the objective is non-convex, we run six starting points and keep the best result. The simulator uses plain scalar arithmetic inside the 20-step loop, so the full optimization finishes in about a second and no further acceleration is needed.
4. Source Code
1 | import math |
5. Code Walkthrough
5.1 Parameters and helper functions
The constants in the first block correspond one-to-one with the table in Section 2.5. base_supply implements the Gaussian-shaped drought, which cuts the base supply by up to 55% around turn 9.
smooth_sat implements the smoothed satisfaction function $s(r)$. It uses np.logaddexp(0, x), which computes $\log(1+e^{x})$ without numerical overflow. The result is clipped to $[0, 1]$ to remove tiny floating-point excursions.
5.2 The simulator
simulate runs the 20-turn dynamics for any allocation matrix of shape (T, 3). In each turn it:
- Computes the effective supply, including the infrastructure bonus from current assets.
- Splits the supply into agricultural, domestic, and industrial water.
- Converts each delivery into a satisfaction level.
- Updates the population from the mortality and growth formulas.
- Updates the assets from the industrial output.
It returns the objective $J$ together with all time series, which are reused later for plotting.
5.3 Softmax parametrization
softmax_rows converts a $20 \times 3$ matrix of logits into valid shares. Every row is non-negative and sums to one, so the optimizer works in an unconstrained space. Subtracting the row maximum before exponentiation is a standard stabilization step.
5.4 Baselines and the constant-policy grid
The three hand-made policies are the reference points. The double loop then scans every fixed allocation $(\alpha^{\mathrm{agr}}, \alpha^{\mathrm{ind}})$ on a grid of step 0.025, with $\alpha^{\mathrm{dom}} = 1 - \alpha^{\mathrm{agr}} - \alpha^{\mathrm{ind}}$. These roughly 800 evaluations serve two purposes. They give the best constant policy, and they provide the data for the 3D surface.
5.5 Dynamic optimization
The decision vector has 60 entries. We run L-BFGS-B from six starting points:
- the uniform allocation,
- the best constant allocation,
- four random perturbations with a fixed seed.
The smooth satisfaction function matters here. A hard min would produce kinks that confuse gradient-based search, while the softplus version has a well-defined gradient everywhere. Bounds of $\pm 8$ on the logits keep the softmax numerically tame.
5.6 Evaluation and printing
Every policy is re-simulated, and the script prints a comparison table followed by the optimized allocation for each turn. The console output is the numerical counterpart of the figure.
5.7 The combined figure
All plots are drawn in a single $2 \times 3$ figure:
- Top left: the optimized allocation as a stacked area, with the effective supply as a dashed line.
- Top middle and right: population and asset trajectories for all five policies.
- Bottom left (3D): the objective $J$ as a surface over constant allocations, with the best constant policy and the dynamic optimum marked.
- Bottom middle (3D): the trajectory of each policy in (population, assets, turn) space.
- Bottom right: a stacked bar chart that splits the final $J$ into its population and asset components.
6. Results
Combined figure

Console output
Optimization time: 4.39 s Best constant allocation (agri, domestic, industry): (0.350, 0.250, 0.400) Policy Population Asset value J Equal split 90.11 390.24 480.36 Agriculture first 115.21 238.17 353.38 Industry first 68.17 415.54 483.71 Best constant 89.24 410.27 499.50 Optimized (dynamic) 90.79 414.54 505.33 Optimized allocation by turn (agri, domestic, industry): turn 1 W= 96.3 (0.308, 0.254, 0.438) turn 2 W= 97.0 (0.309, 0.250, 0.441) turn 3 W= 97.4 (0.309, 0.246, 0.445) turn 4 W= 97.2 (0.307, 0.244, 0.449) turn 5 W= 95.3 (0.303, 0.244, 0.454) turn 6 W= 89.9 (0.295, 0.247, 0.458) turn 7 W= 79.4 (0.282, 0.258, 0.460) turn 8 W= 64.7 (0.267, 0.280, 0.453) turn 9 W= 50.9 (0.272, 0.313, 0.415) turn 10 W= 45.1 (0.324, 0.333, 0.342) turn 11 W= 51.0 (0.375, 0.310, 0.314) turn 12 W= 65.0 (0.379, 0.268, 0.353) turn 13 W= 80.2 (0.362, 0.235, 0.403) turn 14 W= 91.3 (0.348, 0.219, 0.433) turn 15 W= 97.5 (0.344, 0.216, 0.440) turn 16 W= 100.1 (0.347, 0.219, 0.433) turn 17 W= 101.2 (0.353, 0.225, 0.422) turn 18 W= 101.6 (0.358, 0.232, 0.410) turn 19 W= 101.9 (0.362, 0.239, 0.399) turn 20 W= 102.1 (0.367, 0.245, 0.388)
7. Discussion
7.1 The one-sided policies fail in opposite ways
The agriculture-first policy keeps the population large, since farmers and households are almost never short of water. But it starves industry, so the asset value barely moves from its starting level and the final $J$ is by far the lowest.
The industry-first policy shows the opposite failure. Assets grow quickly, but during the drought the population falls to its lowest level. Because industrial output scales with $\sqrt{P_t}$, the shrinking workforce eventually drags on the very thing the policy was trying to maximize.
7.2 The 3D surface has a single broad peak
The surface of $J$ over constant allocations is smooth and unimodal. Its maximum lies at roughly 35% agriculture, 25% domestic use, and 40% industry. The surface falls off steeply when the agricultural share drops very low, because that region produces famine-level mortality, and also when the industrial share approaches zero, because the asset engine stalls. The practical lesson is that a moderately balanced allocation already captures most of the achievable value.
7.3 Dynamic reallocation adds a further gain
The optimized policy beats the best constant allocation. The stacked area chart shows why:
- Before the drought, the optimizer gives industry its largest share. Early assets compound through reinvestment and also raise the effective water supply, so water spent on industry pays back twice.
- During the drought, industry is cut back while the domestic and agricultural shares rise. The effective supply is at its lowest, and protecting the population from the quadratic mortality penalty is worth more than the lost output.
- After the drought, the industrial share recovers and the allocation drifts back toward its pre-drought pattern.
In other words, the optimizer treats industry as an investment to be front-loaded and treats household and farm water as insurance to be strengthened exactly when the supply is scarce.
7.4 State-space view
In the 3D trajectory plot, every policy starts at the same point. The agriculture-first path moves toward high population and low assets, and the industry-first path moves toward high assets and low population. The optimized path stays close to the efficient frontier of the other policies. It accepts a temporary population dip during the drought but ends with the highest combined value.
7.5 Final composition of the objective
The stacked bars make the trade-off explicit. Populations and asset values sit on different scales, so the weight $w$ matters: increasing $w$ shifts the optimum toward industry, and decreasing it shifts the optimum toward households and agriculture. Because the code exposes WEIGHT as a single constant, the policy preference can be explored by changing one line.
8. Conclusion
We modeled the allocation of scarce water as a 20-turn dynamic optimization problem with three coupled effects: shortage-driven mortality, industrial tax revenue that compounds into assets, and infrastructure that improves the effective supply. A smooth satisfaction function made the problem suitable for gradient-based optimization, and a softmax parametrization removed the allocation constraints.
The main findings were:
- Extreme policies are dominated. Neglecting either industry or agriculture sharply lowers the final objective.
- A well-chosen constant split already performs well, and the objective surface around it is smooth and forgiving.
- A time-varying policy performs better still. Invest in industry while water is plentiful, then shift water to people and food during the drought.
The same framework extends naturally to stochastic droughts, multiple regions sharing a river, or water-saving technology investments as an additional decision variable.
















