Fibonacci function in matlab / octave - matlab

Help with Fibonacci function in octave / matlab.
The Fibonacci pattern is http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibtable.html
0 : 0
1 : 1
2 : 1
3 : 2
4 : 3
5 : 5
The function I have works but it skips a one how can I fix this so the function correctly follows the list above? Below is what my function creates.
0 : 0
1 : 1
2 : 2
3 : 3
4 : 5
5 : 8
See function below
function f = rtfib(n)
if n<0
multi=-1; %if neg number store neg in multi variable
n=abs(n); %if neg make pos
else
multi=1;
end
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
f=f*multi; %put sign back
end
Ps: I'm using octave 4.0 which is similar to matlab
Original code found from
Create faster Fibonacci function for n > 100 in MATLAB / octave

The function you provided assumes the 3rd item of the 0-starting Fibonacci sequence is 2, and that is wrong. Just change that.
function f = rtfib(n)
if n<0
multi=-1; %if neg number store neg in multi variable
n=abs(n); %if neg make pos
else
multi=1;
end
if (n == 0)
f = 0;
elseif (n==1)
f=1;
elseif (n == 2)
f = 1; % its 1
else
fOld = 1; % 1 again.
fOlder = 1;
for i = 3 : n
f = fOld + fOlder;
fOlder = fOld;
fOld = f;
end
end
f=f*multi; %put sign back
end
Now it works:
for ii=0:15
r(ii+1)=rtfib(ii);
end
disp(r)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610

Related

Applying an equation to specific rows of an array and concatenating the answers to an array

% Example
array = [1 2 3 4 5 6 0 0 0];
for i = 1:length(array)
if i(1) ~= 0
array_mag_1 = sqrt(array(1)^2 + array(2)^2 + array(3)^2);
if exist('array_mag_1','var') == 1
new_array = array_mag_1;
end
elseif i(4) ~= 0
array_mag_2 = sqrt(array(4)^2 + array(5)^2 + array(6)^2);
if exist('array_mag_2', 'val') == 1
new_array = cat(array_mag_1, array_mag_2);
end
elseif i(7) ~= 0
array_mag_3 = sqrt(array(7)^2 + array(8)^2 + array(9)^2);
if exist('array_mag_3', 'val') == 1
new_array = cat(array_mag_1, array_mag_2, array_mag_3);
end
end
end
for j = 1:length(new_array)
if j > 0
cat_new_array = new_array(j);
else
return
end
end
Whats the best way to take sets of 3 elements (if it's a nonzero), find the magnitude, and concatenate that to 'cat_new_array', then skip the remaining zeros? I'm also finding that it keeps the first 'array_mag_1' even though it has nonzero values in array(4). I'm new to coding, so I apologize for any confusion. Any help is appreciated.
Try this:
array = [1 2 3 4 5 6 8 9 7 0 0]
array_non_zero = find(array);
cat_new_array = [];
for i=1:floor(numel(array_non_zero)/3)
cat_new_array = [cat_new_array, norm(array(array_non_zero((i-1)*3+1:i*3)))]
end
This code takes the non zero elements from array 3 by 3 and calculates the norm of each set of 3 elements. I didn't get clear from your question if that's what you need.
Use the built-in functions vecnorm to calculate the vector norm of each row of the array and the nonzeros function to get only the nonzero values.
A = [1 2 3;4 5 6;0 0 0;7 8 9;0 0 0];
cat_new_array = nonzeros(vecnorm(A,2,2))
> cat_new_array =
> 3.7417
> 8.7750
> 13.9284

Function to accept a matrix as input and goes element by element using for-loops adding one to each of the elements

I have created a function to add one to an element as follows;
function xz = addOne(x)
nrow = size(x,1);
ncol = size(x,1);
for K = 1:nrow
for J = 1:ncol
xz = x(:) + 1;
end
end
Example: given 1 the function results in 2:
addOne(1) [2]
I have tried using a matrix as an argument for the function...
x = [1 2 3; 0 0 0; 4 5 6];
x =
1 2 3
0 0 0
4 5 6
addOneWithFors(x)
ans =
2
1
5
3
1
6
4
1
7
How would I update this function to accept a matrix with multiple rows and columns and output it as such instead of just 1 number or a list of elements. Any help would be greatly appreciated.
In Matlab, you don't need a special function to do this. Matlab natively supports adding a scalar to a matrix. For example:
x = [1 2 3; 0 0 0; 4 5 6];
y = x + 1
will produce:
y =
2 3 4
1 1 1
5 6 7
However, if you specifically want to write this out explicitly using for loops, then your addOne() function only needs minor modifications. For example:
function xz = addOne(x)
nrow = size(x,1);
ncol = size(x,2);
xz = zeros(nrow,ncol);
for K = 1:nrow
for J = 1:ncol
xz(K,J) = x(K,J) + 1;
end
end
Note that ncol = size(x,2); has been defined correctly.

Dynamic window forming in efficient way in MATLAB

Can someone help me to provide an efficient way or help me to perform the provide code to do make same results in minimal possible steps. I shall be grateful to you.
I have an Original Array:
A = [1 1 1 4.3 4.5 4 4.3 3 1 0 0 2 6.2 6.3 6 6.2 7.4 8 7.2 2 2 3 3 2];
Output Looks like:
A = [1 1 1 4 4 4 4 3 1 0 0 2 6 6 6 6 6 7 7 2 2 3 3 2];
I apply some restrictions and removed some values from array of local maxima’s after that I received some new arrays.
Yposlocfiltered = [6 15 23];
idx = [4 6 3];
Yneglocfiltered = [2 9 20];
idx_neg = [1 1 2];
Where I will find idx(local maxima value) I will check if values behind and ahead are greater make a window.
Example
If I will find 4 and 4.5, 4.3 is greater than 4 include it in backward window
4.3 is greater than 4 include it in forward window.
I need to find range of values behind local maxima and ahead local maxima.
I have tried to write a code that’s works fine but issue is that it’s too long.
Can someone please provide me an idea to perform this action in minimal steps and in faster ways?
I have only provided code for positive local maxima’s as for negative local maxima code Is just replica of this.
Code:only for positive local maximas
clc
clear all
A = [1 0 1 4.3 4.5 5 4.3 3 0 0 0 2 6.2 6.3 7 6.2 7.4 8 7.2 1 2 3 4 2];
Yposlocfiltered = [ 6 15 23];
idx = [4 6 3];
Yneglocfiltered = [2 9 20];
idx_neg = [1 1 2];
for b = 1: numel(idx)
for c = 1:numel(A)
f = Yposlocfiltered(1,b)-c ;
g = Yposlocfiltered(1,b)+c ;
% if (f > 0 && g <= numel(X))
if(f > 0)
if (A(Yposlocfiltered(1,b)-c))> idx(1,b)
else
d= f+1;
z(b)= d;
backward_window = z;
break
end
end
end
end
for r = 1: numel(idx)
for s = 1:numel(A)
u = Yposlocfiltered(1,r)-s ;
v = Yposlocfiltered(1,r)+s ;
% if (f > 0 && g <= numel(X))
if(v <=numel(A))
if (A(Yposlocfiltered(1,r)+s))> idx(1,r)
else
w= v-1;
y(r)= w;
forward_window = y;
break
end
end
end
end
n=4
for i=1:length(backward_window)
range = backward_window(i): forward_window(i);
p = range
if n <= numel(p)
p = range(1:n)
A( p) = idx(i);
else
% if (size(range)<= 3)
A( p) = idx(i);
end
end
From the first look at your code, I believe you can combine your first two for loops into one.
sA = numel(A);
sI = numel(idx);
for i = 1:sI
f = Yposlocfiltered(i) - [1:sA];
g = Yposlocfiltered(i) + [1:sA];
f(f<1) = [];
g(g>sA) = [];
backward_window(i) = f(find(A(f) <= idx(i), 1)) + 1;
forward_window(i) = g(find(A(g) <= idx(i), 1)) - 1;
end
Here, you can use find to locate the element of an array matching the specified condition, i.e. g <= numel(X) or A(f) <= idx(i).
Your last loop which modifies A can also be integrated into the same loop, so you can have:
sA = numel(A);
sI = numel(idx);
n=4;
for i = 1:sI
f = Yposlocfiltered(i) - [1:sA];
g = Yposlocfiltered(i) + [1:sA];
f(f<1) = [];
g(g>sA) = [];
backward_window(i) = f(find(A(f) <= idx(i), 1)) + 1;
forward_window(i) = g(find(A(g) <= idx(i), 1)) - 1;
range = backward_window(i) : forward_window(i);
if n <= numel(range)
A(range(1:n)) = idx(i);
else
A(range) = idx(i);
end
end

Efficient Multiplication of Matrices with Large Numbers of Zeroes

I have two arrays that take the following form:
0…0…0 0 0 0…0 0…0…0 0 0 0…0
⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮
0…0 0 0 0 0…0 0…0 0 0 0 0…0
A = 0…0 1 2 3 0…0 B = 0…0 9 8 7 0…0
0…0 4 5 6 0…0 0…0 6 5 4 0…0
0…0 0 0 0 0…0 0…0 0 0 0 0…0
⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮
0…0…0 0 0 0…0 0…0…0 0 0 0…0
The size of the non-zero areas of A and B may not be exactly the same, but the diagram above is already getting a bit unwieldy.
Ultimately, the value I'm after is sum(sum(A .* B)). I feel like there must be a way to only multiply the non-zero elements, but every approach I can come up with seems to cause MATLAB to make a copy of the matrix, which utterly destroys any gains made by reducing the number of operations. B is reused for several iterations of the inner loop, so I can amortize expensive calculations on B over many loop iterations.
I've tried the following approaches so far:
Naive Approach:
function C = innerLoop(A, B)
C = sum(sum(A .* B))
end
innerLoop takes about 4.3 seconds over 86,000 calls using this. (Based on MATLAB's "Run and Time" functionality.)
Shrinking B First:
function B = resize(self, B1)
rows = abs(sum(B, 2)) > 1e-4;
top = find(rows, 1, 'first');
bot = find(rows, 1, 'last');
cols = abs(sum(B, 1)) > 1e-4;
left = find(cols, 1, 'first');
right = find(cols, 1, 'last');
self.Rows = top:bot; % Store in class properties for use in inner loop
self.Cols = left:right; % Store in class properties for use in inner loop
B = B(top:bot, left:right);
end
function C = innerLoop(A, B)
result = A(self.Rows, self.Cols) .* B;
C = sum(sum(result));
end
My hope with this approach was that MATLAB would realize that I wasn't writing to A and elide the copy, but this approach spends about 6.8 seconds in innerLoop.
I also tried only calculation the offsets outside innerLoop in the hopes that MATLAB might be able to pick up on the fact that I'm using the same subscripts on both matrices to optimize things:
function B = resize(self, B1)
rows = abs(sum(B, 2)) > 1e-4;
top = find(rows, 1, 'first');
bot = find(rows, 1, 'last');
cols = abs(sum(B, 1)) > 1e-4;
left = find(cols, 1, 'first');
right = find(cols, 1, 'last');
self.Rows = top:bot; % Store in class properties for use in inner loop
self.Cols = left:right; % Store in class properties for use in inner loop
end
function C = innerLoop(A, B)
result = A(self.Rows, self.Cols) .* B(self.Rows, self.Cols);
C = sum(sum(result));
end
Unfortunately this was the slowest yet at about 8.6 seconds.
I also tried looping with the following code:
function C = innerLoop(A, B)
C = 0;
for i = self.Rows
for j = self.Cols
C = C + field(i, j) * self.Sensitivity.Z(i, j);
end
end
end
I know that looping used to be very slow in MATLAB, but I've read some papers indicating that it is much faster than it used to be. That said, if the loop version ever finishes running, I'll let you know how long it took, but it's well over a couple minutes by now.
Any suggestions on how to optimize this would be greatly appreciated!
You can use sparse matrices for this problem. Matlab handles different sizes of the «non-sparse-part» automatically. To get a sparse matrix, the sparse-function is used. After that you can do the element-wise multiplication and then sum all elements of C in a separate line.
A = [0 0 0 0 0 0 0;
0 0 0 0 0 0 0;
0 0 1 2 3 0 0;
0 0 4 5 6 0 0;
0 0 0 0 0 0 0;
0 0 0 0 0 0 0];
B = [0 0 0 0 0 0 0;
0 0 0 0 0 0 0;
0 0 9 8 7 0 0;
0 0 6 5 4 0 0;
0 0 0 0 0 0 0;
0 0 0 0 0 0 0];
A = sparse(A);
B = sparse(B);
C = A .* B;
sum(C(:))
This is a rewrite of my initial post
I stand corrected. I don't know what went wrong in my former test. I thought it may have been a 32 vs 64 bit implementation of the sparse algorithm but not even. After careful re-running of the benchmark on 2 different machines, the sparse method wins then all.
Benchmark code:
function ExecTimes = bench_sum_sparse
nOrder = (1:9).' * 10.^(2:3) ; nOrder = [nOrder(:) ; (1:2).'*1e4] ;
%// nOrder = (1:30)*100 ;
npt = numel(nOrder) ;
ExecTimes = zeros( npt , 3 ) ;
fprintf('\n%s%5d \n','Calculating for N = ',0) ;
for k = 1:npt
% // sample data
N = nOrder(k) ;
fprintf('\b\b\b\b\b\b%5d\n',N) ; % // display progress
A = zeros(N) ;
B = A ;
innerMat = (1:10).'*(1:10) ; %'
ixInnerMat = innerMat + N/2 - 5 ;
A(ixInnerMat) = innerMat ;
B(ixInnerMat) = innerMat ;
% // benchmark
f1 = #() innerLoop(A,B) ;
ExecTimes(k,1) = timeit( f1 ) ;
clear f1
f2 = #() sum_logicIndex(A, B) ;
ExecTimes(k,2) = timeit( f2 ) ;
clear f2
A = sparse(A);
B = sparse(B);
f3 = #() sum_sparse(A,B) ;
ExecTimes(k,3) = timeit( f3 ) ;
clear f3
%// checksum1 = f1() - f2 ()
%// checksum2 = f1() - f3 ()
end
end
function C = innerLoop(A, B)
C = sum(sum(A .* B)) ;
end
function C = sum_logicIndex(A,B)
idx = A>0 & B>0 ;
C = sum(sum(A(idx).*B(idx))) ;
end
function C = sum_sparse(A,B)
C = A .* B;
C = sum(C(:)) ;
end
All tests ran on Matlab 2013b
64 bit Machine : Intel I7-3820 # 3.6GHz - 16 GB RAM - Windows 7
32 bit Machine : Intel E2200 # 2.2GHz - 3GB RAM - Windows 8.1

matlab - find all possible vectors satisfying irregular constraints

In Matlab, I need to find all possible combinations of a vector that satisfies some constraints that I find quite irregular.
The vector, x, has 12 entries: x_0,x_1,...,x_11
Local constraints:
x_0 in {1,...,6}
x_i in {0,...,6}, i = 1,...,6
x_j in {0,...,12-j}, j = 7,...,11
Global constraints:
sum(x) = 12
for any k, x_k = y ==> x_{k+j} = 0 for j = 1,...,y-1
I have thought about this for quite a while now and can't seem to solve it myself - any ideas anyone?
Use recursion and intermediate constraint checking. Something like this does the trick:
function dispConstraintSatisfyingVectors()
global lb ub sumVal
lb = [1 0 0 0 0 0 0 0 0 0 0 0];
ub = [6 6 6 6 6 6 6 5 4 3 2 1];
sumVal = 12;
x = zeros(1,12);
addValueRecursive(x,1);
end
function addValueRecursive(x,idx)
global lb ub sumVal
for val = lb(idx):ub(idx)
x(idx) = val;
if checkZerosConstraint(x) == 0 && sum(x) <= sumVal
if idx < 12
addValueRecursive(x,idx+1);
else
if sum(x) == sumVal
disp(num2str(x))
end
end
end
end
end
function c = checkZerosConstraint(x)
c = 0;
for j=1:11
c = c + sum(x(j+1:j+x(j)-1));
end
end