Some example economic linear programs

In the previous post I laid out an outline for the case for computerized planning. In this post I will present some simple examples that should help get the point across.

A tiny example economy

In these examples I will use an economy which produces only one good. That good could be anything, for example food. There are two technologies available to produce this good: techA and techB. The difference between the two technologies is that techA uses 2 units of labour and 3 units of CO2 emissions per unit of output while techB is the opposite: 3 units of labour and 2 units of CO2. They complement each other, and the choice between them depends on whether we're minimizing labour input, CO2 emissions or some combination of the two. Given demand ZA==, maximum labour TF97bWF4fQ== and maximum CO2 emission Q197bWF4fQ==, we have the following matrix equation:

ClxsZWZ0WwpcYmVnaW57bWF0cml4fQogMSAmICAxIFxcCi0yICYgLTMgXFwKLTMgJiAtMgpcZW5ke21hdHJpeH0KXHJpZ2h0XQpcbGVmdFsKXGJlZ2lue21hdHJpeH0KeF9BIFxcCnhfQgpcZW5ke21hdHJpeH0KXHJpZ2h0XSBcZ2VxClxsZWZ0WwpcYmVnaW57bWF0cml4fQpkIFxcCi1MX3ttYXh9IFxcCi1DX3ttYXh9ClxlbmR7bWF0cml4fQpccmlnaHRdCg==

Both eF9B and eF9C are non-negative, meaning eCBcZ2VxIDA=. All eA== are implied to be non-negative for the rest of this article.

On its own the preceeding equation is not very useful since neither labour nor CO2 are variables. To be able to optimize on either, the system needs to be extended. Let's start with minimizing labour, which requires adding a third variable eF9M:

ClxsZWZ0WwpcYmVnaW57bWF0cml4fQogMSAmICAxICYgMCBcXAotMiAmIC0zICYgMVxcCi0zICYgLTIgJiAwClxlbmR7bWF0cml4fQpccmlnaHRdClxsZWZ0WwpcYmVnaW57bWF0cml4fQp4X0EgXFwKeF9CIFxcCnhfTApcZW5ke21hdHJpeH0KXHJpZ2h0XSBcZ2VxClxsZWZ0WwpcYmVnaW57bWF0cml4fQpkIFxcCjAgXFwKLUNfe21heH0KXGVuZHttYXRyaXh9ClxyaWdodF0K

The new column in the matrix turns the second row into a "balance equation". Since we are minimizing eF9M the goal is to add as little of it as possible while still keeping the sum of the labour added and the labour consumed non-negative.

The optimal solution eF9cYXN0 that we seek is given by:

CnhfXGFzdCA9IFxvcGVyYXRvcm5hbWUqe2FyZ1wsbWlufV94IGNeVCB4Cg==

where

CmMgPQpcbGVmdFsKXGJlZ2lue21hdHJpeH0KMCBcXAowIFxcCjEKXGVuZHttYXRyaXh9ClxyaWdodF0K

The solution depends only on ZA== and Q197bWF4fQ==. If we let Q197bWF4fSA9IDU= then we can sweep ZA== from 0 to 2.5. The following bash script does this, has lp_solve solve the resulting linear program, parses the result and spits out Octave code the renders the plot below:

#!/bin/bash
# makes seq use decimal dots in Swedish locale, not commas
export LANG=C

echo "x=["
for d in $(seq 0 0.05 2.5)
do
  lp_solve <<EOF > /tmp/lp_result
min: xl;
xa + xb >= $d;
-2 xa - 3 xb + xl >= 0;
-3 xa - 2 xb >= -5;
EOF
  for var in xa xb xl
  do
    V=$(grep $var /tmp/lp_result | sed -e 's/^[^0-9]*//')
    export $var=$V
  done
  echo "$d,$xa,$xb,$xl;"
done
echo "];"
echo "plot(x(:,1),x(:,2),x(:,1),x(:,3),x(:,1),x(:,4));"
echo "legend('techA','techB','labour','location','northeastoutside');"
echo "xlabel('Demand');"
echo "ylabel('Intensity');"
echo "title('CO_2 constrained labour-minimizing economy');"
echo "axis([0,2.5,0,8]);"
echo "print('tiny_economy.png');"

The plot generated by the above bash+Octave code

We can see that techA is preferred as long as CO2 emissions stay below the limit. Once demand goes past 1.66, techB starts getting used and the marginal demand for labour increases.

If we instead minimize CO2 emissions then the result looks much the same, except techA and techB swap roles:

#!/bin/bash
# makes seq use decimal dots in Swedish locale, not commas
export LANG=C

echo "x=["
for d in $(seq 0 0.05 2.5)
do
  lp_solve <<EOF > /tmp/lp_result
min: xc;
xa + xb >= $d;
-2 xa - 3 xb >= -5;
-3 xa - 2 xb + xc >= 0;
EOF
  for var in xa xb xc
  do
    V=$(grep $var /tmp/lp_result | sed -e 's/^[^0-9]*//')
    export $var=$V
  done
  echo "$d,$xa,$xb,$xc;"
done
echo "];"
echo "plot(x(:,1),x(:,2),x(:,1),x(:,3),x(:,1),x(:,4));"
echo "legend('techA','techB','CO_2','location','northeastoutside');"
echo "xlabel('Demand');"
echo "ylabel('Intensity');"
echo "title('CO_2-minimizing labour constrained economy');"
echo "axis([0,2.5,0,8]);"
echo "print('tiny_economy2.png');"

The plot generated by the above bash+Octave code. techA and techB are switched compared to the previous plot

In reality we may want to minimize some combination of labour and CO2. The following is an interesting example:

#!/bin/bash
# makes seq use decimal dots in Swedish locale, not commas
export LANG=C

echo "x=["
for d in $(seq 0 0.05 2.5)
do
  lp_solve <<EOF > /tmp/lp_result
min: xl + 0.5 xc;
xa + xb >= $d;
-2 xa - 3 xb + xl >= 0;
-3 xa - 2 xb + xc >= 0;
xa <= 1.5;
xb <= 1.5;
xc <= 6;
EOF
  for var in xa xb xl xc
  do
    V=$(grep $var /tmp/lp_result | sed -e 's/^[^0-9]*//')
    export $var=$V
  done
  echo "$d,$xa,$xb,$xl,$xc;"
done
echo "];"
echo "plot(x(:,1),x(:,2),x(:,1),x(:,3),x(:,1),x(:,4),x(:,1),x(:,5));"
echo "legend('techA','techB','labour','CO_2','location','northeastoutside');"
echo "xlabel('Demand');"
echo "ylabel('Intensity');"
echo "title('Combination economy');"
echo "axis([0,2.5,0,8]);"
echo "print('tiny_economy3.png');"

The plot generated by the above bash+Octave code. Behavious is much more interesting

In this example the capabilities of techA and techB are limited. Each can only produce 1.5 units of goods. Additionally, CO2 emissions are limited to 6 and we're trying to optimize for a mix that favours labour. Three different regions are clearly visible. The first region is unconstrained, the second region is constrained by the capabilities of techA and the third region is constrained by CO2. As the marginal CO2 "demand"/budget decreases, the marginal demand for labour increases.

Incidentally, the equations for this system look like this:

CnhfXGFzdCA9IFxvcGVyYXRvcm5hbWUqe2FyZ1wsbWlufV94ClxsZWZ0WwpcYmVnaW57bWF0cml4fQowIFxcCjAgXFwKMSBcXAowLjUKXGVuZHttYXRyaXh9ClxyaWdodF1eVApcbGVmdFsKXGJlZ2lue21hdHJpeH0KeF9BIFxcCnhfQiBcXAp4X0wgXFwKeF9DClxlbmR7bWF0cml4fQpccmlnaHRdCg==

ClxsZWZ0WwpcYmVnaW57bWF0cml4fQogMSAmICAxICYgMCAmICAwIFxcCi0yICYgLTMgJiAxICYgIDAgXFwKLTMgJiAtMiAmIDAgJiAgMSBcXAotMSAmICAwICYgMCAmICAwIFxcCiAwICYgLTEgJiAwICYgIDAgXFwKIDAgJiAgMCAmIDAgJiAtMSBcXAogMSAmICAwICYgMCAmICAwIFxcCiAwICYgIDEgJiAwICYgIDAgXFwKIDAgJiAgMCAmIDEgJiAgMCBcXAogMCAmICAwICYgMCAmICAxIFxcClxlbmR7bWF0cml4fQpccmlnaHRdClxsZWZ0WwpcYmVnaW57bWF0cml4fQp4X0EgXFwKeF9CIFxcCnhfTCBcXAp4X0MKXGVuZHttYXRyaXh9ClxyaWdodF0gXGdlcQpcbGVmdFsKXGJlZ2lue21hdHJpeH0KZCBcXAowIFxcCjAgXFwKLTEuNSBcXAotMS41IFxcCi02IFxcCjAgXFwKMCBcXAowIFxcCjAKXGVuZHttYXRyaXh9ClxyaWdodF0K

Here I have chosen to make the non-negativity constraints on eA== explicit, to highlight that the full matrix is tall. We can also see that the system is quite sparse and that it can be slightly simplified:

CnhfXGFzdCA9IFxvcGVyYXRvcm5hbWUqe2FyZ1wsbWlufV94ClxsZWZ0WwpcYmVnaW57bWF0cml4fQoxIFxcCjAuNQpcZW5ke21hdHJpeH0KXHJpZ2h0XV5UClxsZWZ0WwpcYmVnaW57bWF0cml4fQp4X0wgXFwKeF9DClxlbmR7bWF0cml4fQpccmlnaHRdCg==

ClxsZWZ0WwpcYmVnaW57bWF0cml4fQogMSAmICAxICYgICAmICAgIFxcCi0yICYgLTMgJiAxICYgICAgXFwKLTMgJiAtMiAmICAgJiAgMSBcXAotMSAmICAgICYgICAmICAgIFxcCiAgICYgLTEgJiAgICYgICAgXFwKICAgJiAgICAmICAgJiAtMSBcXAogMSAmICAgICYgICAmICAgIFxcCiAgICYgIDEgJiAgICYgICAgXFwKICAgJiAgICAmIDEgJiAgICBcXAogICAmICAgICYgICAmICAxIFxcClxlbmR7bWF0cml4fQpccmlnaHRdClxsZWZ0WwpcYmVnaW57bWF0cml4fQp4X0EgXFwKeF9CIFxcCnhfTCBcXAp4X0MKXGVuZHttYXRyaXh9ClxyaWdodF0gXGdlcQpcbGVmdFsKXGJlZ2lue21hdHJpeH0KZCBcXAowIFxcCjAgXFwKLTEuNSBcXAotMS41IFxcCi02IFxcCjAgXFwKMCBcXAowIFxcCjAKXGVuZHttYXRyaXh9ClxyaWdodF0K

Other examples

Chain economy

A chain economy like A -> B -> C -> ... Z where each industry needs two units of the industry before it, one unit of labour and one unit of CO2, looks like this:

ClxsZWZ0WwpcYmVnaW57bWF0cml4fQogMSAmIC0yICYgICAmICAgICAgICAgJiAgICAmICAgJiAgIFxcCiAgICYgIDEgJi0yICYgICAgICAgICAmICAgICYgICAmICAgXFwKICAgJiAgICAmIDEgJiBcZGRvdHMgICYgICAgJiAgICYgICBcXAogICAmICAgICYgICAmIFxkZG90cyAgJi0yICAmICAgJiAgIFxcCiAgICYgICAgJiAgICYgICAgICAgICAmIDEgICYgICAmICAgXFwKLTEgJiAtMSAmLTEgJiBcaGRvdHMgICYgLTEgJiAxICYgICBcXAotMSAmIC0xICYtMSAmIFxoZG90cyAgJiAtMSAmICAgJiAxIFxcClxlbmR7bWF0cml4fQpccmlnaHRdeCBcZ2VxClxsZWZ0WwpcYmVnaW57bWF0cml4fQpkX0EgXFwKZF9CIFxcCmRfQyBcXApcdmRvdHMgXFwKZF9aIFxcCjAgXFwKMCBcXApcZW5ke21hdHJpeH0KXHJpZ2h0XQo=

Service economy

Services are industries which notionally require only labour. In practice they require more than that, like office supplies. Service workers also need to eat, but that is handled elsewhere in the equations. Service industries do not emit CO2 on their own, but may do so indirectly, like all industries today.

ClxsZWZ0WwpcYmVnaW57bWF0cml4fQogMSAmICAgICYgICAmICAgICAgICAgJiAgICAmICAgXFwKICAgJiAgMSAmICAgJiAgICAgICAgICYgICAgJiAgIFxcCiAgICYgICAgJiAxICYgICAgICAgICAmICAgICYgICBcXAogICAmICAgICYgICAmIFxkZG90cyAgJiAgICAmICAgXFwKICAgJiAgICAmICAgJiAgICAgICAgICYgMSAgJiAgIFxcCi0xICYgLTEgJi0xICYgXGhkb3RzICAmIC0xICYgMSBcXApcZW5ke21hdHJpeH0KXHJpZ2h0XXggXGdlcQpcbGVmdFsKXGJlZ2lue21hdHJpeH0KZF9BIFxcCmRfQiBcXApkX0MgXFwKXHZkb3RzIFxcCmRfWiBcXAowIFxcClxlbmR7bWF0cml4fQpccmlnaHRdCg==

Food production

To ensure everyone is fed and that there's a variety of foods available, one adds a number of constraints. The most important of these are those for macronutrients like energy, carbohydrates, fat, protein and so on. If we were to rely only on nutrients then the solution would likely end up picking a single crop like maize or sorghum. While this keeps people fed, it would be a very depressing diet.

We can use statistics of what kinds of food people prefer and add a constraint for each one: produce at least ZF97UG99 potatoes, ZF97Q019 coconut milk, ZF97SGF9 Habaneros and so on. It is also the case that preferences vary with season and region. We know with high certainty that demand for Julmust will be high for roughly two months around the winter solstice in Sweden, but comparatively low the rest of the year. A similar peak occurs around Easter for Påskmust.

Demand for some goods vary with a frequency different from that of the Gregorian year. For example goods associated with Ramadan and similar traditions that follow a lunar calendar. For regional foods, sizeable diasporas must be accounted for.

For the ten staple foods listed on Wikipedia the following LP for how much area to plant of each crop can be built:

ClxsZWZ0WwpcYmVnaW57YXJyYXl9eyp7MTF9Y30KLjMyICYgLjEyICYgLjEwICYgLjEyICYgLjE5ICYgLjAyICYgLjEwICYgLjExICYgMSAmIC4xMyAmIFxcCi4yNSAmIC4wNyAmIC4xMSAmIC4wOSAmIC4wNSAmIC4wNiAmIC4wNSAmIC4wNCAmIDEgJiAuMDQgJiBcXAouMjkgJiAuMTIgJiAuMTAgJiAuMTIgJiAuMjAgJiAuMDEgJiAuMTAgJiAuMTIgJiAxICYgLjE1ICYgXFwKLjM1ICYgLjAyICYgLjIwICYgLjE4ICYgLjExICYgLjAzICYgLjE4ICYgLjIxICYgMSAmIC4xMyAmIFxcCi4zOCAmIC4wMiAmIC4wMiAmIC4wMCAmIC4wMyAmIC4wNyAmIC4wMCAmIC4wMCAmIDEgJiAuMDEgJiBcXAouNDcgJiAuMDEgJiAuMDUgJiAuMDIgJiAuMDEgJiAuMTIgJiAuMDAgJiAuMDIgJiAxICYgLjAyICYgXFwKLTEgICYgLTEgICYgLTEgICYgLTEgICYgLTEgICYgLTEgICYgLTEgICYgLTEgICYtMSAmIC0xICAmIDEgXFwKXGVuZHthcnJheX0KXHJpZ2h0XQpcbGVmdFsKXGJlZ2lue21hdHJpeH0KeF97TWF9IFxcCnhfe1JpfSBcXAp4X3tXaH0gXFwKeF97UG99IFxcCnhfe0NhfSBcXAp4X3tTb30gXFwKeF97U3d9IFxcCnhfe1lhfSBcXAp4X3tTb30gXFwKeF97UGx9IFxcCnhfe0F9IFxcClxlbmR7bWF0cml4fQpccmlnaHRdClxnZXEKXGxlZnRbClxiZWdpbnttYXRyaXh9CjAuMDY4IFxcCjAuMDUxIFxcCjAuMDIwIFxcCjAuMDU1IFxcCjAuMjU2IFxcCjAuMTA5IFxcCjAgXFwKXGVuZHttYXRyaXh9ClxyaWdodF0K

Each column corresponds to a staple crop from maize to plantain and the final column is for optimizing area. The values are weighted by how much is produced per hectare by the most productive country for each crop. Rows are scaled so that the values for the ninth column (sorghum) are all ones. The right-hand side is given by the RDA column in the Wikipedia article and represents how many hectares must be cultivated to produce 10,000 person-days of each nutrient.

Rows correspond to energy, protein, carbohydrates, fiber, monounsaturated fatty acids and polyunsaturated fatty acids. The final row is the balance equation for area.

We can see by visual inspection that sorghum is the most efficient crop in terms of area, with 0.26 hectares being enough to supply 10,000 person-days of macronutrients. The limiting factor is monounsaturated fatty acids. If canola oil is used for fat, then the necessary area shrinks to around 0.11 hectares.

This sort of diet would only really be acceptable in the most extreme circumstances. As I said in the beginning of this section, one would add extra constraints that certain crops should be grown because people want them. Yields also vary by location, but adding extra variables per grid locator for optimization would not fit in a blog post.