function testfcn ( iexmpl );
% TestFcn
%
% This m-file is part of the material of the lectures on
%   Numerical Methods in Nonlinear Optimization
% at the Math Department of Halle University, Germany.
%
% Author :      Martin Arnold, martin.arnold@mathematik.uni-halle.de
% Version of :  Apr 8, 2009
%
% Visualization of Test Functions in nonlinear optimization
%
% Parameter:
%   iexmpl (input)  : control flag "example"
%                       =1 .. test function with many local minima
%                       =2 .. quadratic test function
%                       =3 .. Function of Rosenbrock
%                       =4 .. Function of Himmelblau
%                       =5 .. Function of Bazaraa / Shetty
%
% Examples:
%   testfcn ( 1 );   %  print -dpng ../png/testfcn1.png
%   testfcn ( 2 );   %  print -dpng ../png/testfcn2.png
%   testfcn ( 3 );   %  print -dpng ../png/testfcn3.png
%   testfcn ( 4 );   %  print -dpng ../png/testfcn4.png
%   testfcn ( 5 );   %  print -dpng ../png/testfcn5.png
%
% Reference: 
%   W. Alt: Nichtlineare Optimierung. - Vieweg Braunschweig. - 2002.  

%
% -> Steuerparameter Ausgabe Bildschirm / PostScript
graphwidth  = 24.0;
graphheight = 10.0;
fac         =  0.92;
shift       =  0.76;
papershifth =  0.0;
papershiftv =  0.0;

% parameters plot
ActFontSize      = 14;
ActFontSizeSmall = 12;
ActLineWidth     =  2;
ActLineWidthThin =  1;
ActMarkerSize    =  6;
RatioFlag        =  0;

border      = 1.0;

%
% -> Bestimme Groesse des Bildschirms und Skalierungsfaktor fuer die Ausgabe
root = 0;
set ( root, 'Units', 'centimeters' );
screensize = get ( root, 'ScreenSize' );
left   = screensize(1);
bottom = screensize(2);
width  = screensize(3);
height = screensize(4);
set ( root, 'Units', 'pixels' );
if RatioFlag==0,
  screenscale = 1.0;
elseif RatioFlag==1,
  screenscale = (width-2*border) / graphwidth;
elseif RatioFlag==-1,
  screenscale = (height-2*border) / graphheight;
end;

%
% -> Definiere den Bildschirmausschnitt
if length ( get ( root, 'Children' ) ) == 0,
  handle = figure;
else
  handle = gcf;
  clf;
end;

stdunits = get ( handle, 'Units' );
set ( handle, 'Units',    'centimeters' );
set ( handle, 'Position', ...
    [ left+width-screenscale*graphwidth-border height-2*border-screenscale*graphheight ...
    screenscale*graphwidth                   screenscale*graphheight ] );
set ( handle, 'Units', stdunits );

%
% -> Skalierung der Ausgabe in PostScript
%
set ( gcf, 'PaperUnits',    'centimeters' );
set ( gcf, 'PaperPosition', [ papershifth papershiftv graphwidth graphheight ] );

% -> initialization
Fmax = NaN;
Vvec = NaN;
XLim = NaN;
carg = NaN;

% -> problem definition
switch iexmpl
    case 1
        F = @(X1,X2) ( ( X1.^2 + X2.^2 ) / 2 - cos ( X1.^2 ) - cos ( X2.^2 ) );
        x1min = -5.0;
        x1max =  5.0;
        x2min = -5.0;
        x2max =  5.0;
        tstr  = 'Alt (2002), Beispiel 1.1.2';
        carg  =  20;
    case 2
        F = @(X1,X2) ( 2*X1.^2 + X2.^2 - 4*X1 - 2*X2 + 3 );
        x1min = -10.0;
        x1max =  10.0;
        x2min = -10.0;
        x2max =  10.0;
        tstr  = 'Alt (2002), Beispiel 1.2.5';
    case 3
        F = @(X1,X2) ( 100 * ( X2 - X1.^2 ).^2 + ( 1 - X1 ).^2 );
        x1min = -2.5;
        x1max =  2.0;
        x2min = -0.5;
        x2max =  3.5;
%         tstr  = 'Funktion von Rosenbrock, vgl. Alt (2002), Beispiel 1.4.1';
        tstr  = 'Funktion von Rosenbrock, vgl. Alt (2002)';
        Fmax  = 2000;
        XLim  = [ x1min x1max ];
        Vvec  = [ 37 45 ];
        carg  = logspace ( 0, 3, 10 );
    case 4
        F = @(X1,X2) ( ( X1.^2 + X2 - 11 ).^2 + ( X1 + X2.^2 - 7 ).^2 );
        x1min = -5.0;
        x1max =  5.0;
        x2min = -5.0;
        x2max =  5.0;
%         tstr  = 'Funktion von Himmelblau, vgl. Alt (2002), Beispiel 1.4.2';
        tstr  = 'Funktion von Himmelblau, vgl. Alt (2002)';
        carg  =  [ 0:10:200, 220, 240:40:800 ];
    case 5
        F = @(X1,X2) ( ( X1 - 2 ).^4 + ( X1 - 2*X2 ).^2 );
        x1min =  1.6;
        x1max =  2.6;
        x2min =  0.8;
        x2max =  1.3;
%         tstr  = 'Funktion von Bazaraa / Shetty, vgl. Alt (2002), Beispiel 1.4.3';
        tstr  = 'Funktion von Bazaraa / Shetty, vgl. Alt (2002)';
        Fmax  =  1.0;
        Vvec  = [ -21 44 ];
        carg  =  [ 0.01, 0.033, 0.1, 0.2:0.2:1.0 ];
end

% -> definition of output grid etc.
nx = 161;
x1 = linspace ( x1min, x1max, nx );
x2 = linspace ( x2min, x2max, nx );
[ X1, X2 ] = meshgrid ( x1, x2 ); 

Fdat = F(X1,X2);

% -> graphical output: mesh plot
subplot ( 1, 2, 1 );

Fmesh = Fdat;
if ~isnan(Fmax),
    Fmesh(Fmesh>Fmax) = NaN;
end;

mesh ( X1, X2, Fmesh );
xlabel ( 'x_1' );
ylabel ( 'x_2' );
zlabel ( 'f(x_1,x_2)' );
title ( tstr );

if min(isnan(Vvec))==0,
    view ( Vvec );
end;

if min(isnan(XLim))==0,
    set ( gca, 'XLim', XLim );
end;

% -> graphical output: contour plot
subplot ( 1, 2, 2 );

if min(isnan(carg))==0,
    [ c, h ] = contour ( X1, X2, Fdat, carg );
else
    [ c, h ] = contour ( X1, X2, Fdat );
end;

if ( (iexmpl==2) || (iexmpl==5) ),
    clabel ( c, h );
end;

xlabel ( 'x_1' );
ylabel ( 'x_2' );
title ( tstr );

%
% -> Korrektur der Groesse und Lage der Koordinatensysteme, Aenderung der Schriftgroesse
allax = get ( gcf, 'Children' )';
for ax = allax,
    rect    = get ( ax, 'Position' );
    rect(2) = rect(2) + shift * (1-fac) * rect(4);
    rect(4) = fac * rect(4);
    set ( ax, 'Position', rect );
    set ( ax, 'FontSize', [ActFontSize] );
    set ( get ( ax, 'title' ), 'FontSize', [ActFontSize] );
    set ( get ( ax, 'xlabel' ), 'FontSize', [ActFontSize] );
    set ( get ( ax, 'ylabel' ), 'FontSize', [ActFontSize] );
    set ( get ( ax, 'zlabel' ), 'FontSize', [ActFontSize] );
end

end
