我写了一个递归函数,迭代生成N个原子的六边形晶格的可能图案。该函数首先在晶格上选择一个点,移除所有离原始点太近的点,然后将下一个原子放置在剩余的有效位置之一。
该函数根据要放置的原子数返回一个嵌套列表的列表。
。对于两个原子,它将返回一个这样的列表:款= [[site1, [valid_sites]], [[valid_sites site2 ]], ...]
对于三个原子:款= [[site1 [site2_1 [valid_sites]]], [site1 site2_2, [valid_sites ]], ...]
原子数目的任意深度。每个site对象是一个2d-numpy数组。
现在我所需要的是一种从这个嵌套列表中产生所有有效配置的可迭代对象的方法:
[[site1, valid_sites [0]], [site1, valid_sites[1]],…[site2 valid_sites [0]]]
我已经尝试了itertools.product(),但这有几个问题。在N=2的情况下,它将site1视为可迭代对象,并通过分割向量(site1[0], valid_sites[0])生成笛卡尔积…一个简单的测试也显示它不会以期望的方式处理嵌套。
我看了这里和这里,但这些似乎不需要深度为N的一般性,后者不编译列表。
下面是我对递归函数的尝试:
def expand_list(configs,n,N):
if n<N:
expand_list(configs[n],n+1,N)
else:
return list(itertools.product(*configs))
最好是尝试"解开"循环,然后做一个笛卡尔积?或者有什么生成器函数可以写出来?
那么你要做的就是删除列表中的最后一项,然后用最后一项扩展列表,对吧?
这是一个递归解:
def expand_sites(sites):
return [getsubsite(site) for site in sites]
def getsubsite(site):
if len(site) == 1:
return site
else:
return site[:1] + getsubsite(site[1])
这是一个非递归解:
def expand_sites(sites):
return [getsubsite(site) for site in sites]
def getsubsite(site):
site = site[:] # copy the list
while len(site[-1]) > 1:
site.extend(site.pop())
site.extend(site.pop())
return site
和一个非递归的解决方案,改变原来的列表,而不是创建一个新的列表:
def expand_sites(sites):
for site in sites:
while len(site[-1]) > 1:
site.extend(site.pop())
site.extend(site.pop())