From f7360b88cc46ab5e61dc8640bf88394aacf9119c Mon Sep 17 00:00:00 2001 From: Hans-Peter Deifel Date: Tue, 9 Apr 2019 09:58:08 +0200 Subject: [PATCH] wta: Swap algorithm if transition count is too large The existing algorithm for generating unique transitions is inefficient if the transition count is close to the maximal number of transitions. This now switches to a different algorithm if the transition count is above 70% of the maximum. --- src/random-wta/Generator.hs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/random-wta/Generator.hs b/src/random-wta/Generator.hs index 05f4948..8f88f9c 100644 --- a/src/random-wta/Generator.hs +++ b/src/random-wta/Generator.hs @@ -15,6 +15,7 @@ import Control.Arrow ( (&&&) ) import qualified Data.Map.Strict as M import qualified Data.Set as S import Data.Coerce +import Data.Ratio import Types hiding ( spec ) import Probability @@ -98,13 +99,28 @@ genTransitions = do -- TODO Implement (Random IndexedTransition) uniqueTransitions :: Int -> IndexedTransition -> IO [IndexedTransition] -uniqueTransitions num (IndexedTransition.Index max) = helper S.empty num +uniqueTransitions num idxMax@(IndexedTransition.Index max) + | fromIntegral num < fromIntegral max * (7%10) = uniqueTransitionsByGeneration num idxMax + | otherwise = uniqueTransitionsByElimination num idxMax + +uniqueTransitionsByGeneration :: Int -> IndexedTransition -> IO [IndexedTransition] +uniqueTransitionsByGeneration num (IndexedTransition.Index max) = helper S.empty num where helper m 0 = return \$ coerce (S.toList m) helper m c = do x <- randomRIO (0, max-1) if x `S.member` m then helper m c else helper (S.insert x m) (c-1) +uniqueTransitionsByElimination :: Int -> IndexedTransition -> IO [IndexedTransition] +uniqueTransitionsByElimination num (IndexedTransition.Index max) = helper whole num + where + helper free 0 = return \$ coerce (S.toList (S.difference whole free)) + helper free c = do + idx <- randomRIO (0, S.size free - 1) + let x = S.elemAt idx free + helper (S.delete x free) (c-1) + + whole = S.fromList [0..max-1] genTransitions' :: Int -> Generator m (Vector (Vector (Transition m))) genTransitions' numTransitions = do -- GitLab