Problems approaching Rosenbrock method - matlab

So I have an assigment where I have to do some... fighting with the code so I can further understand how does it work/what are good parameters for the method. About everything I found in the web is about rosenbrock function, and I am now almost sure it's a different thing from rosenbrock method.
I found this question from a while ago, and it's quite similar to what I was trying (without much success)
While loop Vectorization
The code I have so far is something like:
function [T] = rosenbrock(f,xx0,maxLoop,error,d,a,b)
delta_F=10;
x0=xx0;
y0 = f(x0);
i=0;
vF=[];
while (delta_F > error) && (i < maxLoop)
x1 = x0+d;
y0 = f(x0);
y1 = f(x1);
if y1 < y0
x0= x1;
d = a*d;
else
vF = [vF;x1];
d = -b*d;
end
i = i + 1;
if length(vF) > 1
ultm = vF(end);
pultm = vF(end-1);
delta_F = abs(ultm+pultm)/2;
end
end
T=vF;
And I call it from another script with this:
x0=1;
error=1e-3;
maxLoop=500;
fun=#(x)(sin(x));
[S]=rosenbrock(fun, x0, maxLoop,error,1,2,-1.5)
And it's giving me absurd numbers like 10^88 and such. And part of the problem is I don't really know how I should approach the problem, I find the amount of theory given to us small and don't really know how to differentiate good results from bad ones
and even if I get... something with the method (so far the idea was to store the points used so later I could do something with them), but I also am not sure about what to do them, like, plotting into the function, that short of thing.
Point is, code does not work, I do not understand why because as far as I know it's doing what is supposed to do, and don't really know what to do next. I can explain further but it'd be with my own words since the wikipedia has a poor article and as I said everything else is about rosenbrock function, which seems similar but not quite the same.

I have discovered two mistakes in your code (in the code you copied):
You want to calculate the stepwidth named delta_F. "Delta's" are always calculated as a difference of two values:
delta_F = abs(ultm-pultm)/2;
Your function-call is wrong. Replace the "b"-value with 0.5 instead of -1.5.

Related

Declaring a functional recursive sequence in Matlab

I'd like to declare first of all, that I'm a mathematician. This might be a stupid stupid question; but I've gone through all the matlab tutorials--they've gotten me nowhere. I imagine I could code this in C (it'd be exhausting); but I need matlab for this particular function. And I don't get exactly how to do it.
Here is the pasted Matlab code of where I'm running into trouble:
function y = TAU(z,n)
y=0;
for i =[1,n]
y(z) = log(beta(z+1,i) + y(z+1)) - beta(z,i);
end
end
(beta is an arbitrary "float" to "float" function with an index i.)
I'm having trouble declaring y as a function, in which we call the function at a different argument. I want to define y_n(z) with something something y_{n-1}(z+1). This is all done in a recursive process to create the function. I really feel like I'm missing something stupid.
As a default function it assigns y to be an array (or whatever you call the default index assignment). But I don't want an array. I want y to be assigned as a "function" class (i.e. takes "float" to "float"). And then I'm defining a sequence of y_n : "float" to "float". So that z to z+1 is a map on "float" to "float".
I don't know if I'm asking too much of matlab...
Help a poor mathematician who hasn't coded since the glory days of X-box mods.
...Please don't tell me I have to go back to Pari-GP/C drawing boards over something so stupid.
Please help!
EDIT: At rahnema1 & mimocha's request, I'll describe the math, and of what I am trying to do with my program. I can't see how to implement latex in here. So I'll write the latex code in a generator and upload a picture. I'm not so sure if there even is a work around to what I want to do.
As to the expected output. We'd want,
beta(z+1,i) + TAU(z+1,i) = exp(beta(z,i) + TAU(z,i+1))
And we want to grow i to a fixed value n. Again, I haven't programmed in forever, so I apologize if I'm speaking a little nonsensically.
EDIT2:
So, as #rahnema1 suggests; I should produce a reproducible example. In order to do this, I'll write the code for my beta function. It's surprisingly simple. This is for the case where the "multiplier" variable is set to log(2); but you don't need to worry about any of that.
function f = beta(z,n)
f=0;
for i = 0:n-1
f = exp(f)/(1+exp(log(2)*(n-i-z)));
end
end
This will work fine for z a float no greater than 4. Once you make z larger it'll start to overflow. So for example, if you put in,
beta(2,100)
1.4242
beta(3,100)
3.3235
beta(3,100) - exp(beta(2,100))/(1/4+1)
0
The significance of the 100, is simply how many iterations we perform; it converges fast so even setting this to 15 or so will still produce the same numerical accuracy. Now, the expected output I want for TAU is pretty straight forward,
TAU(z,1) = log(beta(z+1,1)) - beta(z,1)
TAU(z,2) = log(beta(z+1,2) + TAU(z+1,1)) - beta(z,2)
TAU(z,3) = log(beta(z+1,3) + TAU(z+1,2)) - beta(z,3)
...
TAU(z,n) = log(beta(z+1,n) + TAU(z+1,n-1)) -beta(z,n)
I hope this helps. I feel like there should be an easy way to program this sequence, and I must be missing something obvious; but maybe it's just not possible in Matlab.
At mimocha's suggestion, I'll look into tail-end recursion. I hope to god I don't have to go back to Pari-gp; but it looks like I may have to. Not looking forward to doing a deep dive on that language, lol.
Thanks, again!
Is this what you are looking for?
function out = tau(z,n)
% Ends recursion when n == 1
if n == 1
out = log(beta(z+1,1)) - beta(z,1);
return
end
out = log(beta(z+1,n) + tau(z+1,n-1)) - beta(z,n);
end
function f = beta(z,n)
f = 0;
for i = 0:n-1
f = exp(f) / (1 + exp(log(2)*(n-i-z)));
end
end
This is basically your code from the most recent edit, but I've added a simple catch in the tau function. I tried running your code and noticed that n gets decremented infinitely (no exit condition).
With the modification, the code runs successfully on my laptop for smaller integer values of n, where 1e5 > n >= 1; and for floating values of z, real and complex. So the code will unfortunately break for floating values of n, since I don't know what values to return for, say, tau(1,0) or tau(1,0.9). This should easily be fixable if you know the math though.
However, many of the values I get are NaNs or Infs. So I'm not sure if your original problem was Out of memory error (infinite recursion), or values blowing up to infinity / NaN (numerical stability issue).
Here is a quick 100x100 grid calculation I made with this code.
Then I tested on negative values of z, and found the imaginary part of the output to looks kinda cool.
Not to mention I'm slightly geeking out over the fact that pi is showing up in the imaginary part as well :)
tau(-0.3,2) == -1.45179335740446147085 +3.14159265358979311600i

Solve equation numerically containing log

I have the following script that defines a function and sets up and equation:
H = #(f) sum(log(f));
f = rand(1, 1);
syms a
H(f)-H(f-a)
I want to solve H(f)-H(f-a)=0 for a. I tried using fzero in the following manner, fzero('H(f)-H(f-a)', 0), but this doesn't yield me anything useful.
well the clear answer for this would be that a=0. This is of course the obvious answer, and may be why you are not getting "anything useful", especially when only considering one value for f.
However, you can actually get useful information when you add more values and use the solve function.
H = #(f) sum(log(f));
f = rand(5, 1);
syms a
temp = H(f)-H(f-a);
out = double(solve(temp == 0,a));
This will output a vector with all values of a that are solutions to your function. Just note that this may not result in the best answers in general, numerical solving of high order functions is rather difficult and unreliable. Because of this, it may take a long time to run as well.

GUI solving equations project

I have a Matlab project in which I need to make a GUI that receives two mathematical functions from the user. I then need to find their intersection point, and then plot the two functions.
So, I have several questions:
Do you know of any algorithm I can use to find the intersection point? Of course I prefer one to which I can already find a Matlab code for in the internet. Also, I prefer it wouldn't be the Newton-Raphson method.
I should point out I'm not allowed to use built in Matlab functions.
I'm having trouble plotting the functions. What I basically did is this:
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
cla % To clear axes when plotting new functions
ezplot(fun_f);
hold on
ezplot(fun_g);
axis ([-20 20 -10 10]);
The problem is that sometimes, the axes limits do not allow me to see the other function. This will happen, if, for example, I will have one function as log10(x) and the other as y=1, the y=1 will not be shown.
I have already tried using all the axis commands but to no avail. If I set the limits myself, the functions only exist in certain limits. I have no idea why.
3 . How do I display numbers in a static text? Or better yet, string with numbers?
I want to display something like x0 = [root1]; x1 = [root2]. The only solution I found was turning the roots I found into strings but I prefer not to.
As for the equation solver, this is the code I have so far. I know it is very amateurish but it seemed like the most "intuitive" way. Also keep in mind it is very very not finished (for example, it will show me only two solutions, I'm not so sure how to display multiple roots in one static text as they are strings, hence question #3).
function [Sol] = SolveEquation(handles)
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
f = inline(fun_f);
g = inline(fun_g);
i = 1;
Sol = 0;
for x = -10:0.1:10;
if (g(x) - f(x)) >= 0 && (g(x) - f(x)) < 0.01
Sol(i) = x;
i = i + 1;
end
end
solution1 = num2str(Sol(1));
solution2 = num2str(Sol(2));
set(handles.roots1,'string',solution1);
set(handles.roots2,'string',solution2);
The if condition is because the subtraction will never give me an absolute zero, and this seems to somewhat solve it, though it's really not perfect, sometimes it will give me more than two very similar solutions (e.g 1.9 and 2).
The range of x is arbitrary, chosen by me.
I know this is a long question, so I really appreciate your patience.
Thank you very much in advance!
Question 1
I think this is a more robust method for finding the roots given data at discrete points. Looking for when the difference between the functions changes sign, which corresponds to them crossing over.
S=sign(g(x)-f(x));
h=find(diff(S)~=0)
Sol=x(h);
If you can evaluate the function wherever you want there are more methods you can use, but it depends on the size of the domain and the accuracy you want as to what is best. For example, if you don't need a great deal of accurac, your f and g functions are simple to calculate, and you can't or don't want to use derivatives, you can get a more accurate root using the same idea as the first code snippet, but do it iteratively:
G=inline('sin(x)');
F=inline('1');
g=vectorize(G);
f=vectorize(F);
tol=1e-9;
tic()
x = -2*pi:.001:pi;
S=sign(g(x)-f(x));
h=find(diff(S)~=0); % Find where two lines cross over
Sol=zeros(size(h));
Err=zeros(size(h));
if ~isempty(h) % There are some cross-over points
for i=1:length(h) % For each point, improve the approximation
xN=x(h(i):h(i)+1);
err=1;
while(abs(err)>tol) % Iteratively improve aproximation
S=sign(g(xN)-f(xN));
hF=find(diff(S)~=0);
xN=xN(hF:hF+1);
[~,I]=min(abs(f(xN)-g(xN)));
xG=xN(I);
err=f(xG)-g(xG);
xN=linspace(xN(1),xN(2),15);
end
Sol(i)=xG;
Err(i)=f(xG)-g(xG);
end
else % No crossover points - lines could meet at tangents
[h,I]=findpeaks(-abs(g(x)-f(x)));
Sol=x(I(abs(f(x(I))-g(x(I)))<1e-5));
Err=f(Sol)-g(Sol)
end
% We also have to check each endpoint
if abs(f(x(end))-g(x(end)))<tol && abs(Sol(end)-x(end))>1e-12
Sol=[Sol x(end)];
Err=[Err g(x(end))-f(x(end))];
end
if abs(f(x(1))-g(x(1)))<tol && abs(Sol(1)-x(1))>1e-12
Sol=[x(1) Sol];
Err=[g(x(1))-f(x(1)) Err];
end
toc()
Sol
Err
This will "zoom" in to the region around each suspected root, and iteratively improve the accuracy. You can tweak the parameters to see whether they give better behaviour (the tolerance tol, the 15, number of new points to generate, could be higher probably).
Question 2
You would probably be best off avoiding ezplot, and using plot, which gives you greater control. You can vectorise inline functions so that you can evaluate them like anonymous functions, as I did in the previous code snippet, using
f=inline('x^2')
F=vectorize(f)
F(1:5)
and this should make plotting much easier:
plot(x,f(x),'b',Sol,f(Sol),'ro',x,g(x),'k',Sol,G(Sol),'ro')
Question 3
I'm not sure why you don't want to display your roots as strings, what's wrong with this:
text(xPos,yPos,['x0=' num2str(Sol(1))]);

Function to find entries with same maximum value in a vector

In my project I need a function which returns the index of the largest element of a given vector. Just like max. For more than one entry with the same maximum value (which occurs frequently) the function should choose one randomly. Unlike max.
The function is a subfunction in a MATLAB Function Block in Simulink. And the whole Simulink model is compiled.
My basic idea was:
function ind = findOpt(vector)
index_max = find(vector == max(vector));
random = randi([1,length(index_max)],1);
ind = index_max(random);
end
But I got problems with the comparison in find and with randi.
I found out about safe comparison here: Problem using the find function in MATLAB. Also I found a way to replace randi([1,imax],1): Implement 'randi' using 'rand' in MATLAB.
My Code now looks like this:
function ind = findOpt(vector)
tolerance = 0.00001;
index_max = find(abs(vector - max(vector)) < tolerance);
random = ceil(length(index_max)*rand(1));
ind = index_max(random);
end
Still doesn't work. I understand that the length of index_max is unclear and causes problems. But I can not think of any way to know it before. Any ideas how to solve this?
Also, I'm shocked that ceil doesn't work when the code gets executed?? In debug mode there is no change to the input visible.
I thought about creating an array like: index_max = abs(vector - max(vector)) < tolerance; But not sure how that could help. Also, it doesn't solve my problem with the random selection.
Hopefully somebody has more ideas or at least could give me some hints!
I am using MATLAB R2012b (32bit) on a Windows7-64bit PC, with the Lcc-win32 C 2.4.1 compiler.
Edit:
Vector usually is of size 5x1 and contains values between -2000 and zero which are of type double, e.g. vector = [-1000 -1200 -1000 -1100 -1550]'. But I think such a simple function should work with any kind of input vector.
The call of length(index_max) causes an system error in MATLAB and forces me to shut it down. I guess this is due to the strange return I get from find. For a vector with all the same values the return from find is something like [1.000 2.000 1.000 2.000 0.000]' which doesn't make any sense to me at all.
function v= findOpt(v)
if isempty(v)
return;
end
v = find((max(v) - v) < 0.00001);
v = v(ceil(rand(1)*end));
end
I was indeed overloading, just like user664303 suggested! Since I can not use objects in my project, I wanted an function that behaves similar, so I wrote:
function varargout = table(mode, varargin)
persistent table;
if isempty(table) && ~strcmp(mode,'writeTable')
error(...)
end
switch mode
case 'getValue'
...
case 'writeTable'
table = ...
...
end
end
Wanted to avoid passing the dimensions for the table in every call and thought it would be enough if the first call initializes the Table with mode='writeTable'. Looks like this caused my problem.
No problems after changing to:
if isempty(table)
table = zeros(dim1,dim2,...)
end

Avoiding loops in MatLab code (barycentric weights)

After having learned basic programming in Java, I have found that the most difficult part of transitioning to MatLab for my current algorithm course, is to avoid loops. I know that there are plenty of smart ways to vectorize operations in MatLab, but my mind is so "stuck" in loop-thinking, that I am finding it hard to intuitively see how I may vectorize code. Once I am shown how it can be done, it makes sense to me, but I just don't see it that easily myself. Currently I have the following code for finding the barycentric weights used in Lagrangian interpolation:
function w = barycentric_weights(x);
% The function is used to find the weights of the
% barycentric formula based on a given grid as input.
n = length(x);
w = zeros(1,n);
% Calculating the weights
for i = 1:n
prod = 1;
for j = 1:n
if i ~= j
prod = prod*(x(i) - x(j));
end
end
w(i) = prod;
end
w = 1./w;
I am pretty sure there must be a smarter way to do this in MatLab, but I just can't think of it. If anyone has any tips I will be very grateful :). And the only way I'll ever learn all the vectorizing tricks in MatLab is to see how they are used in various scenarios such as above.
One has to be creative in matlab to avoid for loop:
[X,Y] =meshgrid(x,x)
Z = X - Y
w =1./prod(Z+eye(length(x)))
Kristian, there are a lot of ways to vectorize code. You've already gotten two. (And I agree with shakinfree: you should always consider 1) how long it takes to run in non-vectorized form (so you'll have an idea of how much time you might save by vectorizing); 2) how long it might take you to vectorize (so you'll have a better sense of whether or not it's worth your time; 3) how many times you will call it (again: is it worth doing); and 3) readability. As shakinfree suggests, you don't want to come back to your code a year from now and scratch your head about what you've implemented. At least make sure you've commented well.
But at a meta-level, when you decide that you need to improve runtime performance by vectorizing, first start with small (3x1 ?) array and make sure you understand exactly what's happening for each iteration. Then, spend some time reading this document, and following relevant links:
http://www.mathworks.com/help/releases/R2012b/symbolic/code-performance.html
It will help you determine when and how to vectorize.
Happy MATLABbing!
Brett
I can see the appeal of vectorization, but I often ask myself how much time it actually saves when I go back to the code a month later and have to decipher all that repmat gibberish. I think your current code is clean and clear and I wouldn't mess with it unless performance is really critical. But to answer your question here is my best effort:
function w = barycentric_weights_vectorized(x)
n = length(x);
w = 1./prod(eye(n) + repmat(x,n,1) - repmat(x',1,n),1);
end
Hope that helps!
And I am assuming x is a row vector here.