From 1c27a61a5ac9a33ea99a63cb1b44853bb94e7ef8 Mon Sep 17 00:00:00 2001
From: Hans-Peter Deifel <hpd@hpdeifel.de>
Date: Wed, 3 Apr 2019 16:21:39 +0200
Subject: [PATCH] wta: Allow to restrict number of different monoid values

Otherwise states get one of 2^64 different values in the initial partition,
meaning that they will be distinguished already.
---
 src/random-wta/Generator.hs | 13 +++++++++----
 src/random-wta/Main.hs      | 12 +++++++++++-
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/src/random-wta/Generator.hs b/src/random-wta/Generator.hs
index 69e0b91..515ae94 100644
--- a/src/random-wta/Generator.hs
+++ b/src/random-wta/Generator.hs
@@ -11,6 +11,7 @@ import           Control.Monad.Reader
 import           Data.Coerce
 import           Data.Maybe
 import           Data.Foldable
+import           Control.Arrow ((&&&))
 
 import           Types hiding (spec)
 import           Probability
@@ -18,6 +19,7 @@ import           Probability
 data GeneratorConfig m = GeneratorConfig
    { spec :: WTASpec m
    , zeroFreq :: Probability
+   , differentValues :: Maybe Int
    }
 
 type Generator m = ReaderT (GeneratorConfig m) IO
@@ -26,10 +28,13 @@ runGenerator :: GeneratorConfig m -> Generator m a -> IO a
 runGenerator config action = runReaderT action config
 
 genMonoidValue :: Generator m m
-genMonoidValue = asks (monoid . spec) >>= \case
-  Powerset -> liftIO $ randomIO
-  OrWord   -> liftIO $ randomIO
-  MaxInt   -> liftIO $ randomIO
+genMonoidValue = asks ((monoid . spec) &&& differentValues) >>= \case
+  (Powerset, Nothing) -> liftIO $ randomIO
+  (Powerset, _) -> error $ "differentValues not supported for powerset" -- FIXME detect this early (and handle the case <=2)
+  (OrWord, Nothing)   -> liftIO $ randomIO
+  (OrWord, Just x)   -> liftIO $ randomRIO (0, fromIntegral (x-1))
+  (MaxInt, Nothing)   -> liftIO $ randomIO
+  (MaxInt, Just x)   -> liftIO $ randomRIO (0, x-1)
 
 genStates :: Generator m (Vector m)
 genStates = do
diff --git a/src/random-wta/Main.hs b/src/random-wta/Main.hs
index db19d26..0efec8c 100644
--- a/src/random-wta/Main.hs
+++ b/src/random-wta/Main.hs
@@ -18,6 +18,7 @@ import qualified Text.Megaparsec.Char.Lexer    as Mega
 import           Data.Void
 import           System.Random
 import           System.IO
+import           Numeric
 
 import           Types
 import           Generator
@@ -32,6 +33,7 @@ data Opts = Opts
   , optSymbols :: SymbolSpec
   , optZeroFrequency :: Probability
   , optRandomState :: Maybe StdGen
+  , optDifferentValues :: Maybe Int
   }
 
 readMonoid :: Options.ReadM SomeMonoid
@@ -55,6 +57,12 @@ readSymbols = Options.maybeReader (Mega.parseMaybe parser)
     parser :: Mega.Parsec Void String (Vector Int)
     parser = V.fromList <$> Mega.decimal `Mega.sepBy` (Mega.string ",")
 
+readCount :: String -> Either String Int
+readCount input = case readDec input of
+  [(0, "")] -> Left "Count must be >0"
+  [(x, "")] -> Right x
+  _ -> Left "Count not parse Number"
+
 parseOpts :: Options.Parser Opts
 parseOpts =
   Opts
@@ -93,6 +101,8 @@ parseOpts =
           )
     <*> Options.optional
           (Options.option Options.auto (Options.long "random-state"))
+    <*> Options.optional
+          (Options.option (Options.eitherReader readCount) (Options.long "different-values" <> Options.metavar "NUM" <> Options.help "Maximal number of differnt monoid values to generate"))
 
 withSpec :: Opts -> (forall m . WTASpec m -> x) -> x
 withSpec opts f = case optMonoid opts of
@@ -113,6 +123,6 @@ main = do
 
   withSpec opts $ \spec -> do
     randGen <- getStdGen
-    wta <- runGenerator (GeneratorConfig spec (optZeroFrequency opts)) genWTA
+    wta <- runGenerator (GeneratorConfig spec (optZeroFrequency opts) (optDifferentValues opts)) genWTA
     putStrLn $ "# Random state for this automaton: '" <> show randGen <> "'"
     T.putStr (Build.toLazyText (buildWTA wta))
-- 
GitLab