packages feed

ideas-0.6: src/Domain/Math/Polynomial/Generators.hs

-----------------------------------------------------------------------------
-- Copyright 2010, Open Universiteit Nederland. This file is distributed 
-- under the terms of the GNU General Public License. For more information, 
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer  :  bastiaan.heeren@ou.nl
-- Stability   :  provisional
-- Portability :  portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Domain.Math.Polynomial.Generators 
   ( polynomialGen, polynomialDegreeGen
   , cubicGen, quadraticGen, linearGen 
   ) where

import Prelude hiding ((^))
import Domain.Math.Expr
import Domain.Math.Numeric.Generators
import Test.QuickCheck
import Control.Monad

polynomialGen :: Int -> Gen Expr
polynomialGen n = do
   d <- choose (0, n `div` 5)
   polynomialDegreeGen d n

-- Random polynomial generator for (exactly) degree d
-- No division by zero
polynomialDegreeGen :: Int -> Int -> Gen Expr
polynomialDegreeGen d n
   | d==0         = ratGen
   | n==0 && d==1 = return (Var "x") 
   | n==0         = return (Var "x" ^ fromIntegral d) 
   | otherwise    = oneof $
        [ timesGen, plusGen
        , liftM2 (:/:) (rec d) ratGenNZ
        ] ++ [ powerGen | d > 1 ]
 where
   rec i = polynomialDegreeGen i (n `div` 2)
   plusGen = do
      d1 <- choose (0, d)
      a <- rec d1
      b <- rec d
      oneof $ map return [a :+: b, b :+: a, a :-: b, b :-: a, Negate b]
   timesGen = do
      d1 <- choose (0, d)
      a  <- rec d1
      b  <- rec (d-d1)
      return (a :*: b)
   powerGen = do
      i <- oneof [ return i | i <- [2..d], d `mod` i == 0 ]
      a <- rec (d `div` i)
      return (a ^ fromIntegral i)
      
cubicGen, quadraticGen, linearGen :: Int -> Gen Expr
cubicGen     = polynomialDegreeGen 3
quadraticGen = polynomialDegreeGen 2
linearGen    = polynomialDegreeGen 1

ratGen, ratGenNZ :: Gen Expr
ratGen   = sized ratioExprGen
ratGenNZ = sized ratioExprGenNonZero