Related
I have a 10*10 array for a domain
TT =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
, but I need to exclude a square centered in the domain, so the new domain would be :
TT_new =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0 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 will create a for loop for the domain TT_new, how can I do this operation in MATLAB?
Clarification: I need the for loop to go through the "i,j" of the new domain "TT_new".
For example, I have the following mesh plot for steady heat conduction problem for a U-shaped plate:
2D plot
3D plot
I need to exclude the purple rectangular from the plot because it is not within the computational domain.
Have you thought about using a mask?
You can't have matrices with holes in them, but if you element-wise multiply your original array with a matrix containing ones everywhere and zeros in the places you want to remove, your result will be an array containing the original numbers everywhere but zeros where you have zeros in your mask. For example:
my_arr = reshape(1:30, 5, 6);
my_mask = ones(5, 6);
my_mask(1:3, 3:4) = 0;
masked_arr = my_arr .* my_mask;
This gives:
my_arr =
1 6 11 16 21 26
2 7 12 17 22 27
3 8 13 18 23 28
4 9 14 19 24 29
5 10 15 20 25 30
my_mask =
1 1 0 0 1 1
1 1 0 0 1 1
1 1 0 0 1 1
1 1 1 1 1 1
1 1 1 1 1 1
masked_arr =
1 6 0 0 21 26
2 7 0 0 22 27
3 8 0 0 23 28
4 9 14 19 24 29
5 10 15 20 25 30
Whether this is applicable to your situation depends on how you use the boundaries of your computational domain in your computation. Multiplying by a mask containing NaN will change unwanted elements to NaN.
Then, you could apply your mask before (or after, or both) every iteration to ensure that the unwanted elements are set to zero (or NaN, but that can cause problems if you add / subtract / multiply those elements with anything).
domain_mask = ones(size(T));
domain_mask(7:16, 12:31) = 0;
domain_mask_small = domain_mask(2:end-1, 2:end-1);
zero_row = zeros(1, size(T, 2));
zero_col = zeros(size(T, 1), 1);
while error > tol
% Perform operations on the entire array
T_iplus1 = [T(2:end, :); zero_row];
T_iminus1 = [zero_row; T(1:end-1, :)];
T_jplus1 = [T(:, 2:end), zero_col];
T_jminus1 = [zero_col, T(:, 1:end-1)];
T_temp = 0.25 * (T_iplus1 + T_iminus1 + T_jplus1 + T_jminus1);
T(2:end-1, 2:end-1) = T_temp(2:end-1, 2:end-1) .* domain_mask_small;
% Do whatever else
end
Suppose I define the following simple matrix in MATLAB:
myImage3 = zeros(10,10);
for i=1:10
for j=i:2:10
myImage3(i,j) = 20;
end
end
Then myImage is a 10x10 matrix that looks like:
myImage3 =
20 0 20 0 20 0 20 0 20 0
0 20 0 20 0 20 0 20 0 20
0 0 20 0 20 0 20 0 20 0
0 0 0 20 0 20 0 20 0 20
0 0 0 0 20 0 20 0 20 0
0 0 0 0 0 20 0 20 0 20
0 0 0 0 0 0 20 0 20 0
0 0 0 0 0 0 0 20 0 20
0 0 0 0 0 0 0 0 20 0
0 0 0 0 0 0 0 0 0 20
How do I write a function that tracks or traces through all connected nonzero elements of the matrix? For example, if I start at (1,1), we have the following trace:
(1,1) --> (2,2) --> (3,3) ---> ... --> (10,10).
But if I start at (1,3), we have the following trace:
(1,3) --> (2,4) -> (3,5) ---> ... --> (8,10).
Similarly, if I start at (1,5), we have the following trace:
(1,5) --> (2,6) --> (3,7) ---> ... --> (6,10).
The elements do not need to be "20", but rather could be any non-zero number. Also, the elements do not have to be perfectly diagonal. They could be a zig zag like shown below:
myImage2 =
10 0 0 0 0 0 0 0 0 0
0 5 0 0 0 0 0 0 0 0
0 0 20 0 0 0 0 0 0 0
0 0 21 0 0 0 0 0 0 0
0 0 14 15 20 0 0 0 0 0
0 0 0 0 0 20 0 0 0 0
0 0 0 0 0 0 20 0 0 0
0 0 0 0 0 0 0 20 0 0
0 0 0 0 0 0 0 0 20 0
0 0 0 0 0 0 0 0 0 20
But notice that if I start at (1,1) again, every neighboring pixel has another non-zero neighboring pixel (i.e. connected).
The trace, starting at (1,1) would now look like:
(1,1)--> (2,2)--> (3,3) --> (4,3) --> (5,3)--> (5,4)--> (5,5)--> (6,6)--> (7,7)--> (8,8)--> (9,9)--> (10,10)
I think I need to use Depth First Search, but all the algorithms I see apply to adjacency matrices, not the type of matrices shown above.
I've been doing some experimenting with PostGIS, and here's what I've noticed:
Suppose I have a table defined as follows:
CREATE TABLE IF NOT EXISTS geomtest (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
geom geometry(POLYGON, 4326) NOT NULL
);
And I add the following polygon:
SRID=4326;POLYGON((0 0,0 10,10 10,10 0,0 0))
If I query the geom column on its own, I get a Hex representation of the geometry. If I instead call ST_AsBinary(geom), I get a binary representation.
However, when I convert both the hex and binary representations to an array of bytes, the results I get are slightly different. The first comment is the result I get by converting the hex into binary, and the next is straight from ST_AsBinary()
//[1 3 0 0 32 230 16 0 0 1 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 0 0 0 36 64 0 0 0 0 0 0 36 64 0 0 0 0 0 0 36 64 0 0 0 0 0 0 36 64 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 3 0 0 0 1 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 0 0 0 36 64 0 0 0 0 0 0 36 64 0 0 0 0 0 0 36 64 0 0 0 0 0 0 36 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
As you can see, the first 4 bytes are identical; representing whether it's in big or little endian, and the type of geometry (3, in this case a Polygon). The rest of the bytes are the same too. The only difference is there are a few extra bytes added after the first 4.
I wondered if this had to do with representing the projection (SRID=4326), but I haven't found any evidence to that.
If someone could shed some light on this, I'd greatly appreciate it.
I didn't examine the bytes, but I am sure that the difference is the SRID that's not included in the WKB format.
Try st_asewkb instead.
This question already has answers here:
How to perform inverse in GF(2) and multiply in GF(256) in Matlab?
(2 answers)
Closed 7 years ago.
I have a binary matrix A (only 1 and 0), and a vector D in Galois field (256) The vector C is calculated as:
C = (A^^-1)*D
where A^^-1 denotes the inverse matrix of matrix A in GF(2), * is multiplication operation. The result vector C must be in GF(256).
However, I only have a matrix A1 is non-square matrix. The above matrix A in the equation is created by delete some dependence rows of A1. In same manner, the vector D is constructed by delete some element corresponding the deleted rows in A1. Hence, we can solve above equation. My question is that can we have any function in MATLAB to do above steps?
For example, I have A1 is 16x14 matrix, D1 is 16x1 vector
A1 =[1 0 0 1 1 0 0 0 0 0 0 0 0 0
1 1 0 0 0 1 0 0 0 0 0 0 0 0
1 1 1 0 0 0 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0 1 0 0 0 0 0
1 1 0 1 1 0 0 1 0 1 0 0 0 0
1 0 1 1 0 1 0 0 1 0 1 0 0 0
1 1 1 0 0 0 1 1 1 0 0 1 0 0
0 1 1 1 1 1 1 0 0 0 0 0 1 0
0 0 0 0 1 1 1 1 1 0 0 0 0 1
0 1 1 1 1 0 1 1 1 0 1 1 1 0
0 0 0 1 0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 1 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 1 1 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 1 ]
D1=[0; 0; 0; 0 ; 0; 0 ; 0; 0 ; 0 ; 0 ; 103 ; 198 ; 105 ; 115; 175 ; 14]
In above example, we need to delete two dependence rows/cols from A1 to obtain A is 14x14 matrix and D1 also delete 2 elements to obtain D, and then my expected result is
C=A^^-1*D
C= [ 103; 187 ; 125; 210 ; 181; 220 ; 161 ; 20 ; 175; 175; 187; 187 ; 220 ; 115]
This is what I tried
%%A1=gf(A1,8);
%%D1=gf(D1,8); %%2^8=256
%% Do something and last step is
%%C=inv(A)*D
[C,vld] = gflineq(A1,D1,8)
Or
C=gf(A1,8) \ gf(D1,8)
However, these ways did not return the my expected C vector. I found that Gaussian Elimination can be worked, but I don't know how can I apply for my case. Could you give me a correct solution?
First of all, I don't have access to the "Communication system toolbox", so in order to operate in GF(2) I have to add mod(stuff,2) calls in the code, and in order to operate in GF(2^8) I had to implement a function that sums in this field. Just define your variables with gf and remove these calls if you have access to the toolbox.
Prerequisite : Summing in GF(2^8) :
Summing in GF(2^8) is not trivial, as it behaves like (Z/2Z)^8.
In order to sum in this field, I have the following function.
Basically, elements in GF(2^8) are 8-tuples, each element taking a value in {0,1}. For example, (1,1,0,0,0,1,1,0) is one of them. In order to sum two tuples in this field, ones has, for each element to take the sum in Z/2Z.
For example, if we want the sum of (0,0,0,1,0,0,0,1) and (1,1,1,1,1,1,1,1) : (Remember that in Z/2Z, 0+0=0 , 0+1=1 , 1+0=1 and 1+1=0)
First elements of these tuple are 0 and 1, so the first element of the sum will be 0+1=1. Do this with all elements and you obtain :
(0,0,0,1,0,0,0,1)+(1,1,1,1,1,1,1,1)=(1,1,1,0,1,1,1,0)
The function operates the same way :
1) Transform inputs into binary numbers
2) Compare each digit. If they're equal they sum up to 0 (0+0=0 , 1+1=0), if not they sum up to 1 (0+1=1 and 1+0=1).
3) Transform result back into decimal numbers
function [D] = SumInGF256(D1,D2)
%UNTITLED3 Summary of this function goes here
% Detailed explanation goes here
A=size(D1);
P=numel(D1);
D=zeros(A);
D1=dec2bin(D1,8);
D2=dec2bin(D2,8);
% TmpD=cell(A);
for jj=1:P
TmpD1=D1(jj,:);
TmpD2=D2(jj,:);
out='';
for ii=1:8
if isequal(TmpD1(ii),TmpD2(ii))
out=strcat(out,'0');
else
out=strcat(out,'1');
end
end
D(jj)=bin2dec(out);
end
Gaussian elimination in GF(2) works exactly the same way in essance than in R or C, except it's much easier due to the fact that 1+1=0. Here's the code :
A1 =[1 0 0 1 1 0 0 0 0 0 0 0 0 0;...
1 1 0 0 0 1 0 0 0 0 0 0 0 0;...
1 1 1 0 0 0 1 0 0 0 0 0 0 0;...
0 1 1 1 0 0 0 1 0 0 0 0 0 0;...
0 0 1 1 0 0 0 0 1 0 0 0 0 0;...
1 1 0 1 1 0 0 1 0 1 0 0 0 0;...
1 0 1 1 0 1 0 0 1 0 1 0 0 0;...
1 1 1 0 0 0 1 1 1 0 0 1 0 0;...
0 1 1 1 1 1 1 0 0 0 0 0 1 0;...
0 0 0 0 1 1 1 1 1 0 0 0 0 1;...
0 1 1 1 1 0 1 1 1 0 1 1 1 0;...
0 0 0 1 0 0 0 1 0 0 0 0 0 0;...
0 0 1 0 0 0 0 1 0 0 0 0 0 0;...
1 1 1 1 0 0 0 0 0 0 0 0 0 0;...
0 0 1 1 0 0 0 0 1 1 0 0 0 0;...
0 0 1 0 0 0 0 0 0 0 0 0 0 1 ];
D1=[0; 0; 0; 0 ; 0; 0 ; 0; 0 ; 0 ; 0 ; 103 ; 198 ; 105 ; 115; 175 ; 14];
for ii=1:14
% Find ii-th pivot index between row ii and last row
PivIndex=find(A1(ii:end,ii),1)+ii-1;
% Switch ii-th row with Pivot row
A1([ii PivIndex],:)=A1([PivIndex ii],:);
D1([ii PivIndex])=D1([PivIndex ii]);
% Find all rows other than row ii containing a 1 in column ii
RowIndexes=find(A1(:,ii));
RowIndexes(RowIndexes==ii)==[];
% Add row ii to all rows in RowIndexes, do the same in D
A1(RowIndexes,:)=mod(A1(RowIndexes,:)+repmat(A1(ii,:),numel(RowIndexes),1),2);
%% Problem with my answer was here, as the sum in GF(256) doesn t work like that. (GF(256),+) behaves like ((Z/2Z)^8,+)... See prequisite for summing in GF(256)
% D1(RowIndexes)=mod(D1(RowIndexes)+repmat(D1(ii),numel(RowIndexes),1),256);
D1(RowIndexes)=SumInGF256(D1(RowIndexes),repmat(D1(ii),numel(RowIndexes),1));
end
% Now A1 is diagonal, with both last rows being zero. Problem is D
% has to be 0 aswell on the 2 last positions to get 0=0..
% Check if D(15:16)==[0;0] if not the system has no solution
if isequal(D1(15:16),[0;0])
A2=A1(1:14,:);
C=D1(1:14)
else
disp('No solution')
end
Here the output is as you wanted :
C =
103 187 125 210 181 220 161
20 175 175 187 187 220 115
First of all, I would like thank BillBokeey for your work. However, I am working in GF(256), it is more complex than GF(2). After google, I find a good solution for my case. This is source code for rfc-6330. In that source code, he had a function that is rfc6330_gaussian. For my question above, it is easy to apply it by
C=rfc6330_gaussian( A1, D1 )
So the result will be similar my expected result
C=[ 103
187
125
210
181
220
161
20
175
175
187
187
220
115]
This ans. will be useful for anyone who has similar my issue.
I am working on an assignment where I have to take a large matrix containing data, and somehow compress the data so that it will be in a form of more manageable size. However, the data needs to be re-utilized as input to something else. (A toolbox, for example). Here's what I've done so far. For this example matrix, I use the find function to give me a matrix of all the indices where the values are non-zero. But I have no idea as to how to use it as input so that the original figure information is retained. I was curious if other folks had any other better (simple) solutions to this.
number_1 = [0 0 0 0 0 0 0 0 0 0 ...
0 0 1 1 1 1 0 0 0 0 ...
0 1 1 0 1 1 0 0 0 0 ...
0 1 1 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 1 1 1 1 1 1 1 1 0 ...
0 0 0 0 0 0 0 0 0 0];
number = number_1;
compressed_number = find(number);
compressed_number = compressed_number';
disp(compressed_number)
When you have only ones and zeros, and the fill factor is not terribly small, your best bet is to store the numbers as binary numbers; if you need the original size, save it separately. I have expanded the code, showing the intermediate steps a little more clearly, and also showing the amount of storage needed for the different arrays. Note - I reshaped your data into a 13x10 array because it displays better.
number_1 = [0 0 0 0 0 0 0 0 0 0 ...
0 0 1 1 1 1 0 0 0 0 ...
0 1 1 0 1 1 0 0 0 0 ...
0 1 1 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 0 0 0 1 1 0 0 0 0 ...
0 1 1 1 1 1 1 1 1 0 ...
0 0 0 0 0 0 0 0 0 0];
n1matrix = reshape(number_1, 10, [])'; % make it nicer to display;
% transpose because data is stored column-major (row index changes fastest).
disp('the original data in 13 rows of 10:');
disp(n1matrix);
% create a matrix with 8 rows and enough columns
n1 = numel(number_1);
nc = ceil(n1/8); % "enough columns"
npad = zeros(8, nc);
npad(1:n1) = number_1; % fill the first n1 elements: the rest is zero
binVec = 2.^(7-(0:7)); % 128, 64, 32, 16, 8, 4, 2, 1 ... powers of two
compressed1 = uint8(binVec * npad); % 128 * bit 1 + 64 * bit 2 + 32 * bit 3...
% showing what we did...
disp('Organizing into groups of 8, and calculated their decimal representation:')
for ii = 1:nc
fprintf(1,'%d ', npad(:, ii));
fprintf(1, '= %d\n', compressed1(ii));
end
% now the inverse operation: using dec2bin to turn decimals into binary
% this function returns strings, so some further processing is needed
% original code used de2bi (no typo) but that requires a communications toolbox
% like this the code is more portable
decompressed = dec2bin(compressed1);
disp('the string representation of the numbers recovered:');
disp(decompressed); % this looks a lot like the data in groups of 8, but it's a string
% now we turn them back into the original array
% remember it is a string right now, and the values are stored
% in column-major order so we need to transpose
recovered = ('1'==decompressed'); % all '1' characters become logical 1
display(recovered);
% alternative solution #1: use logical array
compressed2 = (n1matrix==1);
display(compressed2);
recovered = double(compressed2); % looks just the same...
% other suggestions 1: use find
compressed3 = find(n1matrix); % fewer elements, but each element is 8 bytes
compressed3b = uint8(compressed); % if you know you have fewer than 256 elements
% or use `sparse`
compressed4 = sparse(n1matrix);
% or use logical sparse:
compressed5 = sparse((n1matrix==1));
whos number_1 comp*
the original data in 13 rows of 10:
0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0
0 1 1 0 1 1 0 0 0 0
0 1 1 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0
Organizing into groups of 8, and their decimal representation:
0 0 0 0 0 0 0 0 = 0
0 0 0 0 1 1 1 1 = 15
0 0 0 0 0 1 1 0 = 6
1 1 0 0 0 0 0 1 = 193
1 0 1 1 0 0 0 0 = 176
0 0 0 0 1 1 0 0 = 12
0 0 0 0 0 0 1 1 = 3
0 0 0 0 0 0 0 0 = 0
1 1 0 0 0 0 0 0 = 192
0 0 1 1 0 0 0 0 = 48
0 0 0 0 1 1 0 0 = 12
0 0 0 0 0 0 1 1 = 3
0 0 0 0 0 0 0 0 = 0
1 1 0 0 0 0 0 1 = 193
1 1 1 1 1 1 1 0 = 254
0 0 0 0 0 0 0 0 = 0
0 0 0 0 0 0 0 0 = 0
the string representation of the numbers recovered:
00000000
00001111
00000110
11000001
10110000
00001100
00000011
00000000
11000000
00110000
00001100
00000011
00000000
11000001
11111110
00000000
00000000
compressed2 =
0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0
0 1 1 0 1 1 0 0 0 0
0 1 1 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0
recovered =
0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0
0 1 1 0 1 1 0 0 0 0
0 1 1 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0
Name Size Bytes Class Attributes
compressed1 1x17 17 uint8
compressed2 13x10 130 logical
compressed3 34x1 272 double
compressed3b 34x1 34 uint8
compressed4 13x10 632 double sparse
compressed5 13x10 394 logical sparse
number_1 1x130 1040 double
As you can see, the original array takes 1040 bytes; the compressed array takes 17. You get almost 64x compression (not quite because 132 is not a multiple of 8); only a very sparse dataset would be better compressed by some other means. The only thing that gets close (and that is super fast) is
compressed3b = uint8(find(number_1));
At 34 bytes, it is definitely a contender for small arrays (< 256 elements).
Note - when you save data in Matlab (using save(fileName, 'variableName')), some compression happens automatically. This leads to an interesting and surprising result. When you take each of the above variables and save them to file using Matlab's save, the file sizes in bytes become:
number_1 195
compressed1 202
compressed2 213
compressed3 219
compressed3b 222
compressed4 256
compressed5 252
On the other hand, if you create a binary file yourself using
fid = fopen('myFile.bin', 'wb');
fwrite(fid, compressed1)
fclose(fid)
It will by default write uint8, so the file sizes are 130, 17, 130, 34, 34 -- sparse arrays cannot be written in this way. It still shows the "complicated" compression having the best compression.
First of all, you can use the find function to get all non-zero indices of your array, instead of doing it manually. More info here: http://www.mathworks.com/help/matlab/ref/find.html
Anyways, you will need not only matrix but also the original size. So when you pass matrix into whatever, you must also pass in length(number_1). This is because matrix will not tell you how many 0s there were after the last 1. You can figure it out by subtracting the last value of matrix from the original length (there might be an off-by-one error there).