3

Haskell で Matrix モジュールを作成しており、QuickCheck を使用してコードのいくつかのプロパティをテストしたいと考えています。具体的には、関連する逆行列を持つランダム行列を生成したいと考えています。以下は、そのような行列を生成する QuickCheck ジェネレーターを作成する試みです。

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 を再帰的に呼び出します。それ以外の場合は、新しい行列を返します。

問題は、このコードをプロパティに入れてテストしても終了しないことです。(明らかに逆行列を持たないゼロ要素の同じ sxs 行列を常に作成しているため、無限ループに入ると思います)。私は何を間違っていますか?これを修正するにはどうすればよいですか? ありがとう。

マーク

4

3 に答える 3

2

問題を回避する方法として、An×n行列の場合、A --tIはtの最大n個の値(つまり、Aの固有値)を除いてすべて可逆であることに気付くでしょう。したがって、行列を生成します。それが可逆でない場合は、それにIDの小さな倍数を追加し、それができるまで試行を続けます。次に、プロセスが終了することが保証されます(基になる数値型が適切に動作する限り、フローティングポイントは時々動作しません。たとえば、Aのエントリが試行したtの値よりもはるかに大きい場合)。

于 2012-04-27T11:25:37.617 に答える
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) 

誰かが知りたい場合は、これが解決策です。

マーク

于 2012-04-28T09:38:31.567 に答える
0

I have not tested this, but I think that the sort of perturbation you want can be taken from CoArbitrary which is usually used to implement a random function.

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)
于 2012-04-27T06:25:20.573 に答える