Python 生成每个数字为0..k的随机矩阵

Python 生成每个数字为0..k的随机矩阵,python,algorithm,Python,Algorithm,给定一个整数k,我正在寻找一种pythonic方法来生成一个nxm矩阵(或嵌套列表),该矩阵包含0..k-1中的每个整数,但没有整数在每行中出现一次以上 目前我正在做类似的事情 random.sample(列表(组合(xrange(k),m)),n) 但这并不保证0..k-1中的每一个数字都包含在内,只保证每一行中不会出现一次以上的整数。此外,这具有组合复杂性,这显然是不可取的 谢谢。你试过使用numpy吗?这段使用的简单代码将为您提供一个包含整数0到k的随机列表,该列表只包含一次: impor

给定一个整数
k
,我正在寻找一种pythonic方法来生成一个
nxm
矩阵(或嵌套列表),该矩阵包含
0..k-1
中的每个整数,但没有整数在每行中出现一次以上

目前我正在做类似的事情

random.sample(列表(组合(xrange(k),m)),n)

但这并不保证
0..k-1
中的每一个数字都包含在内,只保证每一行中不会出现一次以上的整数。此外,这具有组合复杂性,这显然是不可取的


谢谢。

你试过使用numpy吗?这段使用的简单代码将为您提供一个包含整数0到k的随机列表,该列表只包含一次:

import numpy as np
import numpy.random as npr

k = 7 # or whatever you like
thisrow = np.arange(k)
npr.shuffle(thisrow)
你可以重复多次,只要你想得到一个矩阵

import numpy as np
import numpy.random as npr

k = 7 # row length
m = 23 # number of rows
mymatrix = np.zeros((m, k))

for i in range(m):
    mymatrix[i] = np.arange(k)
    npr.shuffle(mymatrix[i])

我同意上述CommuSoft的观点,即您在问题中未明确说明
k
m
n
之间的关系。以随机顺序包含每个整数
0..k-1
的行只有一次长度
k
。可能您给出的示例未能给出范围内的每个整数,因为
n您希望生成一个随机的
n*m
整数矩阵
1..k
,每个整数都被使用,并且在任何一行中没有整数被使用两次。而且你想有效地完成它

如果您只想以合理的速度生成一个合理的答案,那么可以通过随机选择元素并将其放入随机顺序来生成行。numpy.random.random\u sample和numpy.random.shuffle可以做到这一点。您将避免重复元素问题。如果您没有使用所有元素,那么您所能做的就是随机地“进化”到一个正确的解决方案,在每个步骤中识别矩阵中重复多次的所有元素,随机选择一个,并将其从
1..k
转换为尚未使用的整数。这不会导致行内的重复,最多只需
k
步就可以得到所需形式的矩阵

很有可能这是一个很好的答案,你想要什么,这是你应该做的。但它是不完美的——这种形式的矩阵并非都以完全相同的概率发生。(特别是那些有很多元素只出现一次的情况下,显示的比它们应该的稍微多一些。)如果你需要一个完全均匀的分布,那么你将不得不做更多的工作

要做到这一点,你需要一点理论。如果你有这个理论,那么你可以把答案理解为,“向前做一个动态规划解,找到所有可能的解,然后向后运行,做出随机决策,确定一个随机解。”很可能你没有这个理论

我不打算详细解释这个理论。我将简要介绍一下你的工作

您可以从一个简单的语句开始,“有
n!/(n-m)!
种方法,我可以使用
k
整数的
m
得到一个矩阵,其中一行满足我的条件,没有一行使用更多的整数。”

对于
i
from
1..n
,对于
j
from
m
to
k
,您可以计算出使用
k
整数的
j
构建
i
行的方法的计数。您还可以跟踪这些方法中有多少来自上一行的
j
的先前值。(稍后您将需要它。)此步骤可以在双循环中完成

请注意,刚才为
j=k
i=n
生成的表中的值是满足所有条件的矩阵数。我们将自下而上构建一个随机的

首先,为矩阵的最后一行生成一个随机行,所有行的可能性相同

对于每一行,在到达顶部之前,您使用构建的表来随机决定在生成的最后一行中使用的元素中有多少将不再使用。随机决定这些元素将是什么。从仍在使用的整数生成一个随机行


当你到达顶端时,你将选择一个符合你描述的随机矩阵,它的生成方式没有任何偏差。

将每个数字1..k分配给矩阵的某一行

对于矩阵的每一行,不重复地填充间隙。将每一行也洗牌以保持随机性

这似乎相当直接和有效

编辑:


下面的效率取决于k、n和m的相对值,但是如果您知道
n*m
k
大得多,那么它可能与您得到的速度一样快。它还具有简单和无偏见的优点:

from functools import reduce
from itertools import chain
from operator import ior
from random import sample

def gen(k,m,n):
  if m > k or k > m*n:
    raise ValueError("Unsatisfiable constraint")
  while True:
    mat = [sample(range(k), m) for i in range(n)]
    if reduce(ior, (1<<i for i in chain(*mat))) == (1<<k) - 1:
      yield mat
从functools导入reduce
来自itertools进口链
从操作员导入ior
来自随机进口样品
def发生器(k、m、n):
如果m>k或k>m*n:
提升值错误(“不可满足的约束”)
尽管如此:
mat=[范围(k)中i的样本(m)]

如果降低(ior,(1)代码必须短一行吗?你能举个例子说明你的输出应该是什么样子吗?例如,对于4x4矩阵,你问的问题不清楚,如果每行都包含所有的数字,那么
k
m
n
之间的关系是什么?@CommuSoft这个问题对我来说似乎非常清楚。
m谢谢@btilly。完全正确。请参阅我上面关于我认为问题所在的评论。如果该评论正确,则说明您尚未成功解决问题。您是对的@btilly。底线是问题的提出不够具体。祝贺您猜对了意图;这是您以前见过的应用程序吗?没有问题这是一个复杂的问题。只有一组约束可以添加到所述问题中,使其有意义,因此有理由假设应该添加这些约束。记住,有问题的人通常会声明
from functools import reduce
from itertools import chain
from operator import ior
from random import sample

def gen(k,m,n):
  if m > k or k > m*n:
    raise ValueError("Unsatisfiable constraint")
  while True:
    mat = [sample(range(k), m) for i in range(n)]
    if reduce(ior, (1<<i for i in chain(*mat))) == (1<<k) - 1:
      yield mat