Matlab programming dealing with matrix - matlab

I am trying out one of the matlab programming question.
Question:
Write a function called hulk that takes a row vector v as an input and
returns a matrix H whose first column consist of the elements of v,
whose second column consists of the squares of the elements of v, and
whose third column consists of the cubes of the elements v. For
example, if you call the function likes this, A = hulk(1:3) , then A
will be [ 1 1 1; 2 4 8; 3 9 27 ].
My Code:
function H = hulk(v)
H = [v; v.^2; v.^3];
size(H) = (n,3);
end
When I test my code using A = hulk(1:3), it throws an error on console.
Your function made an error for argument(s) 0
Am I doing something incorrect? Have I missed anything?

Remove the line size(H) = (n,3);
and add the line H = H';
Final code should be as follows
function H = hulk(v)
H = [v; v.^2; v.^3];
H = H';
end
Your code giving error in matlab editor on the size(H) = (n,3); line
That's why you should use the matlabeditor itself

For your future reference, you can very easily generalise this function in Matlab to allow the user to specify the number of cols in your output matrix. I also recommend that you make this function a bit more defensive by ensuring that you are working with column vectors even if your user submits a row vector.
function H = hulk(v, n)
%//Set default value for n to be 3 so it performs like your current function does when called with the same signature (i.e. only 1 argument)
if nargin < 2 %// nargin stands for "Number of ARGuments IN"
n = 3;
end if
%// Next force v to be a row vector using this trick (:)
%// Lastly use the very useful bsxfun function to perform the power calcs
H = bsxfun(#power, v(:), 1:n);
end

You could reduce the number of operations using cumprod. That way, each v.^k is computed as the previous v.^k times v:
function H = hulk(v, n)
H = cumprod(repmat(v,n,1),1);
The first input argument is the vector, and the second is the maximum exponent.

Related

How can I factor specific variables out of a formula in Matlab?

Suppose I have a column vector of formulae like this
N =
4*k2 + 5*k3 + k1*x
7*k2 + 8*k3 + k1*y
and a column vector of symbolic variables like this
k =
k1
k2
k3
The formulae are linear with respect to k. I'd like to find a matrix M such that M*k equals N.
I can do this with N/k. However, that gives
[ (4*k2 + 5*k3 + k1*x)/k1, 0, 0]
[ (7*k2 + 8*k3 + k1*y)/k1, 0, 0]
which is correct, but not what I want. What I want is the matrix
x 4 5
y 7 8
which seems to me the simplest answer in that it involves no variables from k.
How do I convince Matlab to factor out the specified variables from a formula or a vector of formulae?
You can use coeffs, specifically the form
C = coeffs(p,vars) returns coefficients of the multivariate polynomial p with respect to the variables vars.
Since the first input needs to be a polynomial, you need to pass each component of N:
coeffs(N(1), k)
coeffs(N(2), k)
Or use a loop and store all results in a symbolic array:
result = sym('result', [numel(N) numel(k)]); % create symbolic array
for m = 1:numel(N)
result(m,:) = coeffs(N(m), k);
end
In your example, this gives
result =
[ 5, 4, x]
[ 8, 7, y]
Based on #LuisMendo's answer, I used coeffs. But there are a couple of problems with coeffs. The first is that its result doesn't include any coefficients that are 0. The second is that it doesn't seem to guarantee that the coefficients are ordered the same way as the variables in its second argument. I came up with the following function to replace coeffs.
Luckily coeffs returns a second result that lists the variables associated with each item in the first result. (It's more complicated if the formula is not linear.)
function m = factorFormula(f, v )
% Pre: f is a 1x1 sym representing a
% linear function of the variables in v.
% Pre: v is a column vector of variables
% Post: m is a row vector such that m*v equals f
% and the formulas in m do not contain the
% variables in v
[cx,tx] = coeffs(f,v)
n = size(v,1)
m = sym(zeros(1,n))
for i = 1:n
j = find(tx==v(i))
if size(j,2) == 1
m(i) = cx(j)
end
end
end
This only works for one formula, but it can be extended to a vector using the loop in #LuisMendo's answer or this equivalent expression in #Sanchises comment there.
cell2sym(arrayfun( #(f)factorFormula(f,k),N,'UniformOutput',false ) )
I hope there is a better answer than this.

MATLAB: For loop structure [duplicate]

This question already has answers here:
Element-wise array replication in Matlab
(7 answers)
Closed 6 years ago.
This is a basic program but since I'm new to MATLAB, I'm not able to figure out the solution.
I have a column vector "Time" in which I want to print value "1" in first 147 cells, followed by "2" in 148 to 2*147 cells and so on. For that, I have written the following script:
Trial>> c=1;
Trial>> k=0;
Trial>> for i = c:146+c
Time(i,1)=1+k;
c=i;
k=k+1;
end
I know I need to iterate the loop over "Time(i,1)=1+k;" before it executes the next statement. I tried using break but that's not supposed to work. Can anyone suggest me the solution to get the desired results?(It was quite simple in C with just the use of curly braces.)
I am sure you don't want to run c=i; in every iteration.
My code should work for you:
x = 10; % Replace 10 by the max number you need in your array.
k = 1;
for i = 1 : x * 147
Time(i, 1) = k;
if rem(i, 147) == 0
k = k + 1;
end
end
This is the prime example of a piece of code that should be vectorized can help you understand vectorization. Your code can be written like this:
n = 147;
reps = 10; %% Replace this by the maximum number you want your matrix to have
Time = reshape(bsxfun(#plus, zeros(n,1), 0:reps), 1, []);
Explanation:
Let A be a column vector (1 column, n rows), and B be a row vector (1 row, m columns.
What bsxfun(#plus, A, B) will do here is to add all elements in A with all elements in B, like this:
A(1)+B(1) A(1)+B(2) A(1)+B(3) ... A(1)+B(m)
A(2)+B(1) A(2)+B(2) ............. A(2)+B(m)
............................................
A(n)+B(1) A(n)+B(2) .............. A(n)+B(m)
Now, for the two vectors we have: zeros(n,1), and 0:reps, this will give us;
0+0 0+1 0+2 0+reps
0+0 0+1 0+2 0+reps
% n rows of this
So, what we need to do now is place each column underneath each other, so that you will have the column with zeros first, then the row with ones, ... and finally the one with reps (147 in your case).
This can be achieved by reshaping the matrix:
reshape(bsxfun(#plus, zeros(n,1), 0:reps), [], 1);
^ ^ ^ ^
| | | Number of rows in the new matrix. When [] is used, the appropriate value will be chosen by Matlab
| | Number of rows in the new matrix
| matrix to reshape
reshape command
Another approach is using kron:
kron(ones(reps+1, 1) * 0:(n-1)
For the record, a review of your code:
You should always preallocate memory for matrices that are created inside loops. In this case you know it will become a matrix of dimensions ((reps+1)*n-by-1). This means you should do Time = zeros((reps+1)*n, 1);. This will speed up your code a lot.
You shouldn't use i and j as variable names in Matlab, as they denote the imaginary unit (sqrt(-1)). You can for instance do: for ii = 1:(n*147) instead.
You don't want c=i inside the loop, when the loop is supposed to go from c to c + 146. That doesn't make much sense.
You can use repmat,
x = 10; % Sequence length (or what ever it can be called)
M = repmat(1:x,147,1); % Replicate array 1:x for 147 columns
M = M(:); % Reshape the matrix so that is becomes a column vector.
I can assume that this is a task to practice for loops, but this will work.
An alternative solution may be to do
n = 147;
reps = 10;
a = ceil( (1:(n*reps)) / n);
You first construct an array with the length you want. Then you divide, and round of upwards. 1 to 147 will then become 1.

matlab concatenating vectors

I'm new to MATLAB, and programming in general, and I am having difficulty accomplishing what I am sure is a very, very simple task:
I have a list of vectors v_i for i from 1 to n (n in some number), all of the same size k. I would like to create a vector v that is a "concatenation" (don't know if this is the correct terminology) of these vectors in increasing order: what I mean by this is that the first k entries of v are the k entries of v_1, the k+1 to 2k entries of v are the k entries of v_2 etc. etc. Thus v is a vector of length nk.
How should I create v?
To put this into context, here is function I've began writing (rpeakindex will just a vector, roughq would be the vector v I mentioned before):
function roughq = roughq(rpeakindex)
for i from 1 to size(rpeakindex) do
v_i = [rpeakindex(i)-30:1:rpeakindex(i)+90]
end
Any help is appreciated
Let's try two things.
First, for concatenating vectors there are a couple of methods here, but the simplest would be
h = horzcat(v_1, v_2);
The bigger problem is to enumerate all vectors with a "for" loop. If your v_n vectors are in a cell array, and they are in fact v{i}, then
h= [];
for j=1:n
h = horzcat(h, v{i});
end
Finally, if they only differ by name, then call them with
h=[];
for j=1:n
h= horzcat(h, eval(sprintf('v_%d',j));
end
Let the arrays (vectors) be:
v_1=1:10;
v_2=11:20;
v_3=21:30;
v_4=31:40;
and so on.
If they are few (e. g. 4), you can directly set then as input in the cat function:
v=cat(2,v_1,v_2,v_3,v_4)
or the horzcat function
v=horzcat(v_1,v_2,v_3,v_4)
otherwise you can use the eval function within a loop
v1=[];
for i=1:4
eval(['v1=[v1 v_' num2str(i) ']'])
end
Hope this helps.
Concatenating with horzcat is definitely an option, but since these vectors are being created in a function, it would be better to concatenate these vectors automatically in the function itself rather than write out horzcat(v1,v2,....vn) manually.
Given the function mentioned in the question, I would suggest something like this:
function v = roughq(rpeakindex)
v = zeros(121,length(rpeakindex)); %// create a 2D array of all zeros
for i = 1:size(rpeakindex)
v(:,i) = [rpeakindex(i)-30:1:rpeakindex(i)+90]; %// set result to ith column of v
end
v = v(:)'; %'//reshape v to be a single vector with the columns concatenated
end
Here's a simplified example of what's going on:
N = 3;
v = zeros(5,N);
for i = 1:N
v(:,i) = (1:5)*i;
end
v = v(:)';
Output:
v =
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15
You may want to read up on MATLAB's colon operator to understand the v(:) syntax.
If you mean 2d matrix, you are using for holding vectors and each row hold vector v then you can simply use the reshape command in matlab like below:
V = [] ;
for i = 1:10
V(i,:) = randi (10,1 ,10) ;
end
V_reshpae = reshape (V, 1, numel(V)) ;

Why does my function return two values when I only return one?

So I'm trying to implement the Simpson method in Matlab, this is my code:
function q = simpson(x,f)
n = size(x);
%subtracting the last value of the x vector with the first one
ba = x(n) - x(1);
%adding all the values of the f vector which are in even places starting from f(2)
a = 2*f(2:2:end-1);
%adding all the values of the f vector which are in odd places starting from 1
b = 4*f(1:2:end-1);
%the result is the Simpson approximation of the values given
q = ((ba)/3*n)*(f(1) + f(n) + a + b);
This is the error I'm getting:
Error using ==> mtimes
Inner matrix dimensions must agree.
For some reason even if I set q to be
q = f(n)
As a result I get:
q =
0 1
Instead of
q =
0
When I set q to be
q = f(1)
I get:
q =
0
q =
0
I can't explain this behavior, that's probably why I get the error mentioned above. So why does q have two values instead of one?
edit: x = linspace(0,pi/2,12);
f = sin(x);
size(x) returns the size of the array. This will be a vector with all the dimensions of the matrix. There must be at least two dimensions.
In your case n=size(x) will give n=[N, 1], not just the length of the array as you desire. This will mean than ba will have 2 elements.
You can fix this be using length(x) which returns the longest dimension rather than size (or numel(x) or size(x, 1) or 2 depending on how x is defined which returns only the numbered dimension).
Also you want to sum over in a and b whereas now you just create an vector with these elements in. try changing it to a=2*sum(f(...)) and similar for b.
The error occurs because you are doing matrix multiplication of two vectors with different dimensions which isn't allowed. If you change the code all the values should be scalars so it should work.
To get the correct answer (3*n) should also be in brackets as matlab doesn't prefer between / and * (http://uk.mathworks.com/help/matlab/matlab_prog/operator-precedence.html). Your version does (ba/3)*n which is wrong.

How to apply a probability to a cell in MATLAB?

Just a simple question today. If I have an m*n matrix and I want to cycle through every value in it and apply a probability based function.
Basically, if the probability is p, then each value in the matrix has p chance of having the function applied to it.
I have the loop and the function itself all worked out, but I haven't found how to actually apply the probability itself.
Any advice would be greatly appreciated! Thanks in advance.
Here's your data matrix:
>> X = reshape(1:9, 3, 3);
and you want to (possibly) apply the following function to every element (note how I've vectorized it, so that it can take a matrix as an argument)
>> f = #(x) x.^2;
You want to apply the function with probability p
>> p = 0.25;
So generate some random numbers between 0 and 1, and see which ones are less than p
>> idx = rand(3,3) < p;
And now apply the function to the relevant indexes
>> X(idx) = f(X(idx));
Here's your result:
>> X
X =
1 16 7
2 5 64
3 6 81
The trick is that you can generate the random numbers first, and then apply the other formulas.
For example:
R = rand(m,n) < p
Now each value of R(row,col) corresponds to the outcome that you need to process your original matrix(row,col).
So I suggest applying your function to every cell and then setting the values to a default value based on some probability. So lets assume M is the result of applying to function to everycell:
default = NaN % Or 0 or whatever
p = 0.8;
M(rand(size(M)) > p) = default;
I think you might have to reshape m after this... not sure
M = reshape(M, m, n);