2014-02-14 2 views
4

Test.QuickCheck를 사용하여 임의의 스도쿠 퍼즐을 생성하고 있습니다.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 

코드가 정상적으로 실행됩니다. 그러나, 나는 수행 할 때

< - 샘플 '(임의 :: 세대 ​​스도쿠)

순서 $지도 printSudoku

가이 같은 반환

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

분명히 전혀 무작위가 아닙니다. 빈 세포의 분포는 처음에는 매우 높았고 천천히 감소합니다. 잘못된 기능을 잘못 사용하고 있습니까? 감사합니다.

+0

을 (오히려 현재의 문제의 당신의 묘사보다) :이 좋은 생각이 아니다 생각한다. 정확한 스도쿠 퍼즐을 생성하는 것은 쉽지만 들리지 않는 것 중 하나 인 것 같습니다. 그리고이 문제를 해결하면 12 가지 이상한 문제가 발생할 것입니다. 하지만 이미 많은 퍼즐이 있습니다. 기존 코퍼스를 사용하여 모든 문제를 건너 뛸 수 있습니까? –

+0

나는 [여기] (http://www.cse.chalmers.se/edu/year/2013/course/TDA555/lab3.html)에서 발견 한 운동을 따르고있다. 너와 나는 동의한다. 예를 들어, 행/열/상자에 반복되는 숫자가 있는지 확인하지 않고 있지만 예상대로 난수가 생성되지 않은 이유를 계속 이해하고 싶습니다. 특히 빈도수가 많아서 채워지지 않은 항목이 많을 것으로 예상 했었습니다. 번호가 매겨진 항목보다 훨씬 많은 항목이 있기 때문에 – dtan

답변

6

이 동작이 나타나는 이유는 빠른 검사가 점차적으로 더 큰 테스트 사례를 시도하기 때문입니다. 이 내용은 설명서의 resizing 섹션에 설명되어 있습니다.

suchThatMaybe의 경우 크기를 늘리면 전달한 조건부와 일치하는 임의의 생성을 다시 시도합니다. 소스 http://hackage.haskell.org/package/QuickCheck-2.6/docs/src/Test-QuickCheck-Gen.html#suchThatMaybe에서 확인할 수 있습니다. 흥미로운 코드는 다음과 같습니다 n 발전기에 전달 된 크기 매개 변수에 따라 달라집니다 어디에 무슨 일

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 배이다.

sample' tries the sizes [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.... 
+0

이 표시됩니다. 나는 hackage에 대한 함수에 대한 설명이 그것의 술어에 대한 확률에 영향을 미친다고 제안하지 않기 때문에 다소 직관력이 없다고 생각한다. 그런 크기를 사용하지 않고도 사용할 수 있을지 궁금합니다. 네가 아주 친절하다면 나에게 모범을 남길 수 있겠 니? 감사합니다. – dtan

+0

'suchThatMaybe'의 아이디어는 최대한 많은 다른 테스트 케이스를 다루는 것입니다. 따라서 매우 만족스럽지 않은 조건부를 사용하는 경우 다시 시도하여 긍정적 인 테스트 케이스를 작성하는 것이 더 쉽습니다. –

관련 문제