module Simplify where import Numeric.Limp.Program as P import Numeric.Limp.Canon as C import Numeric.Limp.Canon.Simplify as CS import Numeric.Limp.Canon.Simplify.Subst as CS import Numeric.Limp.Canon.Simplify.Bounder as CS import Numeric.Limp.Canon.Simplify.Crunch as CS import Numeric.Limp.Canon.Pretty import Arbitrary.Assignment as Arb import Arbitrary.Var as Arb import Arbitrary.Program as Arb import Data.Monoid import Test.Tasty.QuickCheck import Test.Tasty.TH import Debug.Trace tests = $(testGroupGenerator) prop_bounder :: ProgramAss -> Property prop_bounder (ProgramAss p a) = let cp = C.program p cp' = CS.bounderProgram cp valcp = C.checkProgram a cp valcp' | Right p' <- cp' = C.checkProgram a p' -- Infeasible, so assignment is false | otherwise = False in counterexample (unlines [ "CP: " ++ show cp , "CP':" ++ show cp' , "Val: " ++ show (valcp, valcp')]) $ valcp == valcp' prop_crunch :: ProgramAss -> Property prop_crunch (ProgramAss p a) = let cp = C.program p cp' = CS.crunchProgram cp valcp = C.checkProgram a cp valcp' = C.checkProgram a cp' in counterexample (unlines [ "CP: " ++ show cp , "CP':" ++ show cp' , "Val: " ++ show (valcp, valcp')]) $ valcp == valcp' -- | I don't think this property is very interesting. -- The real property should be something like: -- -- > solve cp == solve (simplify cp) -- prop_simplify :: Program' -> Property prop_simplify p = let cp = C.program p simp = CS.simplify cp in case simp of Left _ -> property True Right (a', cp') -> let valcp = C.checkProgram a' cp valcp' = C.checkProgram a' cp' in counterexample (unlines [ "CP: " ++ show cp , "CP':" ++ show cp' , "Ass:" ++ show a' , "Val: " ++ show (valcp, valcp')]) $ valcp == valcp' prop_subst_linear :: Vars -> Property prop_subst_linear vs = forAll (Arb.linearR vs) $ \f -> forAll (Arb.assignment vs) $ \a -> forAll (Arb.assignment vs) $ \b -> let (fc, _) = C.linear f (fc', c') = substLinear a fc in C.evalR (a <> b) fc == C.evalR b fc' + c' -- subst can actually make a failing program pass. -- so this test needs to be implication, not equivalence. prop_subst_program :: Vars -> Property prop_subst_program vs = forAll (Arb.program vs) $ \f -> forAll (Arb.assignment vs) $ \a -> forAll (Arb.assignment vs) $ \b -> let fc = C.program f fc' = substProgram a fc both = a <> b valcp = C.checkProgram both fc valcp'= C.checkProgram b fc' in counterexample (unlines [ "CP: " ++ show fc , "CP':" ++ show fc' , "Ass:" ++ show both , "Val: " ++ show (valcp, valcp')]) $ if valcp then valcp' else True