gpt4 book ai didi

haskell - 随机生成器的意外行为

转载 作者:行者123 更新时间:2023-12-02 10:47:34 24 4
gpt4 key购买 nike

我正在使用 System.Random 库,并且遇到了一些我不完全理解的行为。下面的 shuffle 函数是 Fischer-Yates shuffle 的实现这也可以用作无需替换的随机样本。例如。使用列表和列表的长度调用 shuffle 将会对整个列表进行洗牌,但使用列表和数字 2 调用它应该提取长度为 2 的随机样本。

import           Control.Monad               as M
import Control.Monad.ST
import Data.Vector.Unboxed as VU
import Data.Vector.Unboxed.Mutable as VUM
import System.Random

go = do
g <- newStdGen
let (rand_vec1, g1) = randVector 10 g
let (rand_vec2, g2) = randVector 10 g
let (rand_sample1, g3) = shuffle rand_vec1 2 g
let (rand_sample2, g4) = shuffle rand_vec1 2 g
print rand_vec1
print rand_vec2
print rand_sample1
print rand_sample2

randVector :: (RandomGen g) => Int -> g -> (VU.Vector Int, g)
randVector n = shuffle vector (VU.length vector) where
vector = VU.enumFromN 0 n

shuffle :: (RandomGen g, Unbox a) => VU.Vector a -> Int -> g -> (VU.Vector a, g)
shuffle li size g = runST $ do
vector <- VU.unsafeThaw li
let n = VUM.length vector - 1
let step g i = do
let (j,g') = randomR (0,n) g
VUM.swap vector i j
return g'
g' <- M.foldM step g [0..size-1]
v' <- VU.unsafeFreeze vector
let vec = VU.take size v'
return (vec, g')

我注意到 rand_vec1rand_vec2 始终相同,这是预期的,因为使用相同的随机数生成器。

但是,rand_sample1rand_sample2 即使它们都使用相同的随机生成器,也是不同的。更奇怪的是,超过一半的时间(但并非总是),rand_sample2 仅包含采样向量的前两个数字(如下例所示)。怎么会?示例输出:

[3,0,4,9,7,2,1,8,5,6]

[3,0,4,9,7,2,1,8,5,6]

[9,2]

[3,0]

(此外,欢迎进行代码审查)

最佳答案

因为 shuffle 使用 unsafeThaw/Freeze,它实际上是在修改输入向量,即本例中的 rand_vec1

尝试运行这个:

go = do
g <- newStdGen
let (rand_vec1, g1) = randVector 10 g
print rand_vec1
let (rand_vec2, g2) = randVector 10 g
print rand_vec2
let (rand_sample1, g3) = shuffle rand_vec1 2 g
print rand_sample1
print ("rand_vec1: ", rand_vec1)
let (rand_sample2, g4) = shuffle rand_vec1 2 g
print rand_sample2
print ("rand_vec1: ", rand_vec1)

这是输出:

*Main> go
[7,0,3,5,2,6,9,8,1,4]
[7,0,3,5,2,6,9,8,1,4]
[0,3]
("rand_vec1: ", [0,3,7,5,2,6,9,8,1,4])
[3,7]
("rand_vec1: ", [3,7,0,5,2,6,9,8,1,4])

要回答你的第二个问题,简短的回答是 shuffle 返回的向量与(修改后的)输入向量共享相同的内存。

关于haskell - 随机生成器的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37296825/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com