creating matrix from data-set - matlab

I have a network with edges and points. The FID shows the ID number of each edge that is created by Start_Point and End_Point. For example edge 3 is between the two points of 2 and 3 in the network.
FID Start_Point End_Point
1 1 2
2 1 4
3 2 3
4 2 4
I want to create a 4-by-4 matrix of these points. if there is an edge between 2 points the value is 1 else is inf:
[inf, 1, inf, 1;
1, inf, 1, 1;
inf, 1, inf, inf;
1, 1, inf, inf]
How can I create such a matrix in MATLAB?

You can convert it to a sparse matrix and then use full command to obtain adjacency matrix.
edges= [1 2;
3 4;
3 1
2 3];
n=size(edges,1);
% create sparse matrix with given edges and their reverse direction
A = sparse([edges(:,1); edges(:,2)],[edges(:,2); edges(:,1)],[ones(n,1); ones(n,1)]);
% create adjacency matrix
B=full(A);
% set zeros to inf
B(B==0)=inf;
and this is the result :
A =
(2,1) 1
(3,1) 1
(1,2) 1
(3,2) 1
(1,3) 1
(2,3) 1
(4,3) 1
(3,4) 1
>> B
B =
Inf 1 1 Inf
1 Inf 1 Inf
1 1 Inf 1
Inf Inf 1 Inf
Edit :
the sparse command create a sparse matrix with addressing values of its elements. One prototype for this command is as follow :
A=sparse(rows,cols,values);
for example A=sparse([1;2],[1,3],[10,5]) is a matrix which A(1,1)=10 and A(2,3)=5 and other elements are zero:
A=sparse([1;2],[1,3],[10,5]);
>> full(A)
ans =
10 0 0
0 0 5
In your case you have to add two directions to sparse matrix (symmetric) and all values are one. So you need to construct sparse matrix as :
A = sparse([edges(:,1); edges(:,2)],[edges(:,2); edges(:,1)],[ones(n,1); ones(n,1)]);
full command convert a sparse matrix to a dense one.

So you basically want to create an adjacency matrix from an adjacency list of edges? The number of your edges (i.e. your FID column) is irrelevant so I'm assuming your input data is of the form
edges = [1 2
1 4
2 3
2 4]
Now the first column of edges is the rows of your adjacency matrix and the second is the columns (or vice versa, it doesn't matter since your matrix is symmetrical)
The simplest solution is to use linear index which you would get via the sub2ind function:
adj = inf(size(edges,2));
idx = sub2ind(size(adj),edges(:,1), edges(:,2))
adj(idx) = 1;
I suspect your edges matrix will already be symmetrical but if it's not then just use
edges_sym = [edges; fliplr(edges)]
instead of edges

You can use accumarray:
edges1 = accumarray([startpoint endpoint]),1);
edges2 = edges1.'; % transpose your matrix, to obtain both edges
edges = edges1+edges2;
edges(edges==0)=inf;
accumarray gathers all points with common indices, pastes the value 1 on those indices. edges1 is the transpose of edges2, thus transpose, then add the two together. Find all indices on which the matrix is 0, then fill those values with inf.
Alternative:
edges= [1 2;
3 4;
3 1
2 3];
matrix = accumarray([edges;fliplr(edges)],1,[],[],inf);
fliplr flips your matrix left to right, to get all the desired combinations of indices. Then use accumarray to set a 1 on all locations specified by edges and put inf at the other locations.
If you are sure your matrix is symmetric, don't use fliplr, if you sure your matrix is non-symmetric, use fliplr and if you are not sure use this:
matrix = accumarray([edges;fliplr(edges)],1,[],#mean,inf);
where the #mean makes sure to set double entries to 1 anyway. For weighted edges do the following, where weights is an Nx1 array containing the weights and N is the number of edges.
matrix = accumarray([edges;fliplr(edges)],weights,[],#mean,inf);

Related

How to map vector into nearest point in another vector in Matlab?

Assume I have a vector a of length N and another vector b = [-3 -1 1 3], is there any efficient way to map each element of a to its nearest (Euclidean distance) element in b. I do not want to use loops.
You can use bsxfun to compute the difference between every element in the two vectors. This will return a numel(a) x numel(b) matrix of differences. We can then take the absolute value and find the column at which the smallest differences occurs for each element in a (using the second output of min). If you want the actual value of b that is closest to each element in a, you can then use the second output of min to index into b.
a = linspace(-3, 3, 8);
b = [-3 -1 1 3];
[~, closest] = min(abs(bsxfun(#minus, a(:), b(:).')), [], 2);
% 1 1 2 2 3 3 4 4
b_for_each_a = b(closest);
% -3 -3 -1 -1 1 1 3 3
Your example is in one-dimension so Euclidean distance doesn't actually matter apart from using the absolute value of the distance.

MATLAB localmax() function returns indexes in 1D vector

In order to calculate local maximums of 2D matrix Y, I use this
[~, indices]= localmax(Y);
But the indices is 1D. How to convert it back to 2D so to access its corresponding element in Y?
From the documentation for localmax:
Linear indices of the nonzero values of lmaxima. Use ind2sub to
convert the linear indices to matrix row and column indices.
For example:
inputmatrix = ...
[3 2 5 3
4 6 3 2
4 4 7 4
4 6 2 2];
[~,indices] = localmax(inputmatrix,4,false);
[I, J] = ind2sub(size(indices), indices);
Edit: I should have clarified as well. As #LuisMendo mentions in the comments above, you can access the elements of Y directly with these linear indices by using Y(indices).

Check element wise equality of a 3D matrix Matlab

I have a 3D matrix say for eg. A(10x5x8). I need to get a 2D matrix (Boolean) out of it of size 10x5.
True if its elemental 3 Dimensional values are all same. i.e. Result(1,1) = 1 if A(1,1,1) == A(1,1,2) == A(1,1,3) etc..
False if at least one is different.
I expect a vectored approach which is fast and efficient.
Sample input:
A(:,:,1) = 1 2
2 2
A(:,:,2) = 1 1
2 3
Expected Output:
Result = 1 0
1 0
Use bsxfun with the eq function and use the first slice as the first input and compare with the other slices for the second input. Allow the first input to broadcast itself over the multiple slices.
Once you do that, use all and check the third dimension:
ind1 = bsxfun(#eq, A(:,:,1), A(:,:,2:end);
ind2 = all(ind1, 3);
The logic behind the above is very simple. How the first line of code works is that you would create a temporary matrix that would take the first slice of A and let it duplicate itself for as many slices as you have in A, without the first slice. Once you do this, you would do an element-by-element equality with this temporary matrix and the other slices. If you had a 3D column that was all equal, the one element from the first slice would be compared with every single value that corresponds to the same 3D column. Should they all equal to each other, then you would get a 3D column of all logical 1s. Therefore, to have a 3D column that is all equal to each other, all of the values should be 1, which is why all is used - to check if all values in a 3D column are equal to 1. Should all of the 3D column be a logical 1, we have matched your criteria.
Example run
>> A1 = [1 2; 2 2];
>> A2 = [1 1; 2 3];
>> A3 = [1 3; 2 4];
>> A4 = [1 5; 2 6];
>> A = cat(3, A1, A2, A3, A4);
>> ind1 = bsxfun(#eq, A(:,:,1), A(:,:,2:end);
>> ind2 = all(ind1, 3)
ind2 =
1 0
1 0
I made a matrix of 4 slices where the 3D column at the top left corner and the bottom left corner have all of the same values. Once you run through the code at the beginning of the post, we get what you expect.
Here's with short and sweet diff and must be quite memory efficient -
out = ~any(diff(A,[],3),3)
So, basically with diff along the third dimension diff(..[],3), you would calculate differences between the same (i,j) but on different 3D slices. Thus, if all such diff outputs are zeros, that would indicate that all dim3 elements for the same (i,j) are the same. This all zeros information is then picked up by ~any() also along dim3 with ~any(.,3) for the desired 2D array output.

Matlab: Solve Exponential Equation with two unknown parameters

I have a Matrix called A. For example the following:
A = [1 2 3; 3 4 1; 2 4 4]
Now I have the following equation:
A(x,y) = (j^x)*(i^y)
j and i are normal values (dimension 1x1), not indices of a matrix. ^
Lets make an example:
A(1,1) = 1 (First value of the Matrix)
1 = (j^1)*(i^1)
And a second one:
A(1,2) = 3
3 = (j^1)*(i^2)
Is there a possibility to receive one solution for the two parameters using Matlab?
Here is some code that can find the best solution to your problem, if there is one. In this case, there is no reasonable solution, but defining A by M([4 2]) (for example) does work reasonably well.
A = [1 2 3; 3 4 1; 2 4 4] %// the A matrix
[C,R]=meshgrid(1:3) %// create matrices of row/column indices
M=#(xy) xy(2).^C.*xy(1).^R %// calculates matrix of elements j^x*i^y
d=#(xy) A-M(xy) %// calculates difference between A and the calculated i^x*y^j matrix
r=fsolve(#(xy) norm(d(xy)),[1 1]) %// use fsolve to attempt to find a solution
d(r) %// show resulting difference between target matrix and solution matrix
norm(d(r)) %// norm of that matrix
M(r) %// show the solution matrix

Manipulating sparse matrices in Matlab

Suppose I have a sparse matrix Sparstica that is a vertical concatenation of several other sparse matrices. When I type Sparstica(:), I get a list of the nonzero elements. In the left column, will be the index of the element, in the right column will be the nonzero element.
How can I manipulate the i-th and j-th non-zero element of every other sparse block matrix in the middle n-2 blocks (n sparse block matrices in total)?
Appended: To clarify what I mean by the i-th and j-th element of every other sparse matrix, suppose I have
Sparstica = [A_1; A_2; A_3; ... ; A_n]
This was created from vertcat. Now I need to take the i-th and j-th, say the 3rd and 5th, nonzero element of every other sparse matrix from A_2 to A_{N-1} (I know the notation for this actually isn't allowed, but just for demonstrative purposes). I'd like to accomplish this without using for-loops if possible.
You can find the non-zero elements using find:
>> A = speye(3)
A =
(1,1) 1
(2,2) 1
(3,3) 1
>> I = find(A ~= 0)
I =
1
5
9
If you need the indices in row/column format, use ind2sub:
>> [X, Y] = ind2sub(size(A), I)
X =
1
2
3
Y =
1
2
3