Create an empty symbolic matrix and predefine the dimension in Matlab? - matlab

I want want to do some string calculation using Matlab, and then stored the value in an matrix.
For numerical study, I often predefined the dimensions in Matlab using zeros to create a 4*4 array.
a = zeros(4)
Now I want to do the same thing for the symbolic matrix. Obviously zeros didn't work at this time.
I tried to copy the official tutorial at this page http://www.mathworks.com/help/symbolic/sym.html
a = sym('0' ,4) % error
Still didn't work.
Now I have do use the ugly code like this
a = sym('[0 0 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0]');
Since I will use iterations, and dimension of the matrix grows every time. This method is not convenient.
Do you have any ideas? Thanks a lot!

Num = sym(Num) converts a number or a numeric matrix Num to symbolic form.
a=sym(zeros(4,4))

Can't try but suspect that the variables get initialized as zero by default.
For example when using
a = sym('a' ,[2 2])

Related

How to get the logical matrix corresponding to "scatter" plot?

If I have a two column matrix A like below, I can plot the scatter plot using scatter/plot command. I would like to get the matrix corresponding to such outputs as in hist command. hist command gives the vector output too.
A=[7 1;3 2; 4 3]
For example out=scatter(A(:,1),A(:,2)) must give something like below:
[0 0 0;
0 0 0;
0 1 0;
0 0 1;
0 0 0;
0 0 0;
1 0 0]
Only the indices (7,1), (3,2) and (4,3) are only ones. Or Can someone give me a snippet code to realize this without using loops?
You can use a combination of sparse and full where you can specify the non-zero row and column locations, and the rest of the matrix would be zero:
A = [7 1; 3 2; 4 3];
B = full(sparse(A(:,1), A(:,2), 1, max(A(:,1)), max(A(:,2)))) == 1;
The sparse command takes in the row and column locations of what is non-zero for the first two inputs, the third input is what the non-zero location would be for each row and column location. We can specify a constant to mean that every non-zero location gets the same coefficient, which is 1. We can also specify the size of the matrix, where in this case the rows and columns of the output correspond to the largest number in the first and second columns respectively. Because this is a sparse matrix, you will want to convert this to a full matrix and because you want it to be logical, you will want to compare all elements with the number 1.
We thus get for the output, which is B:
B =
7×3 logical array
0 0 0
0 0 0
0 1 0
0 0 1
0 0 0
0 0 0
1 0 0
Alternatively, we can use sub2ind to create linear indices to index into a pre-allocated matrix of logical false and set only those non-zero row locations to true:
A = [7 1; 3 2; 4 3];
B = false(max(A(:,1)), max(A(:,2)));
ind = sub2ind(size(B), A(:,1), A(:,2));
B(ind) = true;
We first allocate the matrix, then calculate the linear indices to index into the matrix, then finally set the right locations to true. The output here would be the same as the sparse approach.
Just to add: rayryeng's solution is fine if you really want your result to be logical in the sense that it is equal to one if there is anything at the coordinate and zero otherwise. Still, since you added a note on hist, I was wondering if you actually want to count the number of times a specific coordinate is hit. In this case, consider using
S = histcounts2(A(:,2),A(:,1));
if you have access to R2015b+. If not, there is a hist2 function on fileexchange you can use for the purpose.
Here is my solution. Matlab provides a command called accumarray.
S = logical(accumarray(A, 1) )
will give the result too.

removing uniform columns in MATLAB

Say i have a 2D matrix A:
A = [ 1 1 0 0
1 0 0 0
1 1 1 0];
A is not necessarily binary, or even integer (i.e., floats are possible). I want to remove any column that contains uniform valued elements. In the above example, i would get:
1 0
0 0
1 1
To make this fully general, i'd like to allow the user to select the dimension along which rows/columns/slices are removed (i.e., with a DIM option).
Any ideas?
You could try using the min and max functions, which allow you to use the dim argument.
For example
index = min(A,[],1)==max(A,[],1);
A(:,index)=[];
will remove the columns you want. It is straightforward to do the same for rows
index = min(A,[],2)==max(A,[],2);
A(index,:)=[];
One-liner:
B = A(:,range(A)~=0); %//columns
The other one-liner is not that nice, and ugly one-liners should not be written down. :-) But is basically the same solution as S..'s, except is way more expensive (requires stats toolbox).
Please note that "generality" of subscript-based solutions doesn't extend to N-dimensional arrays as easily, because subscripting in ND arrays without checking beforehand the number of dimensions is difficult. Also, for the 1D arrays the notion of "uniformity" is a bit odd along the singleton dimension (the result is always empty).
Besides the neat solution provided by #S.. there is this simple hack also for your example:
for ii = 1:size(A,2)
T(ii) = all(A(:,ii) == sum(A(:,ii))/numel(A(:,ii)));
end
A(:,~T)
ans =
1 0
0 0
1 1
As suggested by #gariepy the right side of the equation can be replaced with mean function.
for ii = 1:size(A,2)
T(ii) = all( A(:,ii) == mean(A(:,ii)) );
end
A(:,~T)
A(:,~all(A == repmat(A(1,:),[size(A,1) 1])))
Inspired by #S.. but only checks if every element of the column equals the first element of the column. Seems like a little less work for the processor than finding the min and the max, and checking for equality.

MATLAB manual error?

I read interesting article about correct memory usage in MATLAB. Here it is: Link at official website
And here I see example:
If your data contains many zeros, consider using sparse arrays, which
store only nonzero elements. The following example compares the space
required for storage of an array of mainly zeros:
A = diag(1e3,1e3); % Full matrix with ones on the diagonal
As = sparse(A) % Sparse matrix with only nonzero elements
I tried to implement it in my code and find interesting moment:
A = diag(1e3,1e3) does not create matrix with ones on the diagonal! It creates matrix of zeros with only one nonzero element:
clear A
A = diag(1e3,1e3);
find(A);
ans =
1001001
A(1001001)
ans =
1000
Ok. I read about diag function in help and see this:
D = diag(v) returns a square diagonal matrix with the elements of
vector v on the main diagonal.
Ok! So it really doesn't create diagonal matrix if v consist of 1 element! Is it mistake at help?
BUT. One more question: why it works this way?
diag(5,5)
ans =
0 0 0 0 0 5
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
I expect to get matrix 5x5 with 5 value at (1,1) or (5,5). Why it creates 6x6 matrix and why 5 is a (1,6) element?
Some time ago they fix documentation:
Manual: diag
you are using the 2nd overloaded version of diag:
D = diag(v,k) places the elements of vector v on the kth diagonal. k=0 represents the main diagonal, k>0 is above the main diagonal, and k<0 is below the main diagonal.
So your command A = diag(5,5) will construct a matrix where the diagonal elements of 5th diagonal above the main diagonal will be equal to the vector [5]. Thus the resulting value where only A(1,6) has a value.
If you want to have a 1e3x1e3 Matrix with ones on the diagonal try
A = diag(ones(1,1e3));
The article is incorrect.
A = diag(1e3,1e3);
does not produce a matrix with ones on the diagonal. The code should instead read:
A = eye(1e3,1e3);
Now reading your question again, I understood it really and have to rewrite my answer. You are refering to this part of the documentation:
A = diag(1e3,1e3); % Full matrix with ones on the diagonal
As = sparse(A) % Sparse matrix with only nonzero elements
whos
Name Size Bytes Class
A 1001x1001 8016008 double array
As 1001x1001 4020 double array (sparse)
That example is definitely wrong, probably it should be:
A=eye(1e3,1e3)
As=sparse(A);
Which creates a 1000x1000 matrix with ones on the main diagonal.
The bug is reported to mathworks

pass a matrix or vector to function handle in Matlab

everyone!
I've got a problem when using function handle in Matlab.
suppose I get a function handle of a transform matrix, say
Tf = #(alpha)reshape([cos(alpha),-sin(alpha),sin(alpha),cos(alpha)],[2,2]);
and I have a alpha vector
alpha_list = [alpha1; alpha2; ...];
I want to get the result like
[Tf1; Tf2; ...];
I have tried the ways like
Tf(alpha_list) feval(Tf,alpha_list) bsxfun(Tf,alpha_list)
They all don't work
Is there an easy or magic way to do this?
Many thanks!
Edit:
Realized a way to make it faster and added explanation.
Using arrayfun allows you to apply the function tf to each element of the a individually.
It outputs as a cell array though so you need to convert it back to a matrix using cell2mat.
tf = #(alpha) [cos(alpha),sin(alpha);-sin(alpha),cos(alpha)];
Tf =#(a) cell2mat(arrayfun(#(A) tf(A), a, 'uni', 0));
so if you put in a 1xN vector you will get back a 2x2N matrix, if you put in a Nx1 vector you will get back a 2Nx2 matrix.
>> a = rand(2)
a =
6.323592462254095e-01 2.784982188670484e-01
9.754040499940953e-02 5.468815192049839e-01
>> Tf(a)
ans =
Columns 1 through 3
8.066353232983801e-01 5.910494524211303e-01 9.614693800974246e-01
-5.910494524211303e-01 8.066353232983801e-01 -2.749120425428361e-01
9.952467051120759e-01 9.738580986754016e-02 8.541503641387258e-01
-9.738580986754016e-02 9.952467051120759e-01 -5.200261103460884e-01
Column 4
2.749120425428361e-01
9.614693800974246e-01
5.200261103460884e-01
8.541503641387258e-01
>> Tf(a) - [tf(a(1,1)), tf(a(1,2)); tf(a(2,1)), tf(a(2,2))]
ans =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
Call Tfs for the solution:
Tf = #(a)[cos(a),sin(a); -sin(a), cos(a)];
Tfs = #(a) reshape(Tf(reshape(a,[1,1,length(a)])),[2,2*length(a)])'
The key here is that I use reshape to point the vector in the 3rd dimension, so that it doesn't interfere with the 2 we're interested in. Then we can use reshape again on the output which will preserve the block structure you're looking for.
This way, calling Tfs([1,2,2]) will return:
0.5403 0.8415
-0.8415 0.5403
-0.4161 0.9093
-0.9093 -0.4161
-0.4161 0.9093
-0.9093 -0.4161
I should also point out that, if you're not concerned about speed very much, there are much simpler ways to do this using simple loops...
Edit:
I switched the sign on Tf(a) because it was putting out Tf(a)'. It is correct now.

Entropy of Matrix using Matlab

Given a matrix A with dimension m x n and the entries in the matrix lies [0,1]
For example
A = [0.5 0 0 0.5 0
0 0.5 0 0 0.5
1 0 0 0 0]
I would like to calculate sum(sum(a_ij log(a_ij))), where a_ij is the i th row and j th col entry in the matrix A. Since there exist an 0 entry in the matrix, i always get NAN as a result.
How do i consider only non-zero entries to calculate sum(sum(a_ij log(a_ij))) [entropy of the matrix].
To consider only specific elements of a matrix you can use logical indexing. For example if you only want to select non-zero entries of A you can use A(A~=0). So for your problem the solution can be written:
sum(A(A~=0).*log(A(A~=0)));
EDIT: wow that is some kind of coincidence, I've just seen your comment after posting this. Well, glad you've worked it out yourself.
If it is a very large array:
sum(A.*log(A+eps))
which should be faster than indexing.
Another possibility:
x = A(:);
E = x' * log(x + (x==0))