What is wrong with this matlab function code? - matlab

I am not sure why this code wouldn't run. PLEASE HELP
function y = PdfMixUnfmBeta(x,alpha)
if x < 0
y = (1-alpha).*1/2;
elseif x >= 0
y = (1-alpha).*1/2 + alpha.*6*x*(1-x);
end;
when I execute this function as follows, there is an error
EDU>> x=-1:0.01:1;
EDU>> a=PdfMixUnfmBeta(x,0.4)
Error in PdfMixUnfmBeta (line 2)
if x < 0

The problem with your function is that you have written it assuming that x is a single value, and then you have passed it a vector. Your code cannot cope with this.
If you try to run your code with a single value, eg: a=PdfMixUnfmBeta(15,0.4) your function should run.
Lets look at what is actually wrong with your code, when I tried running your code I was given the following error:
Output argument "y" (and maybe others) not assigned during call
This indicates that the lines which assign to y are never actually executed. This indicates that neither of the conditional statements (x < 0 and x >= 0) ever evaluate as true. The if statements expects a scalar logical value, but in your example it is provided with a vector of logical.
So, to fix this you either need to deal with your x values one at a time by wrapping it in a for loop, e.g.:
function y = PdfMixUnfmBeta(x_vec, alpha)
for x = x_vec
%do your function here
end
end
Alternatively, you can vectorize your code, which is by far the preferable solution:
y = zeros(1,length(x));
% where x is < 0 use this formula
y(x < 0) = (1-alpha) .*(1/2);
% where x is >= 0 use this formula instead.
y(x >= 0) = (1-alpha) .* (1/2) + (alpha .* 6 .* x .* (1-x));
In the above solution I use logical indexing and change some of the * to .*. You may find it useful to look up the difference between * and .* and to read up on vectorization.

Related

Plotting the Impulsefunction

so I'm new to Matlab and had to draw the Impulsefunction with y(n) is only 1 if n == 3, else 0. The following code works:
n = -5:5;
f = n; % allocate f
for i = 1 : length(n)
f(i) = dd1(n(i)-3);
end
stem(n, f);
function y = dd1(n)
y = 0;
if n == 0
y = 1;
end
end
But I feel like it's to complicated, so I tried the following:
n = -5:5
stem(n, fo)
function y = fo(n)
y = 0
if n == 3
y=1
end
end
This returns
Not enough input arguments.
Error in alternative>fo (line 5)
if n == 3
Error in alternative (line 2)
stem(n, fo)
I feel like I'm missing something trivial here.
if is no vector-wise operation but expects a single boolean (or at least a scalar that it can cast to a boolean).
But you can do this vector-wise:
lg = n == 3;
This produces a logical (MATLAB's name for boolean) array (because n is an array and not a vector), which is true where n is equal (==) to three. So you don't need a function, because you can make use of MATLAB's ability to work with vectors and arrays implicitly.
(for your code it would be f = (n-3) == 3)
A last hint: if you have a state-space system (ss-object), you can use the function step to get the step-response as a plot.

MATLAB - Secant method produces NaN

I'm writing a secant method in MATLAB, which I want to iterate through exactly n times.
function y = secantmeth(f,xn_2,xn_1,n)
xn = (xn_2*f(xn_1) - xn_1*f(xn_2))/(f(xn_1) - f(xn_2));
k = 0;
while (k < n)
k = k + 1;
xn_2 = xn_1;
xn_1 = xn;
xn = (xn_2*f(xn_1) - xn_1*f(xn_2))/(f(xn_1) - f(xn_2));
end
y = xn;
end
I believe the method works for small values of n, but even something like n = 9 produces NaN. My guess is that the quantity f(xn_1) - f(xn_2) is approximately zero, which causes this error. How can I prevent this?
Examples:
Input 1
eqn = #(x)(x^2 + x -9)
secantmeth(eqn,2,3,5)
Input 2
eqn = #(x)(x^2 + x - 9)
secantmeth(eqn, 2, 3, 9)
Output 1
2.7321
Output 2
NaN
The value for xn will be NaN when xn_2 and xn_1 are exactly equal, which results in a 0/0 condition. You need to have an additional check in your while loop condition to see if xn_1 and x_n are equal (or, better yet, within some small tolerance of one another), thus suggesting that the loop has converged on a solution and can't iterate any further:
...
while (k < n) && (xn_1 ~= xn)
k = k + 1;
xn_2 = xn_1;
xn_1 = xn;
xn = (xn_2*f(xn_1) - xn_1*f(xn_2))/(f(xn_1) - f(xn_2));
end
...
As Ander mentions in a comment, you could then continue with a different method after your while loop if you want to try and get a more accurate approximation:
...
if (xn_1 == xn) % Previous loop couldn't iterate any further
% Try some new method
end
...
And again, I would suggest reading through this question to understand some of the pitfalls of floating-point comparison (i.e. == and ~= aren't usually the best operators to use for floating-point numbers).

How to convert logical conditions to a variable of a function

I would like to achieve the above for the following:
Rn = 0.009; % Resolution of simulation (in m^3)
Xs = -1 : Rn : 1;
Ys = -1 : Rn : 1;
Zs = 0 : Rn : 1;
[X Y Z] = meshgrid(Xs, Ys, Zs);
alpha = atan2(Z,X);
ze = x.^2 + y.^2; % define some condition
m = 0.59; % manual input
cond = (pi/3 <= alpha) & ...
(alpha <= (2*pi/3)) & ...
(m <= Z) & ...
(Z <= ze); % more conditions
xl = nnz(cond); % the number of non-zero elements
f = abs(xl*1000 - 90) % guessing m to get f as low as possible
How do I turn m into a variable for some f function so I can call fminsearch to quickly find the corresponding m for f ≈ 0?
In order to use m as a variable, you need to define a function handle. So you need to write:
cond = #(m) ((pi/3) <= alpha) & (alpha <= (2*pi/3)) & (m <= Z) & (Z <= ze);
However, you cannot use a function handle in the nnz routine, since it only accepts matrices as inputs. But, the solution to the problem is that you only have Boolean variables in cond. This means, you can simply sum over cond and get the same result as with nnz.
The only issue I see is how to implement the sum in fminsearch. Unfortunately, I do not have access to fminsearch, however I would assume that you can do something with reshape and then multiply with dot (i.e. .*) with the unity vector to get a sum. But you'll have to try that one out, not sure about it.

MATLAB - Condition to do something only once every x number of loops

I am trying to change the value of z by +1 every 750th, 1500th, 2250th,...,etc loop and this is what I have written:
len = 1500000;
y = 750;
z = 1;
for i = 1:len
if (i == [y.*(1:2000)])
z = z + 1;
end
end
Why is the value of z not changing? Can someone tell me what's wrong with my if statement please?
MATLAB only considers an array to be true if all elements are true. So with that in mind, if we look at your conditional for your if statement
i == (y .* (1:2000))
What this returns is an array of 2000 values where they are either all false (in the case where i isn't a multiple of y) and all false except for one true value when it is. Even when there is one true, this still evaluates to false and your if statement will never be evaluated.
A better way to do this is to use mod to check if a given i is a multiple of y
if mod(i, y) == 0
z = z + 1;
end
However, if the only contents of your loop are what you have shown, then you can simply omit the iterations that you don't care about
for i = y:y:len
z = z + 1;
end
If you actually do want to compare the array as you showed though, you'd be best to compute y .* 1:2000 outside of the loop and then use ismember to see if i is in the array
tmp = y .* (1:2000);
for i = 1:len
if ismember(i, tmp)
z = z + 1;
end
end

Plotting own function in scilab

Hey i have an issuse with plotting my own function in scilab.
I want to plot the following function
function f = test(n)
if n < 0 then
f(n) = 0;
elseif n <= 1 & n >= 0 then
f(n) = sin((%pi * n)/2);
else
f(n) = 1;
end
endfunction
followed by the the console command
x = [-2:0.1:2];
plot(x, test(x));
i loaded the function and get the following error
!--error 21
Invalid Index.
at line 7 of function lala called by :
plot(x, test(x))
Can you please tell me how i can fix this
So i now did it with a for loop. I don't think it is the best solution but i can't get the other ones running atm...
function f = test(n)
f = zeros(size(n));
t = length(n);
for i = 1:t
if n(i) < 0 then
f(i) = 0;
elseif n(i) <= 1 & n(i) >= 0
f(i) = sin((%pi * n(i)/2));
elseif n(i) > 1 then
f(i) = 1;
end
end
endfunction
I guess i need to find a source about this issue and get used with the features and perks matlab/scilab have to over :)
Thanks for the help tho
The original sin is
function f = test(n)
(...)
f(n) = (...)
(...)
endfunction
f is supposed to be the result of the function. Therefore, f(n) is not "the value that the function test takes on argument n", but "the n-th element of f". Scilab then handles this however it can; on your test case, it tries to access a non-integer index, which results in an error. Your loop solution solves the problem.
Replacing all three f(n) by f in your first formulation makes it into something that works... as long as the argument is a scalar (not an array).
If you want test to be able to accept vector arguments without making a loop, the problem is that n < 0 is a vector of the same size as n. My solution would use logical arrays for indexing each of the three conditions:
function f = test(n)
f = zeros(size(n));
negative = (n<0);//parentheses are optional, but I like them for readability
greater_than_1 = (n>1);
others = ~negative & ~greater_than_1;
f(isnegative)=0;
f(greater_than_1)=1;
f(others) = sin(%pi/2*n(others));
endfunction