Splitting a series in two with zeros and the series value - matlab

I have the following in table in matlab
k ak
0 1
1 -0.166666667
2 0.008333333
... ...
where ak = (-1)^k/(2k+1)! but that's not really important, all that is important is that ak is a function of k and the (-1)^k.
I am trying to generate a new set of columns as below
i ai
0 1
1 0
2 -0.166666667
3 0
4 0.008333333
... ...
So far I've figured out that by stretching my indices (incrementing by 2 instead of 1) and applying the ak function it gets pretty close to what I want but it returns the absolute value.
if mod(i,2)=0
ai=(-1)^i/factorial(2*(i/2)+1);
else
ai=0;
end
How can I change this to be what I want?

You should be using this:
ai = (-1)^(ii/2)/factorial(2*(ii/2)+1);
% Notice ----^
Your if-else statements can be given a vector input and written in one-line as:
ai = ~mod(ii,2) .* (-1).^(ii/2)./factorial(2*(ii/2)+1);
%I used ii instead of i since i is for imaginary numbers in MATLAB

Related

How to create an Octave function that evaluate the sum of pairs of numbers in the vector?

It's like a reverse version of Pascal's triangle.
I want to create a vector-input function named
y = lastnum(vect) on Octave, that evaluate the sum of each pair of numbers in any vectors to output the single number from the evaluation loops like this
0 1 2 3 4
1 3 5 7
4 8 12
12 20
32
And the input and output would be like this,
lastnum([0 1 2 3 4])
ans = 32
I mean... is there any progresses that I can do??? You may not understand but, the reverse triangle above can guide you about my question.
I also tagged MATLAB since it has similar language. MATLAB pros may help my problem.
Notice that the number of times each element gets added to produce the final result comes from Pascals triangle itself, so, e.g., for the vector [a b c d] the result will be a+3b+3c+d. So create a vector of entries in Pascals triangle and multiply and add with the original vector v.
I only have access to Matlab, Octave may not have all these functions.
This is a one-liner diag(fliplr(pascal(numel(v)))).'*v(:).
Or a looping version
s = 0;
for i = 0:numel(v)-1
s = s+nchoosek(numel(v)-1,i)*v(i+1);
end
s
Simplest thing I can think of is:
while length(x) > 0
disp(x)
x = x(1:end-1) + x(2:end);
end
or did I misunderstand the question?
Here is the version for both MATLAB and Octave:
function y = lastnum(v)
while 1
if length(v) == 2
y = sum(v)
break;
end
# disp(v); # if you want to print the progress
vt = [];
for k = 1:(length(v)-1)
vt(end+1) = sum(v(k:(k+1)));
end
v = vt;
end
end

Output a matrix size n x m, 1 when the sum of the indices is even, 0 otherwise

I'm attempting the following as a hobby, not as homework. In Computer Programming with MATLAB: J. Michael Fitpatrick and Akos Ledeczi, there is a practice problem that asks this:
Write a function called alternate that takes two positive integers, n and m, as input arguments (the function does not have to check the format of the input) and returns one matrix as an output argument. Each element of the n-by-m output matrix for which the sum of its indices is even is 1.
All other elements are zero.
A previous problem was similar, and I wrote a very simple function that does what it asks:
function A = alternate(n,m)
A(1:n,1:m)=0;
A(2:2:n,2:2:m)=1;
A(1:2:n,1:2:m)=1;
end
Now my question is, is that good enough? It outputs exactly what it asks for, but it's not checking for the sum. So far we haven't discussed nested if statements or anything of that sort, we just started going over very basic functions. I feel like giving it more functionality would allow it to be recycled better for future use.
Great to see you're learning, step 1 in learning any programming language should be to ensure you always add relevant comments! This helps you, and anyone reading your code. So the first improvement would be this:
function A = alternate(n,m)
% Function to return an n*m matrix, which is 1 when the sum of the indices is even
A(1:n,1:m)=0; % Create the n*m array of zeros
A(2:2:n,2:2:m)=1; % All elements with even row and col indices: even+even=even
A(1:2:n,1:2:m)=1; % All elements with odd row and col indicies: odd+odd=even
end
You can, however, make this more concise (discounting comments), and perhaps more clearly relate to the brief:
function A = alternate(n,m)
% Function to return an n*m matrix, which is 1 when the sum of the indices is even
% Sum of row and col indices. Uses implicit expansion (R2016b+) to form
% a matrix from a row and column array
idx = (1:n).' + (1:m);
% We want 1 when x is even, 0 when odd. mod(x,2) is the opposite, so 1-mod(x,2) works:
A = 1 - mod( idx, 2 );
end
Both functions do the same thing, and it's personal preference (and performance related for large problems) which you should use.
I'd argue that, even without comments, the alternative I've written more clearly does what it says on the tin. You don't have to know the brief to understand you're looking for the even index sums, since I've done the sum and tested if even. Your code requires interpretation.
It can also be written as a one-liner, whereas the indexing approach can't be (as you've done it).
A = 1 - mod( (1:n).' + (1:m), 2 ); % 1 when row + column index is even
Your function works fine and output the desired result, let me propose you an alternative:
function A = alternate(n,m)
A = zeros( n , m ) ; % pre-allocate result (all elements at 0)
[x,y] = meshgrid(1:m,1:n) ; % define a grid of indices
A(mod(x+y,2)==0) = 1 ; % modify elements of "A" whose indices verify the condition
end
Which returns:
>> alternate(4,5)
ans =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
initialisation:
The first line is the equivalent to your first line, but it is the cannonical MATLAB way of creating a new matrix.
It uses the function zeros(n,m).
Note that MATLAB has similar functions to create and preallocate matrices for different types, for examples:
ones(n,m) Create
a matrix of double, size [n,m] with all elements set to 1
nan(n,m) Create a
matrix of double, size [n,m] with all elements set to NaN
false(n,m) Create a
matrix of boolean size [n,m] with all elements set to false
There are several other matrix construction predefined function, some more specialised (like eye), so before trying hard to generate your initial matrix, you can look in the documentation if a specialised function exist for your case.
indices
The second line generate 2 matrices x and y which will be the indices of A. It uses the function meshgrid. For example in the case shown above, x and y look like:
| x = | y = |
| 1 2 3 4 5 | 1 1 1 1 1 |
| 1 2 3 4 5 | 2 2 2 2 2 |
| 1 2 3 4 5 | 3 3 3 3 3 |
| 1 2 3 4 5 | 4 4 4 4 4 |
odd/even indices
To calculate the sum of the indices, it is now trivial in MATLAB, as easy as:
>> x+y
ans =
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
Now we just need to know which ones are even. For this we'll use the modulo operator (mod) on this summed matrix:
>> mod(x+y,2)==0
ans =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
This result logical matrix is the same size as A and contain 1 where the sum of the indices is even, and 0 otherwise. We can use this logical matrix to modify only the elements of A which satisfied the condition:
>> A(mod(x+y,2)==0) = 1
A =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
Note that in this case the logical matrix found in the previous step would have been ok since the value to assign to the special indices is 1, which is the same as the numeric representation of true for MATLAB. In case you wanted to assign a different value, but the same indices condition, simply replace the last assignment:
A(mod(x+y,2)==0) = your_target_value ;
I don't like spoiling the learning. So let me just give you some hints.
Matlab is very efficient if you do operations on vectors, not on individual elements. So, why not creating two matrices (e.g. N, M) that holds all the indices? Have a look at the meshgrid() function.
Than you might be able find all positions with an even sum of indices in one line.
Second hint is that the outputs of a logic operation, e.g. B = A==4, yields a logic matrix. You can convert this to a matrix of zeros by using B = double(B).
Have fun!

Build the matrix of all the combinations of given numbers using recursion [matlab]

Let say we have the vector v=[1,2,3] and we want to build the matrix of all the combinations of the numbers contained in v, i.e.
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Since I'm not good in recursion, firstly I tried to write the code to build such a matrix by using for loops
makeLoop([1,2,3])
function A = makeLoop(v)
loops=length(v);
for i = 1:loops
dummy=v;
m=factorial(loops)/loops;
A((1+m*(i-1)):m*i,1)=v(i);
v(i)=[];
loops2=length(v);
for j = 1:loops2
dummy2=v;
m2=factorial(loops2)/loops2;
A(((1+m2*(j-1))+m*(i-1)):(m2*j+m*(i-1)),2)=v(j);
v(j)=[];
loops3=length(v);
for k = 1:loops3
m3=factorial(loops3)/loops3;
A(((1+m2*(j-1))+m*(i-1)):(m2*j+m*(i-1)),3)=v(k);
end
v=dummy2;
end
v=dummy;
end
end
it seems like it work, but obviously write it all for a bigger v would be like hell. Anyway I don't understand how to properly write the recursion, I think the recursive structure will be something like this
function A = makeLoop(v)
if length(v)==1
"do the last for loop"
else
"do a regular loop and call makeLoop(v) (v shrink at each loop)"
end
but I don't get which parts should I remove from the original code, and which to keep.
You were very close! The overall structure that you proposed is sound and your loopy-code can be inserted into it with practically no changes:
function A = makeLoop(v)
% number of (remaining) elements in the vector
loops = length(v);
if loops==1 %"do the last for loop"
A = v; %Obviously, if you input only a single number, the output has to be that number
else %"do a regular loop and call makeLoop(v) (v shrink at each loop)"
%preallocate matrix to store results
A = zeros(factorial(loops),loops);
%number of results per vector element
m = factorial(loops)/loops;
for i = 1:loops
%For each element of the vector, call the function again with that element missing.
dummy = v;
dummy(i) = [];
AOut = makeLoop(dummy);
%Then add that element back to the beginning of the output and store it.
A((1+m*(i-1)):m*i,:) = [bsxfun(#times,v(i),ones(m,1)) AOut];
end
end
Explanation bsxfun() line:
First, read the bsxfun documentation, it explains how it works way better than I could. But long story short, with bsxfun() we can replicate a scalar easily by multiplying it with a column vector of ones. E.g. bsxfun(#times,5,[1;1;1]) will result in the vector [5;5;5]. Note that since Matlab 2016b, bsxfun(#times,5,[1;1;1]) can written shorter as 5.*[1;1;1]
To the task at hand, we want to add v(i) in front (as the first column) of all permutations that may occur after it. Therefore we need to replicate the v(i) into the 1. dimension to match the number of rows of AOut, which is done with bsxfun(#times,v(i),ones(m,1)). Then we just horizontally concatenate this with AOut.
You can simply use the perms function to achieve this:
v = [1 2 3];
perms(v)
ans =
3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3
If you want them sorted using the same criterion you applied in the desired output, use the following code (refer to this page for an official documentation of the sortrows functon):
v = [1 2 3];
p = perms(v);
p = sortrows(p)
p =
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

How to check if cell's elements contain matrix

I have a cell described as the following:
mixed_values = {'jim', 89, [5 2 1; 1 2 3]};
mixed_values{1}
mixed_values{2}
mixed_values{3}
I loop it:
for k=1:length(mixed_values)
curstate=mixed_values{k};
% Check for the [5 2 1; 1 2 3]
if ismatrix(curstate)
disp('yes');
else
disp('no')
end
end
But it founds the matrix multiple times.
yes
yes
yes
How to check it by the way?
From Matlab help:
ismatrix(M) returns logical 1 (true) if SIZE(M) returns [m n] with
nonnegative integer values m and n, and logical 0 (false) otherwise
so I checked size(curstate)
1 3 % 3 character string array
1 1 % of course you can do size of a single elements
2 3
so I modified your code
for k=1:length(mixed_values)
curstate=mixed_values{k};
% Check for the [5 2 1; 1 2 3]
if (size(curstate,1)) > 1 && (size(curstate,2)) > 1
disp('yes');
disp(size(curstate));
else
disp('no')
end
end
It really depends on what you define a matrix to be. In MathWorks case they decided that a matrix would be something with a valid size, which is certainly true. Notice that even scalars are matrices, of size 1x1. You can even have a matrix of characters. A = ['a' 'b';'c' 'd'];. I gather that in your case you want a matrix to be a numerical collection of at least 2 dimensions. I would solve it this way:
function result = TestForMatrix(m)
t1 = isnumeric(m);
t2 = ~isvector(m);
result = all([t1 t2]);
end
Use it as if it was ismatrix.
if (TestForMatrix(curstate))
disp('yes');
else
....
The way this works is the test for numerical numbers will eliminate character strings. The second test will eliminate vectors and scalars. As you find more things to include or eliminate you add those tests. For example, say you want to allow cells. t3 = iscell(m); result = all([t1 t2 t3]); The are many logical tests that can be done on Matlab objects, see Matlab is*.

Vector Function is Always Constant

New to MATLAB, and I need help with the following issue.
I want to create a function val=F(v,e) that takes in two inputs v, a 1xn vector, and a scalar e, and outputs a scalar val that counts the nonzero entries of the vector v-e, i.e. the vector v with e subtracted from all each of its entries. My code for the function is below:
function val = eff(vec, e)
val = sum( (vec - e > 0) );
end
When I evaluate the function at a single point it works as it should. but I want a plot of this function on (0,1). Plotting it gives a constant value over the entire range of e. I am using the following code on the main
figure
e = linspace(0,1);
plot(e, eff(rand(1,100),e),'o',e, e)
Also, when I use a small vector, say, rand(1,10), I get the following error message:
>Error using -
>
>Matrix dimensions must agree.
>
>Error in eff (line 3)
>
>val = sum( (vec - e > 0 ));
Is my function being too careless with matrix dimensions? Or is there an easier way to evaluate eff over a vector range?
Thanks in advance.
You have created a function which is designed to be applied only with a scalar e argument, and where passing e as an array would potentially cause errors ... but then you call it with e = linspace(0,1) which is an array.
The particular error when e is of size 10 is telling you that you cannot subtract it from a matrix of size 100.
When e happens to have the same size as vec, your function subtracts two equal-sized arrays, and returns their sum, which is a scalar. Therefore your plot is essentially doing something like plot(a_range, a_scalar), which is why it looks constant.
Instead, you should probably collect an array V for each value of e in a for loop, or using arrayfun, e.g.
e = linspace(0,1);
V = arrayfun(#eff, e);
and then plot e against V
Alternatively, you could rewrite your function such that it expects e to be an array, and your return value is an array of the same size as e, filled with the appropriate values.
without using arrayfun, your task can also be accomplished using broadcasting. I noticed you had this question tagged Octave as well as Matlab. Octave uses automatic broadcasting when you attempt elementwise operations with vectors in different dimensions. Matlab can do broadcasting with the bsxfun function. (if you want code that will run in either program, Octave also can use bsxfun.) Also, according to the release notes I believe Matlab 2016b will now include automatic broadcasting, although I cannot confirm yet that it will behave the same as Octave does.
Because your vectors vec and e are both row vectors, when you try to subtract them Matlab/Octave will subtract each element if they have the same size, or give a size mismatch error if they do not.
If you instead create one of the vectors as a column vector, broadcasting can take over. a simple example:
>> a = [1:4]
a =
1 2 3 4
>> b = [1:4]'
b =
1
2
3
4
>> a-b //Error in Matlab versions before 2016b
ans =
0 1 2 3
-1 0 1 2
-2 -1 0 1
-3 -2 -1 0
>> bsxfun(#minus,a,b) //works under Octave or Matlab
ans =
0 1 2 3
-1 0 1 2
-2 -1 0 1
-3 -2 -1 0
So, if you are running Octave, your code will run correctly if you just rewrite your function so the vectors use different dimensions. There are a number of ways to do this, but since both Matlab and Octave default to column ordering, you can use the : operator to force them to work the way you want. E.g.:
>> a = [1:4]
a =
1 2 3 4
>> a(:)
ans =
1
2
3
4
>> a(:)'
ans =
1 2 3 4
>> b = [1:4]'
b =
1
2
3
4
>> b(:)
ans =
1
2
3
4
>> b(:)'
ans =
1 2 3 4
So, after all that, you can rewrite your function:
function val = eff(vec, e)
vec = vec(:);
e = e(:)';
val = sum ( (vec-e ) > 0 );
end
If you're running matlab, or you want code that could run in both Octave and Matlab, you can just replace the last line of the function with:
sum ( bsxfun(#minus,vec,e) > 0 )
Finally, if you want, you can add some 'isvector' error checking at the beginning of the function in case you accidentally pass it an array. And note that had I chosen to make 'vec' a row vector and 'e' a column vector I would have had to tell the sum function which dimension to sum over. (it defaults to summing each column and returning a row vector, which matches the choices I made above.)
you function works fine as long as e is a scaler and not an array or matrix. You can then you looping or arrayfun (as already answered) to get a final answer
figure
e = rand(1,10); % create 10 random e numbers
vec = rand(1,100);
for inc = 1:length(e)
v(inc) = eff(vec,e(inc));
end
scatter(e,v);