【问题标题】:Python Numpy Array Mult CombinationsPython Numpy 数组多重组合
【发布时间】:2018-01-14 07:29:53
【问题描述】:

我有一个 1 × N 和一个 N × 1 数组。

至于 Lin All 我们知道,当这两个相乘时,我们得到一个 1 乘以 1 或一个值。

N 是我们想要的值。但我想随机生成第一个数组,而第二个数组有权重。这是针对运筹学问题的。

[0th random, 1st random, N-1th random] * [ [0], [1], [2], ..., [N-1] ]

我的代码是这样的:

import itertools
import numpy as np
N = 4
winner = 0
A = np.array(list(itertools.product(range(N-1), repeat = N-1)))
V_weights = np.arange(1, N, 1).reshape(N-1,1)
for array in A:
    if array.dot(V_weights) == N:
        # print(array)
        # print(V_weights)
        # print(array.dot(V_weights))
        winner += 1
print(winner)

我希望 while 循环在所有组合都通过后结束。理想的迭代次数是正确的。

例如:我有 4 种类型的原木 1 磅、2 磅、3 磅、4 磅,需要总木材量(比如 10 磅)

这会给我几种木材类型的组合:

10 1磅 3 1 磅、2 2 磅、1 3 磅 还 2 磅、1 3 磅、1 5 磅

等等

因此我想我会生成随机数组,直到完成所有操作。

对不起,如果这有点令人困惑 - 很高兴编辑,除非有人需要更快更简单的方法。

【问题讨论】:

  • 如何跳出循环?对random.choice 的每次调用都应该是独立的吗?
  • @hpaulj sry 编辑了它。当值达到我想要的值时。但我想要所有的组合......

标签: python arrays numpy random


【解决方案1】:

查看对选项的调用集:

In [27]: np.random.choice(range(4), size=(1,3), replace=False)
Out[27]: array([[1, 2, 3]])
In [28]: np.random.choice(range(4), size=(1,3), replace=False)
Out[28]: array([[2, 1, 3]])
In [29]: np.random.choice(range(4), size=(1,3), replace=False)
Out[29]: array([[1, 2, 0]])
In [30]: np.random.choice(range(4), size=(1,3), replace=False)
Out[30]: array([[1, 3, 2]])
In [31]: np.random.choice(range(4), size=(1,3), replace=False)
Out[31]: array([[2, 3, 0]])
In [32]: np.random.choice(range(4), size=(1,3), replace=False)
Out[32]: array([[1, 3, 2]])

请注意,[1,3,2] 出现了两次。

这会产生这个范围内所有长度为 3 的排列(不是随机顺序 - 尽管列表可以打乱)

In [33]: import itertools
In [34]: itertools.permutations?
Init signature: itertools.permutations(self, /, *args, **kwargs)
Docstring:     
permutations(iterable[, r]) --> permutations object

Return successive r-length permutations of elements in the iterable.

permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)
Type:           type
In [35]: itertools.permutations(range(4), 3)
Out[35]: <itertools.permutations at 0xaf7193bc>
In [36]: list(_)
Out[36]: 
[(0, 1, 2),
 (0, 1, 3),
 ...
 (3, 2, 1)]

这些排列的加权值:

In [38]: wgts = np.arange(1, 4)
In [39]: A = np.array(list(itertools.permutations(range(4),3)))
In [40]: A.shape
Out[40]: (24, 3)
In [41]: wgts
Out[41]: array([1, 2, 3])
In [42]: A.dot(wgts)
Out[42]: 
array([ 8, 11,  7, 13,  9, 12,  7, 10,  5, 14,  7, 13,  5, 11,  4, 13,  8,
       11,  6,  9,  5, 11,  7, 10])

根据您的评论,我知道您正在抽样更换。这是一种快速的蛮力方法,例如搜索

生成一堆测试值。由于这是对每一行进行替换,因此我们只需一次调用 choice 就可以生成许多行:

In [55]: A = np.random.choice(range(4), size=(100,3), replace=True)
In [56]: A
Out[56]: 
array([[3, 1, 1],
       [0, 3, 0],
       [1, 3, 2],
       [3, 1, 1],
       [2, 0, 2],
       [0, 3, 2],
       ...
       [3, 0, 3]])

和之前一样取加权和:

In [57]: wgts = np.arange(1, 4)
In [58]: A.dot(wgts)
Out[58]: 
array([ 8,  6, 13,  8,  8, 12,  5, 10,  9, 12,  9,  9,  7,  9,  0,  4,  3,
        6, 10,  8,  7,  2,  3, 14, 11,  7,  1,  7,  2,  5, 11,  3, 13, 12,
        7,  9,  4, 15,  1,  7,  7,  9, 10,  7,  9, 11, 14,  3, 13, 11,  2,
        9,  9,  2, 11, 16,  4, 10, 13,  9, 11,  8, 10,  5,  7,  8, 13, 15,
       11,  9, 13,  7,  6,  9,  5, 12,  9, 11,  6,  3,  0,  0,  9,  7, 11,
        0, 12,  9,  7,  7,  3,  7, 13,  3,  9,  5, 14,  1, 16, 12])

并找到总和具有目标值的索引:

In [59]: np.where(_==4)
Out[59]: (array([15, 36, 56], dtype=int32),)
In [60]: A[_]
Out[60]: 
array([[2, 1, 0],
       [2, 1, 0],
       [0, 2, 0]])

对于N=5

In [61]: A = np.random.choice(range(5), size=(100,4), replace=True)
In [62]: A.dot(np.arange(1,5))
Out[62]: 
array([29, 20,... 23])
In [63]: np.where(_==5)
Out[63]: (array([], dtype=int32),)

这个样本不够大,让我们试试更大的:

In [64]: A = np.random.choice(range(5), size=(500,4), replace=True)
In [65]: A.dot(np.arange(1,5))
Out[65]: 
array([23,  8, 17, ...18])
In [66]: np.where(_==5)
Out[66]: (array([ 58, 267, 443], dtype=int32),)
In [67]: A[_]
Out[67]: 
array([[1, 2, 0, 0],
       [3, 1, 0, 0],
       [2, 0, 1, 0]])

itertools.product 可用于通用所有组合

In [71]: A = np.array(list(itertools.product(range(4),repeat=3)))
In [72]: A.shape
Out[72]: (64, 3)
In [73]: x = A.dot(np.arange(1,4))
In [74]: A[x==4]
Out[74]: 
array([[0, 2, 0],
       [1, 0, 1],
       [2, 1, 0]])

对于 N=5:

In [75]: A = np.array(list(itertools.product(range(5),repeat=4)))
In [76]: A.shape
Out[76]: (625, 4)
In [77]: x = A.dot(np.arange(1,5))
In [78]: A[x==5]
Out[78]: 
array([[0, 1, 1, 0],
       [1, 0, 0, 1],
       [1, 2, 0, 0],
       [2, 0, 1, 0],
       [3, 1, 0, 0]])

要迭代地进行搜索,我会使用 product 作为生成器:

In [100]: g = itertools.product(range(5), repeat=4)
In [101]: for cnt, row in enumerate(g):
     ...:     if np.arange(1,5).dot(row)==5:
     ...:         print(cnt, row)
     ...: 
     ...:     
30 (0, 1, 1, 0)
126 (1, 0, 0, 1)
175 (1, 2, 0, 0)
255 (2, 0, 1, 0)
400 (3, 1, 0, 0)

或者只找到第一个:

In [102]: g = itertools.product(range(5), repeat=4)
In [103]: for cnt, row in enumerate(g):
     ...:     if np.arange(1,5).dot(row)==5:
     ...:         print(cnt, row)
     ...:         break
     ...:     
30 (0, 1, 1, 0)

【讨论】:

  • 所以我已经按照你的回答了。
  • 对于 5 的 N - 我应该得到 [3, 1, 0, 0]*[[1], [2], [3], [4]] 和 [0, 1, 1, 0]*[[1], [2], [3], [4]] 但我没有。
  • 我的permutations 代码的作用类似于choicereplace=False。两者都不会产生像 [3,1,0,0] 这样的重复项。
  • 我修好了。是范围的问题。数字越大,速度越慢。
  • 另一种方法是在 product 生成器上进行迭代,而不使用中间的 A 数组。
猜你喜欢
  • 2020-10-16
  • 2021-11-24
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-01
  • 2011-10-08
相关资源
最近更新 更多