Click here to Skip to main content
15,883,901 members
Articles / Programming Languages / Java

Derivative-free nonlinear optimization for .NET and Java

Rate me:
Please Sign up or sign in to vote.
4.92/5 (6 votes)
18 Dec 2012MIT10 min read 35.6K   864   19  
Announcing standalone implementations of derivative-free nonlinear optimizers for .NET and Java platforms
//------------------------------------------------------------------------------
//     Main program of test problems in Report DAMTP 1992/NA5.
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Cureos.Numerics;
using NUnit.Framework;

using TestCaseType = System.Tuple<string, Cureos.Numerics.CalcfcDelegate, int, int, double[], double>;

namespace Cscobyla.Tests
{
    [TestFixture]
    public class Cobyla2Tests
    {
        #region FIELDS

        private const double rhobeg = 0.5;
        private const double rhoend1 = 1.0e-6;
        private const double rhoend2 = 1.0e-8;
        private const int iprint = 1;
        private const int maxfun = 3500;

        #endregion

        #region AUTO-IMPLEMENTED PROPERTIES

        private IEnumerable<TestCaseType> TestCases
        {
            get
            {
                yield return
                    Tuple.Create("1 (Simple quadratic)", (CalcfcDelegate)calcfc1, 2, 0, new[] {-1.0, 0.0}, 1.0e-5);
                yield return
                    Tuple.Create("2 (2D unit circle calculation)", (CalcfcDelegate)calcfc2, 2, 1,
                                 new[] {Math.Sqrt(0.5), -Math.Sqrt(0.5)}, 1.0e-5);
                yield return
                    Tuple.Create("3 (3D ellipsoid calculation)", (CalcfcDelegate)calcfc3, 3, 1,
                                 new[] {1.0 / Math.Sqrt(3.0), 1.0 / Math.Sqrt(6.0), -1.0 / 3.0}, 1.0e-5);
                yield return
                    Tuple.Create("4 (Weak Rosenbrock)", (CalcfcDelegate)calcfc4, 2, 0, new[] {-1.0, 1.0}, 2.0e-5);
                yield return
                    Tuple.Create("5 (Intermediate Rosenbrock)", (CalcfcDelegate)calcfc5, 2, 0, new[] {-1.0, 1.0}, 2.0e-4)
                    ;
                yield return
                    Tuple.Create("6 (Equation (9.1.15) in Fletcher's book)", (CalcfcDelegate)calcfc6, 2, 2,
                                 new[] {Math.Sqrt(0.5), Math.Sqrt(0.5)}, 1.0e-6);
                yield return
                    Tuple.Create("7 (Equation (14.4.2) in Fletcher)", (CalcfcDelegate)calcfc7, 3, 3,
                                 new[] {0.0, -3.0, -3.0}, 1.0e-8);
                yield return
                    Tuple.Create("8 (Rosen-Suzuki)", (CalcfcDelegate)calcfc8, 4, 3,
                                 new[] {0.0, 1.0, 2.0, -1.0}, 1.0e-5);
                yield return
                    Tuple.Create("9 (Hock and Schittkowski 100)", (CalcfcDelegate)calcfc9, 7, 4,
                                 new[] { 2.330499, 1.951372, -0.4775414, 4.365726, -0.624487, 1.038131, 1.594227 }, 1.0e-5);
                yield return
                    Tuple.Create("10 (Hexagon area)", (CalcfcDelegate)calcfc10, 9, 14,
                                 new[] { 0.688341, 0.725387, -0.284033, 0.958814, 0.688341, 0.725387, -0.284033, 0.958814, 0.0 }, 
                                 1.0e-5);
            }
        }
 
        #endregion

        #region METHODS

        [TestCaseSource("TestCases")]
        public void TestProblem(TestCaseType testCase)
        {
            var problem = testCase.Item1;
            var calcfc = testCase.Item2;
            var n = testCase.Item3;
            var m = testCase.Item4;
            var xopt = testCase.Item5;
            var accepted = testCase.Item6;

            Console.WriteLine("{0}Output from test problem {1}", Environment.NewLine, problem);

            var error1 = RunTestProblem(calcfc, n, m, rhoend1, xopt);
            Assert.Less(error1, accepted);
            var error2 = RunTestProblem(calcfc, n, m, rhoend2, xopt);
            Assert.Less(error2, error1);
        }

        public double RunTestProblem(CalcfcDelegate calcfc, int n, int m, double rhoend, double[] xopt)
        {
            var x = Enumerable.Repeat(1.0, n).ToArray();

            var timer = new Stopwatch();
            timer.Restart();
            Assert.That(Cobyla.FindMinimum(calcfc, n, m, x, rhobeg, rhoend, iprint, maxfun),
                        Is.EqualTo(CobylaExitStatus.Normal).Or.EqualTo(CobylaExitStatus.MaxIterationsReached));
            timer.Stop();

            var error = xopt.Select((xo, i) => Math.Pow(xo - x[i], 2.0)).Sum();
            Console.WriteLine("{0}Least squares error in variables = {1,16:E6}", Environment.NewLine, error);
            Console.WriteLine("Elapsed time for optimization = {0} ms", timer.ElapsedMilliseconds);

            return error;
        }

        /// <summary>
        /// Minimization of a simple quadratic function of two variables.
        /// </summary>
        public static void calcfc1(int n, int m, double[] x, out double f, double[] con)
        {
            f = 10.0 * Math.Pow(x[0] + 1.0, 2.0) + Math.Pow(x[1], 2.0);
        }

        /// <summary>
        /// Easy two dimensional minimization in unit circle.
        /// </summary>
        public static void calcfc2(int n, int m, double[] x, out double f, double[] con)
        {
            f = x[0] * x[1];
            con[0] = 1.0 - x[0] * x[0] - x[1] * x[1];
        }

        /// <summary>
        /// Easy three dimensional minimization in ellipsoid.
        /// </summary>
        public static void calcfc3(int n, int m, double[] x, out double f, double[] con)
        {
            f = x[0] * x[1] * x[2];
            con[0] = 1.0 - x[0] * x[0] - 2.0 * x[1] * x[1] - 3.0 * x[2] * x[2];
        }

        /// <summary>
        /// Weak version of Rosenbrock's problem.
        /// </summary>
        public static void calcfc4(int n, int m, double[] x, out double f, double[] con)
        {
            f = Math.Pow(x[0] * x[0] - x[1], 2.0) + Math.Pow(1.0 + x[0], 2.0);
        }

        /// <summary>
        /// Intermediate version of Rosenbrock's problem.
        /// </summary>
        public static void calcfc5(int n, int m, double[] x, out double f, double[] con)
        {
            f = 10.0 * Math.Pow(x[0] * x[0] - x[1], 2.0) + Math.Pow(1.0 + x[0], 2.0);
        }

        /// <summary>
        /// This problem is taken from Fletcher's book Practical Methods of
        /// Optimization and has the equation number (9.1.15).
        /// </summary>
        public static void calcfc6(int n, int m, double[] x, out double f, double[] con)
        {
            f = -x[0] - x[1];
            con[0] = x[1] - x[0] * x[0];
            con[1] = 1.0 - x[0] * x[0] - x[1] * x[1];
        }

        /// <summary>
        /// This problem is taken from Fletcher's book Practical Methods of
        /// Optimization and has the equation number (14.4.2).
        /// </summary>
        public static void calcfc7(int n, int m, double[] x, out double f, double[] con)
        {
            f = x[2];
            con[0] = 5.0 * x[0] - x[1] + x[2];
            con[1] = x[2] - x[0] * x[0] - x[1] * x[1] - 4.0 * x[1];
            con[2] = x[2] - 5.0 * x[0] - x[1];
        }

        /// <summary>
        /// This problem is taken from page 66 of Hock and Schittkowski's book Test
        /// Examples for Nonlinear Programming Codes. It is their test problem Number
        /// 43, and has the name Rosen-Suzuki.
        /// </summary>
        public static void calcfc8(int n, int m, double[] x, out double f, double[] con)
        {
            f = x[0] * x[0] + x[1] * x[1] + 2.0 * x[2] * x[2] + x[3] * x[3] - 5.0 * x[0] - 5.0 * x[1] - 21.0 * x[2] +
                7.0 * x[3];
            con[0] = 8.0 - x[0] * x[0] - x[1] * x[1] - x[2] * x[2] - x[3] * x[3] - x[0] + x[1] - x[2] + x[3];
            con[1] = 10.0 - x[0] * x[0] - 2.0 * x[1] * x[1] - x[2] * x[2] - 2.0 * x[3] * x[3] + x[0] + x[3];
            con[2] = 5.0 - 2.0 * x[0] * x[0] - x[1] * x[1] - x[2] * x[2] - 2.0 * x[0] + x[1] + x[3];
        }

        /// <summary>
        /// This problem is taken from page 111 of Hock and Schittkowski's
        /// book Test Examples for Nonlinear Programming Codes. It is their
        /// test problem Number 100.
        /// </summary>
        public static void calcfc9(int n, int m, double[] x, out double f, double[] con)
        {
            f = Math.Pow(x[0] - 10.0, 2.0) + 5.0 * Math.Pow(x[1] - 12.0, 2.0) + Math.Pow(x[2], 4.0) +
                3.0 * Math.Pow(x[3] - 11.0, 2.0) + 10.0 * Math.Pow(x[4], 6.0) + 7.0 * x[5] * x[5] + Math.Pow(x[6], 4.0) -
                4.0 * x[5] * x[6] - 10.0 * x[5] - 8.0 * x[6];
            con[0] = 127.0 - 2.0 * x[0] * x[0] - 3.0 * Math.Pow(x[1], 4.0) - x[2] - 4.0 * x[3] * x[3] - 5.0 * x[4];
            con[1] = 282.0 - 7.0 * x[0] - 3.0 * x[1] - 10.0 * x[2] * x[2] - x[3] + x[4];
            con[2] = 196.0 - 23.0 * x[0] - x[1] * x[1] - 6.0 * x[5] * x[5] + 8.0 * x[6];
            con[3] = -4.0 * x[0] * x[0] - x[1] * x[1] + 3.0 * x[0] * x[1] - 2.0 * x[2] * x[2] - 5.0 * x[5] + 11.0 * x[6];
        }

        /// <summary>
        /// This problem is taken from page 415 of Luenberger's book Applied
        /// Nonlinear Programming. It is to maximize the area of a hexagon of
        /// unit diameter.
        /// </summary>
        public static void calcfc10(int n, int m, double[] x, out double f, double[] con)
        {
            f = -0.5 * (x[0] * x[3] - x[1] * x[2] + x[2] * x[8] - x[4] * x[8] + x[4] * x[7] - x[5] * x[6]);
            con[0] = 1.0 - x[2] * x[2] - x[3] * x[3];
            con[1] = 1.0 - x[8] * x[8];
            con[2] = 1.0 - x[4] * x[4] - x[5] * x[5];
            con[3] = 1.0 - x[0] * x[0] - Math.Pow(x[1] - x[8], 2.0);
            con[4] = 1.0 - Math.Pow(x[0] - x[4], 2.0) - Math.Pow(x[1] - x[5], 2.0);
            con[5] = 1.0 - Math.Pow(x[0] - x[6], 2.0) - Math.Pow(x[1] - x[7], 2.0);
            con[6] = 1.0 - Math.Pow(x[2] - x[4], 2.0) - Math.Pow(x[3] - x[5], 2.0);
            con[7] = 1.0 - Math.Pow(x[2] - x[6], 2.0) - Math.Pow(x[3] - x[7], 2.0);
            con[8] = 1.0 - x[6] * x[6] - Math.Pow(x[7] - x[8], 2.0);
            con[9] = x[0] * x[3] - x[1] * x[2];
            con[10] = x[2] * x[8];
            con[11] = -x[4] * x[8];
            con[12] = x[4] * x[7] - x[5] * x[6];
            con[13] = x[8];
        }

        [Test]
        public void FindMinimum_LogOutputToConsole_VisualInspection()
        {
            var x = Enumerable.Repeat(1.0, 9).ToArray();
            var actual = Cobyla.FindMinimum(calcfc10, 9, 14, x, rhobeg, rhoend1, 2, maxfun, Console.Out);
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
CEO Cureos AB
Sweden Sweden
I am the owner of Cureos AB, a software development and consulting company located in Uppsala, Sweden. The company's main focus is in developing software for dose-response analysis and optimization of large patient treatment materials, primarily using the .NET framework. In my Ph.D. thesis I outlined a general optimization framework for radiation therapy, and I have developed numerous tools for radiotherapy optimization and dose-response modeling that have been integrated into different treatment planning systems.

Comments and Discussions