简体   繁体   English

Test.QuickCheck没有正确生成随机值

[英]Test.QuickCheck not generating random values correctly

I am using Test.QuickCheck to generate random Sudoku puzzles. 我正在使用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

The code runs fine. 代码运行正常。 However, when I perform 但是,当我表演时

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

sequence $ map printSudoku a sequence $ map printSudoku a

it returns something like this : 它返回这样的东西:

....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.

which obviously is not random at all. 这显然不是随机的。 The distribution of empty cells is very high initially and then slowly decreases. 空单元的分布最初非常高,然后缓慢下降。 Am I using the wrong function or in the wrong way? 我使用错误的功能还是错误的方式? Thanks 谢谢

The reason you are seeing this behaviour is that QuickCheck tries progressively bigger test cases. 您看到此行为的原因是QuickCheck会逐渐尝试更大的测试用例。 This is described in the resizing section of the manual. 这在手册的调整大小部分中有所描述。

In the case of suchThatMaybe increasing the size makes it retry generating an arbitrary to match the predicate you passed to it. 在这样的情况下, suchThatMaybe增加大小,使其重试生成一个任意的,以匹配传递给它的谓词。 You can see that in the source http://hackage.haskell.org/package/QuickCheck-2.6/docs/src/Test-QuickCheck-Gen.html#suchThatMaybe . 你可以在源代码http://hackage.haskell.org/package/QuickCheck-2.6/docs/src/Test-QuickCheck-Gen.html#suchThatMaybe中看到它。 The interesting code is: 有趣的代码是:

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)

What's happening is that suchThatMaybe retries n times where n depends on the size parameter passed to the generator. 发生的事情是, suchThatMaybe重试n次,其中n取决于传递给生成器的size参数。

sample' tries the sizes [0,2..20] which get propagated all the way to suchThatMaybe . sample'尝试大小[0,2..20] ,它们一直传播到这样的suchThatMaybe

You can override the increasing sizes by calling resize on a generator: 您可以通过调用生成器上的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