diff --git a/src/random-wta/Generator.hs b/src/random-wta/Generator.hs index 54d2444c1f4557c954c9b11d1f323c6f176a7fcf..10e935eecd1ebb59eb65f0f36fd7d7f3428da2dc 100644 --- a/src/random-wta/Generator.hs +++ b/src/random-wta/Generator.hs @@ -2,7 +2,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE LambdaCase #-} -module Generator (genWTA, runGenerator, GeneratorConfig(..), ZeroFrequency(..)) where +module Generator (genWTA, runGenerator, GeneratorConfig(..), EdgeConfig(..)) where import Data.Vector ( Vector ) import qualified Data.Vector as V @@ -21,18 +21,18 @@ import Probability import IndexedTransition import qualified IndexedTransition -data ZeroFrequency = Percentage Probability | OutDegree Int +data EdgeConfig = ZeroFrequency Probability | NumTransitions Int data GeneratorConfig m = GeneratorConfig { spec :: WTASpec m - , zeroPolicy :: ZeroFrequency + , zeroPolicy :: EdgeConfig , differentValues :: Maybe Int } type Generator m = ReaderT (GeneratorConfig m) IO zeroFreq :: GeneratorConfig m -> Probability -zeroFreq (GeneratorConfig { zeroPolicy = Percentage p }) = p +zeroFreq (GeneratorConfig { zeroPolicy = ZeroFrequency p }) = p zeroFreq _ = error "zeroFreq: unexpected out degree" -- TODO Ugly as hell runGenerator :: GeneratorConfig m -> Generator m a -> IO a @@ -107,13 +107,12 @@ uniqueTransitions num (IndexedTransition.Index max) = helper S.empty num genTransitions' :: Int -> Generator m (Vector (Vector (Transition m))) -genTransitions' outDegree = do +genTransitions' numTransitions = do wtaSpec <- asks spec let n = numStates wtaSpec m = IndexedTransition.maxIndex wtaSpec - desiredEdges = n * outDegree - transitions <- lift \$ map (IndexedTransition.fromIndex wtaSpec) <\$> uniqueTransitions desiredEdges m + transitions <- lift \$ map (IndexedTransition.fromIndex wtaSpec) <\$> uniqueTransitions numTransitions m weightedTransitions <- (traverse.traverse.traverse) (const genMonoidValue) transitions let byState = foldl' (\m (State s, t) -> M.insertWith (++) s [t] m) M.empty weightedTransitions @@ -126,5 +125,5 @@ genTransitions' outDegree = do genWTA :: Generator m (WTA m) genWTA = asks zeroPolicy >>= \case - OutDegree d -> WTA <\$> asks spec <*> genStates <*> (genTransitions' d) - Percentage _ -> WTA <\$> asks spec <*> genStates <*> genTransitions + NumTransitions d -> WTA <\$> asks spec <*> genStates <*> (genTransitions' d) + ZeroFrequency _ -> WTA <\$> asks spec <*> genStates <*> genTransitions diff --git a/src/random-wta/Main.hs b/src/random-wta/Main.hs index 7e61b053c4ca92321bd7f6404ab6f5d18bab74c4..b7448e4fc6c4b3a4dbb323c9e0c80736e6b95d5e 100644 --- a/src/random-wta/Main.hs +++ b/src/random-wta/Main.hs @@ -32,7 +32,7 @@ data Opts = Opts { optMonoid :: SomeMonoid , optStates :: Int , optSymbols :: SymbolSpec - , optZeroFrequency :: ZeroFrequency + , optEdgeConfig :: EdgeConfig , optRandomState :: Maybe StdGen , optDifferentValues :: Maybe Int } @@ -104,9 +104,9 @@ parseOpts = ) ) -parseZeroFreq :: Options.Parser ZeroFrequency +parseZeroFreq :: Options.Parser EdgeConfig parseZeroFreq = - (Percentage <\$> Options.option + (ZeroFrequency <\$> Options.option (Options.eitherReader readProbability) ( Options.long "zero-frequency" <> Options.showDefault @@ -116,13 +116,12 @@ parseZeroFreq = "Frequency of edges with zero weight as number between 0 and 1." ) ) - <|> (OutDegree <\$> Options.option + <|> (NumTransitions <\$> Options.option Options.auto - ( Options.long "out-degree" - <> Options.metavar "NUM_TRANSITIONS" + ( Options.long "transitions" + <> Options.metavar "NUM" <> Options.help - ("Expected number of outgoing transitions per state." - <> " This calculates the zero frequency from the number of states, symbols and this parameter." + ("Number of transitions to generate. They will be distributed randomly over states." ) ) ) @@ -134,9 +133,9 @@ withSpec opts f = case optMonoid opts of , numSymbols = optSymbols opts } -computeProbability :: WTASpec m -> ZeroFrequency -> Probability -computeProbability _ (Percentage p) = p -computeProbability spec (OutDegree d) = +computeProbability :: WTASpec m -> EdgeConfig -> Probability +computeProbability _ (ZeroFrequency p) = p +computeProbability spec (NumTransitions d) = let n = numStates spec t = V.sum (V.imap (\i syms -> syms * n ^ i) (numSymbols spec)) in fromRationalApprox (1 - fromIntegral d / fromIntegral t) @@ -157,10 +156,10 @@ main = do withSpec opts \$ \spec -> do randGen <- getStdGen - -- let zeroFreq = computeProbability spec (optZeroFrequency opts) + -- let zeroFreq = computeProbability spec (optEdgeConfig opts) -- hPutStrLn stderr \$ "p hacking: " ++ show zeroFreq wta <- runGenerator - (GeneratorConfig spec (optZeroFrequency opts) (optDifferentValues opts)) + (GeneratorConfig spec (optEdgeConfig opts) (optDifferentValues opts)) genWTA putStrLn \$ "# Random state for this automaton: '" <> show randGen <> "'" T.putStr (Build.toLazyText (buildWTA wta))