Mercurial > pub > ImplabNet
diff Implab/Automaton/MapAlphabet.cs @ 171:0f70905b4652 ref20160224
Working on regular DFA
author | cin |
---|---|
date | Thu, 10 Mar 2016 01:19:33 +0300 |
parents | ec35731ae299 |
children | 92d5278d1b10 |
line wrap: on
line diff
--- a/Implab/Automaton/MapAlphabet.cs Fri Mar 04 01:56:31 2016 +0300 +++ b/Implab/Automaton/MapAlphabet.cs Thu Mar 10 01:19:33 2016 +0300 @@ -5,96 +5,57 @@ namespace Implab.Automaton { public class MapAlphabet<T> : IAlphabetBuilder<T> { readonly Dictionary<T,int> m_map; - int m_nextCls = 1; + int m_nextCls; + readonly bool m_supportUnclassified; - public MapAlphabet() { - m_map = new Dictionary<T, int>(); - } - - public MapAlphabet(IEqualityComparer<T> comparer) { - m_map = new Dictionary<T, int>(comparer); + public MapAlphabet(bool supportUnclassified, IEqualityComparer<T> comparer) { + m_map = comparer != null ? new Dictionary<T, int>(comparer) : new Dictionary<T,int>(); + m_supportUnclassified = supportUnclassified; + m_nextCls = supportUnclassified ? 1 : 0; } #region IAlphabetBuilder implementation public int DefineSymbol(T symbol) { int cls; - if (m_map.TryGetValue(symbol, out cls)) - return cls; + return m_map.TryGetValue(symbol, out cls) ? cls : DefineSymbol(symbol, m_nextCls); + } - cls = m_nextCls++; + public int DefineSymbol(T symbol, int cls) { + Safe.ArgumentAssert(cls >= 0, "cls"); + m_nextCls = Math.Max(cls + 1, m_nextCls); m_map.Add(symbol, cls); - return cls; } public int DefineClass(IEnumerable<T> symbols) { + return DefineClass(symbols, m_nextCls); + } + + public int DefineClass(IEnumerable<T> symbols, int cls) { + Safe.ArgumentAssert(cls >= 0, "cls"); Safe.ArgumentNotNull(symbols, "symbols"); + + m_nextCls = Math.Max(cls + 1, m_nextCls); symbols = symbols.Distinct(); - foreach (var symbol in symbols) { - if (!m_map.Contains(symbol)) - m_map.Add(symbol, m_nextCls); - else - throw new InvalidOperationException(String.Format("Symbol '{0}' already in use", symbol)); - } - return m_nextCls++; + foreach (var symbol in symbols) + m_map[symbol] = cls; + return cls; } #endregion #region IAlphabet implementation - public List<T>[] CreateReverseMap() { - var empty = new List<T>(); - var rmap = new List<T>[m_nextCls]; - - for (int i = 0; i < rmap.Length; i++) - rmap[i] = empty; - - foreach (var pair in m_map) { - var symbols = rmap[pair.Value]; - if (symbols == null) { - symbols = new List<T>(); - rmap[pair.Value] = symbols; - } - - symbols.Add(pair.Key); - } - - return rmap; - } - - public int[] Reclassify(IAlphabetBuilder<T> newAlphabet, IEnumerable<IEnumerable<int>> classes) { - Safe.ArgumentNotNull(newAlphabet, "newAlphabet"); - Safe.ArgumentNotNull(classes, "classes"); - - var rmap = CreateReverseMap(); - var map = new int[rmap.Length]; - - foreach (var cls in classes) { - if (cls.Contains(DFAConst.UNCLASSIFIED_INPUT)) - continue; - - var symbols = new List<T>(); - foreach (var id in cls) { - if (id < 0 || id >= rmap.Length) - throw new ArgumentOutOfRangeException(String.Format("Class {0} is not valid for the current alphabet", id)); - if (rmap[id] != null) - symbols.AddRange(rmap[id]); - } - - var newId = newAlphabet.DefineClass(symbols); - - foreach (var id in cls) - map[id] = newId; - } - } - - public int Translate(T symobl) { + public int Translate(T symbol) { int cls; - return m_map.TryGetValue(symobl, out cls) ? cls : DFAConst.UNCLASSIFIED_INPUT; + if (m_map.TryGetValue(symbol, out cls)) + return cls; + if (!m_supportUnclassified) + throw new ArgumentOutOfRangeException("symbol", "The specified symbol isn't in the alphabet"); + return DFAConst.UNCLASSIFIED_INPUT; } public int Count { @@ -103,6 +64,10 @@ } } + public bool Contains(T symbol) { + return m_supportUnclassified || m_map.ContainsKey(symbol); + } + #endregion } }