Python 如何索引笛卡尔积
假设变量Python 如何索引笛卡尔积,python,Python,假设变量x和theta可以分别取可能的值[0,1,2]和[0,1,2,3] 假设在一个实现中,x=1和theta=3。表示这一点的自然方式是使用元组(1,3)。但是,我想用一个索引来标记state(1,3)。一种“蛮力”方法是形成所有可能的有序对的笛卡尔积(x,θ),并进行查找: import numpy as np import itertools N_x = 3 N_theta = 4 np.random.seed(seed = 1) x = np.random.choice(range
x
和theta
可以分别取可能的值[0,1,2]
和[0,1,2,3]
假设在一个实现中,x=1
和theta=3
。表示这一点的自然方式是使用元组(1,3)
。但是,我想用一个索引来标记state(1,3)
。一种“蛮力”方法是形成所有可能的有序对的笛卡尔积(x,θ)
,并进行查找:
import numpy as np
import itertools
N_x = 3
N_theta = 4
np.random.seed(seed = 1)
x = np.random.choice(range(N_x))
theta = np.random.choice(range(N_theta))
def get_box(x, N_x, theta, N_theta):
states = list(itertools.product(range(N_x),range(N_theta)))
inds = [i for i in range(len(states)) if states[i]==(x,theta)]
return inds[0]
print (x, theta)
box = get_box(x, N_x, theta, N_theta)
print box
这给出了(x,θ)=(1,3)
和box=7
,如果我们在状态列表中查找它,这是有意义的:
[(0,0)、(0,1)、(0,2)、(0,3)、(1,0)、(1,1)、(1,2)、(1,3)、(2,0)、(2,1)、(2,2)、(2,3)]
然而,这种“蛮力”方法似乎效率低下,因为应该可以事先确定索引,而无需查找索引。有没有一般的方法可以做到这一点?(实际应用中,N_x
和N_theta
的状态数可能会有所不同,笛卡尔乘积中可能有更多的变量).如果您总是按字典顺序存储状态,并且x
和theta
的可能值始终是从0
到示例所示的某个最大值的完整范围,您可以使用以下公式
index = x * N_theta + theta
其中(x,θ)
是元组之一
这通过以下方式推广到高维元组:如果N
是表示变量范围的列表或元组(因此N[0]
是第一个变量的可能值的数量,等等),并且p
是元组,使用以下代码段将索引放入所有可能元组的字典排序列表中:
index = 0
skip = 1
for dimension in reversed(range(len(N))):
index += skip * p[dimension]
skip *= N[dimension]
这可能不是最具python风格的方法,但它显示了正在发生的事情:您将元组视为一个超立方体,其中只能沿着一个维度移动,但如果到达边缘,“下一个”维度中的坐标将增加,移动坐标将重置。建议读者画一些画 如果您总是按字典顺序存储状态
,并且x
和theta
的可能值总是从0
到您的示例所示的某个最大值的完整范围,那么您可以使用以下公式
index = x * N_theta + theta
其中(x,θ)
是元组之一
这通过以下方式推广到高维元组:如果N
是表示变量范围的列表或元组(因此N[0]
是第一个变量的可能值的数量,等等),并且p
是元组,使用以下代码段将索引放入所有可能元组的字典排序列表中:
index = 0
skip = 1
for dimension in reversed(range(len(N))):
index += skip * p[dimension]
skip *= N[dimension]
这可能不是最具python风格的方法,但它显示了正在发生的事情:您将元组视为一个超立方体,其中只能沿着一个维度移动,但如果到达边缘,“下一个”维度中的坐标将增加,移动坐标将重置。建议读者画一些画 我想这取决于你掌握的数据。如果它们是稀疏的,最好的解决方案是使用字典。并适用于任何元组的维度
import itertools
import random
n = 100
m = 100
l1 = [i for i in range(n)]
l2 = [i for i in range(m)]
a = {}
prod = [element for element in itertools.product(l1, l2)]
for i in prod:
a[i] = random.randint(1, 100)
关于性能的一个很好的来源是。我认为这取决于您拥有的数据。如果它们是稀疏的,最好的解决方案是使用字典。并适用于任何元组的维度
import itertools
import random
n = 100
m = 100
l1 = [i for i in range(n)]
l2 = [i for i in range(m)]
a = {}
prod = [element for element in itertools.product(l1, l2)]
for i in prod:
a[i] = random.randint(1, 100)
关于性能的一个很好的来源是。为了完整起见,我将包括我的Julian Kniephoff解决方案的实现,get_box3
,以及对原始实现稍加修改的版本,get_box2
:
# 'Brute-force' method
def get_box2(p, N):
states = list(itertools.product(*[range(n) for n in N]))
return states.index(p)
# 'Analytic' method
def get_box3(p, N):
index = 0
skip = 1
for dimension in reversed(range(len(N))):
index += skip * p[dimension]
skip *= N[dimension]
return index
p = (1,3,2) # Tuple characterizing the total state of the system
N = [3,4,3] # List of the number of possible values for each state variable
print "Brute-force method yields %s" % get_box2(p, N)
print "Analytical method yields %s" % get_box3(p, N)
“暴力”和“分析”方法都产生相同的结果:
Brute-force method yields 23
Analytical method yields 23
但我预计“分析”方法会更快。根据Julian的建议,我已将表示形式更改为p
和N
。为了完整起见,我将包括Julian Kniephoff解决方案的实现,get_box3
,以及原始实现的稍微修改版本,get_box2
:
# 'Brute-force' method
def get_box2(p, N):
states = list(itertools.product(*[range(n) for n in N]))
return states.index(p)
# 'Analytic' method
def get_box3(p, N):
index = 0
skip = 1
for dimension in reversed(range(len(N))):
index += skip * p[dimension]
skip *= N[dimension]
return index
p = (1,3,2) # Tuple characterizing the total state of the system
N = [3,4,3] # List of the number of possible values for each state variable
print "Brute-force method yields %s" % get_box2(p, N)
print "Analytical method yields %s" % get_box3(p, N)
“暴力”和“分析”方法都产生相同的结果:
Brute-force method yields 23
Analytical method yields 23
但我预计“分析”方法会更快。我已经按照Julian的建议将表示形式更改为p
和N
。您可以使用哈希寻址,将这两个组件模化为一个大常量,然后在发生冲突的情况下附加到每个哈希键后面的列表中。因此,例如c2*(x%c1)+(y%c2)将是散列键。您可以使用散列寻址,将两个组件模化为一个大常量,然后在发生冲突时附加到每个散列键后面的列表中。例如c2*(x%c1)+(y%c2)将是散列键。我考虑过这一点,但它如何扩展到更多变量?例如,除了x
和theta
,还有x\u点和theta\u点
。我考虑过这一点,但它如何扩展到更多变量?例如,除了x
和theta
,还可以有x\u点和theta\u点。