Python 多处理直接计算
问题分解:有相当多的潜在动机,但假设我们得到了一些矩阵Python 多处理直接计算,python,multithreading,numpy,multiprocessing,sage,Python,Multithreading,Numpy,Multiprocessing,Sage,问题分解:有相当多的潜在动机,但假设我们得到了一些矩阵N(代码包含在底部),我们希望解决矩阵向量方程Nv=b,其中b是一个权重为k的二进制字符串。我目前正在使用numpy.linalg.lstsq解决这个问题。如果这个最小二乘计算的“残差”小于0.000001,我接受它作为解决方案 首先,我需要生成特定长度和权重k的所有二进制字符串。下面的函数可以实现这一点 ''' This was provided in one of the answers here: https://stackoverf
N
(代码包含在底部),我们希望解决矩阵向量方程Nv=b
,其中b
是一个权重为k
的二进制字符串。我目前正在使用numpy.linalg.lstsq
解决这个问题。如果这个最小二乘计算的“残差”小于0.000001,我接受它作为解决方案
首先,我需要生成特定长度
和权重k
的所有二进制字符串。下面的函数可以实现这一点
'''
This was provided in one of the answers here:
https://stackoverflow.com/questions/58069431/find-all-binary-strings-of-certain-weight-has-fast-as-possible/
Given a value with weight k, you can get the (co)lexically next value as follows (using bit manipulations).
'''
def ksubsetcolexsuccessor(length,k):
limit=1<<length
val=(1<<k)-1
while val<limit:
yield "{0:0{1}b}".format(val,length)
minbit=val&-val
fillbit = (val+minbit)&~int(val)
val = val+minbit | (fillbit//(minbit<<1))-1
我们将每个都插入Nv=b
并求解:
import numpy as np
solutions = 0
for b in ksubsetcolexsuccessor(n, k):
v = np.linalg.lstsq(N,np.array(list(b), dtype = float))
if v[1] < 0.000001:
solutions += 1
这确实减少了大约45%的计算时间(随着长度和重量的增加)。在此期间,我的CPU大约以50%的速度运行。奇怪的是,如果我分为4个进程,所需的时间与分为2个进程所需的时间大致相同(尽管在此期间我的CPU运行率约为85%)。在我正在测试的笔记本电脑上,我有2个物理核和4个逻辑核。在这样一个CPU上,有多少个进程是最佳的
问题:
np.linalg.lsts
q。有什么聪明的方法来加速这部分吗N
:
'''
Creating the matrix N
'''
def matrixgenerator(G, cardinality, degree):
matrix = np.zeros((size, (n-1)**2 + 1))
#Generate the matrix (it'll be missing stab_nn)
column_index = 0
for i in range(1,n):
for j in range(1,n):
for k in range(size):
if G[k](i) == j:
matrix[k][column_index] = 1
column_index += 1
#Determine the final column of N, which is determined by the characteristic vector of stab_nn
for k in range(size):
if G[k](n) == n:
matrix[k][(n-1)**2] = 1
return matrix
n = 3 #This will give length 6 and weight 2 binary strings
#Try n = 7 and change the second argument below to '4' - this takes roughly 14 min with 2 processes on my device
Group = TransitiveGroup(n, 2) #SageMath 8.8
length = Group.order()
weight = int(size / n)
N = matrixgenerator(Group, length, n)
这需要SageMath 8.8。注意,这是代码中唯一需要SageMath的部分。其他所有内容都有效地用Python 2.7编写。提前感谢。讲讲性能-在所有尽可能快的方法中,(预期的)最快方法的可接受水平是多少?没有量化的目标,任何一条道路都可能引领一个人前进。我想如果你看到任何可以改进的地方,如果你能解释一下这是什么,那就太好了,我会做出改变。我的量化目标是,我不希望n=168和k=21需要6个月的时间来计算,如果我对线性代数的微弱记忆是正确的,那么你就不必解那么多方程了。只需求解标准基,e1,e2,e3,。。。返回项目以获取ehat1、ehat2、ehat3,。。。现在查找满足e_j1+e_j2+e_j3+的所需大小的组j1、j2、j3(二进制字中的位置)。。。约ehat_j1+ehat_j2+ehat_j3+。。。您应该能够一次获得所有EHAT,作为
N@np.linalg.pinv(N)
但是无论你优化得多么好,循环遍历所有168-choose-21(~2.9 x 10^26)字都是不可行的。矩阵N实际上已经是基向量的集合,但我会仔细考虑你所说的。也许我有点热心。那么n=72和k=8呢?
from multiprocessing import Process
'''
A version where you can specify where to start and end by passing start_val and end_val to the function.
It performs the least-squares computation for each b and tallies the trials that work.
'''
def ksubsetcolexsuccessorSegmentComp(n, k, val, limit, num):
while val<limit:
b = "{0:0{1}b}".format(val,n)
v = np.linalg.lstsq(N,np.array(list(b), dtype = float))
if v[1] < 0.000001:
num += 1
minbit=val&-val
fillbit = (val+minbit)&~int(val)
val = val+minbit | (fillbit//(minbit<<1))-1
print(num)
solutions = 0
length = 6
weight = 2
start_val = (1<<k)-1
mid_val = 18 #If splitting into 2 processes
end_val = 1<<n
#Multiprocessing
p1 = Process(target=ksubsetcolexsuccessorSegmentComp, args=(length, weight, start_val, mid_val, solutions))
p2 = Process(target=ksubsetcolexsuccessorSegmentComp, args=(length, weight, mid_val, end_val, solutions))
p1.start()
p2.start()
p1.join()
p2.join()
'''
Creating the matrix N
'''
def matrixgenerator(G, cardinality, degree):
matrix = np.zeros((size, (n-1)**2 + 1))
#Generate the matrix (it'll be missing stab_nn)
column_index = 0
for i in range(1,n):
for j in range(1,n):
for k in range(size):
if G[k](i) == j:
matrix[k][column_index] = 1
column_index += 1
#Determine the final column of N, which is determined by the characteristic vector of stab_nn
for k in range(size):
if G[k](n) == n:
matrix[k][(n-1)**2] = 1
return matrix
n = 3 #This will give length 6 and weight 2 binary strings
#Try n = 7 and change the second argument below to '4' - this takes roughly 14 min with 2 processes on my device
Group = TransitiveGroup(n, 2) #SageMath 8.8
length = Group.order()
weight = int(size / n)
N = matrixgenerator(Group, length, n)