2012-04-27 10 views
3

私はHaskellで行列モジュールを作成していますが、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のサイズを作成し、次にこのサイズのベクトルのベクトルを作成します。行列式がゼロの場合、行列は可逆ではないので、invertibleMatrixを再帰的に呼び出します。それ以外の場合は、新しい行列を返します。

問題は、テストするプロパティにこのコードを挿入しても終了しないということです。 (私はそれが常に逆行列を持たないゼロ要素の行列を作り続けていると思うので、無限ループに入ります)。私は間違って何をしていますか?これをどうやって解決するのですか?ありがとう。

マーク

+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行列であるならば、Aことに気づくことができ - TIはすべてのために可逆であるが、の高々n個値t(すなわち、固有値はAです)。逆行列でない場合は行列を生成し、逆行列を生成します。次に、プロセスは終了することが保証されます(例えば、Aのエントリが、試したtの値よりもはるかに大きい場合など)。