function [x,y]=PokoordinatniSpust(f,a1,b1,a2,b2,x0,y0)
% POKOORDINATNISPUST - Funkcija graficki prikazuje nalazenje minimuma funkcionala 
% metodom najbrzeg spusta
%
% Argumenti funkcije su :
%   f - string koji sadrzi opis funkcionala ciji minimum trazimo 
%   a1,b1,a2,b2 - granice intervala koji se graficki prikazuje,
%                 pozeljno je da se u ovom intervalu nalazi lokalni minimum
%   x0,y0 - pocetna iteracija
%   epsilon - zeljena tacnost.  Ukoliko se ne navede, podrazumeva se eps
%
% Funkcija vraca:
%   x,y - koordinate minimuma funkcionala

% Autor : Filip Maric
% Verzija : 1.0
% Datum : 30.3.2003.

if (nargin<8)
    epsilon=eps;
end

% Provera korektnosti argumenata
if nargin<7
    error(['Upotreba : ' mfilename '(f,a1,b1,a2,b2,x0,y0)']);
end

if (a1>=b1) | max(size(a1))>1 | max(size(b1))>1 | ~isnumeric(a1) | ~isnumeric(b1)
    error('Interval [a1,b1] je nesipravno zadat');
end

if (a2>=b2) | max(size(a2))>1 | max(size(b2))>1 | ~isnumeric(a2) | ~isnumeric(b2)
    error('Interval [a2,b2] je nesipravno zadat');
end

if (max(size(x0))>1) | ~isnumeric(x0) | (max(size(y0))>1) | ~isnumeric(y0)
    error('Pocetna iteracija nije ispravno zadana');
end

if ~isstr(f)
    error('Prvi argument mora da bude string koji sadrzi funkciju nezavisne promenjive x')'
end


%Gradimo simbolicku funkciju na osnovu stringa f
f=sym(f);

% Matrice xg i yg ce da opisuju ekvidistantnu mrezu cvorova u kojima
% cemo da crtamo vrednost funkcionala
[xg,yg]=meshgrid(linspace(a1,b1,20),linspace(a2,b2,20));
% Izracunavamo vrednost funkcionala u tackama mreze
zg=subs(subs(f,{'x','y'},{xg,yg}));
%Crtamo funkcional
mesh(xg,yg,zg);

hold on

% Izracunavamo potrebne izvode funkcionala
fx=diff(f,'x');
fxx=diff(fx,'x');
fy=diff(f,'y');
fyy=diff(fy,'y');

% Iscrtavamo tacku koja odgovara pocetnoj iteraciji
z=subs(subs(f,{'x','y'},{x0,y0}));
plot3(x0,y0,z,'o');

% Postavljamo vrednost tekuce tacke na pocetnu
x=x0;
y=y0;

% Ispisujemo naslov grafika
title(['x=' num2str(x) ', y=' num2str(y)])

% Cekamo da se pritisne taster
pause

while(1)
    % Prvo vrsimo spust po x koordinati
        
    % fpxy je vrednost izvoda fxx u tacki (x,y)
    fpxy=subs(fxx,{'x','y'},{x,y});

    if (fpxy~=0)
        % Ukoliko je potrebno spustati se duz ove koordinate tj. ako je 
        % fxx razlicit od nule u toj tacki, odredjujemo koeficijenat l
        % koji odredjuje "koliko dugo" je potrebno spustati se u pravcu d     

        l=double(-(subs(fx,{'x','y'},{x,y}))/fpxy);
    
        % Odredjuemo novu x koordinatu
        x1=x+l;    
    
        % Iscrtavamo vrednost nove tacke
        z=subs(subs(f,{'x','y'},{x1,y}));
        plot3(x1,y,z,'o');
    
        % Iscrtavamo liniju na funkcionalu koja spaja staru i novu tacku
        xl=linspace(x,x1,20);
        yl=y*ones(size(xl));
        zl=subs(subs(f,{'x','y'},{xl,yl}));
        plot3(xl,yl,zl,'r');

        % Ispisujemo naslov grafika
        title(['x=' num2str(x1) ', y=' num2str(y)])

    end
    
    % Cekamo da korisnik pritisne taster
    pause

    % Sada vrsimo spust po y koordinati

    % fxxxy je vrednost izvoda fyy u tacki (x,y)
      fpxy=subs(fyy,{'x','y'},{x1,y});

    if (fpxy~=0)
        % Ukoliko je potrebno spustati se duz ove koordinate tj. ako je 
        % fyy razlicit od nule u toj tacki, odredjujemo koeficijenat l
        % koji odredjuje "koliko dugo" je potrebno spustati se u pravcu d     

        l=double(-(subs(fy,{'x','y'},{x1,y}))/fpxy);
    
        % Odredjuemo novu x koordinatu
        y1=y+l;    
    
        % Iscrtavamo vrednost nove tacke
        z=subs(subs(f,{'x','y'},{x1,y1}));
        plot3(x1,y1,z,'o');
   
        % Iscrtavamo liniju na funkcionalu koja spaja staru i novu tacku
        yl=linspace(y,y1,20);
        xl=x1*ones(size(yl));
        zl=subs(subs(f,{'x','y'},{xl,yl}));
        plot3(xl,yl,zl,'r');

        % Ispisujemo naslov grafika
        title(['x=' num2str(x1) ', y=' num2str(y1)])

    end

    % Ukoliko je postignuta zeljena tacnost prekidamo iterativni postupak
    if (abs(x1-x)<epsilon & abs(y1-y)<epsilon)
        break;    
    end

    % Pripremamo se za sledecu iteraciju
    y=y1;
    x=x1;

    
    % Cekamo da korisnik pritisne taster
    pause
end
