The Algorithms logo
The Algorithms
Acerca deDonar

Gauss Optimization

P
using System;
using System.Collections.Generic;
using System.Linq;

namespace Algorithms.Other;

/// <summary>
/// The Gaussian method (coordinate descent method) refers to zero-order methods in which only the value
/// of the function Q(X) at different points in the space of variables is used to organize the search
/// for the extremum. This reduces the overall computational cost of finding the extremum. Also in
/// the Gaussian method, the procedures for finding and moving the operating point are simplified as
/// much as possible.
/// </summary>
public class GaussOptimization
{
    /// <summary>
    /// Implementation of function extremum search by the Gauss optimization algorithm.
    /// </summary>
    /// <param name="func">Function for which extremum has to be found.</param>
    /// <param name="n">This parameter identifies how much step size will be decreased each iteration.</param>
    /// <param name="step">The initial shift step.</param>
    /// <param name="eps">This value is used to control the accuracy of the optimization. In case if the error is less than eps,
    /// optimization will be stopped.</param>
    /// <param name="x1">The first function parameter.</param>
    /// <param name="x2">The second function parameter.</param>
    /// <returns>A tuple of coordinates of function extremum.</returns>
    public (double X1, double X2) Optimize(
        Func<double, double, double> func,
        double n,
        double step,
        double eps,
        double x1,
        double x2)
    {
        // The initial value of the error
        double error = 1;

        while (Math.Abs(error) > eps)
        {
            // Calculation of the function with coordinates that are calculated with shift
            double bottom = func(x1, x2 - step);
            double top = func(x1, x2 + step);
            double left = func(x1 - step, x2);
            double right = func(x1 + step, x2);

            // Determination of the best option.
            var possibleFunctionValues = new List<double> { bottom, top, left, right };
            double maxValue = possibleFunctionValues.Max();
            double maxValueIndex = possibleFunctionValues.IndexOf(maxValue);

            // Error evaluation
            error = maxValue - func(x1, x2);

            // Coordinates update for the best option
            switch (maxValueIndex)
            {
                case 0:
                    x2 -= step;
                    break;
                case 1:
                    x2 += step;
                    break;
                case 2:
                    x1 -= step;
                    break;
                default:
                    x1 += step;
                    break;
            }

            // Step reduction
            step /= n;
        }

        return (x1, x2);
    }
}