packages feed

what4-1.7: test/BoolNormalization.hs

-- See what percentage of randomly-generated boolean expressions can be
-- completely simplified away. Higher is better. This is one mechanism for
-- evaluating rewrite rules.

{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}

module Main (main) where

import Control.Monad (foldM)
import qualified Control.Monad.State.Strict as State
import Data.Parameterized.Nonce (newIONonceGenerator)
import Data.Parameterized.Some (Some(Some))
import Data.Parameterized.TraversableFC (traverseFC_)
import qualified Hedgehog.Internal.Gen as HG
import qualified Hedgehog.Internal.Tree as HG
import qualified Hedgehog as HG
import What4.Expr.Builder
import What4.Expr (EmptyExprBuilderState(EmptyExprBuilderState))
import What4.Interface

import Bool

-- | Get the size of an expression. Lower is better.
sz :: Expr t tp -> Int
sz =
  \case
    SemiRingLiteral {} -> 1
    BoolExpr {} -> 1
    FloatExpr {} -> 1
    StringExpr {} -> 1
    AppExpr ae ->
      State.execState (traverseFC_ (\e -> State.modify (+ sz e)) (appExprApp ae)) 1
    NonceAppExpr nae ->
      State.execState (traverseFC_ (\e -> State.modify (+ sz e)) (nonceExprApp nae)) 1
    BoundVarExpr {} -> 1

main :: IO ()
main = do
  Some ng <- newIONonceGenerator
  sym <- newExprBuilder FloatIEEERepr EmptyExprBuilderState ng
  let eliminated i = do
        x <- HG.runTreeT (HG.evalGenT (HG.Size 100) (HG.Seed i 1) (doGenExpr sym))
        case HG.nodeValue x of
          Nothing -> error "whoops"
          Just (bExpr, _vars) -> do
            e <- toSymExpr sym (pure . uninterpVar) bExpr
            -- Audit the quality of the generated expressions:
            -- putStrLn "--------------------------------------"
            -- putStrLn (show bExpr)
            -- putStrLn "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
            -- putStrLn (show (printSymExpr e))
            -- putStrLn "______________________________________"
            -- putStrLn (show (sz e))
            case asConstantPred e of
              Just {} -> pure (1, sz e)
              Nothing -> pure (0, sz e)
  let total = 20000
  let count (accFull, accSize) (full, size) = (accFull + full, accSize + size)
  (full, size) <- foldM (\acc seed -> count acc <$> eliminated seed) (0 :: Int, 0 :: Int) [0..total]
  putStrLn ("Fully eliminated " ++ show full ++ "/" ++ show total)
  putStrLn ("Total size: " ++ show size)