How to store a function-wrapped solve call? - matlab

Bear with me please, I'm completely new to matlab. I am attempting to store the call to eigenvalue in another function, but it's giving me the error: Too many output arguments.
function eigenvalue(M)
syms l;
eq = det(M - l*[1 0; 0 1]);
solve(eq == 0)
end
I've tried storing it in many different ways, but nothing seems to work:
>> a = eigenvalue(M)
Error using eigenvalue
Too many output arguments.
>> [a, b] = eigen(M)
Error using eigenvalue
Too many output arguments.
The weird thing is that if I solve a normal polynomial equation I can do sol=solve(x^2==4) just fine and access sol(0)and sol(1)without any problems. I guess that I haven't picked up on a simple matlab concept and thanks to anyone who's willing to help!

Your problem is that you don't have any output arguments in your function.
function eigenvalue(M)
In MATLAB, you should* use the following syntax:
function output = func_name(input_1,input_2,...)
You have 2 alternatives:
You can skip the first line and save it as script, as this:
syms l;
eq = det(M - l*[1 0; 0 1]);
solve(eq == 0)
Or, you can save it as a function, but with output variable(s), like this:
function output = eigenvalue(M)
syms l;
eq = det(M - l*[1 0; 0 1]);
output = solve(eq == 0)
end
*You should use the syntax I described, but you can use the syntax you used as well. However, if you do, the function won't give you anything back except possibly printing the result to screen. You will not get to use any variables created inside the function.

If you want a function to provide an output argument then you have to declare it in the function definition. E.g.
function a = eigenvalue(M)
You then need to make sure you assign a value to each output variable in the function body.

Related

series of a function

i have problem solving a series of a function.
how should i solve series like Σ F(k)*F(k-1) ?
actually i want to solve the below series in Matlab
"image of the function"
it's only dependent of K variable.
i tried by defining a function as bellow and saving it as an .m file (for testing i simplified it by neglecting B)
function out = teta(x)
if x==9./5
out=(25./(36*1));
else
out=(10./(9.*1.*x.*(x-1))).*(x-9./5).*teta(x-9./5);
end
and wrote this in the main file:
sum(teta(18/5:9/5:72/5))
as i want a sum of the serie from k=18/5 to 72/5
when i run it i get these errors:
Not enough input arguments.
Error in teta (line 2)
if x==9./5
and
Out of memory. The likely cause is an infinite recursion within the program.
Error in teta (line 5)
out=(10./(9*1.*x.*(x-1))).*(x-9./5).*teta(x-9./5);
so where i'm wrong and "how should i solve these kind of series?"
For a start, you shouldn't an equality test on a floating double precision number, but instead compare the difference to a small threshold value.
Not using a vectorised approach (feel free to vectorise if you so desire), the following works:
function out = teta(x)
if abs(x-9/5)<1e-3
out=25/36;
else
out=(10/(9*x*(x-1)))*(x-9/5)*teta(x-9/5);
end
and then use it as such:
kk = 18/5:9/5:72/5;
teta_vec = zeros(size(kk));
for k=1:length(kk)
teta_vec(k) = teta(kk(k));
end
which gives me:
>> sum(teta_vec)
ans = 0.17714

Symbolic diff in matlab should return vector

If I have a symbolic function p(r,s) = r^3 in MATLAB, I obtain the derivatives dp/dr = 3r^2 and dp/ds = 0, but my goal is to use matlabFunction to convert these expressions to function handles, with vector inputs (r,s). I want something similar to zeros(size(s)), for the derivative dp/ds so I don't obtain a scalar output if my input (r,s) is a vector.
This code I tried:
syms r s
p = r^3
dpds = diff(p,s)
gives a scalar zero not variable size zero, i.e scalar output if we have vector input.
This is the nature of how matlabFunction works. If you provide an equation that has no independent variables as part of the equation, it will default to giving you an anonymous function with no inputs and give you a scalar result.
For example:
>> syms r s;
>> p = r^3;
>> dpds = diff(p,s);
>> dpdsFunc = matlabFunction(dpds)
dpdsFunc =
#()0.0
This will only give you a single scalar value each time. This also applies to any scalar function that gives a non-zero output. If you'd like to override this behaviour and give a variable length of this scalar that is dependent on the length of the input, you can first detect if there are any input variables in the function by checking how many variables there are. You can use symvar for that. You would check if this array has a length of 0, and if it does, you override the function.
Something like this comes to mind:
syms r s;
p = r^3;
dpds = diff(p,s);
if numel(symvar(dpds)) == 0
dpdsFunc = #(s) ones(size(s))*double(dpds); %// Thanks Daniel!
else
dpdsFunc = matlabFunction(dpds);
end
This should achieve what you want.
Minor Note
I actually think this variable length of zeroes business is something that should be put into MATLAB by default, rather than defaulting to a single value. It makes vectorizing code a lot easier. I'm tempted to submit a feature request to MathWorks in the future.

octave plot does not work properly

CODE DELETED
Hi, the code above is my (slightly modified) rooo.m file.
I'm just trying to plot the function by typing into (octave) terminal
x = 1:1:40;
plot(x, rooo(x), '+');
But this will only print the graph of y=1.
I believe it's because of the y = 1; in the first line (btw the function itself returns the right value, say when I type rooo(3)).
When I change it to some other number (say b), the graph will show y =b.
Does anyone have an idea why this is happening??
I think it's not working because if you type rooo(x) at the command line, it will return a scalar result of 1, instead of a vector. The 1 < n logical condition doesn't work as you intended to when n is a vector.
Here is a suggestion to make it work (maybe not the most elegant but it seems to work):
CODE DELETED
Which, when called as in your question, gives the following plot
The results seem to be different from the ones reported in MATLAB though.
An alternative, if you don't want to modify your function, is to change the way you call it:
>> x = 1:1:40;
>> y = ones(size(x));
>> for k=1:length(x)
y(k) = rooo(x(k));
end
>> plot(x,y,'+')
This gives the same result as the above suggestion.
It's not working because you never enter the while loop with x starting at 1. Since
1 < n == 1 < x is false at the very beginning, the function returns.
However when you call rooo(3) or actually rooo(Anything > 1) it does work. With x = 1.1:1:40 the plot looks like this ( I made it with Matlab) :

matlab - arrayfun(..) call, "Not enough input arguments."

In the following boiled down example illustrating the error, the function f_what(..) should return the values of input argument y at indices in the array ts:
function Y = f_what(y, ts)
function get_out = get(t)
get_out = y(t);
end
Y = arrayfun(get, ts);
end
Calling it:
>> f_what(1:10, 1:5)
Error using f_what/get (line 4)
Not enough input arguments.
Error in f_what (line 7)
Y = arrayfun(get, ts);
Also, for some reason, the following, where get(..) should be the same as the one above, works:
function Y = f_what(y, ts)
get = #(t) y(t);
Y = arrayfun(get, ts);
end
Calling it:
>> f_what(1:10, 1:5)
ans =
1 2 3 4 5
"Not enough input arguments" ... arrayfun(..) should call its first argument with, in this case, one argument. And get(..) has one input argument. I don't get why it's not enough.
Edit: even more boiled down:
function Y = f_what
function get_out = get_(t)
get_out = t;
end
Y = arrayfun(get_, 1:5);
end
Still the same error.
Edit 2: It works if I supply #get to the first argument of arrayfun(..), instead of get. But I still don't get why it doesn't work without the #.
Looking at the arrayfun documentation
func
Handle to a function that accepts n input arguments and returns m output arguments.
A handle in matlab is denoted using #, so you need to pass #get as first parameter. Otherwise matlab tries to evaluate function get instead of obtaining its handle, which results in "not enough parameters" error.
In the example that works you defined get to be a handle to an anonymous function, that's why it worked.

MATLAB Function (Solving an Error)

I have one file with the following code:
function fx=ff(x)
fx=x;
I have another file with the following code:
function g = LaplaceTransform(s,N)
g = ff(x)*exp(-s*x);
a=0;
b=1;
If=0;
h=(b-a)/N;
If=If+g(a)*h/2+g(b)*h/2;
for i=1:(N-1)
If=If+g(a+h*i)*h;
end;
If
Whenever I run the second file, I get the following error:
Undefined function or variable 'x'.
What I am trying to do is integrate the function g between 0 and 1 using trapezoidal approximations. However, I am unsure how to deal with x and that is clearly causing problems as can be seen with the error.
Any help would be great. Thanks.
Looks like what you're trying to do is create a function in the variable g. That is, you want the first line to mean,
"Let g(x) be a function that is calculated like this: ff(x)*exp(-s*x)",
rather than
"calculate the value of ff(x)*exp(-s*x) and put the result in g".
Solution
You can create a subfunction for this
function result = g(x)
result = ff(x) * exp(-s * x);
end
Or you can create an anonymous function
g = #(x) ff(x) * exp(-s * x);
Then you can use g(a), g(b), etc to calculate what you want.
You can also use the TRAPZ function to perform trapezoidal numerical integration. Here is an example:
%# parameters
a = 0; b = 1;
N = 100; s = 1;
f = #(x) x;
%# integration
X = linspace(a,b,N);
Y = f(X).*exp(-s*X);
If = trapz(X,Y) %# value returned: 0.26423
%# plot
area(X,Y, 'FaceColor',[.5 .8 .9], 'EdgeColor','b', 'LineWidth',2)
grid on, set(gca, 'Layer','top', 'XLim',[a-0.5 b+0.5])
title('$\int_0^1 f(x) e^{-sx} \,dx$', 'Interpreter','latex', 'FontSize',14)
The error message here is about as self-explanatory as it gets. You aren't defining a variable called x, so when you reference it on the first line of your function, MATLAB doesn't know what to use. You need to either define it in the function before referencing it, pass it into the function, or define it somewhere further up the stack so that it will be accessible when you call LaplaceTransform.
Since you're trying to numerically integrate with respect to x, I'm guessing you want x to take on values evenly spaced on your domain [0,1]. You could accomplish this using e.g.
x = linspace(a,b,N);
EDIT: There are a couple of other problems here: first, when you define g, you need to use .* instead of * to multiply the elements in the arrays (by default MATLAB interprets multiplication as matrix multiplication). Second, your calls g(a) and g(b) are treating g as a function instead of as an array of function values. This is something that takes some getting used to in MATLAB; instead of g(a), you really want the first element of the vector g, which is given by g(1). Similarly, instead of g(b), you want the last element of g, which is given by g(length(g)) or g(end). If this doesn't make sense, I'd suggest looking at a basic MATLAB tutorial to get a handle on how vectors and functions are used.