%% Convert Objective Function to Expression
% To use a MATLAB™ function in the problem-based approach when it is not composed of supported functions, first convert it to an optimization expression. See Supported Operations on Optimization Variables and Expressions and Convert Nonlinear Function to Optimization Expression.
% To use the objective function gamma (the mathematical function \Gamma(x), an extension of the factorial function), create an optimization variable x and use it in a converted anonymous function.

x = optimvar('x');
obj = fcn2optimexpr(@gamma,x);
prob = optimproblem('Objective',obj);
show(prob)

% To solve the resulting problem, give an initial point structure and call solve.

x0.x = 1/2;
sol =  solve(prob,x0)

% For more complex functions, convert a function file. The function file gammabrock.m computes an objective of two optimization variables.

type gammabrock

% Include this objective in a problem.

x = optimvar('x','LowerBound',0);
y = optimvar('y');
obj = fcn2optimexpr(@gammabrock,x,y);
prob = optimproblem('Objective',obj);
show(prob)

% The gammabrock function is a sum of squares. You get a more efficient problem formulation by expressing the function as an explicit sum of squares of optimization expressions.

f = fcn2optimexpr(@(x,y)y - gamma(x),x,y);
obj2 = (10*f)^2 + (1-x)^2;
prob2 = optimproblem('Objective',obj2);

% To see the difference in efficiency, solve prob and prob2 and examine the difference in the number of iterations.

x0.x = 1/2;
x0.y = 1/2;
[sol,fval,~,output] = solve(prob,x0);
[sol2,fval2,~,output2] = solve(prob2,x0);
fprintf('prob took %d iterations, but prob2 took %d iterations\n',output.iterations,output2.iterations)

% If your function has several outputs, you can use them as elements of the objective function. In this case, u is a 2-by-2 variable, v is a 2-by-1 variable, and expfn3 has three outputs.

type expfn3

% Create appropriately sized optimization variables, and create an objective function from the first two outputs.

u = optimvar('u',2,2);
v = optimvar('v',2);
[f,g,mineval] = fcn2optimexpr(@expfn3,u,v);
prob = optimproblem;
prob.Objective = f*g/(1 + f^2);
show(prob)

% You can use the mineval output in a subsequent constraint expression.
% Copyright 2018-2019 The MathWorks, Inc.