2012-04-27 2 views
3

Haskell에서 Matrix 모듈을 만들고 QuickCheck를 사용하여 코드의 일부 속성을 테스트하고 싶습니다. 특히 역행렬이있는 임의의 행렬을 생성하려고합니다. 다음은 그러한 행렬을 생성하는 QuickCheck 생성기를 작성하려는 시도입니다.QuickCheck를 이용한 Haskell 행렬 테스트

invertibleMatrix :: (Num a, Arbitrary a) => Gen (Matrix a) 
invertibleMatrix = do s <- choose (2,10) 
         a <- vectorOf s (vector s) 
         if (det (Matrix a) == 0) then 
         invertibleMatrix 
         else 
         return (Matrix a) 

코드는 먼저 2와 10 사이의 크기를 만들고이 크기의 벡터 벡터를 만듭니다. 행렬식이 0이라면 행렬은 역전이 아니므로 invertibleMatrix를 재귀 적으로 호출합니다. 그렇지 않으면 새 행렬을 반환합니다.

문제는이 코드를 테스트 할 속성에 넣을 때 종료되지 않는다는 것입니다. (나는 그것이 항상 역원을 가지지 않는 제로 요소의 같은 s x 행렬을 끊임없이 생성한다고 생각하여 무한 루프로 간다.) 내가 도대체 ​​뭘 잘못하고있는 겁니까? 이 문제를 어떻게 해결할 수 있습니까? 감사.

마크

+0

그 밖의 제안 사항이 있습니까? – Mark

+0

'vectorOf'의 정의는 어떻게 생겼습니까? –

+0

'vectorOf :: Int -> Gen a -> Gen [a]'이며 QuickCheck 자체에서 정의됩니다. – Mark

답변

1
squareMatrix :: (Num a, Arbitrary a) => Gen (Matrix a) 
squareMatrix = do s <- choose (2,6) 
        a <- vectorOf s (vector s) 
        return (Matrix a) 

invertibleMatrix :: (Num a, Arbitrary a) => Gen (Matrix a) 
invertibleMatrix = suchThat squareMatrix ((/=0) . det) 

누구나 알고 싶은 경우, 해결책입니다.

마크

0

나는이 테스트를하지 않은,하지만 난 당신이 원하는 교란의 종류는 일반적으로 임의의 기능을 구현하는 데 사용되는 CoArbitrary에서 취할 수 있다고 생각합니다. 문제를 우회하는 방법으로

invertibleMatrix :: (Num a, Arbitrary a) => Gen (Matrix a) 
invertibleMatrix = kick seed where 
    seed :: Integer 
    seed = 0 
    kick n = do 
    s <- choose (2,10) 
    a <- vectorOf s (vector s) 
    if (det (Matrix a) == 0) then 
     coarbitrary (kick (succ n)) 
    else 
     return (Matrix a) 
+0

좋아요, 나는 coarbitrary를 시도 할 것입니다 ... 아마 위의 코드가 컴파일되지 않을 것으로 생각됩니다. 어쨌든 고마워. – Mark

+0

간결함을 위해'seed = 0 :: Integer'라고 쓸 수있다. – huon

+0

그래 ... 나는 거기에 coarbitrary를 사용하는 것에 놀라지 않는다. 방금 침대에서 굴러 와서 잠이 들었습니다. –

2

, 당신은 N × N 행렬 인 경우 다음 것을 알 수있다 - TI이 모든 가역하지만 의 최대 N 값 t (즉, 고유 값은 A입니다.) 따라서 행렬을 생성하십시오. 역행렬이 아닌 경우에는 정체성의 작은 배수를 더하고 계속 시도하십시오. 그런 다음 (예 : A의 항목이 사용자가 시도한 t 값보다 훨씬 큰 경우) 부동 소수점이 종종 작동하지 않는 한 기본 숫자 유형이 적절하게 작동하는 한 프로세스가 종료됩니다.

관련 문제