簡體   English   中英

Test.QuickCheck沒有正確生成隨機值

[英]Test.QuickCheck not generating random values correctly

我正在使用Test.QuickCheck生成隨機的數獨謎題。

data Sudoku = Sudoku { getSudoku :: [[Maybe Int]] } deriving (Show, Eq)

rows :: Sudoku -> [[Maybe Int]]
rows (Sudoku rs) = rs

--B1
printSudoku :: Sudoku -> IO ()
printSudoku s = do
    putStrLn . unlines . map (map (maybe '.' (head . show))) $ rows s

--C1
cell :: Gen (Maybe Int)
cell = suchThatMaybe (frequency [(90, choose (0,0)),(10, choose(1,9))]) (/=0)

--C2
instance Arbitrary Sudoku where
    arbitrary = do
        rows <- sequence [ sequence [ cell | j <- [1..9] ] | i <- [1..9] ]
        return (Sudoku rows)

--C3
prop_Sudoku :: Sudoku -> Bool
prop_Sudoku = isSudoku

checkRandomSudoku :: IO [Bool]
checkRandomSudoku = do
    s <- sample' (arbitrary :: Gen Sudoku)
    return $ map isSudoku s

代碼運行正常。 但是,當我表演時

a < - sample'(任意:: Gen Sudoku)

sequence $ map printSudoku a

它返回這樣的東西:

....5..3.
...4.....
...2.....
...5.....
.........
...33....
...5.....
...2.4...
.........

.........
.343.....
.........
......9.2
.........
45....5.1
.2......7
.7..88.34
.9....6..

....2..8.
.2121638.
.7.7...9.
4..45.6..
.....6.2.
..6.6....
53..9.6..
..9....7.
.47892...

.373411..
5...3282.
...45..9.
8989..18.
31.8113..
9..35.6..
4.685....
.4....39.
7..6.5.76

48.178.53
1.871.4.4
3165.17..
.1...7.59
.98126.51
6.6...775
9.4636952
.5..239..
372.....8

.34.73129
.5.8.27.1
344.34931
28.6.94.1
6327.3..8
3743.5496
93...7984
..82.8...
..3.54.93

273847853
5568.7465
832.73515
3766..6.7
.7.196256
1.96.9.3.
.7156.268
1615.196.
.392..633

731652284
863.8.768
31..5.5.6
961.5.467
1245.1159
5..275471
52.727759
6.656.849
99.72352.

這顯然不是隨機的。 空單元的分布最初非常高,然后緩慢下降。 我使用錯誤的功能還是錯誤的方式? 謝謝

您看到此行為的原因是QuickCheck會逐漸嘗試更大的測試用例。 這在手冊的調整大小部分中有所描述。

在這樣的情況下, suchThatMaybe增加大小,使其重試生成一個任意的,以匹配傳遞給它的謂詞。 你可以在源代碼http://hackage.haskell.org/package/QuickCheck-2.6/docs/src/Test-QuickCheck-Gen.html#suchThatMaybe中看到它。 有趣的代碼是:

try _ 0 = return Nothing
try k n = do x <- resize (2*k+n) gen
             if p x then return (Just x) else try (k+1) (n-1)

發生的事情是, suchThatMaybe重試n次,其中n取決於傳遞給生成器的size參數。

sample'嘗試大小[0,2..20] ,它們一直傳播到這樣的suchThatMaybe

您可以通過調用生成器上的resize來覆蓋不斷增加的大小:

>>> a <- sample' $ (resize 2 arbitrary :: Gen Sudoku)
>>> sequence $ map printSudoku a
.....8.5.
.......4.
.........
4..25...5
......9..
....5....
........7
.....7...
...4.....

...5.....
.......4.
...6...6.
..14.....
...7...7.
....2....
.....6...
...4..572
.4.....6.

..6..8...
..4......
.........
......9..
839......
67..4....
.5.......
....5....
........3

4...1....
7..9.39..
....6....
...4.1...
.........
.........
..9....6.
.2.9...84
.....8...

.64......
..3.44...
4.......4
....1..8.
.9.......
34.......
.....6...
18.2..593
.4.7.....

.........
...8..6..
.2......5
...5.....
.2.......
........6
.3....13.
8.1.2..85
....5....

..7......
..67...5.
..6......
27....1.9
.9.......
78.....7.
......34.
.......2.
..81...81

3.1......
.........
.....6...
.........
.16.71...
.........
.2.......
.........
.....9.1.

..65..6.9
........5
..1.4....
....86...
.2..2..2.
.....9...
..6......
.........
...7..855

.......94
...14..8.
.....4...
...3....9
.........
.....5...
.5.......
45.....8.
..48.....

4........
......3..
5......4.
.4..6..2.
..3......
.........
..9......
6..9.....
....7....

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM