指定挑战中随机生成的方式


16

注意:根据对Meta的共识问题是此处的主题。

鉴于这种“编写挑战时要避免的事情”,我开始考虑涉及随机生成某些对象的挑战。

有时候,我想发布一个挑战,其中涉及随机生成一个foo,其中

  1. 检查给定的东西是否是foo很容易,并且
  2. 快速生成“优质”随机foo会有点困难。

例如,一个foo可能是一个二进制矩阵,其中在任何方向上都没有4个相等位的段。检查给定的二进制矩阵是否为foo很容易,但是生成具有良好分布分布的随机foo似乎需要回溯算法或类似的算法。

无论如何,现在我需要客观地指定符合条件的随机foo,并且我希望它在我多次运行该程序时的直观含义是“不可预测的”。最严格的方法是要求输出一致地为随机数:所有有效foo的生成概率相同。这通常过于严格,因为我不知道如何保存生成所有有效的foo,删除重复项并选择一个乏味又缓慢的方法。

我的下一个想法是要求所有有效的foo都必须具有正的生成概率。但是,这意味着以下方法是有效的:生成类似foo的随机事物(在我们的示例中为随机二进制矩阵),如果它是foo,则将其返回,否则返回硬编码的foo(例如,恒等矩阵) )。这也有点无聊,因为它基本上只是添加到随机矩阵生成器的foo的识别器。

对于不可预测的随机foo是否可以有一个很好的通用定义?

TL; DR

是否有一种很好的方法来指定一个“不可预测的”随机生成的对象,该对象不能固定发行版但不鼓励硬编码?


对于元数据上的随机数,我们有一个标准定义,定义将禁止硬编码,但就完全统一而言,并没有限制它。
Geobits,2013年

5
好问题。我过去发现指定随机性很困难。特别是对于您描述的场景,还存在一个问题,就是您只能生成随机候选者并在它们无效时重做。这甚至可以为您提供统一的分布,但运行时间不确定。在指定均匀分布时,还存在一个问题,即实际的解决方案永远不会完全均匀。这是一个非常微妙的问题。+1
马丁·恩德

@MartinEnder对,我忘记了这种方法。我可以禁止它以及带有时限的其他慢速算法,但是它们仍然允许“一个硬编码的foo”解决方案。
Zgarb '16

似乎您可以指定K3 / K4 CPRNG,大多数语言都将具有库en.wikipedia.org/wiki/Pseudorandom_number_generator
Ewan

1
@Zgarb不允许“生成并重做”的一个大问题是大多数语言的RNG库都这样做。
内森·美林

Answers:


5

返回一千个不同的foos

这样就不可能返回硬编码的值,并且打高尔夫球也得不偿失。但是,合法的foo生成器确实很少有机会输出重复的foo,除非实际检查它们。为了消除检查的负担,可以将通过经验测试的失败率(例如10%)指定为可以接受。

注意生日悖论,重复的可能性可能比您想象的要高。如果只有一百万个可能的foos,那么一千个随机foos的概率约为0.6,即某个地方有重复的foos,并且假定foo的生成是完全统一的。如果这可能是一个问题,那么每生成1000个就需要900个唯一的foo,这对于真正的foo生成器来说要慷慨得多,但对于硬编码仍然不切实际。

这还允许您重复生成类似foo的东西并检查fooness,直到获得foos。我个人认为这是一个有效的解决方案,但是如果您不喜欢它:

快点做

完全随机的类似foo的事物被foo的机会可能很小,因此指定时间限制可能会强制真正尝试foo的生成。

为了适应不同语言之间的速度差异,您可能希望根据Hackerrank之类的语言设置不同的时间限制:https ://www.hackerrank.com/environment 。但是,如果您指定足够大的foo,则类似foo的随机事物被foo的概率可能会非常低,因此“在宇宙热死之前”规则可能就足够了。


我认为您正在这里。“至少90%的时间运行程序N次将不会产生任何重复”是具体且易于测试的,并且可以与一定时间结合使用,以防止暴力破解和简单的拒绝采样。
Zgarb '16

2

我并没有声称对这个问题有最终的解决方案(或者此列表是详尽无遗的),但是我想概述一些想到的可能方法以及它们为什么会行不通。我还将不讨论切线问题,例如使用当前时间戳作为随机性源是否足够“不可预测”以及如何强制执行概率分布的某些属性-我将仅着眼于避免使用硬编码的解决方案。

不是解决方案:明确禁止硬编码

这是一个坏主意。这是一项不可观察的要求(这意味着您无法仅通过运行程序来确定它是否满足要求),在PPCG上强烈建议不要这样做,如果在其他平台上运行该程序并在此平台上验证了提交,则可能完全不可能。自动化的方式。这样的要求存在的问题是,您必须首先找到“硬编码”的客观定义。通常,如果您尝试这样做,只会使情况变得更糟。

使硬编码不可行

如果您不能完全禁止使用它,但又不想让人们使用它,那么您可以尝试设计挑战,以使硬编码根本不是一种竞争方法。如果应生成的对象足够大且不可压缩,以至于将一个示例放入代码中比编写一种随机生成有效解的算法所需的字节更多,那么这是可能的。在您的特定示例中,当然不是这种情况,因为身份矩阵是有效的并且通常易于生成,但是对于其他问题,情况可能并非如此。如果目标对象足够不规则,则仅要求它们具有较大的大小,这可能不会影响实际算法的字节数,但会炸毁硬编码部分。

参数化输出

通常,这些问题带有一个或多个自然参数,例如示例中矩阵的大小。如果是这样,则将该参数作为输入就足以使硬编码变得不可能或至少不切实际。在某些情况下,对于通过手动或通过广泛搜索找到的给定参数值,对某个特定解决方案进行硬编码可能很容易,但是对于这些解决方案的实例,可能没有简单的封闭形式,因此并非如此可以轻松地为任意输入生成默认值。同样,您提到的示例不是这种情况,因为单位矩阵可以在任何大小下工作,但对于此相关问题通常是高度不规则的,因此无论如何不主动搜索有效值就不可能拥有默认值。您可以将其与时间限制结合使用,以避免暴力搜索默认值。

一些限制的概率分布

如果您愿意放弃一个完全不受限制的概率分布,则可以对其施加一些约束,这些约束仍然使答题者在选择其分布时具有很大的自由度,但是这使硬编码变得困难或不可能:

  • 想到的最简单的约束是要求任何可能的输出的最小和最大概率之差低于某个阈值。硬编码方法对于几乎所有输出都可能具有几乎为零的概率,而对于默认值而言,其概率接近于1。如果您要求最大差值小于0.1(例如),则必须有10个(随机选择)默认值才能使方法成为一种选择。同样,对于每个可能的输出,您也可能只要求最小的概率,例如1 /(2 * N *),其中N是可能的输出数。
  • 或者,您可以要求分布中不存在(似然性)缺口,因此不存在大小δ的间隔(由您选择),因此存在较高和较低的概率。这意味着就可能性而言,不可能有任何异常值,这些异常值可能是由硬编码方法生成的。

这些方法的主要问题在于,它们很难推理,很难证明答案的正确性,而且对于大的输出空间,通过实验验证正确性是不可能的。但是,它们为程序提供了一个原则上可以观察到的要求,这使得不可能进行硬编码。

这些方法可能还需要一个时间限制,因为增加非默认值的概率的一种方法是尝试多次找到随机的foo,然后再回到默认值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.