%% Optimization Using Symbolic Derivatives  
%   7.4.2019
% https://se.mathworks.com/company/newsletters/articles/optimization-using-symbolic-derivatives.html
% OptimUsingSymbDeriv.m
% Minimize:
%%
%
%  $$x + y + \cosh(x-1.1y) + \sinh(z/4)$$
% 
%  over the region defined by the implicit equation:
%%
%
%  $$z^2 = \sin(z-x^2y^2), -1\leq x \leq 1,-1\leq y \leq 1,-1\leq z \leq 1.$$
%%
format compact
clear
close all
%%  Using matlabFunction:
syms x y z
t=[x;y;z];
w=z^2-sin(z-x^2*y^2)   % Cosnstraint: w=0.
obj=x+y+cosh(x-(11*y)/10)+sinh(z/4)  % Objective fn (expr)
objfun=matlabFunction(obj,'vars',{t})
%% Constraints:
 confun=matlabFunction([],w,'vars',{t},'outputs',{'c','ceq'})
%% Own experiments
f=@(x,y,z)x+y+cosh(x-(11*y)/10)+sinh(z/4)
objf=@(u)f(u(1),u(2),u(3))
objf(t)
syms x1 x2 x3
objf([x1 x2 x3])
%% Constraints:
 
%% Perhaps easiest to write objf as an m-file:
%  function w=objfmfile(u)
%  x=u(1);y=u(2);z=u(3);
%  w=x+y+cosh(x-(11*y)/10)+sinh(z/4)
type objfunmfile
%%
objfunmfile([x,y,z])
%%
syms x1 x2 x3
objfunmfile([x1,x2,x3])
%%
x=1:3;objfunmfile(x)
% Let's leave this for a while...
%% First Example: Unconstrained Minimization with Hessian
%
format compact
syms x1 x2 real
x = [x1;x2]; % column vector of symbolic variables
f = log(1 + 3*(x2 - (x1^3 - x1))^2 + (x1 - 4/3)^2)
pretty(f)
fsurf(f,[-2 2],'ShowContours','on')
view(127,38)
%% Gradient and Hessian
%
gradf = gradient(f,x).' % column graddient and Hessian
pretty(gradf)
hessf=hessian(f,x)
pretty(hessf)
%% Use matlabFunction
% 
% The fminunc solver expects to pass in a vector x, and, with the 
% SpecifyObjectiveGradient option set to true and HessianFcn option 
% set to 'objective', expects a list of three outputs: 
% [f(x),gradf(x),hessf(x)].


fh = matlabFunction(f,gradf,hessf,'vars',{x})
% Test fh:
[fval,grval,hessval]=fh(x)


%%

options = optimoptions('fminunc', ...
    'SpecifyObjectiveGradient', true, ...
    'HessianFcn', 'objective', ...
    'Algorithm','trust-region', ...
    'Display','final');
[xfinal,fval,exitflag,output] = fminunc(fh,[-1;2],options)

%anontext = func2str(fh)
%at=anontext;
%for k=1:100:1000
%    at(k,:)=anontext(k:k+99);   
%end