Thursday, 8 July 2010

F# vs Mathematica: parametric plots

Another example from Sal Mangano's Mathematica Cookbook (p.520) is an elegant little Mathematica program that uses a crude numerical integrator to plot the trajectory of a differential equation representing the populations of predators (foxes) and prey (rabbits):

This example, which was derived from this Wolfram Demonstrations sample, really plays to the strengths of the Mathematica language, not least its enormous standard library of graphing libraries.

However, .NET 4 does include new charting functionality so it is interesting to see how elegantly this can be written in F#. The following F# program implements the same functionality when evaluated interactively:

#r "System.Windows.Forms.dll" #r "System.Windows.Forms.DataVisualization.dll" #r "WindowsBase.dll" #r "WindowsFormsIntegration.dll" #r "PresentationCore.dll" #r "PresentationFramework.dll" #r "System.Xaml.dll" open System.Windows.Forms open System.Windows.Forms.DataVisualization.Charting let trajectory g k t = let evolve(r, f) = let dtrf = 0.0001 * r * f r + (1.0 - r/k)*r*g - dtrf, dtrf + (1.0 - g)*f Seq.scan (fun s _ -> evolve s) (50.0, 10.0) {1..t} use series = new Series(ChartType=SeriesChartType.Line) for x, y in trajectory 0.02 5e2 1500 do series.Points.AddXY(x, y) |> ignore use area = new ChartArea() area.AxisX.Title <- "Rabbits" area.AxisX.Minimum <- 0.0 area.AxisY.Title <- "Foxes" use chart = new Chart(Dock=DockStyle.Fill) chart.ChartAreas.Add area chart.Series.Add series use form = new Form() form.Controls.Add chart form.Show()

When evaluated, this F# program produces the following output:

This program will be the basis for a future F#.NET Journal article that introduces user interaction. Although Mathematica also makes user interaction easy as well, its relatively poor performance often makes interactive programs sluggish whereas the relevant code in our F# version of this program runs 64× faster than the original Mathematica and, consequently, produces a fluid user interface.


Art said...

Excellent F# WPF example, #r complete.

Bohdan Szymanik said...

I think you posted that a touch too quickly. " warning FS0046: The identifier 'fixed' is reserved for future use by F#"; and when I execute fixed() after the program I think the use bindings are disposing the form and chart straight away (if I change them to let bindings it's fine...)

Flying Frog Consultancy Ltd. said...

@Bohdan: Good catch! Its fixed now, thanks.

Aren'tWeRunning? said...

Hey where you have this

for x, y in trajectory 0.02 5e2 1500 do

series.Points.AddXY(x, y) |> ignore

is this just as valid ?

Seq.iter (fun (a, b) -> series.Points.AddXY(a, b) |> ignore ) (trajectory 0.02 5e2 1500)

i know it doesn't make a huge amount of difference :D

Flying Frog Consultancy Ltd. said...

@Aren'tWeRunning: Yes, although you'll probably need a type annotation or to rearrange it into something like trajectory 0.02 5e2 1500 |> Seq.iter (series.Points.AddXY >> ignore).