error with matrix inverse only when matrix created through script - matlab

A=[ 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
1 -3 1 0 0 0 0 0 0 1 0 0 0 0 0 0;
0 1 -3 1 0 0 0 0 0 0 1 0 0 0 0 0;
0 0 1 -7.94E+05 7.94E+05 0 0 0 0 0 0 2 0 0 0 0;
0 0 0 +7.94E+05 -7.94E+05 1 0 0 0 0 0 0 2 0 0 0;
0 0 0 0 1 -3 1 0 0 0 0 0 0 1 0 0;
0 0 0 0 0 1 -3 1 0 0 0 0 0 0 1 0;
0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0;
0 1 0 0 0 0 0 0 1 -3 1 0 0 0 0 0;
0 0 1 0 0 0 0 0 0 1 -3 1 0 0 0 0;
0 0 0 2 0 0 0 0 0 0 1 -7.94E+05 7.94E+05 0 0 0;
0 0 0 0 2 0 0 0 0 0 0 7.94E+05 -7.94E+05 1 0 0;
0 0 0 0 0 1 0 0 0 0 0 0 1 -3 1 0;
0 0 0 0 0 0 1 0 0 0 0 0 0 1 -3 1;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1];
This matrix has an inverse when created manually. But the same matrix when generated through script and inverted gives me "Matrix is close to singular or badly scaled. Results may be inaccurate." error and the inverse generated is not the same as inv(A). I tried using the backslash too. I tried creating the matrix through program using format long, short and bank and continue to face the same problem. What could be my mistake? Thanks in advance.

Related

Comparison between two rows and change value

i have a matrix 20 rows and 20 columns,
If the value 1 in the row 5 the column take 0
matric=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ;
0 1 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1 1 1 1;
0 1 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 1 0 1;
0 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1;
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 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;
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 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;
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 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;
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 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;
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 0 0 0 0 0 0 0 0 0 0;];
if (matric(5,:)==1)
matric(1:5,1:end)=0;end
I try to compare the second row and the 5 row
If we have "1" in row 2 and row 5
The row 2 take 0
if (matric(5,:)==matric(2,:)==1)
matric(2,1:end)=0;end
do you have an idea
Thank you
The desired output is:
matric=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
1 0 1 1 0 0 1 1 1 1 0 1 0 1 1 1 1 0 1 0 ;2row will change
0 1 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1 1 1 1;
0 1 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 1 0 1;
0 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1; % 5 row
You can use logical indexing.
I strongly encourage you to read the following references:
Mathworks documentation page: Find Array Elements That Meet a Condition
Loren on the Art of MATLAB blog entry: Logical Indexing – Multiple
Conditions
Use the following lines of code:
Put 0 in all those columns that have a value of 1 in row 5:
matric(:, matric(5, :) == 1) = 0;
Put 0 in all those columns of row 2 that have a value of 1 both in rows 2 and 5:
matric(2, matric(2, :) == matric(5, :)) = 0;
You can use logical indexing to achieve this. Now I must say I am a bit confused by what exactly you want to achieve based on your description, but based on the your code the first statement can be done as follow:
matric(1:5,matric(5,:)==1) = 0;
and the second would look like:
matric(2,matric(5,:)==1 & matric(2,:)==1)=0;

MxN matrix with ones and zeros following a specific rule

I want to create a MxN matrix as shown below:
[1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1]
I have window size, let's say, 5 and it moves 3 in every row. Is it possible to create such a matrix without using for loops? Or is there any optimum way to do it?
This is a one line solution:
reshape([reshape([ones(5,6);zeros(21,6)], 1,[]), ones(1,5)],[],7).'
note:
The desired matrix can be seen as concatenation of a [6, 5+21] matrix:
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
and a [1 ,5] matrix:
1 1 1 1 1
that reshaped to a [7 , 23] matrix.
Other solution using repelem + bsxfun + accumarray:
r = repelem (1:7,5);
c= bsxfun(#plus, ((1:5)-3).',3*(1:7));
out = accumarray([r(:) c(:)] ,1)
Indices of rows and columns of 1 s can be generated and accumarray can be used to create the desired matrix.

"""Diagonal""" -1/+1 Matrix

I need to construct the tech cycle constraint matrix Aa and the right side ba. The aim is building the technology cycle matrices in order to solve the scheduling linear problem constrained by Ax<=b. In this case -1 and +1 in A refers to the coefficients of the constraints of the problem such as starting times and precedences
TC = [1,2,3,4,6,7;1,2,5,4,6,7;2,5,6,7,0,0]; % Technology cycle
CT = [100,60,200,160,80,120;100,60,150,120,60,150;50,120,40,30,0,0]; % Cycle time
n_jb = size(TC,1); % number of jobs
n_op = sum(TC~=0,2); % number of operations for each job
N_op = sum(n_op); % total number of operations
c=1; % indice for constraints in Aa
Op=1; % counter for overall operation
n_tf = N_op - n_jb- sum(n_op==1); % number of job transfer between machines (also number of tech cycle constraint numbers)
Aa = zeros(n_tf,N_op); % Constraint matrx for tech cycle
ba = zeros(n_tf,1); % The right vector of the constraint function: Aa*x<=ba
for j=1:n_jb
if n_op(j)>1
for op=1:n_op(j)-1
Aa(c,Op)=-1;
Aa(c,Op+1)=1;
ba(c,1)=CT(j,op);
c=c+1;
Op=Op+1;
end
else
Op=Op+1;
end
Op=Op+1;
end
The output, like Aa is 3 """diagonal""" -1/+1 matrices:
-1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1
In order to be more precise in the following there is an image: showing the 3 different part of the matrix Aa. My question is: Is there a way to build the same this avoiding loops since A is not a 3x1 but will definitely become 30-50x1?
You can use diag to create the positive and negative ones. The second input to diag is to shift the diagonal to the side. In this case, 1 to the right.
Use cumsum to find the rows you want to remove. For n = [6, 6, 4], you want to remove the 6th, 12th and 16th row.
n = [6, 6, 4];
cols = sum(n);
A = -eye(cols) + diag(ones(cols-1,1), 1);
A(cumsum(n),:) = []
A =
-1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1

Flipping Around 5 percent of 1's and 0's

For the following letter, I wish to add noise to it by changing 5 percent of the 1's into 0's. So far, I have the following code which turns them all into 0's. Can someone please point me in the right direction? Thank you!
letterA = [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 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 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 0 0 0 1 0 0 0 1 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 0 1 0 0 0 0 0 1 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 1 0 0 0 0 0 0 0 1 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 1 0 0 0 0 0 0 0 0 0 1 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 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 ...
0 0 0 0 0 1 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 1 0 0 0 0 0 ...
0 0 0 0 1 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 1 0 0 0 0 ...
0 0 0 1 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 1 0 0 0 ...
0 0 1 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 0 1 0 0 ...
0 1 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 0 0 0 1 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 0 0 0 0 0 0 0 0];
for i=1:numel(letterA)
if letterA(i)==1
letterA(i)=0;
end
end
disp(letterA)
try this:
letterA( letterA == 1 & rand(size(letterA)) <= 0.05 ) = 0;
In fact you could also do
letterA( rand(size(letterA)) <= 0.05 ) = 0;
which sets each element with probability of 5% to zero. The already zero elements are not affected. I think what causes confusion here is that you have to recognize that each element is independently handled from each other. It makes no difference if you do the first or the second version.
You can check it:
letterA = (rand(1e5,1) < 0.2); N1 = nnz(letterA);
letterA( rand(size(letterA)) <= 0.05 ) = 0;
(N1 - nnz(letterA))/N1
which gives values around 0.05, i.e. 5%. And it is not true what EitanT says, that it will flip at maximum 5%. It can be more than 5% or less, but on average it is 5%.
EitanTs version flippes exactly 5%, so which version to select depends on the application. For EitanT version the noise is correlated to the signal (because it is exact), which may or may not be what you want.
The basic approach is to find the indices of the 1's and count them, randomly pick a desired amount of indices out of them, and then operate on them:
one_flip_ratio = 0.05;
idx_ones = find(letterA == 1); %// Indices of 1's
flips = round(one_flip_ratio * numel(idx_ones)); %// Number of flips
idx_flips = idx_ones(randperm(numel(idx_ones), flips)); %// Indices of elements
letterA(idx_flips) = 0; %// Flip elements
This will flip 5% of the 1's to 0's.
Thanks for throwing out all these ideas, but eventually I came up with this. It will allow me to easily control both letter and background noise, which is what I intend to do. I'm just a novice, so this may not be the most efficient code, but it gets the job done! (I'm not looking for exactly 5%, the naked eye display value is what I'm more worried about.) PLEASE let me know how this can be improved! Thank you.
background_noise_intensity=0.05;
letter_noise_intensity=0.05;
for i=1:numel(letterA)
if letterA(i)==0
if rand < background_noise_intensity
letterA(i)=1;
end
elseif letterA(i)==1
if rand < letter_noise_intensity
letterA(i)=0;
end
end
end
noisy_letters=letterA;
reshaped_noisy_letters=reshape(noisy_letters,37,19)';
imshow(reshaped_noisy_letters);

How to replace elements of a matrix by an another matrix in MATLAB?

How to replace elements of a matrix by an another matrix in MATLAB?
Ex: let say if we have a matrix A, where
A=[1 0 0; 0 1 0; 1 0 1]
I want to replace all ones by
J=[1 0 0; 0 1 0; 0 0 1]
and zeros by
K=[0 0 0; 0 0 0; 0 0 0]
So that I can get 9x9 matrix. So how we will code it in MATLAB
Thanks
Sounds like you might want to take a look at the kronecker tensor product. This is not a general case but the idea should work for what you want
>> kron(A==1,J)+kron(A==0,K)
ans =
1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 1
which, for the example case, would simplify to a simpler command:
>> kron(A,J)
ans =
1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0 1
You can do:
A2=imresize(A,size(A).*size(J),'nearest');
J2=repmat(J,size(A));
K2=repmat(K,size(A));
A2(A2==1)=J2(A2==1);
A2(A2==0)=K2(A2==0)