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
     }
 }