Nonlinear Systems in Visual Basic QuickStart Sample

Illustrates the use of the NewtonRaphsonSystemSolver and DoglegSystemSolver classes for solving systems of nonlinear equations in Visual Basic.

View this sample in: C# F# IronPython

Option Infer On

' The optimization classes reside in the
' Extreme.Mathematics.Optimization namespace.
Imports Extreme.Mathematics.EquationSolvers
' Vectors and Function delegates reside in the Extreme.Mathematics
' namespace.
Imports Extreme.Mathematics
Imports Extreme.Mathematics.Algorithms

    ' Illustrates solving systems of non-linear equations using 
    ' classes in the Extreme.Mathematics.EquationSolvers namespace 
    ' of Extreme Numerics.NET.
    Module NonlinearSystems

        Sub Main()
        ' The license is verified at runtime. We're using
        ' a demo license here. For more information, see
        ' https://numerics.net/trial-key
        Extreme.License.Verify("Demo license")

        '
        ' Target function
        '

        ' The function we are trying to solve can be provided
        ' on one of two ways. The first is as an array of 
        ' Func(Of Vector, Double) delegates. See the end of this
        ' sample for definitions of the methods that are referenced here.
        Dim f As Func(Of Vector(Of Double), Double)() = {AddressOf f1, AddressOf f2}
        ' We can also supply the Jacobian, which is the matrix of partial
        ' derivatives. We do so by providing the gradient of each target
        ' function as a Func(Of Vector, Vector, Vector) delegate.
        '
        ' The Func(Of Vector, Vector, Vector) takes a second argument:
        ' the vector that is to hold the return value. This avoids unnecessary
        ' creation of new Vector instances.
        Dim df As Func(Of Vector(Of Double), Vector(Of Double), Vector(Of Double))() =
                {AddressOf df1, AddressOf df2}

        ' The initial values are supplied as a vector:
        Dim initialGuess = Vector.Create(0.5, 0.5)

        '
        ' Newton-Raphson Method
        '

        ' The Newton-Raphson method is implemented by
        ' the NewtonRaphsonSystemSolver class.
        Dim solver As New NewtonRaphsonSystemSolver(f, df, initialGuess)

        ' and call the Solve method to obtain the solution:
        Dim solution = solver.Solve()

        Console.WriteLine("N-dimensional Newton-Raphson Solver:")
        Console.WriteLine("exp(x)*cos(y) - x^2 + y^2 = 0")
        Console.WriteLine("exp(x)*sin(y) - 2xy = 0")
        Console.WriteLine("  Initial guess: {0:F2}", initialGuess)
        ' The Status property indicates
        ' the result of running the algorithm.
        Console.WriteLine("  Status: {0}", solver.Status)
        ' The result is also available through the
        ' Result property.
        Console.WriteLine("  Solution: {0}", solver.Result)
        Console.WriteLine("  Function value: {0}", solver.ValueTest.Error)
        ' You can find out the estimated error of the result
        ' through the EstimatedError property:
        Console.WriteLine("  Estimated error: {0}", solver.EstimatedError)
        Console.WriteLine("  # iterations: {0}", solver.IterationsNeeded)
        Console.WriteLine("  # evaluations: {0}", solver.EvaluationsNeeded)
#If NET40 Then
#Else
#End If

            ' In .NET 4.0, you can use Automatic Differentiation to compute the Jacobian.
            ' To do so, set the target functions using the SetSymbolicTargetFunctions
            ' method:
            solver = New NewtonRaphsonSystemSolver()
            solver.InitialGuess = initialGuess

            solver.SetSymbolicTargetFunctions(
                Function(x) Math.Exp(x(0)) * Math.Cos(x(1)) - x(0) * x(0) + x(1) * x(1),
                Function(x) Math.Exp(x(0)) * Math.Sin(x(1)) - 2 * x(0) * x(1))

            solution = solver.Solve()
            Console.WriteLine("Using Automatic Differentiation:")
            Console.WriteLine("  Solution: {0}", solver.Result)
            Console.WriteLine("  Function value: {0}", solver.ValueTest.Error)
            Console.WriteLine("  # iterations: {0}", solver.IterationsNeeded)

            ' When you don't have the Jacobian for the target functions
            ' and you don't use Automatic Differentiation, the equation solver 
            ' will use a numerical approximation.
        ' When you don't have the Jacobian for the target functions,
        ' the equation solver will use a numerical approximation.

        '
        ' Controlling the process
        '
        Console.WriteLine("Same with modified parameters:")
        ' You can set the maximum # of iterations:
        ' If the solution cannot be found in time, the
        ' Status will return a value of
        ' IterationStatus.IterationLimitExceeded
        solver.MaxIterations = 10

        ' The ValueTest property returns the convergence
        ' test based on the function value. We can set
        ' its tolerance property:
        solver.ValueTest.Tolerance = 0.0000000001
        ' Its Norm property determines how the error
        ' is calculated. Here, we choose the maximum
        ' of the function values:
        solver.ValueTest.Norm = VectorConvergenceNorm.Maximum

        ' The SolutionTest property returns the test
        ' on the change in location of the solution.
        solver.SolutionTest.Tolerance = 0.0000000001
        ' You can specify how convergence is to be tested
        ' through the ConvergenceCriterion property:
        solver.SolutionTest.ConvergenceCriterion = ConvergenceCriterion.WithinRelativeTolerance

        solver.InitialGuess = initialGuess
        solution = solver.Solve()
        Console.WriteLine("  Status: {0}", solver.Status)
        Console.WriteLine("  Solution: {0}", solver.Result)
        ' The estimated error will be less than 5e-14
        Console.WriteLine("  Estimated error: {0}", solver.SolutionTest.Error)
        Console.WriteLine("  # iterations: {0}", solver.IterationsNeeded)
        Console.WriteLine("  # evaluations: {0}", solver.EvaluationsNeeded)

        '
        ' Powell's dogleg method
        '

        ' The dogleg method is more robust than Newton's method.
        ' It will converge often when Newton's method fails.
        Dim dogleg As New DoglegSystemSolver(f, df, initialGuess)

        ' Unique to the dogleg method is the TrustRegionRadius property.
        ' Any step of the algorithm is not larger than this value.
        ' It is adjusted at each iteration.
        dogleg.TrustRegionRadius = 0.5

        ' Call the Solve method to obtain the solution:
        solution = dogleg.Solve()

        Console.WriteLine("Powell's Dogleg Solver:")
        Console.WriteLine("  Initial guess: {0:F2}", initialGuess)
        Console.WriteLine("  Status: {0}", dogleg.Status)
        Console.WriteLine("  Solution: {0}", dogleg.Result)
        Console.WriteLine("  Estimated error: {0}", dogleg.EstimatedError)
        Console.WriteLine("  # iterations: {0}", dogleg.IterationsNeeded)
        Console.WriteLine("  # evaluations: {0}", dogleg.EvaluationsNeeded)

        ' The dogleg method can work without derivatives. Care is taken
        ' to keep the number of evaluations down to a minimum.
        dogleg.JacobianFunction = Nothing
        ' Call the Solve method to obtain the solution:
        solution = dogleg.Solve()

        Console.WriteLine("Powell's Dogleg Solver (no derivatives):")
        Console.WriteLine("  Initial guess: {0:F2}", initialGuess)
        Console.WriteLine("  Status: {0}", dogleg.Status)
        Console.WriteLine("  Solution: {0}", dogleg.Result)
        Console.WriteLine("  Estimated error: {0}", dogleg.EstimatedError)
        Console.WriteLine("  # iterations: {0}", dogleg.IterationsNeeded)
        Console.WriteLine("  # evaluations: {0}", dogleg.EvaluationsNeeded)

        Console.Write("Press Enter key to exit...")
        Console.ReadLine()
    End Sub

    ' First set of functions.
    Function f1(x As Vector(Of Double)) As Double
        Return Math.Exp(x(0)) * Math.Cos(x(1)) - x(0) * x(0) + x(1) * x(1)
    End Function

    Function f2(x As Vector(Of Double)) As Double
        Return Math.Exp(x(0)) * Math.Sin(x(1)) - 2 * x(0) * x(1)
    End Function

    ' Gradient of the first set of functions.
    Function df1(x As Vector(Of Double), df As Vector(Of Double)) As Vector(Of Double)
        df(0) = Math.Exp(x(0)) * Math.Cos(x(1)) - 2 * x(0)
        df(1) = -Math.Exp(x(0)) * Math.Sin(x(1)) + 2 * x(1)
        Return df
    End Function

    Function df2(x As Vector(Of Double), df As Vector(Of Double)) As Vector(Of Double)
        df(0) = Math.Exp(x(0)) * Math.Sin(x(1)) - 2 * x(1)
        df(1) = Math.Exp(x(0)) * Math.Cos(x(1)) - 2 * x(0)
        Return df
    End Function

End Module