Getting the most from a limited garden or greenhouse area is a prime concern to producers. In a scientific horticultural context this mainly concerns planting density, pruning methods, time and rate of fertilizer application, variety chosen and so on. Once these parameters are decided, it then becomes a matter of profitability; how much of each plant should we produce given our limited resources and a knowledge of unit profitability?

This is the domain of constraint programming. The job of the constraint programme is to maximize, minimize or satisfy a target variable given basic information about the situation (the production resources, labour, space, fertilizer, heating and so on) plus the constraints of the situation (the limits on otherwise boundless possibilities).

One such constraint programming optimizer is the open-source effort MiniZinc produced by NICTA in Australia. The goal of this software is to act as a go-between linking a plain statement of the problem (the model) with a specialized back-end programme (the solver). MiniZinc translates the instructions into a form that the back-end can handle well, and then reports back the results from the solver's effort.

Here is a toy example of a constraint programme in a garden or greenhouse context. To fresh eyes it will look complicated. There is a line by line explanation below the programme.

% first garden model int: np = 4; set of 1..np: Splants = 1..np; array[Splants] of var 0..10: plants; array[Splants] of int: ppp = [2,1,4,-3]; constraint forall(p in Splants)(plants[p] >= 0); constraint sum(plants) = 7; constraint plants[3] <= 2; var int: profits; constraint profits = sum([plants[p]*ppp[p] | p in Splants]); solve maximize profits; output ["\(profits) \(plants)"];

In this model we set out the simple problem. The parameter np sets the number of plant varieties to 4, and based on this we ask for a set of numbers running from 1 to 4 which we place in Splants. We then ask for two arrays, both 4 elements long. The first one can contain numbers from 0..10; that is, we can produce from 0 to 10 of each of the four products. The note "var" in this line tells the programme that it is free to choose the best value here for each item. The second array contains numbers related to the profitability per plant variety (ppp). The first plant type brings 2 which is good, the second only 1 which is poor, the third 4 which is very nice and the last -3 which indicates a loss on that plant, not good at all.

Now we add details about the constraints or restrictions. We want to make sure that we cannot produce negative amounts of a plant, that we have only enough room to produce a total of 7 units of anything, and that there is an upper limit of 2 on the most profitable item number 3 (perhaps because of lack of seed, for example). We are interested in maximizing the profits from this venture, so we request a variable "profits" and with a constraint we show the programme how to calculate the profits with a comprehension (using the sum() function). A comprehension is just a shorthand way of telling the computer how to calculate something.

Finally the solve line says maximize please by choosing the best numbers for the variable components in the model, and the output line says "show me the results contained in these variables." The result appears below.

Compiling g1.mzn Running g1.mzn 14 [7, 0, 0, 0] ---------- 16 [6, 0, 1, 0] ---------- 18 [5, 0, 2, 0] ---------- ========== Finished in 6msec

In this result, MiniZinc says it is preparing the input to the solver, asks the solver to run it, and then produces the results. At first the solver finds a profitability of 14 by producing the whole of the 7 allotment of plant 1. Then it finds a better solution by producing 6 of plant 1 and 1 of plant 3, and finally decides that a profit of 18 by producing 5 of plant 1 and 2 of plant 3 is the best we can do. It signifies that there are no better outcomes with the line of equals signs. The result is good in that it does not ask us to produce any of item 4 which has negative return, and finds that item 2 does not need to be produced since its return is too low.

For programmers accustomed to sequential programming commands, declarative processes (telling the computer what you want, not how to do it) can seem strange. One way to become accustomed to this type of puzzle is to start with a toy example and build up the complexity until it represents a real business situation. In the process you can gain confidence that the solver is in fact producing a viable and optimized solution to the problem.

Yes, this is just a toy problem and you could probably have come to the same conclusion on the back of an envelope. But if you scale up the problem to hundreds and even thousands of plants, a computer and MiniZinc will probably do a lot better than you can, faster and more accurately. To see a more complicated example, see optimizing with 30 different plants.

Copyright © 2016