matrix cells of the same row and column - kdb

Is there a more efficient/idiomatic way to retrieve cells of a matrix that are on the same row and column as the given cell?
q) f:{except[;y] x[y div n;],x[;y mod n:count first x]}
q) show A:s#til prd s:2 3
0 1 2
3 4 5
q) f[A;4]
3 5 1
q) f[A;2]
0 1 5

g:{
s:count each 1 first\x; // shape
rc:s vs y; // y as row-column
on:rc+/:{x,reverse each x} -1 1,'0; // orthogonal neighbours of rc
nn:on where all flip[on]within'0,'s-1; // near neighbours: eliminate out of range
x ./:nn }
q)A:2 3#til prd 2 3
q)g[A;4]
1 3 5
q)g[A;2]
5 1
If A contains only the indices of its raze (raze A) then we need only its shape, and g can return the indexes of the orthogonal neighbours of y.
h:{[s;y]
rc:s vs y; // y as row-column
on:rc+/:{x,reverse each x} -1 1,'0; // orthogonal neighbours of rc
nn:on where all flip[on]within'0,'s-1; // near neighbours: eliminate out of range
s sv/:nn }
q)h[2 3;4]
1 3 5
q)h[2 3;2]
5 1
Note that this can easily be adapted to diagonal neighbours instead of or as well as orthogonal neighbours; also to vector y.
Key concepts
Use sv and vs to encode/decode numbers to any arithmetical base
Use of map iterators Each and Each Right to control iteration

I'm not sure if your approach works in the general case? It may only work for your specific setup, e.g.
q)A:3 cut neg[6]?20
q)A
12 13 4
7 9 17
q)f[A;9]
12 7
One alternative approach is to use in to find the columns and rows to include
f2:{except[raze(x where y in'x),f where y in'f:flip x;y]}
q)f2[A;9]
7 17 13

Related

kdb q - create 2d buckets for positive integers

I am trying create 2d buckets in q
Given a 2d grid
5 o---o---o
| | |
3 o---o---o
| | |
0 o---o---o
0 3 5
each node on the grid defines the boundary of 2d buckets for positive integers. For example the center node would contain tuples (x;y) where 3<=x<5 and 3<=y<5. The nine buckets are indexed from 0,...,8.
The way I tried to implemented this in q is
bucketidx:{((0 3 5i) cross (0 3 5i)) bin "i"$(first x;last x)}
To traverse through the buckets:
bucketidx each ((0 3 5i) cross (0 3 5i))
/0j, 1j, 2j, 3j, 4j, 5j, 6j, 7j, 8j
However I get a strange behavior on bucketidx 6 0. I expect this to be in the upper left node
(5<=y) and (x=0)
but it returns index 8 which would be the upper right node. I hope it is clear what I am trying to do.
Thanks for the help
Thats because of the bin behavior.
Binary search returns the index of the last item in x which is <=y
https://code.kx.com/q/ref/search/#bin-binr
Your list is :
q) a:(0 3 5i) cross (0 3 5i)
q) a / (0 0; 0 3;0 5;3 0; 3 3; 3 5;5 0;5 3; 5 5)
You are searching (6 0) in this list using bin function and last item in that list which is <=(6;0) is (5;5) and index of that item is 8.
q) a bin 6 0 / 8
thats the reason you are getting 8.
I think 'tuple with bin' approach is not the right way to go for this problem.
You could use something similar to below idea. First argument to function is X coordinate and second is Y coordinate.
q) node:{b:0 3 5;(b bin x)+3*b bin y}
q) node[0;6] / 6
Another approach is to use a dictionary with sorted attribute, which makes it a step function.
q)d:`s#0 3 5!0 1 2
q)3 sv' d#(0 3 5i) cross (0 3 5i)
0 1 2 3 4 5 6 7 8
q)3 sv' d#enlist 6 0
,6

Choose multiple combination (matlab)

I have 3 sets of array each contains 12 elements of same type
a=[1 1 1 1 1 1 1 1 1 1 1];
b=[2 2 2 2 2 2 2 2 2 2 2];
c=[3 3 3 3 3 3 3 3 3 3 3];
I have to find how many ways it can be picked up if I need to pickup 12 items at a time
here, 1 1 2 is same as 2 1 1
I found this link Generating all combinations with repetition using MATLAB.
Ho this can be done in matlab within reasonable time.
is that way correct
abc=[a b c];
allcombs=nmultichoosek(abc,12);
combs=unique(allcombs,'rows');
If you only need to find the number of ways to select the items, then using generating functions is a way to very efficiently compute that, even for fairly large values of N and k.
If you are not familiar with generating functions, you can read up on the math background here:
http://mathworld.wolfram.com/GeneratingFunction.html
and here:
http://math.arizona.edu/~faris/combinatoricsweb/generate.pdf
The solution hinges on the fact that the number of ways to choose k items from 36, with each of 3 items repeated 12 times, can be determined from the product of the generating function:
g(x) = 1 + x + x^2 + x^3 + ... + x^12
with itself 3 times. The 12 comes from the fact the elements are repeated 12 times (NOT from the fact you are choosing 12), and multiplying by itself 3 times is because there are three different sets of elements. The number of ways to choose 12 elements is then just the coefficient of the power of x^12 in this product of polynomials (try it for smaller examples if you want to prove to yourself that it works).
The great thing about that is that MATLAB has a simple function conv for multiplying polynomials:
>> g = ones(1,13); %% array of 13 ones, for a 12th degree polynomial with all `1` coefficents
>> prod = conv(g, conv(g, g)); %% multiply g by itself 3 times, as a polynomial
>> prod(13)
ans =
91
So there are 91 ways to select 12 elements from your list of 36. If you want to select 11 elements, that's z(12) = 78. If you want to select 13 elements, that's z(14) = 102.
Finally, if you had different numbers of elements in the sets, say 10 1's, 12 2's, and 14 3's, then you would have 3 distinct polynomials of the same form, 1 + x + x^2 + ..., with degrees 10, 12 and 14 respectively. Inspecting the coefficient of the degree k term again gives you the number of ways to choose k elements from this set.

Vector-defined cross product application matrix and vectorization in Matlab

I ran into an operation I cannot seem to achieve via vectorization.
Let's say I want to find the matrix of the application defined by
h: X -> cross(V,X)
where V is a predetermined vector (both X and V are 3-by-1 vectors).
In Matlab, I would do something like
M= cross(repmat(V,1,3),eye(3,3))
to get this matrix. For instance, V=[1;2;3] yields
M =
0 -3 2
3 0 -1
-2 1 0
Let's now suppose that I have a 3-by-N matrix
V=[V_1,V_2...V_N]
with each column defining its own cross-product operation. For N=2, here's a naive try to find the two cross-product matrices that V's columns define
V=[1,2,3;4,5,6]'
M=cross(repmat(V,1,3),repmat(eye(3,3),1,2))
results in
V =
1 4
2 5
3 6
M =
0 -6 2 0 -3 5
3 0 -1 6 0 -4
-2 4 0 -5 1 0
while I was expecting
M =
0 -3 2 0 -6 5
3 0 -1 6 0 -4
-2 1 0 -5 4 0
2 columns are inverted.
Is there a way to achieve this without for loops?
Thanks!
First, make sure you read the documentation of cross very carefully when dealing with matrices:
It says:
C = cross(A,B,DIM), where A and B are N-D arrays, returns the cross
product of vectors in the dimension DIM of A and B. A and B must
have the same size, and both SIZE(A,DIM) and SIZE(B,DIM) must be 3.
Bear in mind that if you don't specify DIM, it's automatically assumed to be 1, so you're operating along the columns. In your first case, you specified both the inputs A and B to be 3 x 3 matrices. Therefore, the output will be the cross product of each column independently due to the assumption that DIM=1. As such, you expect that the i'th column of the output contains the cross product of the i'th column of A and the i'th column of B and the number of rows is expected to be 3 and the number of columns needs to match between A and B.
You're getting what you expect because the first input A has [1;2;3] duplicated correctly over the columns three times. From your second piece of code, what you're expecting for V as the first input (A) looks like this:
V =
1 1 1 4 4 4
2 2 2 5 5 5
3 3 3 6 6 6
However, when you do repmat, you are in fact alternating between each column. In fact, you are getting this:
V =
1 4 1 4 1 4
2 5 2 5 2 5
3 6 3 6 3 6
repmat tile matrices together and you specified that you wanted to tile V horizontally three times. That's obviously not correct. This explains why the columns are swapped because the second, fourth and sixth columns of V actually should appear at the last three columns instead. As such, the ordering of your input columns is the reason why the output appears swapped.
As such, you need to re-order V so that the first three vectors are [1;2;3], followed by the next three vectors as [4;5;6] after. Therefore, you can generate your original V matrix first, then create a new matrix such that the odd column comes first in a group of three, followed by the even column in a group of three after:
>> V = [1,2,3;4,5,6].';
>> V = V(:, [1 1 1 2 2 2])
V =
1 1 1 4 4 4
2 2 2 5 5 5
3 3 3 6 6 6
Now use V with cross and maintain the same second input:
>> M = cross(V, repmat(eye(3), 1, 2))
M =
0 -3 2 0 -6 5
3 0 -1 6 0 -4
-2 1 0 -5 4 0
Looks good to me!

Matlab, Sum Function for a Matrix row

Basically the sum function calculate the sum of the columns, that is to say if we have a 4x4 matrix we would get a 1X4 vector
A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
sum(A)
ans =
34 34 34 34
But if I want to get the Summation of the rows then i have 2 methods, the first is to get the transpose of the matrix then get the summation of the transposed matrix,and finally get the transpose of the result...., The Second method is to use dimension argument for the Sum function "sum(A, 2)"
A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
sum(A,2)
ans =
34
34
34
34
The problem is here I cannot understand how this is done, If anyone could please tell me the idea/concept behind this method,
It's hard to tell exactly how sum internally works, but we can guess it does something similar to this.
Matlab stores matrices (or N-dimensional arrays) in memory using column-major order. This means the order for the elements in memory for a 3 x 4 matrix is
1 4 7 10
2 5 8 11
3 6 9 12
So it first stores element (1,1), then (1,2), then (13), then (2,1), ...
In fact, this is the order you use when you apply linear indexing (that is, index a matrix with a single number). For example, let
A = [7 8 6 2
9 0 3 5
6 3 2 1];
Then A(4) gives 8.
With this in mind, it's easy to guess that what sum(A,1) does is traverse elements consecutively: A(1)+A(2)+A(3) to obtain the sum of the first column, then A(4)+A(5)+A(6) to sum the second column, etc. In contrast, sum(A,2) proceeds in steps of size(A,1) (3 in this example): A(1)+A(4)+A(7)+A(10) to compute the sum of the first row, etc.
As a side note, this is probably related with the observed fact that sum(A,1) is faster than sum(A,2).
I'm really not sure what you are asking. sum takes two inputs, the first of which is a multidimensional array A, say.
Now let's take sA = size(A), and d between 1 and ndims(A).
To understand what B = sum(A,d) does, first we find out what the size of B is.
That's easy, sB = sA; sB(d) = 1;. So in a way, it will "reduce" the size of A along dimension d.
The rest is trivial: every element in B is the sum of elements in A along dimension d.
Basically, sum(A) = sum(A,1) which outputs the sum of the columns in the matrix. 1 indicates the columns. So, sum(A,2) outputs the sum of the rows in the matrix. 2 indicating the rows. More than that, the sum command will output the entire matrix because there is only 2 dimensions (rows and columns)

Matlab - Quickly subtract [1xN] array from [MxN] matrix elements [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
How to subtract a vector from each row of a matrix?
How can I divide each row of a matrix by a fixed row?
I have matrix (M1) of M rows and 4 columns. I have another array (M2) of 1 row and 4 columns. I'd like to subtract every element in M1 by its respective column element in M2. In other words, each column of M1 needs to be subtraced by the scalar in the same column position in M2. I could call repmat(M2,M,1), which would create a NEW matrix of size MxN, where each element in a column was the same, and then do a element by element subtraction:
M2new = repmat(M2,M,1)
final = M1 - M2new
, however, this is two lines of code and creates a new element in memory. What is the fastest and least memory intensive way of performing this operation?
Use bsxfun like in the following example.
x=magic(4);
y=x(1,:);
z=bsxfun(#minus,x,y)
z =
0 0 0 0
-11 9 7 -5
-7 5 3 -1
-12 12 12 -12
Here z is obtained by subtracting the first row from every row. Just replace x with your matrix and y with your row vector, and you'r all set.
bsxfun(.) can potentially be more efficient, but personally as an old timer, I'll would recommend not to totally ignore linear algebra based solutions, like:
> M1= magic(4)
M1 =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
> M2= M1(1, :)
M2 =
16 2 3 13
> M1- ones(4, 1)* M2
ans =
0 0 0 0
-11 9 7 -5
-7 5 3 -1
-12 12 12 -12
Let the actual use case and profiler to decide the functionality actually utilized.