Plotting own function in scilab - matlab

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

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.

Fibonacci function not accepting 0 and not displaying the last term only

I wrote a function that displays the Fibonacci sequence up to the nth term. The code runs fine, but I want to make two changes and am not sure how to do so.
Here is my code:
function [ F ] = get_fib( k )
F(1) = 1;
F(2) = 1;
i = 3;
while k >= i;
F(i) = F(i-1) + F(i-2);
i = i + 1;
end
end
The first problem is that the code does not accept 0 as an input. I tried changing the function to:
function [ F ] = get_fib( k )
F(0) = 0;
F(1) = 1;
F(2) = 1;
i = 3;
while k >= i;
F(i) = F(i-1) + F(i-2);
i = i + 1;
end
end
But the following error appears:
Attempted to access F(0); index must be a positive integer or logical.
Error in get_fib (line 2)
F(0) = 0;
I would also like the code to display the last term in the sequence, rather than the entire sequence.
I changed the function to:
function [ F ] = get_fib( k );
F(1) = 1;
F(2) = 1;
i = 3;
while k >= i;
F(i) = F(i-1) + F(i-2);
i = i + 1;
end
term = F(k)
end
but the sequence it still being assigned to ans.
How can I make my function accept 0 as an argument and only display the last term of the sequence?
First let's get your function to output just the last item in the sequence. You're setting term like this:
term = F(k);
Which is good (notice I added the ; at the end, though). But the return value from your function is F. You need to change it to term.
function [ term ] = get_fib( k )
%// ^^^^- change this ^-- semicolon not necessary here
Now, to handle an input of 0, you can add a special check for zero:
function [ term ] = get_fib( k )
if k == 0
term = [];
return;
end
while k >= i
%// ^-- semicolon not needed here, either
<the rest of your code>
The semicolons after the function header and the while statement don't hurt anything, they just represent empty statements. But they might be misleading, so it's best to remove them.
The semicolon after the assignment to term prevents the ans = ... line from printing out to the console.
To address your first problem, F(0) is not a valid call. This is because MATLAB indexing starts from 1. In other words, the first element of a matrix is index 1. There is no 0th index of a matrix in MATLAB. See here for why MATLAB indexing starts from 1. What I would recommend to address this is to shift your output array by one index.
Thus, your code for the function should be:
function [ F ] = get_fib( k )
k = k + 1
F(1) = 0; % 0th Fibonacci term
F(2) = 1; % 1st Fibonacci term
F(3) = 1; % 2nd Fibonacci term
i = 4;
while k >= i
F(i) = F(i-1) + F(i-2);
i = i + 1;
end
term = F(k)
end
To address your second problem, it would depend on what you want. Do you (1) want the last term in the sequence to be returned when you call term = get_fib(k)or (2) want the last term of the sequence to be displayed and the entire sequence to be returned?
To achieve (1), fix the top line of your code to function term = F(k). To achieve (2), call the function with F = get_fib(some_number), as #rayryeng stated.
Since others already pointed out how to fix your code, I'd like to show you one approach to calculate the nth Fibonacci number without relying on the F(n-1) and F(n-2) terms calculation.
It involves the golden ratio, and you can read more about its relationship to the Fibonacci sequence here.
function [ F ] = get_fib( n )
% Changed your input variable from k to n (standard notation)
Phi = (1+sqrt(5))/2; % Golden ratio value
F = round((Phi^n - ((-1)^n)/(Phi^n))/sqrt(5)); %nth fibonacci number
end
Since you are only interested in the last value of the sequence, it could speed up the calculation for large values of n.
Note i have rounded the output (F) to avoid floating point arithmetic errors.

vectorizing function in octave / matlab

I have a function that I was wondering if it was possible to vectorize it and not have to use a for loop. The code is below.
a=1:2:8
for jj=1:length(a)
b(jj)=rtfib(a(jj)); %fibbonacci function
end
b
output below:
a =
1 3 5 7
>>>b =
1 3 8 21
I was trying to do it this way
t = 0:.01:10;
y = sin(t);
but doing the code below doesn't work any suggestions?
ps: I'm trying to keep the function rtfib because of it's speed and I need to use very large Fibonacci numbers. I'm using octave 3.8.1
a=1:2:8
b=rtfib(a)
Here's the rtfib code below as requested
function f = rtfib(n)
if (n == 0)
f = 0;
elseif (n==1)
f=1;
elseif (n == 2)
f = 2;
else
fOld = 2;
fOlder = 1;
for i = 3 : n
f = fOld + fOlder;
fOlder = fOld;
fOld = f;
end
end
end
You can see that your function rtfib actually computes every Fibonacci number up to n.
You can modify it so that is stores and returns all these number, so that you only have to call the function once with the maximum number you need:
function f = rtfib(n)
f=zeros(1,n+1);
if (n >= 0)
f(1) = 0;
end
if (n>=1)
f(2)=1;
end
if (n >= 2)
f(3) = 2;
end
if n>2
fOld = 2;
fOlder = 1;
for i = 3 : n
f(i+1) = fOld + fOlder;
fOlder = fOld;
fOld = f(i+1);
end
end
end
(It will return fibonnaci(n) in f(n+1), if you don't need the 0 you could change it so that it returns fibonnaci(n) in f(n) if you prefer)
Then you only need to call
>>f=rtfib(max(a));
>>b=f(a+1)
b =
1 3 8 21
If you don't want to store everything you could modify the function rtfib a little more, so that it takes the the array a as input, compute the Fibonacci numbers up to max(a) but only stores the one needed, and it would directly return b.
Both solutions will slow down rtfib itself but it will be a lot faster than calculating the Fibonacci numbers from 0 each time.

MATLAB: Unit step function

For some reason when I try to create a simple unit step function I just receive a straight line. I am pretty sure this is correct, but my graph tells me otherwise. Is there something I am doing wrong?
function mone=myOne(t)
[n,~] = size(t);
mone=zeros(n,1);
for i=1:n,
if (t(i)>0),
mone(i) = 1;
end
end
in the command window I type,
t = [-5:0.01:5]
plot(t, myOne(t))
The error is your line:
[n,~] = size(t);
You only query the first dimension of t, which is 1 following
t = [-5:0.01:5]
size(t)
ans =
1 1001
You can either transpose t
t = [-5:0.01:5].';
size(t)
ans =
1001 1
or you length instead of size.
n = length(t);
Finally, a solution without the loop as proposed by #Dan is much faster.
I can't see anything wrong with the logic behind your function but your implementation is very long winded. In Matlab you can just do this:
function mone=myOne(t)
mone = t > 0;
end
or if you want to get a matrix of numbers and not logicals returned try
function mone=myOne(t)
mone = (t > 0)*1; %// Or if you prefer to cast explicitly:
%// double(t>0)
end
Also to add a shift parameter with default set to zero:
function mone=myOne(t, T)
if nargin < 2
T = 0;
end
mone = (t > T)*1;
end
usage:
t = [-5:0.01:5]
plot(t, myOne(t))
plot(t, myOne(t,3))

optimizing nested for loop in matlab

I'm trying to optimize the performance (e.g. speed) of my code. I 'm new to vectorization and tried myself to vectorize, but unsucessful ( also try bxsfun, parfor, some kind of vectorization, etc ). Can anyone help me optimize this code, and a short description of how to do this?
% for simplify, create dummy data
Z = rand(250,1)
z1 = rand(100,100)
z2 = rand(100,100)
%update missing param on the last updated, thanks #Bas Swinckels and #Daniel R
j = 2;
n = length(Z);
h = 0.4;
tic
[K1, K2] = size(z1);
result = zeros(K1,K2);
for l = 1 : K1
for m = 1: K2
result(l,m) = sum(K_h(h, z1(l,m), Z(j+1:n)).*K_h(h, z2(l,m), Z(1:n-j)));
end
end
result = result ./ (n-j);
toc
The K_h.m function is the boundary kernel and defined as (x is scalar and y can be vector)
function res = K_h(h, x,y)
res = 0;
if ( x >= 0 & x < h)
denominator = integral(#kernelFunc,-x./h,1);
res = 1./h.*kernelFunc((x-y)/h)/denominator;
elseif (x>=h & x <= 1-h)
res = 1./h*kernelFunc((x-y)/h);
elseif (x > 1 - h & x <= 1)
denominator = integral(#kernelFunc,-1,(1-x)./h);
res = 1./h.*kernelFunc((x-y)/h)/denominator;
else
fprintf('x is out of [0,1]');
return;
end
end
It takes a long time to obtain the results: \Elapsed time is 13.616413 seconds.
Thank you. Any comments are welcome.
P/S: Sorry for my lack of English
Some observations: it seems that Z(j+1:n)) and Z(1:n-j) are constant inside the loop, so do the indexing operation before the loop. Next, it seems that the loop is really simple, every result(l, m) depends on z1(l, m) and z2(l, m). This is an ideal case for the use of arrayfun. A solution might look something like this (untested):
tic
% do constant stuff outside of the loop
Zhigh = Z(j+1:n);
Zlow = Z(1:n-j);
result = arrayfun(#(zz1, zz2) sum(K_h(h, zz1, Zhigh).*K_h(h, zz2, Zlow)), z1, z2)
result = result ./ (n-j);
toc
I am not sure if this will be a lot faster, since I guess the running time will not be dominated by the for-loops, but by all the work done inside the K_h function.