#include <iostream>

// Coordinates of the starting point
#define     X_INIT  30
#define     Y_INIT  20

// Step size multiplier
#define     ALPHA   0.05

// Function to optimize
inline double function(double x, double y) { return (x-2)*(x-2) + 2*(y-3)*(y-3); }

// Gradient
inline double gradient_x(double x, double y) { return 2*x-4; }
inline double gradient_y(double x, double y) { return 4*y-12; }


int main(void)
{
    // Starting point
    double X[2]= { X_INIT , Y_INIT };

    // Gradient descent main loop
    for (int i=0;i<200;i++)
    {
        X[0]=X[0]-ALPHA*gradient_x(X[0],X[1]);
        X[1]=X[1]-ALPHA*gradient_y(X[0],X[1]);
    }

    std::cout << "::: Results :::" << std::endl;

    // Display X and Y
    std::cout << "x=" << X[0] << std::endl;
    std::cout << "y=" << X[1] << std::endl;

    // Display minimum of the function
    std::cout << "f(" << X[0] << "," << X[1] << ")=" << function(X[0],X[1]) << std::endl;

    return 0;
}

/* Expected output:
::: Results :::
x=2
y=3
f(2,3)=3.90229e-16

*/