Commit dbd78cf8 authored by Hans-Peter Deifel's avatar Hans-Peter Deifel 🐢

wta: Change --out-degree to --transitions

It's now used to specify how many transitions you want instead of how many
transitions per state. This is strictly more powerful because you can always
just specify states*out-degree as transition count.
parent cab34a04
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
module Generator (genWTA, runGenerator, GeneratorConfig(..), ZeroFrequency(..)) where module Generator (genWTA, runGenerator, GeneratorConfig(..), EdgeConfig(..)) where
import Data.Vector ( Vector ) import Data.Vector ( Vector )
import qualified Data.Vector as V import qualified Data.Vector as V
...@@ -21,18 +21,18 @@ import Probability ...@@ -21,18 +21,18 @@ import Probability
import IndexedTransition import IndexedTransition
import qualified IndexedTransition import qualified IndexedTransition
data ZeroFrequency = Percentage Probability | OutDegree Int data EdgeConfig = ZeroFrequency Probability | NumTransitions Int
data GeneratorConfig m = GeneratorConfig data GeneratorConfig m = GeneratorConfig
{ spec :: WTASpec m { spec :: WTASpec m
, zeroPolicy :: ZeroFrequency , zeroPolicy :: EdgeConfig
, differentValues :: Maybe Int , differentValues :: Maybe Int
} }
type Generator m = ReaderT (GeneratorConfig m) IO type Generator m = ReaderT (GeneratorConfig m) IO
zeroFreq :: GeneratorConfig m -> Probability 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 zeroFreq _ = error "zeroFreq: unexpected out degree" -- TODO Ugly as hell
runGenerator :: GeneratorConfig m -> Generator m a -> IO a runGenerator :: GeneratorConfig m -> Generator m a -> IO a
...@@ -107,13 +107,12 @@ uniqueTransitions num (IndexedTransition.Index max) = helper S.empty num ...@@ -107,13 +107,12 @@ uniqueTransitions num (IndexedTransition.Index max) = helper S.empty num
genTransitions' :: Int -> Generator m (Vector (Vector (Transition m))) genTransitions' :: Int -> Generator m (Vector (Vector (Transition m)))
genTransitions' outDegree = do genTransitions' numTransitions = do
wtaSpec <- asks spec wtaSpec <- asks spec
let n = numStates wtaSpec let n = numStates wtaSpec
m = IndexedTransition.maxIndex 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 weightedTransitions <- (traverse.traverse.traverse) (const genMonoidValue) transitions
let byState = foldl' (\m (State s, t) -> M.insertWith (++) s [t] m) M.empty weightedTransitions let byState = foldl' (\m (State s, t) -> M.insertWith (++) s [t] m) M.empty weightedTransitions
...@@ -126,5 +125,5 @@ genTransitions' outDegree = do ...@@ -126,5 +125,5 @@ genTransitions' outDegree = do
genWTA :: Generator m (WTA m) genWTA :: Generator m (WTA m)
genWTA = asks zeroPolicy >>= \case genWTA = asks zeroPolicy >>= \case
OutDegree d -> WTA <$> asks spec <*> genStates <*> (genTransitions' d) NumTransitions d -> WTA <$> asks spec <*> genStates <*> (genTransitions' d)
Percentage _ -> WTA <$> asks spec <*> genStates <*> genTransitions ZeroFrequency _ -> WTA <$> asks spec <*> genStates <*> genTransitions
...@@ -32,7 +32,7 @@ data Opts = Opts ...@@ -32,7 +32,7 @@ data Opts = Opts
{ optMonoid :: SomeMonoid { optMonoid :: SomeMonoid
, optStates :: Int , optStates :: Int
, optSymbols :: SymbolSpec , optSymbols :: SymbolSpec
, optZeroFrequency :: ZeroFrequency , optEdgeConfig :: EdgeConfig
, optRandomState :: Maybe StdGen , optRandomState :: Maybe StdGen
, optDifferentValues :: Maybe Int , optDifferentValues :: Maybe Int
} }
...@@ -104,9 +104,9 @@ parseOpts = ...@@ -104,9 +104,9 @@ parseOpts =
) )
) )
parseZeroFreq :: Options.Parser ZeroFrequency parseZeroFreq :: Options.Parser EdgeConfig
parseZeroFreq = parseZeroFreq =
(Percentage <$> Options.option (ZeroFrequency <$> Options.option
(Options.eitherReader readProbability) (Options.eitherReader readProbability)
( Options.long "zero-frequency" ( Options.long "zero-frequency"
<> Options.showDefault <> Options.showDefault
...@@ -116,13 +116,12 @@ parseZeroFreq = ...@@ -116,13 +116,12 @@ parseZeroFreq =
"Frequency of edges with zero weight as number between 0 and 1." "Frequency of edges with zero weight as number between 0 and 1."
) )
) )
<|> (OutDegree <$> Options.option <|> (NumTransitions <$> Options.option
Options.auto Options.auto
( Options.long "out-degree" ( Options.long "transitions"
<> Options.metavar "NUM_TRANSITIONS" <> Options.metavar "NUM"
<> Options.help <> Options.help
("Expected number of outgoing transitions per state." ("Number of transitions to generate. They will be distributed randomly over states."
<> " This calculates the zero frequency from the number of states, symbols and this parameter."
) )
) )
) )
...@@ -134,9 +133,9 @@ withSpec opts f = case optMonoid opts of ...@@ -134,9 +133,9 @@ withSpec opts f = case optMonoid opts of
, numSymbols = optSymbols opts , numSymbols = optSymbols opts
} }
computeProbability :: WTASpec m -> ZeroFrequency -> Probability computeProbability :: WTASpec m -> EdgeConfig -> Probability
computeProbability _ (Percentage p) = p computeProbability _ (ZeroFrequency p) = p
computeProbability spec (OutDegree d) = computeProbability spec (NumTransitions d) =
let n = numStates spec let n = numStates spec
t = V.sum (V.imap (\i syms -> syms * n ^ i) (numSymbols spec)) t = V.sum (V.imap (\i syms -> syms * n ^ i) (numSymbols spec))
in fromRationalApprox (1 - fromIntegral d / fromIntegral t) in fromRationalApprox (1 - fromIntegral d / fromIntegral t)
...@@ -157,10 +156,10 @@ main = do ...@@ -157,10 +156,10 @@ main = do
withSpec opts $ \spec -> do withSpec opts $ \spec -> do
randGen <- getStdGen randGen <- getStdGen
-- let zeroFreq = computeProbability spec (optZeroFrequency opts) -- let zeroFreq = computeProbability spec (optEdgeConfig opts)
-- hPutStrLn stderr $ "p hacking: " ++ show zeroFreq -- hPutStrLn stderr $ "p hacking: " ++ show zeroFreq
wta <- runGenerator wta <- runGenerator
(GeneratorConfig spec (optZeroFrequency opts) (optDifferentValues opts)) (GeneratorConfig spec (optEdgeConfig opts) (optDifferentValues opts))
genWTA 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))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment