comparison 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
comparison
equal deleted inserted replaced
162:0526412bbb26 163:419aa51b04fd
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4
5 namespace Implab.Automaton {
6 public class MapAlphabet<T> : IAlphabetBuilder<T> {
7 readonly Dictionary<T,int> m_map;
8 int m_nextCls;
9
10 public MapAlphabet(IEqualityComparer<T> comparer) {
11 m_map = new Dictionary<T, int>(comparer);
12 m_nextCls = 1;
13 }
14
15 #region IAlphabetBuilder implementation
16
17 public int DefineSymbol(T symbol) {
18 int cls;
19 if (m_map.TryGetValue(symbol, out cls))
20 return cls;
21
22 cls = m_nextCls++;
23
24 m_map.Add(symbol, cls);
25
26 return cls;
27 }
28
29 public int DefineClass(IEnumerable<T> symbols) {
30 Safe.ArgumentNotNull(symbols, "symbols");
31 symbols = symbols.Distinct();
32
33 foreach (var symbol in symbols) {
34 if (!m_map.Contains(symbol))
35 m_map.Add(symbol, m_nextCls);
36 else
37 throw new InvalidOperationException(String.Format("Symbol '{0}' already in use", symbol));
38 }
39 return m_nextCls++;
40 }
41
42 #endregion
43
44 #region IAlphabet implementation
45
46 public List<T>[] CreateReverseMap() {
47 var empty = new List<T>();
48 var rmap = new List<T>[m_nextCls];
49
50 for (int i = 0; i < rmap.Length; i++)
51 rmap[i] = empty;
52
53 foreach (var pair in m_map) {
54 var symbols = rmap[pair.Value];
55 if (symbols == null) {
56 symbols = new List<T>();
57 rmap[pair.Value] = symbols;
58 }
59
60 symbols.Add(pair.Key);
61 }
62
63 return rmap;
64 }
65
66 public int[] Reclassify(IAlphabetBuilder<T> newAlphabet, IEnumerable<IEnumerable<int>> classes) {
67 Safe.ArgumentNotNull(newAlphabet, "newAlphabet");
68 Safe.ArgumentNotNull(classes, "classes");
69
70 var rmap = CreateReverseMap();
71 var map = new int[rmap.Length];
72
73 foreach (var cls in classes) {
74 var symbols = new List<T>();
75 foreach (var id in cls) {
76 if (id < 0 || id >= rmap.Length)
77 throw new ArgumentOutOfRangeException(String.Format("Class {0} is not valid for the current alphabet", id));
78 if (rmap[id] != null)
79 symbols.AddRange(rmap[id]);
80 }
81
82 var newId = newAlphabet.DefineClass(symbols);
83
84 foreach (var id in cls)
85 map[id] = newId;
86 }
87 }
88
89 public int Translate(T symobl) {
90 int cls;
91 return m_map.TryGetValue(symobl, out cls) ? cls : DFAConst.UNCLASSIFIED_INPUT;
92 }
93
94 public int Count {
95 get {
96 return m_nextCls;
97 }
98 }
99
100 #endregion
101 }
102 }
103