Optimization In One Dimension in F# QuickStart Sample
Illustrates the use of the Brent and Golden Section optimizer classes in the Numerics.NET.Optimization namespace for one-dimensional optimization in F#.
This sample is also available in: C#, Visual Basic, IronPython.
Overview
This QuickStart sample demonstrates how to find the minimum or maximum of a function in one dimension using Numerics.NET’s optimization capabilities.
The sample shows two different optimization algorithms:
- Brent’s algorithm - A sophisticated and efficient method that combines golden section search with
parabolic interpolation. It is the recommended method for most one-dimensional optimization problems.
The sample demonstrates how to:
- Create and configure a BrentOptimizer
- Find an interval containing an extremum using FindBracket
- Locate the precise minimum or maximum
- Access results and error estimates
- Golden Section Search - A simpler but slower algorithm based on the golden ratio. The sample shows how to use the GoldenSectionOptimizer class to find extrema.
Both methods are demonstrated on two test functions:
- A cubic polynomial f(x) = x� - 2x - 5
- An exponential function f(x) = 1/exp(x� - 0.7x + 0.2)
The sample illustrates proper error handling, accessing optimization results, and comparing estimated versus actual errors. It also shows how to use lambda expressions for defining objective functions in C# 3.0 and later.
The code
//=====================================================================
//
// File: optimization-in-1d.fs
//
//---------------------------------------------------------------------
//
// This file is part of the Numerics.NET Code Samples.
//
// Copyright (c) 2004-2025 ExoAnalytics Inc. All rights reserved.
//
//=====================================================================
module OptimizationIn1D
// Illustrates the use of the Brent and Golden Section optimizers
// in the Numerics.NET.Optimization namespace of Numerics.NET.
#light
open System
open Numerics.NET
// The optimization classes resides in the
// Numerics.NET.EquationSolvers namespace.
open Numerics.NET.Optimization
// The license is verified at runtime. We're using a 30 day trial key here.
// For more information, see:
// https://numerics.net/trial-key
let licensed = Numerics.NET.License.Verify("your-trial-key-here")
// Several algorithms exist for optimizing functions
// in one variable. The most common one is
// Brent's algorithm.
// The function we are trying to minimize is called the
// objective function and must be provided as a Func<double, double>.
//
// Brent's algorithm
//
// Now let's create the BrentOptimizer object.
let optimizer = BrentOptimizer()
// Set the objective function:
optimizer.ObjectiveFunction <- Func<_,_> (fun x -> x * x * x - 2.0 * x - 5.0)
// Optimizers can find either a minimum or a maximum.
// Which of the two is specified by the ExtremumType
// property
optimizer.ExtremumType <- ExtremumType.Minimum
// The first phase is to find an interval that contains
// a local minimum. This is done by the FindBracket method.
optimizer.FindBracket(0.0, 3.0)
// You can verify that an interval was found from the
// IsBracketValid property:
if (not optimizer.IsBracketValid) then
raise (Exception("An interval containing a minimum was not found."))
// Finally, we can run the optimizer by calling the FindExtremum method:
let extremum = optimizer.FindExtremum()
printfn "Function 1: x^3 - 2x - 5"
// The Status property indicates
// the result of running the algorithm.
printfn " Status: %A" optimizer.Status
// The result is available through the
// Result property.
printfn " Minimum: %A" optimizer.Result
let exactResult = sqrt(2.0/3.0)
let result = optimizer.Extremum
printfn " Exact minimum: %A" exactResult
// You can find out the estimated error of the result
// through the EstimatedError property:
printfn " Estimated error: %A" optimizer.EstimatedError
printfn " Actual error: %A" (abs(result - exactResult))
printfn " # iterations: %d" optimizer.IterationsNeeded
printfn "Function 2: 1/Exp(x*x - 0.7*x +0.2)"
// You can also perform these calculations more directly
// using the FindMinimum or FindMaximum methods. This implicitly
// calls the FindBracket method.
let f2 = Func<_,_> (fun x -> 1.0 / exp(x*x - 0.7*x + 0.2))
let result2 = optimizer.FindMaximum(f2, 0.0)
printfn " Maximum: %A" result2
printfn " Actual maximum: %A" 0.35
printfn " Estimated error: %A" optimizer.EstimatedError
printfn " Actual error: %A" (result - 0.35)
printfn " # iterations: %d" optimizer.IterationsNeeded
//
// Golden section search
//
// A slower but simpler algorithm for finding an extremum
// is the golden section search. It is implemented by the
// GoldenSectionMinimizer class:
let optimizer2 = GoldenSectionOptimizer()
printfn "Using Golden Section optimizer:"
let result3 = optimizer2.FindMaximum(f2, 0.0)
printfn " Maximum: %A" result3
printfn " Actual maximum: %A" 0.35
printfn " Estimated error: %A" optimizer2.EstimatedError
printfn " Actual error: %A" (result - 0.35)
printfn " # iterations: %d" optimizer2.IterationsNeeded
printf "Press Enter key to exit..."
Console.ReadLine() |> ignore