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 @@
{-# 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
......@@ -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))
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