Find solution of homegenous system in MATLAB - matlab

General solution of A*x=b in MATLAB is given by
x=A\b
for example
A = [2 -1 1; 1 2 3; 3 0 -1]
A =
2 -1 1
1 2 3
3 0 -1
b = [8; 9; 3]
b =
8
9
3
x = A\b
x =
2.0000
-1.0000
3.0000
what about solution of system A*x=0?please help me
Testing on singular matrix
A=[1 2 3;2 1 4;3 3 7]
A =
1 2 3
2 1 4
3 3 7
>> det(A)
ans =
0
b=[0;0;0];
>> linsolve(A,b)
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 1.903239e-017.
ans =
0
0
0
#Robert P.
is this correct?
A=[2 3 1;-1 3 1;1 6 2]
A =
2 3 1
-1 3 1
1 6 2
>> det(A);
>> det(A)
ans =
0
>> [U S V]=svd(A);
>> x=V(:,end);
>> A*x
ans =
1.0e-015 *
0.2220
0.2220
0.4441

You can use Singular value decomposition, svd to get an x that satisfies Ax=0 if there are non-trivial solutions:
A = [2 -1 1; 2 -1 1; 3 2 1];
[U S V] = svd(A);
x = V(:,end)
x =
-0.39057
0.13019
0.91132
A*x =
0
0
0

A = [2 -1 1; 1 2 3; 3 0 -1]
b = [0; 0; 0]
x = A\b
Assuming that "0" stands for a zero vector and not the scalar.

Ok in your case:
>> A = [2 -1 1; 1 2 3; 3 0 -1]
A =
2 -1 1
1 2 3
3 0 -1
>> b = [0; 0; 0]
b =
0
0
0
>> x = A\b
x =
0
0
0
Or you can use linsolve:
>> linsolve(A,b)
ans =
0
0
0
But if det(A==0) you should use the eigenvector corresponds the zero eigenvalue, something like that:
>> A = [2 -1 1; 1 2 3; 3 0 -1]
A =
2 -1 1
1 2 3
3 0 -1
>> b = [0; 0; 0]
b =
0
0
0
>> [v m] = eig(A)
v =
1.0000 0.4472 0
0 0.8944 0
0 0 1.0000
m =
0 0 0
0 2 0
0 0 3
You will have infinite number of solutions, every vector parallel to [1 0 0] will be a solution.

Related

How to leave only the elements that appear once per specific row x column per page?

I have a 3D array. I need to remove any elements that are in the same row, column position but on the next page (3rd dimension), and only use the first occurrence at that position. So if all pages were to multiply the result would be 0.
Since the 3D array may be of any size, I can't hard code solutions like isMember. I also can't use unique because elements can be the same, just not share the same position.
For example, input:
A(:,:,1) = [ 1 0 2];
A(:,:,2) = [ 1 1 0];
A(:,:,3) = [ 0 1 0];
the desired output is:
A(:,:,1) = [ 1 0 2];
A(:,:,2) = [ 0 1 0];
A(:,:,3) = [ 0 0 0];
How can I accomplish this?
Not the most elegant, but at least it works.
A(:,:,1) = [ 1 0 2 ];
A(:,:,2) = [ 1 1 0 ];
A(:,:,3) = [ 0 1 0 ];
for ii = 1:size(A,1)
for jj = 1:size(A,2)
unique_el = unique(A(ii, jj, :)); % Grab unique elements
for kk = 1:numel(unique_el)
idx = find(A(ii,jj,:) == kk); % Contains indices of unique elements
if numel(idx) > 1 % If an element occurs more than once
A(ii, jj, idx(2:end)) = 0; % Set to 0
end
end
end
end
A
A(:,:,1) =
1 0 2
A(:,:,2) =
0 1 0
A(:,:,3) =
0 0 0
I loop over the first two dimensions of A (rows and columns), find any unique elements which occur on a certain row and column location through the third dimensions (pages). Then set all occurrences of a unique element after the first to 0.
Given a more elaborate 3D matrix this still works:
A(:,:,1) = [1 0 2 0; 2 1 3 0];
A(:,:,2) = [1 1 0 0; 2 2 1 0];
A(:,:,3) = [0 1 1 3; 1 2 2 4];
A(:,:,1) =
1 0 2 0
2 1 3 0
A(:,:,2) =
0 1 0 0
0 2 1 0
A(:,:,3) =
0 0 1 3
1 0 2 4
If you want the first non-zero element and discard any element occurring afterwards, simply get rid of the unique() call:
A(:,:,1) = [1 0 2 0; 2 1 3 0];
A(:,:,2) = [1 1 0 0; 2 2 1 0];
A(:,:,3) = [0 1 1 3; 1 2 2 4];
for ii = 1:size(A,1)
for jj = 1:size(A,2)
idx = find(A(ii,jj,:) ~= 0); % Contains indices of nonzero elements
if numel(idx) > 1 % If more than one element
A(ii, jj, idx(2:end)) = 0; % Set rest to 0
end
end
end
A(:,:,1) =
1 0 2 0
2 1 3 0
A(:,:,2) =
0 1 0 0
0 0 0 0
A(:,:,3) =
0 0 0 3
0 0 0 4
My solution assumes, that, for a given "position", EVERY value after the first occurence of any value is cleared. Some of the MATLAB regulars around here had some discussions on that, from there comes the "extended" example as also used in Adriaan's answer.
I use permute and reshape to rearrange the input, so that we have all "positions" as "page" columns in a 2D array. Then, we can use arrayfun to find the proper indices of the first occurence of a non-zero value (kudos to LuisMendo's answer here). Using this approach again, we find all indices to be set to 0.
Let's have a look at the following code:
A(:,:,1) = [1 0 2 0; 2 1 3 0];
A(:,:,2) = [1 1 0 0; 2 2 1 0];
A(:,:,3) = [0 1 1 3; 1 2 2 4]
[m, n, o] = size(A);
B = reshape(permute(A, [3 1 2]), o, m*n);
idx = arrayfun(#(x) find(B(:, x), 1, 'first'), 1:size(B, 2));
idx = arrayfun(#(x) find(B(idx(x)+1:end, x)) + idx(x) + 3*(x-1), 1:size(B, 2), 'UniformOutput', false);
idx = vertcat(idx{:});
B(idx) = 0;
B = permute(reshape(B, o, m , n), [2, 3, 1])
Definitely, it makes sense to have a look at the intermediate outputs to understand the functioning of my approach. (Of course, some lines can be combined, but I wanted to keep a certain degree of readability.)
And, here's the output:
A =
ans(:,:,1) =
1 0 2 0
2 1 3 0
ans(:,:,2) =
1 1 0 0
2 2 1 0
ans(:,:,3) =
0 1 1 3
1 2 2 4
B =
ans(:,:,1) =
1 0 2 0
2 1 3 0
ans(:,:,2) =
0 1 0 0
0 0 0 0
ans(:,:,3) =
0 0 0 3
0 0 0 4
As you can see, it's identical to Adriaan's second version.
Hope that helps!
A vectorized solution. You can use the second output of max to find the index of the first occurence of a nonzero value along the third dimension and then use sub2ind to convert that to linear index.
A(:,:,1) = [ 1 0 2];
A(:,:,2) = [ 1 1 0];
A(:,:,3) = [ 0 1 0];
[~, mi] =max(logical(A) ,[], 3);
sz=size(A) ;
[x, y] =ndgrid(1:sz(1),1:sz(2));
idx=sub2ind( sz, x,y,mi);
result=zeros(sz) ;
result(idx) =A(idx);

Writing a loop that works for any value of N

I have a code for a 1D heat equation. Im trying to format a for loop so that the A matrix will follow a certain pattern of 1 -2 1 down the entire diagonal of a matrix that could be infinite. The pattern starts to take shape when I mess around with the initialized count at the beginning of the for loop but this changes the size of the matrix which fails the rest of the code.
My current code is below. The commented A matrix edits are what it should be.
N = 5;
%A(2,1:3) = [1 -2 1];
%A(3,2:4) = [1 -2 1];
%A(4,3:5) = [1 -2 1];
%A(5,4:6) = [1 -2 1];
A = zeros(N+1,N+1);
A(1,1) = 1;
for count=N:N+1
A(count+1,count:count+2) = [1 -2 1];
end
A(N+1,N+1) = 1;
In Matlab you can often avoid loops. In this case you can get the desired result with 2D convolution:
>> N = 6;
>> A = [1 zeros(1,N-1); conv2(eye(N-2), [1 -2 1]); zeros(1,N-1) 1]
A =
1 0 0 0 0 0
1 -2 1 0 0 0
0 1 -2 1 0 0
0 0 1 -2 1 0
0 0 0 1 -2 1
0 0 0 0 0 1
Or, depending on what you want,
>> A = conv2(eye(N), [1 -2 1], 'same')
A =
-2 1 0 0 0 0
1 -2 1 0 0 0
0 1 -2 1 0 0
0 0 1 -2 1 0
0 0 0 1 -2 1
0 0 0 0 1 -2
There are many simple ways of creating this matrix.
Your loop can be amended as follows:
N = 5;
A = zeros(N+1,N+1);
A(1,1) = 1;
for row = 2:N
A(row, row-1:row+1) = [1 -2 1];
end
A(N+1,N+1) = 1;
I've renamed count to row, we're indexing each row (from 2 to N, skipping the first and last rows), then finding with row-1:row+1 the three indices for that row that you want to address.
Directly indexing the diagonal and off-diagonal elements. Diagonal elements for an NxN matrix are 1:N+1:end. This is obviously more complex, I'd prefer the loop:
N = 6;
A = zeros(N,N);
A(1:N+1:end) = -2;
A(2:N+1:end-2*N) = 1; % skip last row
A(2*N+2:N+1:end) = 1; % skip first row
A(1,1) = 1;
A(N,N) = 1;
Using diag. We need to special-case the first and last rows:
N = 6;
A = diag(-2*ones(N,1),0) + diag(ones(N-1,1),1) + diag(ones(N-1,1),-1);
A(1,1:2) = [1,0];
A(end,end-1:end) = [0,1];

Subtracting rows and columns from a vector at non-zero indices MATLAB

Suppose I have the following matrix in MATLAB:
A =[0 0 4 0;
0 5 0 3;
1 2 0 0];
given the following vectors:
b1 = [1 2 3];
b2 = [2 3 4 5];
the output should look like this:
C1 =[0 0 3 0;
0 3 0 1;
-2 -1 0 0];
C2 =[0 0 0 0;
0 2 0 -2;
-2 -1 0 0];
C1 and C2 are column-wise and row-wise subtraction of the original matrix A from vectors happening at non-zero elements. Note A in reality is sparse matrix. Obviously answers without using loop is appreciated! Thank you
This one might be a little more memory efficient:
A =[0 0 4 0;
0 5 0 3;
1 2 0 0];
b1 = [1 2 3].'; % transpose so it's a column vector
b2 = [2 3 4 5].';
[Arows Acols Avals] = find(A);
C1 = sparse([Arows;Arows], [Acols;Acols], [Avals;-b1(Arows)]);
C2 = sparse([Arows;Arows], [Acols;Acols], [Avals;-b2(Acols)]);
Results:
>> full(C1)
ans =
0 0 3 0
0 3 0 1
-2 -1 0 0
>> full(C2)
ans =
0 0 0 0
0 2 0 -2
-1 -1 0 0
This takes advantage of the fact that sparse adds the values given for duplicate subscripts. A can be sparse or full.
No need to use a loop. First perform the subtractions and then replace the elements that should remain 0.
C1 = A - repmat(b1.',1,size(A,2));
C2 = A - repmat(b2,size(A,1),1);
C1(A==0)=0;
C2(A==0)=0;
C1 =
0 0 3 0
0 3 0 1
-2 -1 0 0
C2 =
0 0 0 0
0 2 0 -2
-1 -1 0 0
Test on Sparse Matrix
You can also confirm that this will work on Sparse Matirces
A = sparse(10,10);
A(5:6,5:6)=rand(2);
b1 = rand(10,1);
b2 = rand(1,10);
B1 = A - repmat(b1,1,size(A,2));
B2 = A - repmat(b2,size(A,1),1);
B1(A==0)=0;
B2(A==0)=0;
C1 = A ~= 0; // save none zero elements of A
b1 = b1.'; // transpose b1
b1 = [b1, b1, b1, b1]; // create matrix of same size as A
C1 = C1.*b1;
C1 = A-C1;
C1:
0 0 3 0
0 3 0 1
-2 -1 0 0
Next is C2
C2 = A ~= 0;
k = [b2; b2; b2];
C2 = C2.*k;
C2 = A-C2;
C2:
0 0 0 0
0 2 0 -2
-1 -1 0 0

Matlab, generate new matrix

How do you translate matrix of A [(N) x (N)] to matrix B [(2N) x (2N)], such that:
if A(i,j)>=0, then:
B(i,j) = [ A(i,j) 0
0 A(i,j)]
if A(i,j)<0, then:
B(i,j) = [ 0 A(i,j)
A(i,j) 0 ]
?
For example1 by:
1 2
3 4
I'm want to get:
1 0 2 0
0 1 0 2
3 0 4 0
0 3 0 4
For example2 by:
1 -2
3 -4
I'm want to get:
1 0 0 2
0 1 2 0
3 0 0 4
0 3 4 0
Use the Kronecker tensor product:
B = kron(A.*(A>=0), [1 0; 0 1]) + kron(A.*(A<0), [0 1; 1 0]);
Or maybe
B = kron(A.*(A>=0), [1 0; 0 1]) - kron(A.*(A<0), [0 1; 1 0]);
if you want all positive values (your examples and your original formulation don't agree on this)
very simple using logical conditions:
B=[A.*(A>=0), A.*(A<0) ; A.*(A<0), A.*(A>=0)];
for example,
A=[1 2 ; -3 4];
B =
1 2 0 0
0 4 -3 0
0 0 1 2
-3 0 0 4
Postscipt:
This answer was written to answer the question above in its initial forms:
How do you translate matrix of A [(N) x (N)] to matrix B [(2N) x (2N)], such that:
if A(i,j)>=0, then:
B(i,j) = [ A(i,j) 0
0 A(i,j)]
if A(i,j)<0, then:
B(i,j) = [ 0 A(i,j)
A(i,j) 0 ]
?
later the OP wrote down some examples that made clear what he\she were after.

finding matching rows in matrix

Suppose I have an (m x n) matrix Q, and a row vector r, e.g.
Q = [ 1 2 3 ; 4 2 3 ; 5 6 7 ; 1 2 3 ; 1 2 3 ; 1 2 5 ];
r = [ 1 2 3 ];
What is the easiest way to obtain a logical vector (of length m) that indicates which of the rows in Q are identical (for all elements) to the specified row r?
In the sample case above, that should be
[ 1 0 0 1 1 0 ];
You can use ismember and do it in a single line:
>> ismember(Q,r,'rows')'
ans =
1 0 0 1 1 0
all(bsxfun(#eq, r, Q),2)'
bsxfun(#eq, r, Q) compares each row and returns a matrix with same size as Q:
>> bsxfun(#eq, r, Q)
ans =
1 1 1
0 1 1
0 0 0
1 1 1
1 1 1
1 1 0
the all function computes if the result of bsxfun is all true along each row separately. Thus it returns:
>> all(ans,2)'
ans =
1 0 0 1 1 0
and yeah, there is also a transpose operator ' to match your desired row output
a = [1 1 1; 2 2 2; 3 3 3];
b = a(1:2,;);
[temp locb] = ismember(a,b,'rows');
b(locb(locb~=0),:)
ans =
1 1 1
2 2 2
Easier way with repmat:
a = [1 2 3; 4 5 6; 7 8 9];
t = [4 5 6];
[x,y] = size(a);
r = all(a==repmat(t,y,1), 2)'