簡體   English   中英

生成在每個元素上遵循特定條件的n尺寸向量的所有可能組合

[英]Generating all possible combinations of n-sized vector that follow certain conditions on each element

我有一個長度為r的列表d,使得d = (d_1, d_2,..., d_r) 我想生成所有可能的長度為r的向量,以便for any i (from 0 to r), v_i is between 0 and d_i

例如,

if r =2 and d= (1,2), v_1 can be 0 or 1 and v_2 can be 0,1 or 2. 

因此,有6種可能的向量: [0,0] , [0,1], [0,2], [1,0] , [1,1], [1,2]

我已經研究了Itertools及其組合,我有一種感覺,我將不得不使用遞歸,但是我還沒有設法解決它,並希望向正確的方向尋求幫助或建議。

編輯:我為我的問題寫了以下代碼, 它可以工作,但是我通過忽略條件並生成所有可能的向量然后修剪無效的向量,以非常低效的方式做到了。 我取了最大的d_i並從(0,0,...0)一直到(max_d_i,max_d_i,....max_d_i)生成了所有大小為r向量,然后消除了那些無效的(max_d_i,max_d_i,....max_d_i)

碼:

import itertools
import copy
def main(d):
    arr = []
    correct_list =[]
    curr = []
    r= len(d)
    greatest = max(d)
    for i in range(0,greatest+1):
        arr = arr + [i]
    #all_poss_arr is a list that holds all possible vectors of length r from (0,0,...,0) to (max,max,...,max)
    # for example if greatest was 3 and r= 4, all_poss_arr would have (0,0,0,0), then (0,0,0,1) and so on,
    #all the way to (3,3,3,3)
    all_poss_arr = list(itertools.product(arr,repeat = r))    
    #Now I am going to remove all the vectors that dont follow the v_i is between 0 and d_i
    for i in range(0,len(all_poss_arr)):
        curr = all_poss_arr[i]
        cnt = 0
        for j in range(0,len(curr)):
            if curr[j] <= d[j]:
                cnt = cnt +1
        if cnt == r:
            curr = list(curr)
            currcopy = copy.copy(curr)
            correct_list = correct_list + [currcopy]
            cnt =0
    return correct_list

如果有人知道更好的方法,請告訴我,我們將不勝感激。

您基本上需要笛卡爾積。 我將演示一種基本,功能和迭代的方法。

給定

import operator as op
import functools as ft
import itertools as it


def compose(f, g):
    """Return a function composed of two functions."""
    def h(*args, **kwargs):
        return f(g(*args, **kwargs))
    return h


d = (1, 2)

選項1:基本-手動拆箱

list(it.product(range(d[0] + 1), range(d[1] + 1)))
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]

選項2:功能-自動映射

def vector_combs(v):
    """Return a Cartesian product of unpacked elements from `v`."""
    plus_one = ft.partial(op.add, 1)
    range_plus_one = compose(range, plus_one)
    res = list(it.product(*map(range_plus_one, v)))
    return res


vector_combs(d)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]

選項3:迭代-范圍復制(推薦)

list(it.product(*[range(x + 1) for x in d]))
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]

細節

選項1

基本思想在選項1中說明:

  • 使用一系列修改后的范圍來制作笛卡爾積

注意,每個范圍都是手動遞增的,並作為d的索引傳遞 我們在最后的選項中自動實現了這些限制。

選項2

我們采用一種功能方法來處理各種參數和功能:

  • 將部分 1參數傳遞給add()函數。 這將返回一個將遞增任何數字的函數。
  • 讓我們將此功能傳遞給composition range 這使我們可以使用修改后的范圍函數,該函數會自動遞增傳入的整數。
  • 最后,我們將后一個函數映射到元組d每個元素。 現在d可以使用任何長度r

例子( d = (1, 2, 1), r = 3 ):

vector_combs((1, 2, 1))
# [(0, 0, 0),
#  (0, 0, 1),
#  (0, 1, 0),
#  (0, 1, 1),
#  (0, 2, 0),
#  (0, 2, 1),
#  (1, 0, 0),
#  (1, 0, 1),
#  (1, 1, 0),
#  (1, 1, 1),
#  (1, 2, 0),
#  (1, 2, 1)]

選項3

也許最優雅的做法是,僅使用列表推導來創建r范圍。 ;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM