我正在纸牌游戏中进行一些假设检验。
为此,我实现了游戏和玩游戏的 AI。对于测试,我必须对我的牌组中所有可能的牌排列空间进行抽样(牌组有 24 张牌,所以有 24 种!牌组的不同初始状态)。然而,采样应该是独立的,因为(a)在洗牌后,每个初始排列应该有概率(1/24!)和(b)如果 i 和 i' 是两次洗牌后的两个初始排列,则排列 i 和排列 i' 是初始排列的概率应该是 (1/24!)x(1/24!)。[注 1]
所以,如果 d 是我的牌组,而 shuffleDeck 是我洗牌的功能。我相信随机单子(monad)是以概率((suffleDeck d)== i)= 1/24的方式构建的!
但我的问题是:这个函数在与函数 replicateM 交互时是独立的吗?换句话说,以下是真的吗?
P((replicateM 2 (shuffleDeck d) )== [i,i']) = P((suffleDeck d) == i ) * P((suffleDeck d) == i' )
其中 P(x = X) 是 x 为 X 的概率。
我用于洗牌的代码如下:
import System.Random
shuffleDeck d = do
seed <- newStdGen
return $ shuffle seed d
shuffle :: StdGen -> [Card] -> [Card]
shuffle g [] = []
shuffle g d = c : shuffle g' d'
where (c, g') = oneRandomCard g d
d' = d\\[c]
oneRandomCard :: StdGen -> [Card] -> (Card, StdGen)
oneRandomCard g d =((last $ take n d), g1 )
where (n,g1) = randomR (1, length d) g
我看到乍一看这个问题似乎微不足道,但考虑到 haskell 处理随机性的方式,我认为值得提出一个问题。
[1]注意:分布不需要像我说的那样均匀。它必须是一个已知的分布,这样我才能掌握测试的力量。但在这种情况下,它应该是统一的。
[2]注意:如评论中所述,该函数仅使用 System.Random 而不是 Control.Monad.Random 起作用。
最佳答案
由于您的示例仅使用 replicateM
在 IO
,这个问题实际上有点不正确。 replicateM 2 (shuffleDeck d)
有类型 IO [[Card]]
.它永远不会等于 [[Card]]
类型的东西.但是,虽然在使用 Haskell 时该技术问题非常重要,但我将忽略它来回答我认为是您的潜在问题。
据我所知,您的基本问题是以下两个代码片段之间是否存在差异:
decks d = replicateM 2 (shuffleDeck d)
和
decks d = do
d1 <- shuffleDeck d
d2 <- shuffleDeck d
return [d1, d2]
如果这两者之间存在差异,
Monad
有问题的类型的实例已损坏。单子(monad)定律与 replicateM
的定义相结合要求这些表达式具有相同的结果。
关于haskell - Random Monad 在replicatM 迭代之间是独立的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26735523/