private ChainMap InitSimpleChainMapp() { ChainMap cm = new ChainMap() ; cm.AddToChain(new ChainKey(new string[]{null, "word1"}), "valnull") ; cm.AddToChain(new ChainKey(new string[]{"word1", "word2"}), "val1") ; cm.AddToChain(new ChainKey(new string[]{"word2", "word3"}), "val2") ; cm.AddToChain(new ChainKey(new string[]{"word1", "word2"}), "val3") ; return cm ; }
/// <summary> /// Initializes word generator with random seed as parameter /// </summary> /// <param name="chains"></param> /// <param name="rand"> Rng used if better randomness is desired. The default .NET Rng is /// not completely random </param> public WordGenerator(ChainMap chains, Random rand) { _chains = chains ; if(rand != null) { _rand = rand ; } else { _rand = new Random() ; } Initialize() ; }
/// <summary> /// Initializes word generator with random seed as parameter /// </summary> /// <param name="chains"></param> /// <param name="rand"> Rng used if better randomness is desired. The default .NET Rng is /// not completely random </param> public WordGenerator(ChainMap chains, Random rand) { _chains = chains; if (rand != null) { _rand = rand; } else { _rand = new Random(); } Initialize(); }
/// <summary> /// Generate markov chains using input text /// </summary> public void GenerateChains() { //Split text string[] splits = _text.Split(); List <string> advancedSplits = new List <string>(); foreach (string baseSplit in splits) { advancedSplits.AddRange(StringUtils.SplitAndKeep(baseSplit.ToLower(), _delims)); } Chains = new ChainMap(); if (advancedSplits.Count < _chainSize * 2) { throw new Exceptions.InvalidArguments(string.Format("Chain size: {0} to small relative to text split {1}", _chainSize, advancedSplits.Count)); } //Insert null elements in the beginning so chains are created for the first _chainSize elements for (int i = 0; i < _chainSize; i++) { advancedSplits.Insert(0, null); } List <string> .Enumerator listEnum = advancedSplits.GetEnumerator(); string[] chainWords = new string[_chainSize]; for (int i = 0; i < _chainSize; i++) { listEnum.MoveNext(); chainWords[i] = listEnum.Current; } while (listEnum.MoveNext()) { string current = listEnum.Current; ChainKey currKey = new ChainKey(chainWords); Chains.AddToChain(currKey, current); for (int i = 0; i < _chainSize - 1; i++) { chainWords[i] = chainWords[i + 1]; } chainWords[_chainSize - 1] = current; } }
/// <summary> /// Generate markov chains using input text /// </summary> public void GenerateChains() { //Split text string[] splits = _text.Split() ; List<string> advancedSplits = new List<string>() ; foreach(string baseSplit in splits) { advancedSplits.AddRange(StringUtils.SplitAndKeep(baseSplit.ToLower(), _delims)) ; } Chains = new ChainMap() ; if(advancedSplits.Count < _chainSize * 2) { throw new Exceptions.InvalidArguments(string.Format("Chain size: {0} to small relative to text split {1}", _chainSize, advancedSplits.Count)) ; } //Insert null elements in the beginning so chains are created for the first _chainSize elements for(int i = 0 ; i < _chainSize ; i++) { advancedSplits.Insert(0, null) ; } List<string>.Enumerator listEnum = advancedSplits.GetEnumerator() ; string[] chainWords = new string[_chainSize] ; for(int i = 0 ; i < _chainSize ; i++) { listEnum.MoveNext(); chainWords[i] = listEnum.Current ; } while(listEnum.MoveNext()) { string current = listEnum.Current; ChainKey currKey = new ChainKey(chainWords) ; Chains.AddToChain(currKey, current) ; for(int i = 0 ; i < _chainSize - 1 ; i++) { chainWords[i] = chainWords[i+1] ; } chainWords[_chainSize - 1] = current ; } }
private ChainKey[] CreateKeysArray(ChainMap map, Predicate <ChainKey> keyCondition) { List <ChainKey> newKeys = new List <ChainKey>(); List <ChainKey> origKeys = map.GetAllKeys(); foreach (ChainKey origKey in origKeys) { if (keyCondition.Invoke(origKey)) { //Add key multiple times to ensure probability of picking it is proportional to the //number of values foreach (string val in map.GetValues(origKey)) { newKeys.Add(origKey); } } } return(newKeys.ToArray()); }
/// <summary> /// Get subchain of chainkeys and words that satisfies the passed in condition /// </summary> /// <param name="condition"></param> /// <returns></returns> internal ChainMap GetSubChain(ChainCondition condition) { //If conditions won't be applied return original chains if (condition == null || condition == _alwaysTrueCondition || (condition.WordCondition == null && condition.KeyCondition == null)) { return(_chains); } ChainMap newMap = new ChainMap(); bool valuesFound = false; foreach (ChainKey key in _chains.GetAllKeys()) { if (condition.KeyCondition != null) { if (condition.KeyCondition.Invoke(key)) { foreach (string word in _chains.GetValues(key)) { if (condition.WordCondition != null) { if (condition.WordCondition.Invoke(word)) { newMap.AddToChain(key, word); valuesFound = true; } } } } } } if (!valuesFound) { throw new Exceptions.NoPossibleElements("Chain map filter filtered everything out"); } return(newMap); }
/// <summary> /// Compare chain tables ignoring duplicates /// </summary> public static void CompareChainTablesNoDuplicates(ChainMap inputChainMap1, ChainMap inputChainMap2) { CompareChainTables(GetUnderlyingDictionary(inputChainMap1), GetUnderlyingDictionary(inputChainMap2), true); }
public static void CompareChainTables(ChainMap inputChainMap, Dictionary<ChainKey, List<string>> inputChains) { CompareChainTables(GetUnderlyingDictionary(inputChainMap), inputChains) ; }
public void T_GetSubChain() { WordGenerator gen = InitSimpleWordGen() ; //Should give me both "hello world one" and "hello world two" ChainMap tempMap = gen.GetSubChain(new ChainCondition(cw => cw.Words[0] == "hello", w => w.Length == 3)) ; ChainMap correctMap = new ChainMap() ; correctMap.AddToChain(new ChainKey(new string[] {"hello", "world"}), "one") ; correctMap.AddToChain(new ChainKey(new string[] {"hello", "world"}), "two") ; TestUtils.CompareChainTables(correctMap, tempMap) ; //Should give me just "hello world one" tempMap = gen.GetSubChain(new ChainCondition(cw => cw.Words[0] == "hello", w => w.StartsWith("o"))) ; correctMap = new ChainMap() ; correctMap.AddToChain(new ChainKey(new string[] {"hello", "world"}), "one") ; TestUtils.CompareChainTables(correctMap, tempMap) ; //If passed in condition is null nothing should change tempMap = gen.GetSubChain(new ChainCondition(null, null)) ; TestUtils.CompareChainTables(gen.Chains, tempMap) ; //If impossible condition is passed in exception should be thrown Assert.Throws(typeof(Exceptions.NoPossibleElements), delegate { gen.GetSubChain(new ChainCondition(null, w => w == "Does not exist")) ;}) ; }
public void T_GetRandomKey_WithParams() { WordGenerator gen = InitSimpleWordGen() ; ChainMap subMap = new ChainMap() ; ChainKey key1 = new ChainKey(new string[]{"key1", "key2", "key3"}) ; ChainKey key2 = new ChainKey(new string[]{"key1", "key2", "key4"}) ; subMap.AddToChain(key1, "val1") ; subMap.AddToChain(key2, "val2") ; bool key1Found, key2Found ; key1Found = key2Found = false ; for(int i = 0 ; i < 10 ; i++) { ChainKey currKey = gen.GetRandomKey(subMap); if(key1.Equals(currKey)) { key1Found = true ; } else if(key2.Equals(currKey)) { key2Found = true ; } else { Assert.Fail("Invalid key returned") ; } } if(!(key1Found && key2Found)) { Assert.Fail("GetRandomKey is not random") ; } }
/// <summary> /// Get a random key from passed in chain map /// The probability of getting a key should be proportional to the number of values /// </summary> /// <returns></returns> internal ChainKey GetRandomKey(ChainMap map) { ChainKey[] keys = CreateKeysArray(map, _alwaysTrueCondition.KeyCondition) ; return keys[_rand.Next(keys.Length)]; }
/// <summary> /// Initializes word generator with default random seed /// </summary> /// <param name="chains"></param> public WordGenerator(ChainMap chains) : this(chains, null) { }
/// <summary> /// Reset CurrentWord based on conditions /// </summary> /// <param name="keyCondition"> Condition for key of first word </param> /// <param name="onEndCondition"> Condition for new word after there are no more chains /// By default this is the same as @keyCondition </param> private void Reset(ChainCondition initialCondition, ChainCondition onEndCondition) { ChainCondition realInitialConditions = initialCondition; //Set null conditions to always true conditions to simplify our code if(realInitialConditions == null) { realInitialConditions = _alwaysTrueCondition; } else { if (realInitialConditions.KeyCondition == null) { realInitialConditions.KeyCondition = _alwaysTrueCondition.KeyCondition; } if (realInitialConditions.WordCondition == null) { realInitialConditions.WordCondition = _alwaysTrueCondition.WordCondition; } } ChainCondition realOnEndCondition = onEndCondition ; //Set on end condition to start condition if it is null if(realOnEndCondition == null) { realOnEndCondition = realInitialConditions ; } else { if (realOnEndCondition.KeyCondition == null) { realOnEndCondition.KeyCondition = _alwaysTrueCondition.KeyCondition; } if (realOnEndCondition.WordCondition == null) { realOnEndCondition.WordCondition = _alwaysTrueCondition.WordCondition; } } ChainMap initialConditionMap ; //Only generate subchains if we need to if(realInitialConditions != _alwaysTrueCondition) { initialConditionMap = GetSubChain(realInitialConditions) ; } else { initialConditionMap = Chains; } ChainKey[] initialConditionSubKeys = CreateKeysArray(initialConditionMap, _alwaysTrueCondition.KeyCondition) ; //All chains and words should match condition so we can just get random ChainKey currKey = GetRandomKey(initialConditionSubKeys) ; string currWord ; GetCandidate(initialConditionMap.GetValues(currKey), null, out currWord) ; if(realOnEndCondition != _alwaysTrueCondition) { //Verify on end map has valid elements. If no exception is thrown we are good to go _onEndSubChains = GetSubChain(realOnEndCondition) ; } else { _onEndSubChains = initialConditionMap; } CurrentWord = currWord; _currKey = currKey; _initialConditionSubChains = initialConditionMap ; _initialConditionSubKeys = initialConditionSubKeys; _currentOnEndCondition = realOnEndCondition; SubchainsInitialized = true ; }
/// <summary> /// Get a random key from passed in chain map /// The probability of getting a key should be proportional to the number of values /// </summary> /// <returns></returns> internal ChainKey GetRandomKey(ChainMap map) { ChainKey[] keys = CreateKeysArray(map, _alwaysTrueCondition.KeyCondition); return(keys[_rand.Next(keys.Length)]); }
/// <summary> /// Get random key from passed in chain map matching passed in condition /// </summary> /// <param name="map"></param> /// <param name="keyCondition"></param> /// <returns></returns> internal ChainKey GetRandomKey(ChainMap map, Predicate<ChainKey> keyCondition) { ChainKey[] keys = CreateKeysArray(map, keyCondition) ; return keys[_rand.Next(keys.Length)]; }
/// <summary> /// Reset CurrentWord based on conditions /// </summary> /// <param name="keyCondition"> Condition for key of first word </param> /// <param name="onEndCondition"> Condition for new word after there are no more chains /// By default this is the same as @keyCondition </param> private void Reset(ChainCondition initialCondition, ChainCondition onEndCondition) { ChainCondition realInitialConditions = initialCondition; //Set null conditions to always true conditions to simplify our code if (realInitialConditions == null) { realInitialConditions = _alwaysTrueCondition; } else { if (realInitialConditions.KeyCondition == null) { realInitialConditions.KeyCondition = _alwaysTrueCondition.KeyCondition; } if (realInitialConditions.WordCondition == null) { realInitialConditions.WordCondition = _alwaysTrueCondition.WordCondition; } } ChainCondition realOnEndCondition = onEndCondition; //Set on end condition to start condition if it is null if (realOnEndCondition == null) { realOnEndCondition = realInitialConditions; } else { if (realOnEndCondition.KeyCondition == null) { realOnEndCondition.KeyCondition = _alwaysTrueCondition.KeyCondition; } if (realOnEndCondition.WordCondition == null) { realOnEndCondition.WordCondition = _alwaysTrueCondition.WordCondition; } } ChainMap initialConditionMap; //Only generate subchains if we need to if (realInitialConditions != _alwaysTrueCondition) { initialConditionMap = GetSubChain(realInitialConditions); } else { initialConditionMap = Chains; } ChainKey[] initialConditionSubKeys = CreateKeysArray(initialConditionMap, _alwaysTrueCondition.KeyCondition); //All chains and words should match condition so we can just get random ChainKey currKey = GetRandomKey(initialConditionSubKeys); string currWord; GetCandidate(initialConditionMap.GetValues(currKey), null, out currWord); if (realOnEndCondition != _alwaysTrueCondition) { //Verify on end map has valid elements. If no exception is thrown we are good to go _onEndSubChains = GetSubChain(realOnEndCondition); } else { _onEndSubChains = initialConditionMap; } CurrentWord = currWord; _currKey = currKey; _initialConditionSubChains = initialConditionMap; _initialConditionSubKeys = initialConditionSubKeys; _currentOnEndCondition = realOnEndCondition; SubchainsInitialized = true; }
/// <summary> /// Get subchain of chainkeys and words that satisfies the passed in condition /// </summary> /// <param name="condition"></param> /// <returns></returns> internal ChainMap GetSubChain(ChainCondition condition) { //If conditions won't be applied return original chains if(condition == null || condition == _alwaysTrueCondition || (condition.WordCondition == null && condition.KeyCondition == null)) { return _chains ; } ChainMap newMap = new ChainMap() ; bool valuesFound = false ; foreach(ChainKey key in _chains.GetAllKeys()) { if(condition.KeyCondition != null) { if(condition.KeyCondition.Invoke(key)) { foreach(string word in _chains.GetValues(key)) { if(condition.WordCondition != null) { if(condition.WordCondition.Invoke(word)) { newMap.AddToChain(key, word) ; valuesFound = true ; } } } } } } if(!valuesFound) { throw new Exceptions.NoPossibleElements("Chain map filter filtered everything out") ; } return newMap ; }
public static Dictionary<ChainKey, List<string>> GetUnderlyingDictionary(ChainMap inputChainMap) { Dictionary<ChainKey, List<string>> retValues = new Dictionary<ChainKey, List<string>>() ; List<ChainKey> keys = inputChainMap.GetAllKeys() ; foreach(ChainKey key in keys) { retValues.Add(key, inputChainMap.GetValues(key)) ; } return retValues; }
/// <summary> /// Get random key from passed in chain map matching passed in condition /// </summary> /// <param name="map"></param> /// <param name="keyCondition"></param> /// <returns></returns> internal ChainKey GetRandomKey(ChainMap map, Predicate <ChainKey> keyCondition) { ChainKey[] keys = CreateKeysArray(map, keyCondition); return(keys[_rand.Next(keys.Length)]); }
private ChainKey[] CreateKeysArray(ChainMap map, Predicate<ChainKey> keyCondition) { List<ChainKey> newKeys = new List<ChainKey>() ; List<ChainKey> origKeys = map.GetAllKeys() ; foreach(ChainKey origKey in origKeys) { if(keyCondition.Invoke(origKey)) { //Add key multiple times to ensure probability of picking it is proportional to the //number of values foreach(string val in map.GetValues(origKey)) { newKeys.Add(origKey) ; } } } return newKeys.ToArray() ; }