Function fzero in Matlab is not converging - matlab

I am solving a problem in my Macroeconomics class. Consider the following equation:
Here, k is fixed and c(k) was defined through the ```interp1''' function in Matlab. Here is my code:
beta = 0.98;
delta = 0.13;
A = 2;
alpha = 1/3;
n_grid = 1000; % Number of points for capital
k_grid = linspace(5, 15, n_grid)';
tol = 1e-5;
max_it = 1000;
c0 = ones(n_grid, 1);
new_k = zeros(n_grid, 1);
dist_c = tol + 1;
it_c = 0;
while dist_c > tol && it_c < max_it
c_handle = #(k_tomorrow) interp1(k_grid, c0, k_tomorrow, 'linear', 'extrap');
for i=1:n_grid
% Solve for k'
euler = #(k_tomorrow) (1/((1-delta)* k_grid(i) + A * k_grid(i)^alpha - k_tomorrow)) - beta*(1-delta + alpha*A*k_tomorrow^(alpha - 1))/c_handle(k_prime);
new_k(i) = fzero(euler, k_grid(i)); % What's a good guess for fzero?
end
% Compute new values for consumption
new_c = A*k_grid.^alpha + (1-delta)*k_grid - new_k;
% Check convergence
dist_c = norm(new_c - c0);
c0 = new_c;
it_c = it_c + 1;
end
When I run this code, for some indexes $i$, it runs fine and fzero can find the solution. But for indexes it just returns NaN and exits without finding the root. This is a somewhat well-behaved problem in Economics and the solution we are looking indeed exists and the algorithm I tried to implement is guaranteed to work. But I don't have much experience with solving this in MATLAB and I guess I have a silly mistake somewhere. Any ideas on how to procede?
This is the typical error message:
Exiting fzero: aborting search for an interval containing a sign change
because complex function value encountered during search.
(Function value at -2.61092 is 0.74278-0.30449i.)
Check function or try again with a different starting value.
Thanks a lot in advance!

The only term that can produce complex numbers is
k'^(alpha - 1) = k'^(-2/3)
You probably want the result according to the real variant of the cube root, which you could get as
sign(k') * abs(k')^(-2/3)
or more generally and avoiding divisions by zero
k' * (1e-16+abs(k'))^(alpha - 2)

Related

Vectorizing a for-loop operation

I have an SDE I'm approximating by a numerical scheme using this code:
mu = 1.5;
Sigma = 0.5;
TimeStep = 0.001;
Time = 0:TimeStep:5;
random1 = normrnd(2,0.05,[1,500]);
random2 = randn(1,length(Time));
X = zeros(500, length(Time));
for j = 1:500
X(j,1)= random1(j);
for i = 1:length(Time)
X(j,i+1) = X(j,i) - mu*X(j,i)*TimeStep + Sigma*sqrt(2*mu)*sqrt(TimeStep)*random2(i);
end
end
How would it be possible to remove the outer for-loop and vectorize, so that at each time step, the first value is calculated for all 500 plots?
That's pretty simple, especially since j is only used for row indexing here:
X(:,1)= random1;
for i = 1:length(Time)
X(:,i+1) = X(:,i) - mu*X(:,i)*TimeStep + Sigma*sqrt(2*mu)*sqrt(TimeStep)*random2(i);
end
I tested both versions (Octave 5.1.0), and get identical results. Speed-up is about 400x on my machine.
General remark: Never use i and/or j as loop variables, since they are also used as imaginary units, cf. i and j.
Hope that helps!

Input equations into Matlab for Simulink Function

I am currently working on an assignment where I need to create two different controllers in Matlab/Simulink for a robotic exoskeleton leg. The idea behind this is to compare both of them and see which controller is better at assisting a human wearing it. I am having a lot of trouble putting specific equations into a Matlab function block to then run in Simulink to get results for an AFO (adaptive frequency oscillator). The link has the equations I'm trying to put in and the following is the code I have so far:
function [pos_AFO, vel_AFO, acc_AFO, offset, omega, phi, ampl, phi1] = LHip(theta, eps, nu, dt, AFO_on)
t = 0;
% syms j
% M = 6;
% j = sym('j', [1 M]);
if t == 0
omega = 3*pi/2;
theta = 0;
phi = pi/2;
ampl = 0;
else
omega = omega*(t-1) + dt*(eps*offset*cos(phi1));
theta = theta*(t-1) + dt*(nu*offset);
phi = phi*(t-1) + dt*(omega + eps*offset*cos(phi*core(t-1)));
phi1 = phi*(t-1) + dt*(omega + eps*offset*cos(phi*core(t-1)));
ampl = ampl*(t-1) + dt*(nu*offset*sin(phi));
offset = theta - theta*(t-1) - sym(ampl*sin(phi), [1 M]);
end
pos_AFO = (theta*(t-1) + symsum(ampl*(t-1)*sin(phi* (t-1))))*AFO_on; %symsum needs input argument for index M and range
vel_AFO = diff(pos_AFO)*AFO_on;
acc_AFO = diff(vel_AFO)*AFO_on;
end
https://www.pastepic.xyz/image/pg4mP
Essentially, I don't know how to do the subscripts, sigma, or the (t+1) function. Any help is appreciated as this is due next week
You are looking to find the result of an adaptive process therefore your algorithm needs to consider time as it progresses. There is no (t-1) operator as such. It is just a mathematical notation telling you that you need to reuse an old value to calculate a new value.
omega_old=0;
theta_old=0;
% initialize the rest of your variables
for [t=1:N]
omega[t] = omega_old + % here is the rest of your omega calculation
theta[t] = theta_old + % ...
% more code .....
% remember your old values for next iteration
omega_old = omega[t];
theta_old = theta[t];
end
I think you forgot to apply the modulo operation to phi judging by the original formula you linked. As a general rule, design your code in small pieces, make sure the output of each piece makes sense and then combine all pieces and make sure the overall result is correct.

How does one compute a single finite differences in Matlab efficiently?

I wanted to compute a finite difference with respect to the change of the function in Matlab. In other words
f(x+e_i) - f(x)
is what I want to compute. Note that its very similar to the first order numerical partial differentiation (forward differentiation in this case) :
(f(x+e_i) - f(x)) / (e_i)
Currently I am using for loops to compute it but it seems that Matlab is much slower than I thought. I am doing it as follows:
function [ dU ] = numerical_gradient(W,f,eps)
%compute gradient or finite difference update numerically
[D1, D2] = size(W);
dU = zeros(D1, D2);
for d1=1:D1
for d2=1:D2
e = zeros([D1,D2]);
e(d1,d2) = eps;
f_e1 = f(W+e);
f_e2 = f(W-e);
%numerical_derivative = (f_e1 - f_e2)/(2*eps);
%dU(d1,d2) = numerical_derivative
numerical_difference = f_e1 - f_e2;
dU(d1,d2) = numerical_difference;
end
end
it seems that its really difficult to vectorize the above code because for numerical differences follow the definition of the gradient and partial derivatives which is:
df_dW = [ ..., df_dWi, ...]
where df_dWi assumes the other coordinates are fixed and it only worries about the change of the variable Wi. Thus, I can't just change all the coordinates at once.
Is there a better way to do this? My intuition tells me that the best way to do this is to implement this not in matlab but in some other language, say C and then have matlab call that library. Is that true? Does it mean that the best solution is some Matlab library that does this for me?
I did see:
https://www.mathworks.com/matlabcentral/answers/332414-what-is-the-quickest-way-to-find-a-gradient-or-finite-difference-in-matlab-of-a-real-function-in-hig
but unfortunately, it computes exact derivatives, which isn't what I am looking for. I am explicitly looking for differences or "bad approximation" to the gradient.
Since it seems this code is not easy to vectorize (in fact my intuition tells me its not possible to do so) my only other idea is to implement this finite difference function in C and then have C call the function. Is this a good idea? Anyone know how to do this?
I did try reading the following:
https://www.mathworks.com/help/matlab/matlab_external/standalone-example.html
but it was too difficult to understand for me because I have no idea what a mex file is, if I need to have a arrayProduct.c file as well as a mex.h file, if I also needed a matlab file, etc. If there just existed a way to simply download a working example with all the functions they suggest there and some instructions to compile it, then it would be super helpful. But just reading the hmtl/article like that its impossible for me to infer what they want me to do.
For the sake of completness it seems reddit has some comments in its discussion of this:
https://www.reddit.com/r/matlab/comments/623m7i/how_does_one_compute_a_single_finite_differences/
Here is a more efficient doing so:
function [ vNumericalGrad ] = CalcNumericalGradient( hInputFunc, vInputPoint, epsVal )
numElmnts = size(vInputPoint, 1);
vNumericalGrad = zeros([numElmnts, 1]);
refVal = hInputFunc(vInputPoint);
for ii = 1:numElmnts
% Set the perturbation vector
refInVal = vInputPoint(ii);
vInputPoint(ii) = refInVal + epsVal;
% Compute Numerical Gradient
vNumericalGrad(ii) = (hInputFunc(vInputPoint) - refVal) / epsVal;
% Reset the perturbation vector
vInputPoint(ii) = refInVal;
end
end
This code allocate less memory.
The above code performance will be totally controlled by the speed of the hInputFunction.
The small tricks compared to original code are:
No memory reallocation of e each iteration.
Instead of addition of vectors W + e there are 2 assignments to the array.
Decreasing the calls to hInputFunction() by half by defining the reference value outside the loop (This only works for Forward / Backward difference).
Probably this will be very close to C code unless you can code in C more efficiently the function which computes the value (hInputFunction).
A full implementation can be found in StackOverflow Q44984132 Repository (It was Posted in StackOverflow Q44984132).
See CalcFunGrad( vX, hObjFun, difMode, epsVal ).
A way better approach (numerically more stable, no issue of choosing the perturbation hyperparameter, accurate up to machine precision) is to use algorithmic/automatic differentiation. For this you need the Matlab Deep Learning Toolbox. Then you can use dlgradient to compute the gradient. Below you find the source code attached corresponding to your example.
Most importantly, you can examine the error and observe that the deviation of the automatic approach from the analytical solution is indeed machine precision, while for the finite difference approach (I choose second order central differences) the error is orders of magnitude higher. For 100 points and a range of $[-10, 10]$ this errors are somewhat tolerable, but if you play a bit with Rand_Max and n_points you observe that the errors become larger and larger.
Error of algorithmic / automatic diff. is: 1.4755528111219851e-14
Error of finite difference diff. is: 1.9999999999348703e-01 for perturbation 1.0000000000000001e-01
Error of finite difference diff. is: 1.9999999632850161e-03 for perturbation 1.0000000000000000e-02
Error of finite difference diff. is: 1.9999905867860374e-05 for perturbation 1.0000000000000000e-03
Error of finite difference diff. is: 1.9664569947425062e-07 for perturbation 1.0000000000000000e-04
Error of finite difference diff. is: 1.0537897883625319e-07 for perturbation 1.0000000000000001e-05
Error of finite difference diff. is: 1.5469326944467290e-06 for perturbation 9.9999999999999995e-07
Error of finite difference diff. is: 1.3322061696937969e-05 for perturbation 9.9999999999999995e-08
Error of finite difference diff. is: 1.7059535957436630e-04 for perturbation 1.0000000000000000e-08
Error of finite difference diff. is: 4.9702408787320664e-04 for perturbation 1.0000000000000001e-09
Source Code:
f2.m
function y = f2(x)
x1 = x(:, 1);
x2 = x(:, 2);
x3 = x(:, 3);
y = x1.^2 + 2*x2.^2 + 2*x3.^3 + 2*x1.*x2 + 2*x2.*x3;
f2_grad_analytic.m:
function grad = f2_grad_analytic(x)
x1 = x(:, 1);
x2 = x(:, 2);
x3 = x(:, 3);
grad(:, 1) = 2*x1 + 2*x2;
grad(:, 2) = 4*x2 + 2*x1 + 2 * x3;
grad(:, 3) = 6*x3.^2 + 2*x2;
f2_grad_AD.m:
function grad = f2_grad_AD(x)
x1 = x(:, 1);
x2 = x(:, 2);
x3 = x(:, 3);
y = x1.^2 + 2*x2.^2 + 2*x3.^3 + 2*x1.*x2 + 2*x2.*x3;
grad = dlgradient(y, x);
CalcNumericalGradient.m:
function NumericalGrad = CalcNumericalGradient(InputPoints, eps)
% (Central, second order accurate FD)
NumericalGrad = zeros(size(InputPoints) );
for i = 1:size(InputPoints, 2)
perturb = zeros(size(InputPoints));
perturb(:, i) = eps;
NumericalGrad(:, i) = (f2(InputPoints + perturb) - f2(InputPoints - perturb)) / (2 * eps);
end
main.m:
clear;
close all;
clc;
n_points = 100;
Rand_Max = 20;
x_test_FD = rand(n_points, 3) * Rand_Max - Rand_Max/2;
% Calculate analytical solution
grad_analytic = f2_grad_analytic(x_test_FD);
grad_AD = zeros(n_points, 3);
for i = 1:n_points
x_test_dl = dlarray(x_test_FD(i,:) );
grad_AD(i,:) = dlfeval(#f2_grad_AD, x_test_dl);
end
Err_AD = norm(grad_AD - grad_analytic);
fprintf("Error of algorithmic / automatic diff. is: %.16e\n", Err_AD);
eps_range = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9];
for i = 1:length(eps_range)
eps = eps_range(i);
grad_FD = CalcNumericalGradient(x_test_FD, eps);
Err_FD = norm(grad_FD - grad_analytic);
fprintf("Error of finite difference diff. is: %.16e for perturbation %.16e\n", Err_FD, eps);
end

MATLAB roots function different behavior in MATLAB then Simulink?

I implemented the following user defined function in MATLAB:
function Q = Calc_Q(Head, freq)
b6 = [3.7572E-07 -1.5707E-05 6.0490E-03 5.0018E-02 2.1180E-01];
b5 = [-9.0927E-06 8.9033E-04 -3.2415E-02 5.4525E-01 -8.1649E+00] / 10e2;
b4 = [7.5172E-06 -5.6565E-04 1.0024E-02 3.5888E-01 3.8894E-02] / 10e5;
b3 = [-4.8767E-06 4.8787E-04 -1.3311E-02 -1.2189E-01 -5.3522E+00] / 10e8;
b2 = [5.9227E-06 -8.1716E-04 3.5392E-02 -4.5413E-01 1.9547E+00] / 10e11;
b1 = [-2.0004E-06 2.9027E-04 -1.3754E-02 2.3490E-01 -1.2363E+00] / 10e14;
a = [polyval(b1,abs(freq)), polyval(b2, abs(freq)), polyval(b3, abs(freq)), polyval(b4, abs(freq)), polyval(b5, abs(freq)), polyval(b6, abs(freq)) - Head];
Q_roots = roots(a);
%Delete roots with imaginary part
i = 1;
while i <= length(Q_roots)
if(imag(Q_roots(i)) ~= 0)
Q_roots(i) = [];
i = i - 1;
end
i = i + 1;
end
%Delete roots with real part greater then 3100
i = 1;
while i <= length(Q_roots)
if(Q_roots(i) >= 3100 || Q_roots(i) < 0)
Q_roots(i) = [];
i = i - 1;
end
i = i +1;
end
if freq < 0
Q = real(Q_roots(1)) * -1;
else
Q = real(Q_roots(1));
end
end
When I Call this function in Matlab it works fine. However if I use this exact code as a MATLAB function in simulink it stop's working. (actually it works, but the ouput is always zero.)
I do have a suspicion of what the problem might be. When running the script in de-bugging mode, I cannot view a result for Q_roots (It just doesn't display anything).
Q_roots = roots(a);
Any ideas ?
The problem is most likely due to your logic that eliminates any roots that do not have exactly zero in the imaginary part. This is a mathematical way of thinking that does not really work well numerically, at least not in general. All the roots are probably being found in both cases (there is no limitation that implies otherwise), but in Simulink and in code generation the problem is treated as a complex one, and some roots might be coming back with tiny imaginary parts. Instead of deleting roots if their imaginary parts are not exactly zero, eliminate the roots with imaginary parts that are numerically insignificant, either very small relative to the real part or very small altogether. Something like
tol = 10*eps(class(Q_roots));
keepers = abs(imag(Q_roots)) < tol*max(abs(real(Q_roots)),1) & ...
real(Q_roots) >= 0 & real(Q_roots) <= 3100;
Q_roots = Q_roots(keepers);
would take care of all the deletions in one fell swoop. I used 10*eps as a tolerance here.
But if you only need the first qualifying root, then you could just do this:
Q = nan('like',a);
tol = 10*eps(class(a));
for k = 1:numel(Q_roots)
r = real(Q_roots(k));
if abs(imag(Q_roots(k))) < tol*max(abs(r),1) && r >= 0 && r <= 3100;
Q = r;
break
end
end
if freq < 0
Q = -Q;
end
Oke I found the problem.
From a different forum:
Hi Cosmin,
I took a look at the implementation of roots for the Embedded MATLAB
Function block (\toolbox\eml\lib\matlab\polyfun\roots.m).
It's stated there:
% Limitations: % Output is always variable size. % Output is
always complex. % Roots may not be in the same order as MATLAB. %
Roots of poorly conditioned polynomials may not match MATLAB. The last
sentence is what makes you the headache (and yes, your polynomial is
badly conditioned!). If you take a look at the plot you will see, that
the curve hardly touches the x-axis.
I have a suggestion though: the value -z/b is a (very) good
approximation of the root you are looking for ...?
Titus
http://www.mathworks.com/matlabcentral/answers/25624-roots-in-simulink
Apparently the root function in simulink does not always found all the roots of a given polynominal.
This is unfortunate and not easily solvable. I did however found a solution.
For all the different polynomials I have to solve, I know the interval of the root I am interested in ( [-3000, 3000]).
I just basically takes steps of 50 from -3000 to 3000, until the function drops below 0. I then know the approximate solution of the root. I use this approximation as seed for the Newton-Raphson method.
Straight implementation of the Newton raphson method with a given seed for all the polynomials I have to solve did not work because sometimes it iterated to a different root (one which i was not interested in.)
Here's the code:
function Q = Calc_Q(Head, freq)
b6 = [3.7572E-07 -1.5707E-05 6.0490E-03 5.0018E-02 2.1180E-01];
b5 = [-9.0927E-06 8.9033E-04 -3.2415E-02 5.4525E-01 -8.1649E+00] / 10e2;
b4 = [7.5172E-06 -5.6565E-04 1.0024E-02 3.5888E-01 3.8894E-02] / 10e5;
b3 = [-4.8767E-06 4.8787E-04 -1.3311E-02 -1.2189E-01 -5.3522E+00] / 10e8;
b2 = [5.9227E-06 -8.1716E-04 3.5392E-02 -4.5413E-01 1.9547E+00] / 10e11;
b1 = [-2.0004E-06 2.9027E-04 -1.3754E-02 2.3490E-01 -1.2363E+00] / 10e14;
%coeff for the polynominal
a = [polyval(b1,abs(freq)), polyval(b2, abs(freq)), polyval(b3, abs(freq)), polyval(b4, abs(freq)), polyval(b5, abs(freq)), polyval(b6, abs(freq)) - Head];
%coeff for the derrivative of polynominal
da = [5*a(1) 4*a(2) 3*a(3) 2*a(4) a(5)];
Q = -3000;
%Search for point where function goes below 0
while (polyval(a, Q) > 0)
Q = Q + 25;
end
error_max = 0.01
iter_counter = 1;
while abs(polyval(a,Q)) >= error_max && iter_counter <= 1000
Q = Q - polyval(a, Q)/polyval(da, Q);
iter_counter = iter_counter + 1;
error = abs(polyval(a,Q));
end
if(freq < 0)
Q = Q * - 1;
end
end

Matlab optimiziation where objective is implicitly given by a fixed point equation

I have the following problem:
max CEQ(w) s.t. w in (0,1) and I don't know anything about CEQ(w) except that is given by a fixed point equation of the form CEQ(w) = F(CEQ(w)). If I fix a w, I can solve the fixed point equation using the fzero function and obtain a value for CEQ. If I choose a different w, I get another value for CEQ. Thus, I could loop over all possible values of w and then choose the one that gives the highest CEQ. This seems bad programming though and I was wondering whether I can do this more efficient in MATLAB: I want to model the solution to my fixed point equation as a function of w but I don't know how to implement it.
To be more precise, here is a sample code:
clear all
clc
NoDraws = 1000000;
T_hat = 12;
mu = 0.0058;
variance = 0.0017;
rf = 0.0036;
sim_returns(:,T_hat/12) = T_hat*mu + sqrt(T_hat*variance)*randn(NoDraws,1);
A = 5;
kappa=1;
l=0;
theta = 1 - l*(kappa^(1-A) - 1) *(kappa>1);
CEQ_DA_0 = 1.1;
CEQ_opt = -1000;
w_opt = 0;
W_T = #(w) (1-w)*exp(rf*T_hat) + w*exp(rf*T_hat + sim_returns(:,T_hat/12));
for w=0.01:0.01:0.99
W=W_T(w);
fp = #(CEQ) theta*CEQ^(1-A)/(1-A) - mean( W.^(1-A)/(1-A)) + l*mean( ((kappa*CEQ)^(1-A)/(1-A) - W.^(1-A)/(1-A)) .* (W < kappa*CEQ));
CEQ_DA = fzero(fp,CEQ_DA_0);
if CEQ_DA > CEQ_opt
CEQ_opt = CEQ_DA;
w_opt = w;
end
end
That is, in the loop, I fix a w, solve the fixed point equation and store the value for CEQ. If some other w gives a bigger value for CEQ, the current optimal w gets replaced by that new w. what I would like to have (instead of the loop part) is something like this:
fp = #(CEQ,w) theta*CEQ^(1-A)/(1-A) - mean( W_T(w).^(1-A)/(1-A)) + l*mean( ((kappa*CEQ)^(1-A)/(1-A) - W_T(w).^(1-A)/(1-A)) .* (W_T(w) < kappa*CEQ));
CEQ_DA = #(w) fzero(fp,CEQ_DA_0);
[w_opt, fval]=fminbnd(CEQ_DA,0,1);
Your proposed solution is very close. In words, you're defining fp as a function of two arguments, and would like CEQ_DA to be a function of w, which solves fp for CEQ, with that given w. The only issue is that fzero doesn't know which parameter of fp to solve over, because it can't match anonymous function parameters and fp parameters by name.
The answer is yet one more anonymous function inside the fzero, to turn fp(CEP,w) into fp_w(CEP), which will be solveable for CEQ
CEQ_DA = #(w) fzero(#(CEQ) fp(CEQ, w),CEQ_DA_0);