For the purposes of this example, tomatoes come in three sizes: tiny (salad size), small, medium, and large. Of the three larger sizes, people tend to prefer medium, so they are the most expensive. Large (being overripe and watery) are cheaper, and small are the cheapest. However, tiny tomatoes, useful for salads and garnishes, command a premium price.
My solution encodes this tomato wisdom in a set of four rules. It also prints a list of tomato size vs. price, estimated using the rules. I have taken the liberty of graphing this output, complete with gratuitous tomato colorization in the chart below:
And below is the code. It relies on the F# fuzzy logic functions presented in yesterday’s blog. As always, all the code here is presented "as-is" and without warranty or implied fitness of any kind; use at your own risk.
Admittedly, this is not a stunning example of the power of fuzzy logic, but it does illustrate a few of the basic techniques. A good reference, like the previously mentioned Fuzzy Logic With Engineering Applications, by Timothy J. Ross, will reveal the broader range of fuzzy logic techniques.
Tomorrow I will show how conjunction can be used to create rules which use more than one input set to combine different types of data.
// This function will turn a pair of
// fuzzy sets into a function that will
// act as a rule. The input to the function
// is the x value, and the output is a tuple
// of the output set area and its centroid.
let makeRule (l0,l1) =
let f =
let a0 = f l0
let a1 = f l1
Trapezoid.height x a0
|> Trapezoid.project a1)
// Tomato size in inches.
let tiny = [(0.0,1.0);(1.0,1.0);(2.0,0.0)]
let small = [(1.0,0.0);(2.0,1.0);(3.0,0.0)]
let medium = [(2.0,0.0);(3.0,1.0);(4.0,0.0)]
let large = [(3.0,0.0);(5.0,1.0);(9.0,1.0)]
// Tomato price in $.
let cheap = [(0.50,0.0);(1.00,1.0);(1.50,0.0)]
let moderate = [(1.00,0.0);(1.50,1.0);(2.00,0.0)]
let expensive = [(1.50,0.0);(2.00,1.0);(2.50,0.0)]
let outrageous = [(2.00,0.0);(4.00,1.0);(6.00,0.0)]
// The ruleset.
let rules =
] |> List.map makeRule
// Map the ruleset to a range of
// tomato sizes.
for size in 0.25..0.25..5.00 do
printfn "%f, %f"
(List.map (fun r->r size) rules
|> List.fold (fun (a,b)(ax,bx)->a+ax,b+ax*bx) (0.0,0.0)
|> (fun (a,b)->b/a))
printf "Your breakpoint here."