Matlab: Solve Exponential Equation with two unknown parameters - matlab

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

Related

Dividing each slice of a MATLAB 3D array by a different number

I have a 3D MATLAB function.
I want to multiply each slice of the matrix by a different number.
I tried to implement this by bsxfun in the following example code:
a=randi(10,4,3,2);
b=[2 3];
c=bsxfun(#times,a,b)
I intended that the first 4*3 slice of 'a' would be multiplied by 2, and the second 4*3 slice of 'a' would be multiplied by 3.
However, I only got the following error:
??? Error using ==> bsxfun
Non-singleton dimensions of the two
input arrays must match each other.
How to solve the problem without using a loop?
As the error says, you need to make the dimensions of the vector and the matrix match. Since b is a row vector, you can make the slices of the matrix into columns. You can do this with permute:
a = randi(10, 4, 3, 2);
b = [2 3];
ap = permute(a, [1 3 2]);
c = bsxfun(#times, ap, b)
Then, to get the result matrix back into the correct shape, you need to permute again. You can either figure out the correct permutation order (it happens to be the same in this case, i.e. [1 3 2]) or you can use ipermute (inverse permute) and let it figure it out for you. Just give it the same permutation order you gave permute earlier.
c = ipermute(c, [1 3 2]);
Alternatively, you can permute the vector b to be the right shape to multiply the slices by making it extend in the 3rd dimension:
a = randi(10, 4, 3, 2);
b = [2 3];
bp = permute(b, [1 3 2]);
c = bsxfun(#times, a, bp)
In this case, since we didn't change a, we don't have to permute c again to get the correct shape.

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).

creating matrix from data-set

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);

How to multiply two vectors with different length

Let's say I have two vectors:
A = [1 2 3];
B = [1 2];
And that I need a function similar to multiplication of A*B to produce the following output:
[
1 2 3
2 4 6
]
It seems that things like A*B, A*B' or A.*B are not allowed as the number of elements is not the same.
The only way I managed to do this (I am quite new at MATLAB) is using ndgrid to make two matrices with the same number of elements like this:
[B1,A1] = ndgrid(B, A);
B1.*A1
ans =
1 2 3
2 4 6
Would this have good performance if number of elements was large?
Is there a better way to do this in MATLAB?
Actually I am trying to solve the following problem with MATLAB:
t = [1 2 3]
y(t) = sigma(i=1;n=2;expression=pi*t*i)
Nevertheless, even if there is a better way to solve the actual problem in place, it would be interesting to know the answer to my first question.
You are talking about an outer product. If A and B are both row vectors, then you can use:
A'*B
If they are both column vectors, then you can use
A*B'
The * operator in matlab represents matrix multiplication. The most basic rule of matrix multiplication is that the number of columns of the first matrix must match the number of rows of the second. Let's say that I have two matrices, A and B, with dimensions MxN and UxV respectively. Then I can only perform matrix multiplication under the following conditions:
A = rand(M,N);
B = rand(U,V);
A*B % Only valid if N==U (result is a MxV matrix)
A'*B % Only valid if M==U (result is a NxV matrix)
A*B' % Only valid if N==V (result is a MxU matrix)
A'*B' % Only valid if V==M (result is a UxN matrix)
There are four more possible cases, but they are just the transpose of the cases shown. Now, since vectors are just a matrix with only one non-singleton dimension, the same rules apply
A = [1 2 3]; % (A is a 1x3 matrix)
B = [1 2]; % (B is a 1x2 matrix)
A*B % Not valid!
A'*B % Valid. (result is a 3x2 matrix)
A*B' % Not valid!
A'*B' % Not valid!
Again, there are four other possible cases, but the only one that is valid is B'*A which is the transpose of A'*B and results in a 2x3 matrix.

MATLAB: Matrix containing values of another matrix at specific indices

I need help solving an indexing problem. The assigned problem states: Two matrices (x and y) give the coordinates to form matrix B from matrix A. Produce the matrix B which contains the values of A at the given coordinates in x and y.
For instance:
x = [1 1 1; 2 2 1]
y = [1 2 1; 3 2 4]
%This would read as (1,1),(1,2),(1,1),(2,3),(2,2),(1,4)
% Given matrix:
A = [6 7 8 9; 10 11 12 13];
%This would give us this answer for B (using the coordinate scheme above):
B=[6 7 6; 12 11 9];
I'm guessing I need to use the find function in conjunction with a sub2ind function, but I'm not 100% sure how to translate that into working code. The only thing I can think of would be to do something like this:
B=((x(1),(y(1)), (x(2),y(2)).......
But that would only work for the defined matrix above, not a randomly generated matrix. I tried looking for a similar problem on the site, but I couldn't find one. Your help would be really appreciated!
You can't do it for randomly generated matrices, because you have to ensure that matrix A has lines and columns as required from the values of x and y.
In this case, you can write:
for i=1:length(x(:))
B(i)=A(x(i),y(i));
end
B=reshape(B,size(x));