How to count the elements of a sparse matrix in a certain region? - matlab
I have a sparse matrix and want to divide the region into 4 parts, dividing x and y in 2 equidistant pieces and want to calculate the sum of the corresponding values.
For the example below, the coordinates x-y each corresponds to [0,16] so the region is a square. There is a sparse matrix in this square, which is symmetrical. I would like to divide the region into smaller squares and sum up the sparse values. Region 0:8,0:8 has 2 elements and their values are both (2,3)=(3,2)=8 so the sum is 16.
Summation of the 1st region should give 16, 2nd and 3rd are 36 and the 4th one is 26.
x = sparse(16,16);
x (3,2) = 8;
x (10,2) = 8;
x (13,2) = 8;
x (14,2) = 4;
x (15,2) = 4;
x (2,3) = 8;
x (10,3) = 4;
x (13,3) = 4;
x (14,3) = 2;
x (15,3) = 2;
x (2,10) = 8;
x (3,10) = 4;
x (13,10) = 4;
x (14,10) = 2;
x (15,10) = 2;
x (2,13) = 8;
x (3,13) = 4;
x (10,13) = 4;
x (14,13) = 2;
x (15,13) = 2;
x (2,14) = 4;
x (3,14) = 2;
x (10,14) = 2;
x (13,14) = 2;
x (15,14) = 1;
x (2,15) = 4;
x (3,15) = 2;
x (10,15) = 2;
x (13,15) = 2;
x (14,15) = 1;
i would rather appriciate a shorter way, rather than writing a line for each sub-square. lets say for 6000 sub-squares one should write 6000 lines?
Let's define the input in a more convenient way:
X = sparse([...
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 8, 0, 0, 0, 0, 0, 0, 8, 0, 0, 8, 4, 4
0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 2, 2
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 8, 4, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 2, 2
0, 4, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 1
0, 4, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 1, 0]);
For convenience, we first make the array dimensions even. We don't use padarray() for this because this makes the sparse matrix full!
sz = size(X);
newX = sparse(sz(1)+1,sz(2)+1);
padTopLeft = true; % < chosen arbitrarily
if padTopLeft
newX(2:end,2:end) = X;
else % bottom right
newX(1:sz(1),1:sz(2)) = X;
end
%% Preallocate results:
sums = zeros(2,2,2);
Method #1: accumarray
We create a mask of the form:
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
and then use it to sum the appropriate elements of newX:
sums(:,:,1) = reshape(...
accumarray(reshape(repelem([1,2;3,4], ceil(sz(1)/2), ceil(sz(2)/2)),[],1),...
reshape(newX, [],1),...
[],#sum) ,2,2);
Method #2: blockproc (requires the Image Processing Toolbox)
sums(:,:,2) = blockproc(full(newX), ceil(sz/2), #(x)sum(x.data(:)));
Several notes:
I also tried histcounts2, which is very short, but it only tells you the amount of values in each quadrant, not their sum:
[r,c] = find(newX);
histcounts2(r,c,[2,2])
I might've overcomplicated the accumarray solution.
Although your question is not very precise and you don't made any efford to find a solution, here is what you are asking..
clear;clc;close;
Matrix=rand(20,20);
Acc=zeros(1,4);
Acc(1)=sum(sum( Matrix(1:size(Matrix,1)/2,1:size(Matrix,2)/2) ));
Acc(2)=sum(sum( Matrix((size(Matrix,1)/2)+1:end,1:size(Matrix,2)/2)));
Acc(3)=sum(sum( Matrix(1:size(Matrix,1)/2,((size(Matrix,2)/2)+1):end )));
Acc(4)=sum(sum( Matrix((size(Matrix,1)/2)+1:end,((size(Matrix,2)/2)+1):end)));
% Verification
sum(sum(Matrix)) % <- is the same with
sum(Acc) % <- this
You can define any rectangle within the matrix by defining the 4 corners of it. Then use a for loop to process all rectangles.
regions = [
1 8 1 8
9 16 1 8
1 8 9 16
9 16 9 16
];
regionsum = zeros(size(regions,1),1);
for rr = 1:size(regions,1)
submat = x(regions(rr,1):regions(rr,2),regions(rr,3):regions(rr,4));
regionsum(rr) = sum(submat(:));
end
>> regionsum
regionsum =
16
36
36
26
If you mean you want to divide the square matrix into 2^N (N>2) squares of the same size then you can write regions with a for loop.
N = 1; % 2^N-by-2^N sub-squares
L = size(x,1);
dL = L/(2^N);
assert(dL==int32(dL),'Too many divisions')
segments = zeros(2^N,2);
for nn = 1:2^N
segments(nn,:) = [1,dL]+dL*(nn-1);
end
regions = zeros(2^(2*N),4);
for ss = 1:2^N
for tt = 1:2^N
regions((2^N)*(ss-1) + tt,:) = [segments(ss,:),segments(tt,:)];
end
end
example output with dividing into 16 (N=2) square submatrices:
>> regions
regions =
1 4 1 4
1 4 5 8
1 4 9 12
1 4 13 16
5 8 1 4
5 8 5 8
5 8 9 12
5 8 13 16
9 12 1 4
9 12 5 8
9 12 9 12
9 12 13 16
13 16 1 4
13 16 5 8
13 16 9 12
13 16 13 16
>> regionsum
regionsum =
16
0
12
24
0
0
0
0
12
0
0
8
24
0
8
10
>>
Related
How to render a structured mesh in Octave
I would like to recreate this sort of "cubic" surface rendering in GNU Octave: [From AEG Mesher documentation] How can I achieve this, given a list of coordinates which represent a surface or volume in a structured grid?
Obviously there's probably much more elaborate frameworks out there, but just to demonstrate the concept: the idea that you can only work with triangular patches is incorrect. You can specify your own patches as elaborately as you want. In the following example, I create a simple function which draws a 3D cube 'patch', to be treated as a 'pixel' element in a structured 'mesh'. function drawpatchpixel( x, y, z, c ) Vertices = [ 0, 0, 0 0, 1, 0 1, 1, 0 1, 0, 0 0, 0, 1 0, 1, 1 1, 1, 1 1, 0, 1 ]; Faces = [ 1, 2, 3, 4 # front 2, 6, 7, 3 # top 5, 6, 7, 8 # back 1, 5, 8, 4 # bottom 1, 2, 6, 5 # left 4, 3, 7, 8 ]; # right patch( 'Faces', Faces, 'Vertices', Vertices + [x, y, z], 'facecolor', c ) endfunction Then I simply draw the pixels in the preferred colour: Pixels = { 0, 0, 0, 'r'; # base 1, 0, 0, 'r'; 2, 0, 0, 'r'; 3, 0, 0, 'r'; 4, 0, 0, 'r'; 4, 1, 0, 'r'; 4, 2, 0, 'r'; 4, 3, 0, 'r'; 4, 4, 0, 'r'; 3, 4, 0, 'r'; 2, 4, 0, 'r'; 1, 4, 0, 'r'; 0, 4, 0, 'r'; 0, 3, 0, 'r'; 0, 2, 0, 'r'; 0, 1, 0, 'r'; 0, 0, 1, [0.5, 0.5, 0.5]; # pillars 0, 0, 2, [0.5, 0.5, 0.5]; 0, 0, 3, [0.5, 0.5, 0.5]; 0, 0, 4, [0.5, 0.5, 0.5]; 4, 0, 1, [0.5, 0.5, 0.5]; 4, 0, 2, [0.5, 0.5, 0.5]; 4, 0, 3, [0.5, 0.5, 0.5]; 4, 0, 4, [0.5, 0.5, 0.5]; 4, 4, 1, [0.5, 0.5, 0.5]; 4, 4, 2, [0.5, 0.5, 0.5]; 4, 4, 3, [0.5, 0.5, 0.5]; 4, 4, 4, [0.5, 0.5, 0.5]; 0, 4, 1, [0.5, 0.5, 0.5]; 0, 4, 2, [0.5, 0.5, 0.5]; 0, 4, 3, [0.5, 0.5, 0.5]; 0, 4, 4, [0.5, 0.5, 0.5]; 0, 1, 4, 'g'; # roof 0, 2, 4, 'g'; 0, 3, 4, 'g'; 4, 1, 4, 'g'; 4, 2, 4, 'g'; 4, 3, 4, 'g'; 1, 0, 4, 'g'; 2, 0, 4, 'g'; 3, 0, 4, 'g'; 1, 4, 4, 'g'; 2, 4, 4, 'g'; 3, 4, 4, 'g'; }; NPixels = size( Pixels, 1 ); for i = 1 : NPixels drawpatchpixel( Pixels{i, :} ) endfor axis equal view( 30, 30 ) xlabel( 'x'); ylabel('y'), zlabel('z'); camlight Result:
multiply the number in the array if it matches the given one
I have an array like this, and I need to multiply a number if it is 3, but in the end reduce eliminates all numbers equal to 3, and multiplies the rest. How do I fix this ? let arr = [2, 4, 3, 1, 4, 3, 1, 3, 10, 4, 2, 13] let aaa = arr.reduce([]) { $1 == 3 ? $0 : $0 + [$1 * 5] } //[10, 20, 5, 20, 5, 50, 20, 10, 65] //[2,4,15,1,4,15,1,15,10,4,2,13] need this
You should use map instead of reduce let arr = [2, 4, 3, 1, 4, 3, 1, 3, 10, 4, 2, 13] let result = arr.map { $0 == 3 ? 15 : $0 } // [2, 4, 15, 1, 4, 15, 1, 15, 10, 4, 2, 13 Or if it should work for any multiple of 3 let result = arr.map { $0.isMultiple(of: 3) ? $0 * 5 : $0 }
How to manage the hidden state dims when using pad_sequence?
Using Pytorch LSTM architecture trying to build a text generation model. For every batch, I'm using pad_sequence to have min padding for every sequence, therefore I have a variable dims batch (batch_size * seq_len). I'm applying also pack_padded_seq to only give the non-zero (non-padding) tokens to the LSTM. But, the variable dims batch throws an error while feeding it to the LSTM as following; Expected hidden[0] size (1, 8, 16), got (1, 16, 16). In this error, I have provided batch size 16 with 8 tokens for every sequence, but the hidden state is 16 * 16. I have tried to create the hidden state in the forward function, but that did not work well. How can I create the hidden state such that it can accept variable dims batch and it will not be lost for the whole epoche? class RNNModule(nn.Module): def __init__(self, n_vocab, seq_size, embedding_size, lstm_size): super(RNNModule, self).__init__() self.seq_size = seq_size self.lstm_size = lstm_size self.embedding, num_embeddings, embedding_dim = create_emb_layer(weight_matrix, False) self.lstm = nn.LSTM(embedding_size, lstm_size, num_layers=flags.n_layers, batch_first=True ) self.dense = nn.Linear(lstm_size, n_vocab) def forward(self, x,length,prev_state): embed = self.embedding(x) packed_input = db.pack_src(embed,length) packed_output, state = self.lstm(packed_input,prev_state) padded,_ = db.pad_pack(packed_output) logits = self.dense(padded) return logits, state def zero_state(self, batch_size = flags.batch_size): return (torch.zeros(flags.n_layers, batch_size, self.lstm_size), torch.zeros(flags.n_layers, batch_size, self.lstm_size)) input: tensor([[ 19, 9, 4, 3, 68, 8, 6, 2], [ 19, 9, 4, 3, 7, 8, 6, 2], [ 3, 12, 17, 10, 6, 40, 2, 0], [ 4, 3, 109, 7, 6, 2, 0, 0], [ 188, 6, 7, 18, 3, 2, 0, 0], [ 4, 3, 12, 6, 7, 2, 0, 0], [ 6, 7, 3, 13, 2, 0, 0, 0], [ 3, 28, 17, 69, 2, 0, 0, 0], [ 6, 3, 12, 11, 2, 0, 0, 0], [ 3, 13, 6, 7, 2, 0, 0, 0], [ 3, 6, 7, 13, 2, 0, 0, 0], [ 6, 3, 23, 7, 2, 0, 0, 0], [ 3, 28, 10, 2, 0, 0, 0, 0], [ 6, 3, 23, 2, 0, 0, 0, 0], [ 3, 6, 37, 2, 0, 0, 0, 0], [1218, 2, 0, 0, 0, 0, 0, 0]]) Zero tokens are padding. Embedding size: 64 LSTM size: 16 batch size: 16
The size of the hidden state you create has the correct size, but your input does not. When you pack it with nn.utils.rnn.pack_padded_sequence you've set batch_first=False, but your data has size [batch_size, seq_len, embedding_size] when you pass it to the packing, so that has batch_size as the first dimension. Also for the LSTM you use batch_first=True, which is appropriate for your data. You only need to pack it correctly by setting batch_first=True as well, to match the order of your data. rnn_utils.pack_padded_sequence(embed,length,batch_first=True)
Remove zero rows from a list of list in Scala
I have a list of list in Scala such as: val lst = List(List(60, 0, 1, 2, 3, 28, 0, 0, 0, 0), List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), List(47, 0, 1, 1, 2, 28, 0, 0, 0, 0)) and I want to remove all zero rows and the result should be like: List(List(60, 0, 1, 2, 3, 28, 0, 0, 0, 0), List(47, 0, 1, 1, 2, 28, 0, 0, 0, 0)) Does Scala list have any built-in method to remove these rows?
You can use filter to keep only items (lists) matching a predicate; The predicate can use exists to check for non-zero elements: lst.filter(_.exists(_ != 0))
#Tzach Zohar answer is perfectly fine but here is another way to approach it. scala> lst.filterNot(xs => xs.forall(_ == 0)) res0: List[List[Int]] = List( List(60, 0, 1, 2, 3, 28, 0, 0, 0, 0), List(47, 0, 1, 1, 2, 28, 0, 0, 0, 0) )
Extendible hashing for file with given search key values for records
I know that SO might be the wrong place to look for answers to questions such as these, but at the moment I need the answer and how to work it out step by step urgently. Suppose that we are using extendable hashing on a file that contains records with the following search-key values: 2, 3, 5, 7, 11, 17, 19, 23, 29, 31 Show the extendable hash structure for this file if the hash function is h(x) = x mod 8 and buckets can hold three records. EDIT: I have the "supposed" answer to this: http://i.imgur.com/CW8H8vG.png But I am not sure if this is correct, since when I work it out, I get a different hash structure. If it is correct, could anyone explain to me why?
h(2) = 2 => 0, 0, 2, 0, 0, 0, 0, 0 h(3) = 3 => 0, 0, 2, 3, 0, 0, 0, 0 h(5) = 5 => 0, 0, 2, 3, 0, 5, 0, 0 h(7) = 7 => 0, 0, 2, 3, 0, 5, 0, 7 h(11) = 3 => 0, 0, 2, { 3, 11 }, 0, 5, 0, 7 h(17) = 1 => 0, 17, 2, { 3, 11 }, 0, 5, 0, 7 h(19) = 3 => 0, 17, 2, { 3, 11, 19 }, 0, 5, 0, 7 h(23) = 7 => 0, 17, 2, { 3, 11, 19 }, 0, 5, 0, { 7, 23 } h(29) = 5 => 0, 17, 2, { 3, 11, 19 }, 0, { 5, 29 }, 0, { 7, 23 } h(31) = 7 => 0, 17, 2, { 3, 11, 19 }, 0, { 5, 29 }, 0, { 7, 23, 31 }