aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 0d526e5784f8688b4a7cdf7cbdac1d33d86d8d53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
This library implements a simple eDSL for linear programming and a simple
wrapper around lp_solve (potentially other solvers can also be plugged in
easily).  Here's how to solve the farmer example from the lp_solve
documentation:

> Suppose a farmer has 75 acres on which to plant two crops: wheat and barley.
> To produce these crops, it costs the farmer (for seed, fertilizer, etc.) $120
> per acre for the wheat and  $210 per acre for the barley. The farmer has
> $15000 available for expenses. But after the harvest, the farmer must store
> the crops while awaiting favourable market conditions. The farmer has storage
> space for 4000 bushels. Each acre yields an average of 110 bushels of wheat
> or 30 bushels of barley.  If the net profit per bushel of wheat (after all
> expenses have been subtracted) is $1.30 and for barley is $2.00, how should
> the farmer plant the 75 acres to maximize profit?

    import Control.Monad
    import Math.LinProg.LPSolve
    import Math.LinProg.Types

    data Crop = Wheat | Barley
      deriving (Eq, Show, Ord)

    lp :: LinProg Double Crop ()
    lp = do
      let vs@[w, b] = map var [Wheat, Barley]
      obj $ negate $ 110 * 1.3 * w + 30 * 2 * b
      120 * w + 210 * b <: 15000
      110 * w + 30 * b <: 4000
      w + b <: 75

    main :: IO ()
    main = do
      sol <- solve lp
      print sol

This outputs the solution: Right [(Wheat,21.875),(Barley,53.12499999999999)].
Due to the monadic structure one can build up LPs using the usual monadic
controls such as mapM/forM etc, making it quite easy to specify constraints.