diff Implab/Automaton/MapAlphabet.cs @ 163:419aa51b04fd ref20160224

JSON moved to Formats namespace Working in RegularDFA
author cin
date Wed, 24 Feb 2016 20:12:52 +0300
parents
children ec35731ae299
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Implab/Automaton/MapAlphabet.cs	Wed Feb 24 20:12:52 2016 +0300
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Implab.Automaton {
+    public class MapAlphabet<T> : IAlphabetBuilder<T> {
+        readonly Dictionary<T,int> m_map;
+        int m_nextCls;
+
+        public MapAlphabet(IEqualityComparer<T> comparer) {
+            m_map = new Dictionary<T, int>(comparer);
+            m_nextCls = 1;
+        }
+
+        #region IAlphabetBuilder implementation
+
+        public int DefineSymbol(T symbol) {
+            int cls;
+            if (m_map.TryGetValue(symbol, out cls))
+                return cls;
+
+            cls = m_nextCls++;
+
+            m_map.Add(symbol, cls);
+
+            return cls;
+        }
+
+        public int DefineClass(IEnumerable<T> symbols) {
+            Safe.ArgumentNotNull(symbols, "symbols");
+            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++;
+        }
+
+        #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) {
+                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) {
+            int cls;
+            return m_map.TryGetValue(symobl, out cls) ? cls : DFAConst.UNCLASSIFIED_INPUT;
+        }
+
+        public int Count {
+            get {
+                return m_nextCls;
+            }
+        }
+
+        #endregion
+    }
+}
+