Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python进行准随机化_Python_Random - Fatal编程技术网

使用Python进行准随机化

使用Python进行准随机化,python,random,Python,Random,问题是:我尝试在两个元素之间随机选择n次,比如[0,1]>0或1,我的最终列表将有n/2[0]+n/2[1]。我倾向于得到这样的结果:[01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01

问题是:我尝试在两个元素之间随机选择n次,比如[0,1]>0或1,我的最终列表将有n/2[0]+n/2[1]。我倾向于得到这样的结果:[01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01。我知道我可以使用准随机过程,但我不知道如何使用Python。

为了保证将有相同数量的零和一,您可以生成一个包含n/2个零和n/2个一的列表,并使用random.shuffle将其洗牌

对于小n,如果您对结果通过验收标准(例如,没有太多连续相等的数字)不满意,请再次洗牌。请注意,这样做会减少结果的随机性,而不是增加结果的随机性

对于较大的n,使用此方法查找通过条件的结果将花费太长时间,因为大多数结果将失败。相反,您可以使用以下规则一次生成一个元素:

如果一行中已经生成了4个数字,则下一个数字必须为零,反之亦然。 否则,如果需要多生成x个1和y个0,则下一个数字为1的概率为x/x+y。
为了保证有相同数量的0和1,您可以生成一个包含n/2个0和n/2个1的列表,并使用random.shuffle将其洗牌

对于小n,如果您对结果通过验收标准(例如,没有太多连续相等的数字)不满意,请再次洗牌。请注意,这样做会减少结果的随机性,而不是增加结果的随机性

对于较大的n,使用此方法查找通过条件的结果将花费太长时间,因为大多数结果将失败。相反,您可以使用以下规则一次生成一个元素:

如果一行中已经生成了4个数字,则下一个数字必须为零,反之亦然。 否则,如果需要多生成x个1和y个0,则下一个数字为1的概率为x/x+y。
连续6个1不是特别不可能的-你确定你没有得到你想要的吗


对于均匀分布的随机数,有一个简单的Python接口,这就是您想要的吗?

一行有6个1不是特别不可能的-您确定没有得到您想要的吗


对于均匀分布的随机数,有一个简单的Python接口,这就是您要寻找的吗?

可能不是最聪明的方法,但它不适用于连续运行,同时不生成相同数量的0和1。有关符合所有要求的版本,请参见下文

from random import choice
CHOICES = (1, 0)

def quasirandom(n, longest=3):
  serial = 0
  latest = 0
  result = []
  rappend = result.append

  for i in xrange(n):
    val = choice(CHOICES)
    if latest == val:
      serial += 1
    else:
      serial = 0
    if serial >= longest:
      val  = CHOICES[val]
    rappend(val)
    latest = val
  return result

print quasirandom(10)
print quasirandom(100)
import random


def next_value(selected):

    # Mathematically, this isn't necessary but it accounts for
    # potential problems with floating point numbers.
    if selected.count(0) == 0:
        return 0
    elif selected.count(1) == 0:
        return 1

    N = len(selected)
    selector = float(selected.count(1)) / N

    if random.uniform(0, 1) > selector:
        return 1
    else:
        return 0


def get_sequence(N, max_run):
    lim = min(N, max_run - 1)
    seq = [random.choice((1, 0)) for _ in xrange(lim)]

    for _ in xrange(N - lim):
        seq.append(next_value(seq[-max_run+1:]))
    return seq


def test(N, max_run, test_count):
    ones = 0.0
    zeros = 0.0

    for _ in xrange(test_count):
        seq = get_sequence(N, max_run)

        # Keep track of how many ones and zeros we're generating
        zeros += seq.count(0)
        ones += seq.count(1)

        # Make sure that the max_run isn't violated.
        counts = [0, 0]
        for i in seq:
            counts[i] += 1
            counts[not i] = 0
            if max_run in counts:
                print seq
                return


    # Print the ratio of zeros to ones. This should be around 1.
    print zeros/ones


test(200, 5, 10000)
下面这一条修正了过滤洗牌的想法,并在AICT下正常工作,同时警告最后的数字可能会形成一个运行。Pass debug=True以检查是否满足要求

from random import random
from itertools import groupby # For testing the result
try: xrange
except: xrange = range

def generate_quasirandom(values, n, longest=3, debug=False):
  # Sanity check
  if len(values) < 2 or longest < 1:
    raise ValueError

  # Create a list with n * [val]
  source = []
  sourcelen = len(values) * n
  for val in values:
    source += [val] * n

  # For breaking runs
  serial = 0
  latest = None

  for i in xrange(sourcelen):
    # Pick something from source[:i]
    j = int(random() * (sourcelen - i)) + i
    if source[j] == latest:
      serial += 1
      if serial >= longest:
        serial = 0
        guard = 0
        # We got a serial run, break it
        while source[j] == latest:
          j = int(random() * (sourcelen - i)) + i
          guard += 1
          # We just hit an infinit loop: there is no way to avoid a serial run
          if guard > 10:
            print("Unable to avoid serial run, disabling asserts.")
            debug = False
            break
    else:
      serial = 0
    latest = source[j]
    # Move the picked value to source[i:]
    source[i], source[j] = source[j], source[i]

  # More sanity checks
  check_quasirandom(source, values, n, longest, debug)

  return source


def check_quasirandom(shuffled, values, n, longest, debug):
  counts = []
  # We skip the last entries because breaking runs in them get too hairy
  for val, count in groupby(shuffled):
    counts.append(len(list(count)))
  highest = max(counts)
  print('Longest run: %d\nMax run lenght:%d' % (highest, longest))

  # Invariants
  assert len(shuffled) == len(values) * n
  for val in values:
    assert shuffled.count(val) == n

  if debug:
    # Only checked if we were able to avoid a sequential run >= longest
    assert highest <= longest

for x in xrange(10, 1000):
  generate_quasirandom((0, 1, 2, 3), 1000, x//10, debug=True)

可能不是最聪明的方法,但它不适用于连续运行,同时不会生成相同数量的0和1。有关符合所有要求的版本,请参见下文

from random import choice
CHOICES = (1, 0)

def quasirandom(n, longest=3):
  serial = 0
  latest = 0
  result = []
  rappend = result.append

  for i in xrange(n):
    val = choice(CHOICES)
    if latest == val:
      serial += 1
    else:
      serial = 0
    if serial >= longest:
      val  = CHOICES[val]
    rappend(val)
    latest = val
  return result

print quasirandom(10)
print quasirandom(100)
import random


def next_value(selected):

    # Mathematically, this isn't necessary but it accounts for
    # potential problems with floating point numbers.
    if selected.count(0) == 0:
        return 0
    elif selected.count(1) == 0:
        return 1

    N = len(selected)
    selector = float(selected.count(1)) / N

    if random.uniform(0, 1) > selector:
        return 1
    else:
        return 0


def get_sequence(N, max_run):
    lim = min(N, max_run - 1)
    seq = [random.choice((1, 0)) for _ in xrange(lim)]

    for _ in xrange(N - lim):
        seq.append(next_value(seq[-max_run+1:]))
    return seq


def test(N, max_run, test_count):
    ones = 0.0
    zeros = 0.0

    for _ in xrange(test_count):
        seq = get_sequence(N, max_run)

        # Keep track of how many ones and zeros we're generating
        zeros += seq.count(0)
        ones += seq.count(1)

        # Make sure that the max_run isn't violated.
        counts = [0, 0]
        for i in seq:
            counts[i] += 1
            counts[not i] = 0
            if max_run in counts:
                print seq
                return


    # Print the ratio of zeros to ones. This should be around 1.
    print zeros/ones


test(200, 5, 10000)
下面这一条修正了过滤洗牌的想法,并在AICT下正常工作,同时警告最后的数字可能会形成一个运行。Pass debug=True以检查是否满足要求

from random import random
from itertools import groupby # For testing the result
try: xrange
except: xrange = range

def generate_quasirandom(values, n, longest=3, debug=False):
  # Sanity check
  if len(values) < 2 or longest < 1:
    raise ValueError

  # Create a list with n * [val]
  source = []
  sourcelen = len(values) * n
  for val in values:
    source += [val] * n

  # For breaking runs
  serial = 0
  latest = None

  for i in xrange(sourcelen):
    # Pick something from source[:i]
    j = int(random() * (sourcelen - i)) + i
    if source[j] == latest:
      serial += 1
      if serial >= longest:
        serial = 0
        guard = 0
        # We got a serial run, break it
        while source[j] == latest:
          j = int(random() * (sourcelen - i)) + i
          guard += 1
          # We just hit an infinit loop: there is no way to avoid a serial run
          if guard > 10:
            print("Unable to avoid serial run, disabling asserts.")
            debug = False
            break
    else:
      serial = 0
    latest = source[j]
    # Move the picked value to source[i:]
    source[i], source[j] = source[j], source[i]

  # More sanity checks
  check_quasirandom(source, values, n, longest, debug)

  return source


def check_quasirandom(shuffled, values, n, longest, debug):
  counts = []
  # We skip the last entries because breaking runs in them get too hairy
  for val, count in groupby(shuffled):
    counts.append(len(list(count)))
  highest = max(counts)
  print('Longest run: %d\nMax run lenght:%d' % (highest, longest))

  # Invariants
  assert len(shuffled) == len(values) * n
  for val in values:
    assert shuffled.count(val) == n

  if debug:
    # Only checked if we were able to avoid a sequential run >= longest
    assert highest <= longest

for x in xrange(10, 1000):
  generate_quasirandom((0, 1, 2, 3), 1000, x//10, debug=True)
可以使用将列表随机化

import random
n = 100
seq = [0]*(n/2) + [1]*(n-n/2)
random.shuffle(seq)
现在,您可以在列表中运行,每当您看到一个运行过长时,交换一个元素以分解序列。我还没有这部分的任何代码。

您可以使用它来随机排列列表

import random
n = 100
seq = [0]*(n/2) + [1]*(n-n/2)
random.shuffle(seq)

现在,您可以在列表中运行,每当您看到一个运行过长时,交换一个元素以分解序列。我还没有那部分的代码。

这是我的看法。前两个函数是实际实现,最后一个函数用于测试它

键是第一个函数,它查看列表的最后N个元素,其中N+1是一个数字在一行中出现次数的限制。它计算出现的数量,然后以1-N/N的概率返回1,其中N是已经出现的数量。注意,在N个连续1的情况下,该概率为0,在N个连续0的情况下,该概率为1

与真正的随机选择一样,不能保证1和0的比率为1,但经过数千次运行的平均值,它确实会产生与0一样多的1。 对于较长的列表,这比反复调用shuffle并检查它是否满足您的需求要好

from random import choice
CHOICES = (1, 0)

def quasirandom(n, longest=3):
  serial = 0
  latest = 0
  result = []
  rappend = result.append

  for i in xrange(n):
    val = choice(CHOICES)
    if latest == val:
      serial += 1
    else:
      serial = 0
    if serial >= longest:
      val  = CHOICES[val]
    rappend(val)
    latest = val
  return result

print quasirandom(10)
print quasirandom(100)
import random


def next_value(selected):

    # Mathematically, this isn't necessary but it accounts for
    # potential problems with floating point numbers.
    if selected.count(0) == 0:
        return 0
    elif selected.count(1) == 0:
        return 1

    N = len(selected)
    selector = float(selected.count(1)) / N

    if random.uniform(0, 1) > selector:
        return 1
    else:
        return 0


def get_sequence(N, max_run):
    lim = min(N, max_run - 1)
    seq = [random.choice((1, 0)) for _ in xrange(lim)]

    for _ in xrange(N - lim):
        seq.append(next_value(seq[-max_run+1:]))
    return seq


def test(N, max_run, test_count):
    ones = 0.0
    zeros = 0.0

    for _ in xrange(test_count):
        seq = get_sequence(N, max_run)

        # Keep track of how many ones and zeros we're generating
        zeros += seq.count(0)
        ones += seq.count(1)

        # Make sure that the max_run isn't violated.
        counts = [0, 0]
        for i in seq:
            counts[i] += 1
            counts[not i] = 0
            if max_run in counts:
                print seq
                return


    # Print the ratio of zeros to ones. This should be around 1.
    print zeros/ones


test(200, 5, 10000)

这是我的看法。前两个函数是实际实现,最后一个函数用于测试它

键是第一个函数,它查看列表的最后N个元素,其中N+1是一个数字在一行中出现次数的限制。它计算出现的数量,然后以1-N/N的概率返回1,其中N是已经出现的数量。注意,对于N个连续的概率,该概率为0 在N个连续零的情况下为1

与真正的随机选择一样,不能保证1和0的比率为1,但经过数千次运行的平均值,它确实会产生与0一样多的1。 对于较长的列表,这比反复调用shuffle并检查它是否满足您的需求要好

from random import choice
CHOICES = (1, 0)

def quasirandom(n, longest=3):
  serial = 0
  latest = 0
  result = []
  rappend = result.append

  for i in xrange(n):
    val = choice(CHOICES)
    if latest == val:
      serial += 1
    else:
      serial = 0
    if serial >= longest:
      val  = CHOICES[val]
    rappend(val)
    latest = val
  return result

print quasirandom(10)
print quasirandom(100)
import random


def next_value(selected):

    # Mathematically, this isn't necessary but it accounts for
    # potential problems with floating point numbers.
    if selected.count(0) == 0:
        return 0
    elif selected.count(1) == 0:
        return 1

    N = len(selected)
    selector = float(selected.count(1)) / N

    if random.uniform(0, 1) > selector:
        return 1
    else:
        return 0


def get_sequence(N, max_run):
    lim = min(N, max_run - 1)
    seq = [random.choice((1, 0)) for _ in xrange(lim)]

    for _ in xrange(N - lim):
        seq.append(next_value(seq[-max_run+1:]))
    return seq


def test(N, max_run, test_count):
    ones = 0.0
    zeros = 0.0

    for _ in xrange(test_count):
        seq = get_sequence(N, max_run)

        # Keep track of how many ones and zeros we're generating
        zeros += seq.count(0)
        ones += seq.count(1)

        # Make sure that the max_run isn't violated.
        counts = [0, 0]
        for i in seq:
            counts[i] += 1
            counts[not i] = 0
            if max_run in counts:
                print seq
                return


    # Print the ratio of zeros to ones. This should be around 1.
    print zeros/ones


test(200, 5, 10000)


这在我的书中是完全随机的:[0,0,0,0,0,1,1,1,1,1]当你们指的是一些对我来说足够混乱的分布时,你们需要停止说随机。我不想如此频繁地连续4或5倍于同一个数字为什么不?这就是随机的工作原理。有1/32的几率可以看到5个1连成一行。在我的书中,这是完全随机的:[0,0,0,0,1,1,1,1,1]当你们指的是一些对我来说足够混乱的分布时,你们需要停止说随机。我不想让相同的数字连续出现4或5倍,为什么不呢?这就是随机的工作原理。有1/32的几率在一行中看到5个1。当然,如果生成所有n/20的速度太快,那么该算法就会崩溃,然后其余的1将违反“一行中有太多1”约束。@Adam Rosenfield:啊。。。说得好,很好!这是可以解决的,但这可能会比它的价值更麻烦,这取决于需求的重要性。当然,这只是第三种算法的问题。前两项工作正常,但不完全符合要求。虽然被接受的答案也是如此,所以我猜要求比问题中所述的更灵活。我尝试在洗牌过程中进行过滤,但得出的结论是一个简单的洗牌也是一样的。。。幸好我的答案不被接受:当然,如果生成所有n/2 0的速度太快,那么该算法就会崩溃,而其余的1将违反“一行中有太多1”的约束。@Adam Rosenfield:啊。。。说得好,很好!这是可以解决的,但这可能会比它的价值更麻烦,这取决于需求的重要性。当然,这只是第三种算法的问题。前两项工作正常,但不完全符合要求。虽然被接受的答案也是如此,所以我猜要求比问题中所述的更灵活。我尝试在洗牌过程中进行过滤,但得出的结论是一个简单的洗牌也是一样的。。。好消息是我的答案被拒绝了:谢谢,我将使用这个并修改代码,以便对于一个100元素的列表,其中25个元素的n=2,25个元素的n=3…嗯,val=CHOICES[val]技巧将不起作用。此外,此版本不保证0和1的数量相等。如果这是一个要求,请选择Mark Ransom的答案,我将展示如何使其限制连续运行的次数。不要选择我的答案,我刚刚意识到回头看问题,Mark Byers早在我之前就提出了相同的建议。好的,我想我找到了一条出路,但它涉及暴力和迭代处理列表以打破运行。我不确定是否值得写下来,必须有一个更聪明的方法…这几乎是Mark Byers的一个实现答案:生成序列检查,确保没有连续运行,但要以shuffley的方式进行:谢谢,我将使用它并修改代码,对于100个元素的列表,有25个元素的n=2,25如果n=3…嗯,那么val=CHOICES[val]技巧就行不通了。此外,此版本不保证0和1的数量相等。如果这是一个要求,请选择Mark Ransom的答案,我将展示如何使其限制连续运行的次数。不要选择我的答案,我刚刚意识到回头看问题,Mark Byers早在我之前就提出了相同的建议。好的,我想我找到了一条出路,但它涉及暴力和迭代处理列表以打破运行。我不确定是否值得写下来,必须有一个更聪明的方法…这几乎是Mark Byers的一个实现答案:生成序列检查,确保没有连续运行,但要以随机方式进行:你如何决定交换哪个其他元素,以仅考虑这个想法?@ChristopheD,我没有这部分的代码的一个原因是我还没有弄清楚所有的细节:这比我最初想象的要难一点:D+1-我通常不会对重复项进行上推投票,但你的答案添加了一些我没有源代码的东西,我认为值得投一票你如何决定换成只考虑这个想法的其他因素?@ChristopheD,我没有这部分的代码的一个原因是我还没有弄清楚所有的细节:这比我最初想象的要难一点:D+1-我通常不会对重复项进行上推投票,但你的答案添加了一些我没有源代码的东西,我认为值得投一票我想如果你能对值和它们的数字进行概括,OP会很感激,但这非常优雅。我想OP会感激你能对值和它们的数字进行概括,但这非常优雅。@小丑:是吗 你读过了吗?若否,原因为何?如果是的话,你的具体问题是什么?@小丑:你读了吗?若否,原因为何?如果是,你的具体问题是什么?