Consider two graphs, G1 = (V1, E1), G2 = (V2, E2)
V1 = {1,2,3,4,5,6}
V2 = {7,8,9,10,11,12}
In space, these vertices are connected by triangles faces (each with three vertices)
F1 = [[ 2, 1, 0], [ 0, 3, 2], [ 1, 4, 0], [ 0, 4, 3], [ 5, 1, 2], [ 3, 5, 2], [ 5, 4, 1], [ 4, 5, 3]]
F2 = [[ 8, 7, 6], [ 6, 9, 8], [ 7, 10, 6], [ 6, 10, 9], [11, 7, 8], [ 9, 11, 8], [11, 10, 7], [10, 11, 9]]
The above is what I am trying to find. If we are given the entire array of faces:
faces = [[ 2, 1, 0], [ 0, 3, 2], [ 1, 4, 0], [ 0, 4, 3], [ 5, 1, 2], [ 3, 5, 2],
[ 5, 4, 1], [ 4, 5, 3], [ 8, 7, 6], [ 6, 9, 8], [ 7, 10, 6], [ 6, 10, 9],
[11, 7, 8], [ 9, 11, 8], [11, 10, 7], [10, 11, 9]]
can we find the connected components, and separate into F1 and F2?
A version of this problem has been solved in Mathematica, but I cannot translate.
My work is found in this post.
Making a graph from your faces is pretty straightforward: each triplet yields 3 edges corresponding to all combinations of the triplet's members. Then it is just a matter of instantiating the networkx Graph object and calling networkx.algorithms.components.connected_components.
#!/usr/bin/env python
"""
Given a list of triangles, find the connected components.
https://stackoverflow.com/q/61584283/2912349
"""
import itertools
import networkx as nx
faces = [[ 2, 1, 0], [ 0, 3, 2], [ 1, 4, 0], [ 0, 4, 3], [ 5, 1, 2], [ 3, 5, 2],
[ 5, 4, 1], [ 4, 5, 3], [ 8, 7, 6], [ 6, 9, 8], [ 7, 10, 6], [ 6, 10, 9],
[11, 7, 8], [ 9, 11, 8], [11, 10, 7], [10, 11, 9]]
#create graph
edges = []
for face in faces:
edges.extend(list(itertools.combinations(face, 2)))
g = nx.from_edgelist(edges)
# compute connected components and print results
components = list(nx.algorithms.components.connected_components(g))
for component in components:
print(component)
# {0, 1, 2, 3, 4, 5}
# {6, 7, 8, 9, 10, 11}
# separate faces by component
component_to_faces = dict()
for component in components:
component_to_faces[tuple(component)] = [face for face in faces if set(face) <= component] # <= operator tests for subset relation
for component, component_faces in component_to_faces.items():
print(component, component_faces)
# (0, 1, 2, 3, 4, 5) [[2, 1, 0], [0, 3, 2], [1, 4, 0], [0, 4, 3], [5, 1, 2], [3, 5, 2], [5, 4, 1], [4, 5, 3]]
# (6, 7, 8, 9, 10, 11) [[8, 7, 6], [6, 9, 8], [7, 10, 6], [6, 10, 9], [11, 7, 8], [9, 11, 8], [11, 10, 7], [10, 11, 9]]
Related
Assuming i have the following array:
a = array([[[4, 8, 7, 3, 1, 2],
[3, 1, 8, 7, 1, 9],
[0, 0, 3, 0, 7, 6],
[1, 1, 5, 0, 5, 1],
[1, 6, 7, 0, 6, 2]],
[[8, 1, 1, 0, 0, 0],
[2, 8, 1, 6, 4, 9],
[1, 8, 7, 2, 2, 2],
[6, 6, 2, 6, 0, 5],
[3, 2, 2, 0, 6, 8]],
[[4, 6, 3, 2, 1, 4],
[0, 4, 3, 5, 9, 4],
[1, 4, 6, 7, 2, 4],
[6, 3, 5, 7, 7, 8],
[1, 0, 3, 9, 2, 5]],
[[7, 7, 3, 9, 7, 0],
[8, 5, 1, 4, 3, 9],
[9, 7, 9, 5, 4, 9],
[2, 0, 6, 0, 8, 5],
[4, 4, 4, 7, 5, 2]],
[[4, 0, 8, 2, 1, 0],
[2, 4, 0, 7, 3, 7],
[4, 6, 8, 7, 9, 6],
[3, 2, 7, 5, 2, 3],
[7, 6, 3, 0, 1, 5]]])
Is there an easy way to reduce the column values by summing to get the following array:
b = array([[[12, 10, 3],
[4, 15, 10],
[0, 3, 13],
[2, 5, 6],
[7, 7, 8]],
...])
The first row is achieved by:[4+8, 7+3, 1+2]. I know we can use np.sum to merge columns but I am lost on how to select the right columns to add together. Help is greatly appreciated!
You can do simply this:
a.reshape((5,5,3,2)).sum(axis=-1)
reshape((5,5,3,2)) will 'split' the last dimension into groups of 2, the sum(axis=-1) will sum over that last freshly created dimension.
In the general case (if the dimensions of a change) you can also use
a.reshape(a.shape[:-1]+(-1,2)).sum(axis=-1)
We can do this with simple numpy slicing.
b = a[:,:,::2] + a[:,:,1::2]
This tells us to select the whole array, and at the last dimension select the even columns, then the odd columns, and add them together elementwise.
I have two numpy arrays A and l. The dimension of A is (n, x, y) and the dimension of l is (n,1). I get the result as follows:
res = []
for i in range(n):
res.append(A[i, x, l[i])
This way of getting the result is very time consuming for a larger value of n. Is there an alternative to get the same result quickly?
If 0<=l[i]<y for all values of i:
>>> n,x,y = 4,5,6
>>> A = np.random.randint(0,10,(n,x,y))
array([[[3, 3, 3, 8, 7, 0],
[8, 1, 1, 5, 3, 8],
[0, 1, 0, 4, 1, 3],
[2, 2, 1, 8, 6, 5],
[2, 5, 9, 2, 6, 3]],
[[9, 7, 4, 6, 7, 7],
[1, 7, 0, 4, 9, 6],
[8, 0, 8, 6, 7, 8],
[1, 9, 7, 8, 7, 6],
[2, 4, 6, 3, 6, 8]],
[[2, 8, 5, 7, 9, 4],
[7, 2, 2, 5, 2, 1],
[0, 8, 6, 4, 1, 2],
[6, 9, 9, 0, 2, 4],
[9, 9, 1, 6, 7, 0]],
[[3, 8, 4, 3, 5, 6],
[5, 3, 7, 7, 4, 6],
[9, 0, 7, 9, 2, 1],
[1, 6, 2, 2, 9, 5],
[5, 0, 9, 0, 5, 2]]])
>>> l = np.random.randint(low=0, high=y-1, size=(n,1))
array([[0],
[1],
[3],
[1]])
>>> x0 = 2
>>> res = []
>>> for i in range(n):
res.append(A[i, x0, l[i])
>>> res
[array([0]), array([0]), array([4]), array([0])]
numpy:
>>> A[range(n), 2, l.flatten()]
array([0, 0, 4, 0])
what about list comprehension?
res=[A[i, x, l[i] for i in range(n)]
I have a 4000 x 16 matrix A. I have 256 x 1 vector B. I need to get the elementwise addition for each element in A with every element of B and get a 3D array of size 4000 x 16 x 256. What is the most efficient way to achieve this without loops with numpy?
You can first reshape A to a 4000×16×1 matrix, and B to 1×1×256 matrix. Then you can perform addition:
A[:,:,None] + B.reshape(1, 1, -1)
For A a 4×5 matrix, and B a 3×1 matrix, for example, we get:
>>> A
array([[1, 2, 2, 2, 2],
[2, 1, 0, 3, 2],
[4, 1, 2, 1, 3],
[3, 2, 3, 2, 2]])
>>> B
array([[0],
[3],
[3],
[6],
[4],
[3]])
>>> A[:,:,None] + B.reshape(1, 1, -1)
array([[[ 1, 4, 4, 7, 5, 4],
[ 2, 5, 5, 8, 6, 5],
[ 2, 5, 5, 8, 6, 5],
[ 2, 5, 5, 8, 6, 5],
[ 2, 5, 5, 8, 6, 5]],
[[ 2, 5, 5, 8, 6, 5],
[ 1, 4, 4, 7, 5, 4],
[ 0, 3, 3, 6, 4, 3],
[ 3, 6, 6, 9, 7, 6],
[ 2, 5, 5, 8, 6, 5]],
[[ 4, 7, 7, 10, 8, 7],
[ 1, 4, 4, 7, 5, 4],
[ 2, 5, 5, 8, 6, 5],
[ 1, 4, 4, 7, 5, 4],
[ 3, 6, 6, 9, 7, 6]],
[[ 3, 6, 6, 9, 7, 6],
[ 2, 5, 5, 8, 6, 5],
[ 3, 6, 6, 9, 7, 6],
[ 2, 5, 5, 8, 6, 5],
[ 2, 5, 5, 8, 6, 5]]])
Performance: If I run the above 100 times with A a 4000×16 matrix, and B a 256×1 matrix of floating points, I get the following results:
>>> timeit(lambda: A[:,:,None] + B.reshape(1, 1, -1), number=100)
5.949456596048549
It thus takes roughly 59.49457ms for a single run. This looks reasonable to calculate 16'384'000 elements.
This is where numpy's broadcasting and np.transpose() features really shine!
A[:,:, np.newaxis] + B[np.newaxis,:,:].transpose(2,0,1)
I am having some trouble with this algorithm. I am only able to grab one sub grid. I've only included the sub grid part here as I've done checkRows and checkColumns on my own. How can I connect this code to capture the rest? Your help is greatly appreciated. Thanks.
class Sudoku_Checker:
def __init__(self,board):
self.board = board
def board_validater(self,board):
self.checkSquares(board)
return self.checkSquares(board) == True
def checkSquares(self,board):
compare = [1,2,3,4,5,6,7,8,9]
hold = []
row = 0
column = 0
square = 0
for p in range(square, square+3):
for i in range(row, row + 3):
for j in range(column, column + 3):
hold.append(board[i][j])
if len(hold)==9:
if sorted(hold) == compare:
hold =[]
continue
else:
return False
square +=3
row += 3
return True
board = [ [5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 0],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9]]
s = Sudoku_Checker(board)
s.board_validater(board)
So in my exemple with line and column variable i get the upper left corner of eaxh 3x3 matrix and then i iterate from there to construct the square.
Please let me know if this is what you are looking for.
board = [
[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 0],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9]
]
for line in range(0, 9, 3):
for column in range(0, 9, 3):
square = [[board[l][c] for c in range(column, column + 3)] for l in range(line, line + 3)]
print(square)
Result:
[[5, 3, 4], [6, 7, 2], [1, 9, 8]]
[[6, 7, 8], [1, 9, 5], [3, 4, 2]]
[[9, 1, 2], [3, 4, 8], [5, 6, 0]]
[[8, 5, 9], [4, 2, 6], [7, 1, 3]]
[[7, 6, 1], [8, 5, 3], [9, 2, 4]]
[[4, 2, 3], [7, 9, 1], [8, 5, 6]]
[[9, 6, 1], [2, 8, 7], [3, 4, 5]]
[[5, 3, 7], [4, 1, 9], [2, 8, 6]]
[[2, 8, 4], [6, 3, 5], [1, 7, 9]]
Hopefully someone finds this useful. I prefer this implementation because it is more readable and understandable to me. The other commentor also has a good solution except for the list comprehension which is too much of a loop.
class Sudoku_Checker:
def __init__(self,board):
self.board = board
def board_validater(self,board):
return self.checkSquares(board) == True
def checkSquares(self,board):
compare = range(1,10)
for i in range(0, 9, 3):
for j in range(0, 9, 3):
nums = board[i][j:j+3] + board[i+1][j:j+3] + board[i+2][j:j+3]
if sorted(nums) == compare:
continue
else:
return False
return True
board = [ [5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 0],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9]]
s = Sudoku_Checker(board)
s.board_validater(board)
For example, x = np.random.randint(low=0, high=10, shape=(6,6)) gives me a 6x6 numpy array:
array([[3, 1, 0, 1, 5, 4],
[2, 9, 9, 4, 8, 8],
[2, 3, 4, 3, 2, 9],
[5, 8, 4, 5, 7, 6],
[3, 0, 8, 1, 8, 0],
[6, 7, 1, 9, 0, 5]])
How can I get a list of, say, all 2x3 submatrices? What about non-overlapping ones?
I could code this in myself, but I'm sure this is a common enough operation that it already exists in numpy, I just can't find it.
Listed in this post is a generic approach to get a list of submatrices with given shape. Based on the order of submatrices being row (C-style) or column major (fortran-way), you would have two choices. Here's the implementation with np.reshape , np.transpose and np.array_split -
def split_submatrix(x,submat_shape,order='C'):
p,q = submat_shape # Store submatrix shape
m,n = x.shape
if np.any(np.mod(x.shape,np.array(submat_shape))!=0):
raise Exception('Input array shape is not divisible by submatrix shape!')
if order == 'C':
x4D = x.reshape(-1,p,n/q,q).transpose(0,2,1,3).reshape(-1,p,q)
return np.array_split(x4D,x.size/(p*q),axis=0)
elif order == 'F':
x2D = x.reshape(-1,n/q,q).transpose(1,0,2).reshape(-1,q)
return np.array_split(x2D,x.size/(p*q),axis=0)
else:
print "Invalid output order."
return x
Sample run with a modified sample input -
In [201]: x
Out[201]:
array([[5, 2, 5, 6, 5, 6, 1, 5],
[1, 1, 8, 4, 4, 5, 2, 5],
[4, 1, 6, 5, 6, 4, 6, 1],
[5, 3, 7, 0, 5, 8, 6, 5],
[7, 7, 0, 6, 5, 2, 5, 4],
[3, 4, 2, 5, 0, 7, 5, 0]])
In [202]: split_submatrix(x,(3,4))
Out[202]:
[array([[[5, 2, 5, 6],
[1, 1, 8, 4],
[4, 1, 6, 5]]]), array([[[5, 6, 1, 5],
[4, 5, 2, 5],
[6, 4, 6, 1]]]), array([[[5, 3, 7, 0],
[7, 7, 0, 6],
[3, 4, 2, 5]]]), array([[[5, 8, 6, 5],
[5, 2, 5, 4],
[0, 7, 5, 0]]])]
In [203]: split_submatrix(x,(3,4),order='F')
Out[203]:
[array([[5, 2, 5, 6],
[1, 1, 8, 4],
[4, 1, 6, 5]]), array([[5, 3, 7, 0],
[7, 7, 0, 6],
[3, 4, 2, 5]]), array([[5, 6, 1, 5],
[4, 5, 2, 5],
[6, 4, 6, 1]]), array([[5, 8, 6, 5],
[5, 2, 5, 4],
[0, 7, 5, 0]])]