function varargout = nma_HW4(varargin)
% NMA_HW4 MATLAB code for nma_HW4.fig
%      NMA_HW4, by itself, creates a new NMA_HW4 or raises the existing
%      singleton*.
%
%      H = NMA_HW4 returns the handle to a new NMA_HW4 or the handle to
%      the existing singleton*.
%
%      NMA_HW4('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in NMA_HW4.M with the given input arguments.
%
%      NMA_HW4('Property','Value',...) creates a new NMA_HW4 or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before nma_HW4_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to nma_HW4_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help nma_HW4

% Last Modified by GUIDE v2.5 15-Jan-2016 18:38:23

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @nma_HW4_OpeningFcn, ...
                   'gui_OutputFcn',  @nma_HW4_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before nma_HW4 is made visible.
function nma_HW4_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to nma_HW4 (see VARARGIN)

% Choose default command line output for nma_HW4
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

set(handles.figure1, 'UserData',[]);
set(handles.figure1, 'MenuBar','figure');

set(handles.figure1,'Name','steepest descent algorithm. Minimize f(x,y)=(11-x-y)^2+(1+x+10 y- x y)^2');

userData.stop = false;
userData.stepSize = 0.1;
userData.x = 8;
userData.y = 12;
userData.stop = false;
userData.maxIter =40;
userData.relError =0.0001;
set(handles.figure1, 'UserData',userData);

% UIWAIT makes nma_HW4 wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = nma_HW4_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;



function manualStepValue_tag_Callback(hObject, eventdata, handles)
% hObject    handle to manualStepValue_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of manualStepValue_tag as text
%        str2double(get(hObject,'String')) returns contents of manualStepValue_tag as a double

stepSize = get(hObject,'String');
[stepSize, status] = nma_verify_valid_positive_numeric(stepSize, hObject, 'step size');
if not(status)
   return
end

if stepSize>1
   uiwait(errordlg(sprintf('step size %f is too large, must be between 0..1',stepSize),...
      'Bad Input', 'modal'));
   uicontrol(hObject);
   return
end

userData = get(handles.figure1, 'UserData');
userData.stepSize = stepSize;
set(handles.figure1, 'UserData',userData);




% --- Executes during object creation, after setting all properties.
function manualStepValue_tag_CreateFcn(hObject, eventdata, handles)
% hObject    handle to manualStepValue_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in optimalBtn_tag.
function optimalBtn_tag_Callback(hObject, eventdata, handles)
% hObject    handle to optimalBtn_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of optimalBtn_tag
s=get(hObject,'Value');
if s==1 
   set(handles.manualStepBtn_tag,'Value',0);
   set(handles.manualStepValue_tag,'Enable','off');
else
   set(handles.manualStepBtn_tag,'Value',1);
   set(handles.manualStepValue_tag,'Enable','on');
end


% --- Executes on button press in manualStepBtn_tag.
function manualStepBtn_tag_Callback(hObject, eventdata, handles)
% hObject    handle to manualStepBtn_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of manualStepBtn_tag

s=get(hObject,'Value');
if s==1 
   set(handles.optimalBtn_tag,'Value',0);
   set(handles.manualStepValue_tag,'Enable','on');
else
   set(handles.optimalBtn_tag,'Value',1);
   set(handles.manualStepValue_tag,'Enable','off');
end


function [n, status] = nma_verify_valid_positive_numeric(str, h, msg)
%verifies input string represents positive number

n = str2double(str);

if isnan(n)
   uiwait(errordlg(sprintf('non - numeric value for %s',msg),...
      'Bad Input', 'modal'));
   uicontrol(h);
   return
end

if abs(n) < 2 * eps
   uiwait(errordlg(sprintf('You must enter non - zero value for %s',msg),...
      'Bad Input', 'modal'));
   uicontrol(h);
   status = 0;
   return
end

if n < 0
   uiwait(errordlg(sprintf('%s must be positive',msg),...
      'Bad Input', 'modal'));
   uicontrol(h);
   status = 0;
   return
end

status = 1;

function [n, status] = nma_verify_valid_numeric(str, h, msg)
%verfies input string represents a numerical value

n = str2double(str);

if isnan(n)
  uiwait(errordlg(sprintf('non - numeric value for %s',msg),...
      'Bad Input', 'modal'));
  uicontrol(h);
  return
end

status=1;


function xPointValue_tag_Callback(hObject, eventdata, handles)
% hObject    handle to xPointValue_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of xPointValue_tag as text
%        str2double(get(hObject,'String')) returns contents of xPointValue_tag as a double

x = get(hObject,'String');
[x, status] = nma_verify_valid_numeric(x, hObject, 'x coordinate');
if not(status)
   return
end

if x>100 || x<-100
   uiwait(errordlg(sprintf('x %f is too large, must be between -100..100',x),...
      'Bad Input', 'modal'));
   uicontrol(hObject);
   return
end

userData = get(handles.figure1, 'UserData');
userData.x =x;
set(handles.figure1, 'UserData',userData);



% --- Executes during object creation, after setting all properties.
function xPointValue_tag_CreateFcn(hObject, eventdata, handles)
% hObject    handle to xPointValue_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function yPointValue_tag_Callback(hObject, eventdata, handles)
% hObject    handle to yPointValue_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of yPointValue_tag as text
%        str2double(get(hObject,'String')) returns contents of yPointValue_tag as a double

y = get(hObject,'String');
[y, status] = nma_verify_valid_numeric(y, hObject, 'y coordinate');
if not(status)
   return
end

if y>100 || y<-100
   uiwait(errordlg(sprintf('y %f is too large, must be between -100..100',y),...
      'Bad Input', 'modal'));
   uicontrol(hObject);
   return
end

userData = get(handles.figure1, 'UserData');
userData.y =y;
set(handles.figure1, 'UserData',userData);



% --- Executes during object creation, after setting all properties.
function yPointValue_tag_CreateFcn(hObject, eventdata, handles)
% hObject    handle to yPointValue_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end


% --- Executes on button press in guiInputBtn_tag.
function guiInputBtn_tag_Callback(hObject, eventdata, handles)
% hObject    handle to guiInputBtn_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of guiInputBtn_tag

s=get(hObject,'Value');
if s==1 
   set(handles.manualXYinputBtn_tag,'Value',0);
   set(handles.xPointValue_tag,'Enable','off');
   set(handles.yPointValue_tag,'Enable','off');
else
   set(handles.manualXYinputBtn_tag,'Value',1);
   set(handles.xPointValue_tag,'Enable','on');
   set(handles.yPointValue_tag,'Enable','on');
end

% --- Executes on button press in manualXYinputBtn_tag.
function manualXYinputBtn_tag_Callback(hObject, eventdata, handles)
% hObject    handle to manualXYinputBtn_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of manualXYinputBtn_tag

s=get(hObject,'Value');
if s==1 
   set(handles.guiInputBtn_tag,'Value',0);
   set(handles.xPointValue_tag,'Enable','on');
   set(handles.yPointValue_tag,'Enable','on');
else
   set(handles.guiInputBtn_tag,'Value',1);
   set(handles.xPointValue_tag,'Enable','off');
   set(handles.yPointValue_tag,'Enable','off');
end


% --- Executes on button press in runBtn_tag.
function runBtn_tag_Callback(hObject, eventdata, handles)
% hObject    handle to runBtn_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

del      = 0.05;
u1       = 0:del:20;
u2       = -10:del:15;
[u1,u2]  = meshgrid(u1,u2);
z        = (11-u1-u2).^2 + (1+u1+10*u2-u1.*u2).^2;

userData = get(handles.figure1, 'UserData');
u=[userData.x,userData.y];

set(handles.figure1, 'CurrentAxes',handles.axes1_tag);

%u = [8 12];  %starting guess
%u = [7 -2];
%u=zeros(1,2);
plot(0,0);
xlim([0 20]); ylim([-5 15]);
hold on;
%[u(1),u(2)] = ginput(1);
%t=text(1.08*u(1),u(2),sprintf('[%2.1f,%2.1f]',u(1),u(2)));
%t.FontSize=8;
%t.Color='red';
x = fminsearch(@objectiveFunc, u); %used to find the minumum in order to show
% progress in plot towards it.

hold on;
plot(x(1),x(2),'*r')
plot(u(1),u(2),'or')
grid;
MAX_ITER = userData.maxIter;
REL_TOL  = userData.relError;

if get(handles.optimalBtn_tag,'Value')==1
   stepSize =-1; %optimal
else
   stepSize =str2double(get(handles.manualStepValue_tag,'String'));
end

[p,levelSets] = steepestDescentPoints(u,MAX_ITER,REL_TOL,stepSize,@objectiveFunc,@gradientFunc);
[C,h]    = contour(u1,u2,z,levelSets); %,'ShowText','on');
assignin('base','p',p);
assignin('base','levelSets',levelSets);

if length(p(:,1))>1
    for k=1:length(p)-1
        userData = get(handles.figure1, 'UserData');
        if userData.stop ==true
           userData.stop = false;
           set(handles.figure1, 'UserData',userData);
           break;
        end
        line([p(k,1),p(k+1,1)],[p(k,2),p(k+1,2)]); %draw line between each step
        drawnow;
        pause(.2);
        %title(sprintf('f(u)=%3.3f, step size=%3.3f, step = %d, telTol=%3.3f',...
        %    norm(f(u)),lam,k,relTol));
        title(sprintf('current point [%3.3f,%3.3f], f(u)=%3.3f,  step = %d',...
            p(k,1),p(k,2),norm(objectiveFunc(p(k,:))),k));
    end
end



function [pointsFound,levelSets] = steepestDescentPoints(...
    u,MAX_ITER,REL_TOL,stepSize,objectiveFunc,gradientFunc)
% This function returns a matrix n by 2, of each point visited at end of
% each step of the steepest descent walk to the minimum. The points can
% then be used by client to make countour plots with. It also return the
% objective function value at each point. Typical use of this function is
% as follows:
%
%  [p,levelSets] = steepestDescentPoints(initialPoint,1000,0.001,-1,@objectiveFunc,@gradientFunc);
%  [C,h]    = contour(.....,levelSets);
%
% INPUT:
% ======
% u                is 2 element row  vector that contains the initial
%                  starting guess point, as in [x y]
% MAX_ITER         an integer, which is the maximium iteration allowed
%                  before giving up the search. Example 1000
% REL_TOL          small floating point number. The releative tolerance
%                  to use to decide when to stop the search. Example 10^-6
% stepSize         number, which is the step size to take. If stepSize=-1
%                  then an optimal step size is used
% objectiveFunc    is a handle to the objective function, which accepts
%                  an n by 2 matrix, that contain points, and return
%                  the numerical value of objectiveFunc at each point.
% gradientFunc     is handle to the gradiant of f. Same input and output
%                  as objectiveFunc
%
% OUTPUT:
% =======
% pointsFound      n by 2 matrix, as in [x1 y1; x2 y2; .....] which contain
%                  coordinates of each point visited during steepestDescent
% levelSets        a column vector, contains the value of the objective
%                  function at each point

pointsFound = zeros(MAX_ITER,2);
levelSets   = zeros(MAX_ITER,1);

fLambda = @(lam,u,s) objectiveFunc(u-lam*s);%function to find optimal step size
%call by fminbnd at each step, line search

% initialize counters before main loop
k      = 1;
relTol = inf;
pointsFound(k,:) = u(:);
levelSets(k)     = norm(objectiveFunc(u));

while k<MAX_ITER && relTol>REL_TOL

    k    = k + 1; 
    s    = gradientFunc(u);
    
    if abs(s) >eps('double')
       s  = s/norm(s);                           %direction vector
    end

    if stepSize == -1
       lam  = fminbnd(@(lam) fLambda(lam,u,s),0,1); %optimal step size
    else
       lam  = stepSize;
    end

    u = u - lam*s;                              %take step

    pointsFound(k,:) = u(:);
    levelSets(k)     = norm(objectiveFunc(u));
    relTol           = abs(( levelSets(k)-levelSets(k-1))/levelSets(k-1));
end

pointsFound = pointsFound(1:k,:);
levelSets   = levelSets(1:k);

function f = objectiveFunc(u)
f  = (11-u(:,1)-u(:,2)).^2 + (1+u(:,1)+10.*u(:,2)-u(:,1).*u(:,2)).^2;

function g = gradientFunc(u)
g  =[-2*(11-u(:,1)-u(:,2))+2*(1+u(:,1)+10*u(:,2)-u(:,1)*u(:,2)).*...
    (1-u(:,2)) , -2*(11-u(:,1)-u(:,2))+2*(1+u(:,1)+10*u(:,2)-u(:,1).*...
    u(:,2))*(10-u(:,1))];


% --- Executes on button press in clearBtn_tag.
function clearBtn_tag_Callback(hObject, eventdata, handles)
% hObject    handle to clearBtn_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

cla(handles.axes1_tag);


% --- Executes on button press in stopBtn_tag.
function stopBtn_tag_Callback(hObject, eventdata, handles)
% hObject    handle to stopBtn_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

userData = get(handles.figure1, 'UserData');
userData.stop =true;
set(handles.figure1, 'UserData',userData);



function maxIter_tag_Callback(hObject, eventdata, handles)
% hObject    handle to maxIter_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of maxIter_tag as text
%        str2double(get(hObject,'String')) returns contents of maxIter_tag as a double

maxIter = get(hObject,'String');
[maxIter, status] = nma_verify_valid_positive_numeric(maxIter, hObject, 'maxiumum iterations');
if not(status)
   return
end

userData = get(handles.figure1, 'UserData');
userData.maxIter =maxIter;
set(handles.figure1, 'UserData',userData);


% --- Executes during object creation, after setting all properties.
function maxIter_tag_CreateFcn(hObject, eventdata, handles)
% hObject    handle to maxIter_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end



function relError_tag_Callback(hObject, eventdata, handles)
% hObject    handle to relError_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of relError_tag as text
%        str2double(get(hObject,'String')) returns contents of relError_tag as a double

relError = get(hObject,'String');
[relError, status] = nma_verify_valid_positive_numeric(relError, hObject, 'relative error');
if not(status)
   return
end

if relError>1
   uiwait(errordlg(sprintf('relError %f is too large, must be between 10^-6 .. 1',relError),...
      'Bad Input', 'modal'));
   uicontrol(hObject);
   return
end

userData = get(handles.figure1, 'UserData');
userData.relError =relError;
set(handles.figure1, 'UserData',userData);


% --- Executes during object creation, after setting all properties.
function relError_tag_CreateFcn(hObject, eventdata, handles)
% hObject    handle to relError_tag (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
