2012-04-27 87 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中,然后这个尺寸的向量的向量之间的尺寸。如果行列式为零,那么矩阵不是可逆的,所以我递归地调用invertibleMatrix。否则,我返回新的矩阵。

问题是,当我把它放在一个属性中进行测试时,这段代码不会终止。 (我认为它不断创建同样的零元素矩阵,它显然不具有逆元素,因此它会进入无限循环)。我究竟做错了什么?我该如何解决?谢谢。

马克

+0

还有其他人有什么建议吗? – Mark 2012-04-27 08:32:47

+0

'vectorOf'的定义是什么样的? – 2012-04-27 15:11:30

+0

'vectorOf :: Int - > Gen a - > Gen [a]'并且在QuickCheck中定义。 – Mark 2012-04-28 02:46:13

回答

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 2012-04-27 08:05:35

+0

你也可以写'seed = 0 :: Integer'来简洁。 – huon 2012-04-27 08:10:43

+0

是啊......我不惊讶我用coarbitrary错了。我刚刚从床上爬起来,还在半睡半醒。 – 2012-04-27 09:31:10

2

由于绕过你的问题的一种方式,你可以注意到,如果一个n×n的矩阵然后A - TI是可逆的,但所有的最多ñ值t(即A的特征值)。因此,生成一个矩阵,如果它不是可逆的,则为它添加一个小的倍数,并继续尝试直到它。然后该过程被保证终止(只要底层数字类型表现得相当好,哪些浮点有时不会,例如,如果条目的数量远大于你尝试的数值t)。