首页 > 解决方案 > 如何在python中找到满足条件的n个向量的所有组合

问题描述

我希望找到向量的 n 个副本的元素组合,其中向量很简单:np.arange(0,0.1,0.01)。该组合是通过从每个向量中选择一个元素来组成的。

我需要组合来满足组合中的每个元素都是非零且组合之和 = 1 的标准。我有以下功能很好:

# cols is a vector of length n.
def feasibility_test(row_in, cols):
    
    if np.around(np.sum(row_in), decimals = 2) == 1 and np.count_nonzero(row_in)>= len(cols):
        pass_test = True
    else:
        pass_test = False
    return pass_test

然而,对于 n= 6 或以上的组合,meshgrid(下面的代码)会产生一个会占用计算机内存的数组:

def generate_all_combos(range_in, cols):
    j = range_in
    if len(cols) == 4:
        new_array = np.array(np.meshgrid(j,j,j,j)).T.reshape(-1,len(cols))
    elif len(cols) == 5:
        new_array = np.array(np.meshgrid(j,j,j,j,j)).T.reshape(-1,len(cols))
    elif len(cols) == 6:
        new_array = np.array(np.meshgrid(j,j,j,j,j,j)).T.reshape(-1,len(cols))
    elif len(cols) == 7:
        new_array = np.array(np.meshgrid(j,j,j,j,j,j,j)).T.reshape(-1,len(cols))
        
    return new_array

上面的代码可以调用:

# Create range of values in parameter space of interest
underlying_range = [np.around(i, decimals=2) for i in np.arange(0,0.1,0.01)]

# Generate all possible combinations of col values
comb_array = generate_all_combos(underlying_range, cols)

# Check which combinations are feasible
feasible_combos_high_level = [row for row in comb_array if feasibility_test(row)]

有没有办法在不产生整个组合范围的情况下获得一系列可行组合(其中大多数不符合可行性测试)?

标签: pythonarrayscombinationslogical-operatorscombinatorics

解决方案


您可以使用递归生成器函数,该函数只会生成符合您的标准的组合。此外,通过使用生成器,您不会立即将所有值存储在内存中,因此您可以稍后按需访问它们:

import numpy as np
def combos(d, max_l, total_s, valid_f, rt = 0, c = []):
   if rt == total_s and len(c) == max_l:
      yield np.array(c)
   elif len(c) < max_l and rt < total_s:
      for i in filter(valid_f, d):
         for j in range(1, int(total_s/i)+1):
            if rt+(i*j) <= total_s and i not in c:
               yield from combos(d, max_l, total_s, valid_f, rt=rt+(i*j), c=c+([i]*j))

vals = np.arange(0,0.1,0.01)
result = combos(vals, len(cols), 1, lambda x: x > 0) #passing len(cols)
#printing first 100 valid combinations
for _ in range(100):
   print(next(result))

推荐阅读