Commit 1f8b6e79 by Hans-Peter Deifel 🐢

wta: Implement --out-degree parameter

parent 36bc8d65
 ... @@ -19,6 +19,7 @@ import System.Random ... @@ -19,6 +19,7 @@ import System.Random import Numeric import Numeric import System.IO import System.IO import System.Exit import System.Exit import Control.Applicative import Types import Types import Generator import Generator ... @@ -27,11 +28,13 @@ import Probability ... @@ -27,11 +28,13 @@ import Probability data SomeMonoid = forall m. SomeMonoid (MonoidType m) data SomeMonoid = forall m. SomeMonoid (MonoidType m) data ZeroFrequency = Percentage Probability | OutDegree Int data Opts = Opts data Opts = Opts { optMonoid :: SomeMonoid { optMonoid :: SomeMonoid , optStates :: Int , optStates :: Int , optSymbols :: SymbolSpec , optSymbols :: SymbolSpec , optZeroFrequency :: Probability , optZeroFrequency :: ZeroFrequency , optRandomState :: Maybe StdGen , optRandomState :: Maybe StdGen , optDifferentValues :: Maybe Int , optDifferentValues :: Maybe Int } } ... @@ -90,19 +93,23 @@ parseOpts = ... @@ -90,19 +93,23 @@ parseOpts = <> Options.help <> Options.help "Comma separated list of symbols per arity. E.g. 2,0,1 means two symbols with arity 0, non with arity 1 and one with arity two" "Comma separated list of symbols per arity. E.g. 2,0,1 means two symbols with arity 0, non with arity 1 and one with arity two" ) ) <*> Options.option <*> parseZeroFreq <*> 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")) parseZeroFreq :: Options.Parser ZeroFrequency parseZeroFreq = (Percentage <\$> Options.option (Options.eitherReader readProbability) (Options.eitherReader readProbability) ( Options.long "zero-frequency" ( Options.long "zero-frequency" <> Options.showDefault <> Options.showDefault <> Options.value (Probability 7 1) <> Options.value 0.7 <> Options.metavar "FREQ" <> Options.metavar "FREQ" <> Options.help <> Options.help "Frequency of edges with zero weight as number between 0 and 1." "Frequency of edges with zero weight as number between 0 and 1." ) )) <*> Options.optional <|> (OutDegree <\$> Options.option Options.auto (Options.long "out-degree" <> Options.metavar "NUM_TRANSITIONS" <> Options.help ("Expected number of outgoing transitions per state." <> " This calculates the zero frequency from the number of states, symbols and this parameter."))) (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 -> (forall m . WTASpec m -> x) -> x withSpec opts f = case optMonoid opts of withSpec opts f = case optMonoid opts of ... @@ -111,6 +118,13 @@ withSpec opts f = case optMonoid opts of ... @@ -111,6 +118,13 @@ withSpec opts f = case optMonoid opts of , numSymbols = optSymbols opts , numSymbols = optSymbols opts } } computeProbability :: WTASpec m -> ZeroFrequency -> Probability computeProbability _ (Percentage p) = p computeProbability spec (OutDegree d) = let n = numStates spec t = V.sum (V.imap (\i syms -> syms * n^i) (numSymbols spec)) in fromRationalApprox (1 - fromIntegral d/fromIntegral t) main :: IO () main :: IO () main = do main = do let optSpec = let optSpec = ... @@ -130,6 +144,8 @@ main = do ... @@ -130,6 +144,8 @@ main = do withSpec opts \$ \spec -> do withSpec opts \$ \spec -> do randGen <- getStdGen randGen <- getStdGen wta <- runGenerator (GeneratorConfig spec (optZeroFrequency opts) (optDifferentValues opts)) genWTA let zeroFreq = computeProbability spec (optZeroFrequency opts) hPutStrLn stderr \$ "p hacking: " ++ show zeroFreq wta <- runGenerator (GeneratorConfig spec zeroFreq (optDifferentValues opts)) genWTA putStrLn \$ "# Random state for this automaton: '" <> show randGen <> "'" putStrLn \$ "# Random state for this automaton: '" <> show randGen <> "'" T.putStr (Build.toLazyText (buildWTA wta)) T.putStr (Build.toLazyText (buildWTA wta))
 {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Probability (Probability(..), readProbability, decide) where module Probability (Probability(..), readProbability, decide, fromRationalApprox) where import System.Random import System.Random import Data.Scientific import Data.Scientific newtype Probability = Probability Scientific newtype Probability = Probability Scientific deriving newtype (Show) deriving newtype (Show,Fractional,Num) readProbability :: String -> Either String Probability readProbability :: String -> Either String Probability readProbability input = Probability <\$> case input of readProbability input = Probability <\$> case input of ... @@ -29,3 +29,16 @@ decide (Probability science) = do ... @@ -29,3 +29,16 @@ decide (Probability science) = do let exp = negate (base10Exponent science) let exp = negate (base10Exponent science) randomNumber <- randomRIO (0, (10^exp)-1) randomNumber <- randomRIO (0, (10^exp)-1) return \$ randomNumber < digits return \$ randomNumber < digits fromRationalApprox :: Rational -> Probability fromRationalApprox r = Probability \$ clamp 0 1 \$ case fromRationalRepetend (Just 100) r of Left (s, _) -> s -- TODO Maybe make this case more precise. Currently, 1/3 gets converted to -- 0.3, which might not be precise enough. Right (s, _) -> s clamp :: (Ord a, Num a) => a -> a -> a -> a clamp low high x | x < low = low | x > high = high | otherwise = x
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!