Iterating a function in MATLAB - matlab

Incredibly simple question, but I think I'm unable to come up with the correct terminology to google search it.
If I have a snippet of code that relies on three independent variables:
code(x,y,z)
That produces two values, i.e.:
output1, output2
How do I go about iterating like so (pseudocode):
for x
for y
for z
code(x,y,z)
end
end
end
And have data I can parse to generate 3D graphs such as
surf(x,y,output1)
A naive solution I came up with was just to create a bin of n length and then iterating one variable n times to come up with a 2D graph, i.e:
x_axis = zeros(1,25)
for m = 1:25
xm = x + 1
x_axis(m) = xm
code(x,y,z)
Even a referral to some documentation would be extremely helpful.
Thanks!

Brute force approach:
for x=[1:50]
for y=[1:50]
for z=[1:50]
result(y,x,z)=code(x,y,z);
end
end
end
More paradigmatic approach (in MATLAB) is to meshgrid it, and pump those in.
[XX,YY,ZZ]=meshgrid([1:50],[1:50],[1:50]);
result=code(XX,YY,ZZ);

Related

Create vector-valued function with arbitrary components

Good evening everyone,
I want to create a function
f(x) = [f1(x), f2(x), ... , fn(x)]
in MatLab, with an arbitrary form and number for the fi. In my current case they are meant to be basis elements for a finite-dimensional function space, so for example a number of multi variable polynomials. I want to able to be able to set form (e.g. hermite/lagrange polynomials, ...) and number via arguments in some sort of "function creating" function, so I would like to solve this for arbitrary functions fi.
Assume for now that the fi are fi:R^d -> R, so vector input to scalar output. This means the result from f should be a n-dim vector containing the output of all n functions. The number of functions n could be fairly large, as there is permutation involved. I also need to evaluate the resulting function very often, so I hope to do it as efficiently as possible.
Currently I see two ways to do this:
Create a cell with each fi using a loop, using something like
funcell{i}=matlabFunction(createpoly(degree, x),'vars',{x})
and one of the functions from the symbolic toolbox and a symbolic x (vector). It is then possible to create the desired function with cellfun, e.g.
f=#(x) cellfun(#(v) v(x), funcell)
This is relatively short, easy and what can be found when doing searches. It even allows extension to vector output using 'UniformOutput',false and cell2mat. On the downside it is very inefficient, first during creation because of matlabFunction and then during evaluation because of cellfun.
The other idea I had is to create a string and use eval. One way to do this would be
stringcell{i}=[char(createpoly(degree, x)),';']
and then use strjoin. In theory this should yield an efficient function. There are two problems however. The first is the use of eval (mostly on principle), the second is inserting the correct arguments. The symbolic toolbox does not allow symbols of the form x(i), so the resulting string will not contain them either. The only remedy I have so far is some sort of string replacement on the xi that are allowed, but this is also far from elegant.
So I do have ways to do what I need right now, but I would appreciate any ideas for a better solution.
From my understanding of the problem, you could do the straightforward:
Initialization step:
my_fns = cell(n, 1); %where n is number of functions
my_fns{1} = #f1; % Assuming f1 is defined in f1.m etc...
my_fns{2} = #f2;
Evaluation at x:
z = zeros(n, 1);
for i=1:n,
z(i) = my_fns{i}(x)
end
For example if you put it in my_evaluate.m:
function z = my_evaluate(my_fns, x)
z = zeros(n, 1);
for i=1:n,
z(i) = my_fns{i}(x)
end
How might this possibly be sped up?
Depends on if you have special structure than can be exploited.
Are there calculations common to some subset of f1 through fn that need not be repeated with each function call? Eg. if the common calculation step is costly, you could do y = f_helper(x) and z(i) = fi(x, y).
Can the functions f1...fn be vector / matrix friendly, allowing evaluation of multiple points with each function call?
The big issue is how fast your function calls f1 through fn are, not how you collect the results from those calls in a vector.

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))]);

First Derivative filter Matlab

I have recently been tasked with using a first derivative filter on an image of myself. The instructor said that I should first fix the value of y and preform f(x+1) - f(x) on the rows and then fix the new "X" values and preform f(y+1)-f(y) on the columns.
Note: I have been asked to do this task manually, not using filter2() or any other programmed function, so please do not suggest that I use filter2() or similar. Thanks!
I tried calling up all the pixels and subtracting each successive one by doing
fid = fopen('image.raw')
myimage = fread(fid,[512 683], '*int8')
fclose(fid)
imsz = size(myimage)
x = imsz(1)
for I = 1:512
for J = 1:683
X(I) - X(I-1) = XX
But it doesnt seem to work, and I dont quite understand why. If you could help me, or point me in the right direction, I would be very appreciative.
First of all, your code is syntatically incorrect:
There is no end statement to any of your loops, and besides, you don't even need loops here.
You seem to read your image into the variable myimage, but you're using an undefined variable X when attempting to calculate the derivative.
The order of your assignment statements is reversed. The variable you wish to assign to should be written in the left hand part of the assignement.
I strongly suggest that you read online tutorials and get yourself familiar with MATLAB basics before taking on more complicated tasks.
As to your specific problem:
MATLAB encourages vectorized operations, i.e operations on entire arrays (vectors or matrices) at once. To subtract adjacent values in an array, what you're basically doing is subtracting two arrays, shifted by one element with respect to each other. For one dimensional arrays, that would translate in MATLAB to:
a(2:end) - a(1:end-1)
where a is your array. The end keyword specifies the last index in the array.
To compute the derivative of an image (a 2-D matrix), you need to decide along which axis you want to perform that operation. To approximate the derivate along the y-axis, do this:
X(2:end, :) - X(1:end-1, :)
You can verify that this gives you the same result as diff(X, 1) (or simply diff(X)). To compute the approximate derivative along the x-axis, which is equivalent to diff(X, 2), do this:
X(:, 2:end) - X(:, 1:end-1)
The colon (:) is the same as writing 1:end as the array subscript for the corresponding dimension.
If your filtered image is div then
for Y = 1:682
for X = 1:511
div(X, Y) = myimage(X + 1, Y + 1) - myimage(X,Y);
end
end
Remember the last row and the last column are not filtered!

Problems which matlab is good for

Let me ask whether using Matlab for my particular problem is nonsense or some people do the similar.
I have an initial sequence S(1), where each term is a 2D point.
I create a new sequence S(2) by inserting a new term point p
between each consecutive 2 term points p(i) and p(i+1).
Where p is a function f of 4 term points of nearest indices on S(2).
Namely,
p= f( p(i-1),p(i),p(i+1),p(i+2) )
And the function f is written in a C like style
but not in the pure style of matrix language.
In the same way , I repeat generating the new longer sequence S(i+1) up to S(m).
The above may be vague for you, but please give some advice.
I do not ask whether Matlab is the best choice for the problem , but whether no expert will use Matlab for such a problem or some will.
Thank you in advance.
It heavily depends on f. If f could be coded efficiently in Matlab or you are willing to spend the time to MEX it (Matlab C extension), then Matlab will perform efficiently.
The code could be vectorized like this:
f = #(x) mean(x,3);
m=3;
S{1}=[1,2,3;4,5,6];
for i=2:m
S{i} = cat(3,...
[[0;0] S{i-1}(:,1:end-2)],...
S{i-1}(:,1:end-1),...
S{i-1}(:,2:end),...
[S{i-1}(:,3:end) [0;0]]);
S{i} = [f(S{i}) [0;0]];
S{i} = cat(3,S{i-1},S{i});
S{i} = permute(S{i},[1 3 2]);
S{i} = S{i}(:,:);
S{i}(:,end)=[];
end
Yes, Matlab seems to be suitable for such a task. For the data structure of your list of sequences, consider using cell arrays. You could have S as a cell array, and S{1} would correspond to your S(1), and could again be a cell array of points, or a usual matrix if points are just pairs or triples of numbers.
As an alternative, Python in my opinion is particulary strong when it comes to all kind of sequences.

matlab matrices and fold list

i have two problems in mathematica and want to do them in matlab:
measure := RandomReal[] - 0.5
m = 10000;
data = Table[measure, {m}];
fig1 = ListPlot[data, PlotStyle -> {PointSize[0.015]}]
Histogram[data]
matlab:
measure =# (m) rand(1,m)-0.5
m=10000;
for i=1:m
data(:,i)=measure(:,i);
end
figure(1)
plot(data,'b.','MarkerSize',0.015)
figure(2)
hist(data)
And it gives me :
??? The following error occurred
converting from function_handle to
double: Error using ==> double
If i do :
measure =rand()-0.5
m=10000;
data=rand(1,m)-0.5
then, i get the right results in plot1 but in plot 2 the y=axis is wrong.
Also, if i have this in mathematica :
steps[m_] := Table[2 RandomInteger[] - 1, {m}]
steps[20]
Walk1D[n_] := FoldList[Plus, 0, steps[n]]
LastPoint1D[n_] := Fold[Plus, 0, steps[n]]
ListPlot[Walk1D[10^4]]
I did this :
steps = # (m) 2*randint(1,m,2)-1;
steps(20)
Walk1D =# (n) cumsum(0:steps(n)) --> this is ok i think
LastPointold1D= # (n) cumsum(0:steps(n))
LastPoint1D= # (n) LastPointold1D(end)-->but here i now i must take the last "folding"
Walk1D(10)
LastPoint1D(10000)
plot(Walk1D(10000),'b')
and i get an empty matrix and no plot..
Since #Itamar essentially answered your first question, here is a comment on the second one. You did it almost right. You need to define
Walk1D = # (n) cumsum(steps(n));
since cumsum is a direct analog of FoldList[Plus,0,your-list]. Then, the plot in your code works fine. Also, notice that, either in your Mathematica or Matlab code, it is not necessary to define LastPoint1D separately - in both cases, it is the last point of your generated list (vector) steps.
EDIT:
Expanding a bit on LastPoint1D: my guess is that you want it to be a last point of the walk computed by Walk1D. Therefore, it would IMO make sense to just make it a function of a generated walk (vector), that returns its last point. For example:
lastPoint1D = #(walk) (walk(end));
Then, you use it as:
walk = Walk1D(10000);
lastPoint1D(walk)
HTH
You have a few errors/mistakes translating your code to Matlab:
If I am not wrong, the line data = Table[measure, {m}]; creates m copies of measure, which in your case will create a random vector of size (1,m). If that is true, in Matlab it would simply be data = measure(m);
The function you define gets a single argument m, therefor it makes no sense using a matrix notation (the :) when calling it.
Just as a side-note, if you insert data into a matrix inside a for loop, it will run much faster if you allocate the matrix in advance, otherwise Matlab will re-allocate memory to resize the matrix in each iteration. You do this by data = zeros(1,m);.
What do you mean by "in plot 2 the y=axis is wrong"? What do you expect it to be?
EDIT
Regarding your 2nd question, it would be easier to help you if you describe in words what you want to achieve, rather than trying to read your (error producing) code. One thing which is clearly wrong is using expression like 0:steps(n), since you use m:n with two scalars m and n to produce a vector, but steps(n) produces a vector, not a scalar. You probably get an empty matrix since the first value in the vector returned by steps(n) might be -1, and 0:-1 produces an empty vector.