YANE-Framework Tutorial 1.1.0

Tutorial page of class yane::MinProg::GaussNewton

Setup

In this example we solve an optimization problem with yane::MinProg::GaussNewton. Given are

\begin{eqnarray*} \mbox{Modelfunction:} && f(x) = a_0 * sin(a_1 * x) + a_2 \\ \mbox{Measurement data:} && (x_i, y_i) \qquad 2 \le i \le dim\_y \\ \mbox{Initial values:} && a_j \qquad 0 \le j \le 2 \end{eqnarray*}

whereas a_0, a_1, a_2 are the parameters to optimzie, x_i the measurement instances, y_i the measurement values and a_j the starting values of a. As solution we get the optimised parameters a.

To show the difference between the amount of imput data, we solve the problem several times, starting with the minimal amount of data (not very good solution) and use more data every step.

Code

In the following the code is explained.

Libraries

The first thing to do is to define the libraries which we require. These libraries form the head of our main program:

#include <yane/utils.h>
#include <yane/minprog.h>

#include <cmath>
#include <cstring>
#include <fstream>
#include <sstream>
#include <time.h>
#include <stdlib.h>

Namespaces

Having defined the libraries which we are going to use, we now have to define the namespaces in which the classes of these libraries operate:

using namespace std;
using namespace yane::MinProg;

Functions

Next the functions we'll use in this example. Function is the model-function we want to optimise, grad the gradient respective a of the model function. GaussNewton is also able to compute the gradient by itself and dist a function to disturb a value to simluate imprecise measurement data.

void function ( int * dim_x, int * dim_a, double * a, double * x, double * fx )
{       
        fx[0] = a[0] * sin(a[1] * x[0]) + a[2];
}

void grad ( int * dim_x, int * dim_a, double * a, double * x, double * dfx )
{       
        dfx[0] = sin(a[1] * x[0]);
        dfx[1] = a[0] * x[0] * cos(a[1] * x[0]);
        dfx[2] = 1;
}

double dist( double a )
{
        return a + (double) (rand() % 20 - 10) / 100.0;
}

Main Program

In the main function we declare and initialize the variables we are going to use and create the data arrays.

        int dim_x, dim_a, dim_y;
        double *x, *a, *y;
        stringstream plot_functions, toplot;
        ofstream out;

        dim_x = 1;
        dim_a = 3;
        dim_y = 10;

        x = new double[dim_x*dim_y];
        a = new double[dim_a];
        y = new double[dim_y];

Now we set the initial parameter values, create the measurement data and write the data into a file.

        a[0] = 1.0;
        a[1] = 1.0;
        a[2] = 0.0;

        srand (time(NULL));

        out.open ( "data.txt" );
        for(int i = 0; i < dim_y; i++)
        {
                x[i] = (double) i / (double) dim_y * 6.0;
                y[i] = dist(a[0]) * sin(dist(a[1]) * x[i] + dist(a[2])) + dist(a[3]);
                out << x[i] << " " << y[i] << endl;
        }
        out.close();

After that we create an GaussNewton object with the 3 dimensions, the measurement data and the two function pointer.

        GaussNewton * gn = new yane::MinProg::GaussNewton ( dim_x, dim_a, dim_y, x, y, function, grad);

In this part we iteratively call calcParams which calculates the parameters of the model function. We also prepare the output data to use with gnuplot and print the solution function to the screen.

        toplot << "plot 'data.txt'";
        for(int i = dim_a; i <= dim_y; i = i + 2)
        {
                gn->calcParams ( a, i);
                plot_functions << "f" << i << "(x) =" << a[0] << " * sin(" << a[1] << " * x) + " << a[2] << endl;
                toplot << ", f" << i << "(x)";
        }

        cout << plot_functions.str() << endl;

To display the results we open a pipe to gnuplot and get gnuplot to plot the functions.

        FILE * gnuplotpipe = popen("gnuplot","w");
        
        fprintf(gnuplotpipe,"%s\n", plot_functions.str().c_str());
        fprintf(gnuplotpipe,"%s\n", toplot.str().c_str());
        fflush(gnuplotpipe);
        
        cin.get();
        
        fprintf(gnuplotpipe,"exit\n");
        pclose(gnuplotpipe);

After that we clean up.

        delete gn;
        delete[] x;
        delete[] a;
        delete[] y;

Results

Upon execution of this program, we obtain the solution functions and a gnuplot plot of the different solution functions.