function []=startls(fktname,x0,gradname,nlines,verfahren);
% ======================================================================
% Startroutine fuer das Verfahren "Methode der kleinsten Quadrate"
% engl. "method of least squares".
% Zielfunktion muss von folgender Form sein:
%   f(x) = f1(x)^2 + f2(x)^2 + ... + fm(x)^2
%
% Erstellt fuer die Veranstaltung
% Weiterbildenes Studium fuer Ingenieure WS 98/99
%
% Helge Baumann, 13.8.1998
% ----------------------------------------------------------------------
% Aurufparameter:
%  
% fktname : Name der Funktion F, deren Minimum bestimmt 
%   werden soll. An <fktname> wird ein Spaltenvektor(!) uebergeben. 
%   Achtung! Fuer diese Methode liefert F nicht einen skalaren Ausdruck,
%   sondern einen Vektor . Die Summe der Quadrate dieses Vektors ergibt
%   die Zielfunktion.
% x0 : Spaltenvektor der Dimension n
% gradname : Name der Gradientenfunktion zu fktname.
% nlines : Anzahl der zu zeichnenden Hoehenlinien. Standard: 40

%% Initialisierung 
% xmin haelt fuer jede Dimension die kleinste waehrend der Iteration
%      auftretende Zahl fest.
% xmax haelt fuer jede Dimension die groeste waehrend der Iteration
%      auftretende Zahl fest.
% xmin und xmax werden benoetigt um den richtigen Bildschirmausschnitt
% bei der Darstellung des Iterationsverlaufes anzuzeigen.
global xmin
global xmax

% Wahl des Verfahrens
if nargin < 5, verfahren = 0; end;

% Anzahl der Hoehenlinien
if nargin < 4, nlines = 40; end;

% Name der Gradientenfunktion zu fktname
if nargin < 3, gradname = 'grosenbrock'; end;

% Startvektor
if nargin < 2, x0 = [-2; 2]; end
[n,m] = size(x0); % n = Dimension des Startvektors/ der Startvektoren

% Name der zu minimierenden Funktion
if nargin < 1, fktname = 'rosenbrock'; end

% Name der Ausgaberoutine
global outputname
outputname = '';

% Optionen vorgeben
options = [];
% Genauigkeit einstellen
options(2) = 1e-6;
options(3) = 1e-6;
% Welches Verfahren soll angewendet werden?
% options(5) = 0    : Levenberg-Marquardt
% options(5) = 1    : Gauss-Newton
options(5) = verfahren;
% Konstanten
xpoints = 21;   % Anzahl der Gitterpunkte in x Richtung fuer contour-plot
ypoints = 21;   % Anzahl der Gitterpunkte in y Richtung fuer contour-plot

% Im Fall n==2 kann eine graphische Ausgabe erfolgen. Dafuer sind einige
% Vorarbeiten noetig, die fuer die eigentliche Minimierung keine Rolle
% spielen. Der gesamte 'if'-Block dient ausschliesslich diesen Vorbereitungen.
if (n==2) 
   % Fuer xmin (xmax) werden die groestmoeglichen (kleinstmoeglichen) Zahlen
   % vorgegeben. Dient nur dazu einen Vektor in entsprechender
   % Groesse bereitzustellen.
   xmin = ones(n,1)*realmax;
   xmax = -ones(n,1)*realmax;
   
   outputname = 'minmax';
   % Der erste Durchlauf ist nur zur Bestimmung von xmin und xmax gedacht.
   [lsg,options] = leastsq(fktname,x0,options,gradname);   
   % Beobachtungsfenster festlegen, um 10% groesser als ermittelte Werte.
   xlaenge = (xmax-xmin)/2; xmitte = (xmax+xmin)/2;
   xmin = xmitte -(xlaenge* 1.1);
   xmax = xmitte + (xlaenge*1.1);

   % Einheitliches Koordinatensystem und Graphikausgabe in ein Fenster
   clf;
   axis([xmin(1), xmax(1), xmin(2), xmax(2)]);
   hold on
      
   %% Hoehenlinien einzeichnen
   % Gitter erzeugen; zu den Knoten wird der Funktionswert ermittelt.
   xrange = xmin(1):(xmax(1)-xmin(1))/(xpoints-1):xmax(1);
   yrange = xmin(2):(xmax(2)-xmin(2))/(ypoints-1):xmax(2);
  [xgitter,ygitter] = meshgrid(xrange,yrange);
  for i=1:xpoints
     [zgitter(i,1:ypoints)] = ...
	  sum( feval(fktname,[xrange(i)*ones(1,ypoints);yrange(1:ypoints)]).^2) ;     
   end 
   
   % Erzeugzung der Hoehenlinien
   contour(xgitter,ygitter,zgitter',nlines);
   
   % Erlaeuterungen in die Zeichnung einfuegen
   title('Methode der kleinsten Quadrate');
   % nur wenn ein Minimum gefunden wurde, wird es eingezeichnet
   if options(10) < options(14)
      plot(lsg(1),lsg(2),'g*');	% Minimum einzeichnen
      legend('berechnetes Minimum');
   end
   
   % Handle fuer das Polyeder erzeugen.
   outputname = 'zeichnung'; % Name der Ausgaberoutine

end

% Der Durchlauf, bei dem in jedem Iterationsschritt eine Ausgabe
% erfolgen kann.
[lsg,options,wert] = leastsq(fktname,x0,options,gradname);

if n==2, hold off; end;


% Ergebnisse anzeigen
format long
disp('Loesungsvektor')
disp(lsg)
disp('Der Funktionswert im Minimum betraegt')
disp( sum(wert.^2))
disp(sprintf('%s\n%s %d %s', 'Fuer einen Durchlauf dieses Verfahrens',' wurden',options(10),'Funktionsauswertungen benoetigt.'))
disp(sprintf('%s\n%s %d %s', 'Fuer einen Durchlauf dieses Verfahrens',' wurden',options(11),'Gradientenauswertungen benoetigt.'))
