You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

258 lines
8.6 KiB

  1. import java.io.*;
  2. import java.lang.*;
  3. import java.util.*;
  4. class Edge {
  5. public int s, a;
  6. Edge(int s, int a) {
  7. this.s = s;
  8. this.a = a;
  9. }
  10. public String toString() {
  11. return this.s + ", " + this.a;
  12. }
  13. }
  14. class FSM {
  15. private ArrayList<String> states, alpha, finalState, transitions;
  16. private String initialState;
  17. private Integer initialStateID;
  18. private ArrayList<ArrayList<Edge>> tr;
  19. private ArrayList<ArrayList<Edge>> tr2way;
  20. private HashMap<String, Integer> stateToInt, alphaToInt;
  21. private HashSet<Integer> isFinal;
  22. private FileWriter out;
  23. private Integer szs, sza;
  24. private Boolean used[];
  25. private ArrayList<ArrayList<ArrayList<String>>> r;
  26. public void error(String msg) throws IOException {
  27. out.write("Error:\n" + msg);
  28. out.close();
  29. System.exit(0);
  30. }
  31. int dfs(int v) {
  32. int ans = 1, n = tr.get(v).size();
  33. used[v] = true;
  34. for (int i = 0; i < n; ++i) {
  35. int to = tr.get(v).get(i).s;
  36. if (!used[to])
  37. ans += dfs(to);
  38. }
  39. return ans;
  40. }
  41. void dfs2way(int v) {
  42. used[v] = true;
  43. int n = tr2way.get(v).size();
  44. for (int i = 0; i < n; ++i) {
  45. int to = tr2way.get(v).get(i).s;
  46. if (!used[to])
  47. dfs2way(to);
  48. }
  49. }
  50. FSM(String states, String alpha, String initialState, String finalState, String transitions,
  51. FileWriter out)
  52. throws IOException {
  53. this.out = out;
  54. // validate input
  55. if (!states.matches("states=\\[.*\\]$") || !alpha.matches("alpha=\\[.*\\]$")
  56. || !initialState.matches("initial=\\[.*\\]$")
  57. || !finalState.matches("accepting=\\[.*\\]$")
  58. || !transitions.matches("trans=\\[.*\\]$"))
  59. error("E0: Input file is malformed");
  60. this.states = new ArrayList<String>(Arrays.asList(states.split("states=\\[|,|\\]")));
  61. this.alpha = new ArrayList<String>(Arrays.asList(alpha.split("alpha=\\[|,|\\]")));
  62. this.finalState =
  63. new ArrayList<String>(Arrays.asList(finalState.split("accepting=\\[|,|\\]")));
  64. this.transitions =
  65. new ArrayList<String>(Arrays.asList(transitions.split("trans=\\[|,|\\]")));
  66. // initialization
  67. this.szs = this.states.size() - 1;
  68. this.sza = this.alpha.size() - 1;
  69. if (szs <= 0 || sza <= 0) {
  70. error("E0: Input file is malformed");
  71. }
  72. stateToInt = new HashMap<String, Integer>();
  73. alphaToInt = new HashMap<String, Integer>();
  74. isFinal = new HashSet<Integer>();
  75. tr = new ArrayList<ArrayList<Edge>>();
  76. tr2way = new ArrayList<ArrayList<Edge>>();
  77. for (int i = 0; i < szs; ++i) {
  78. tr.add(new ArrayList<Edge>());
  79. tr2way.add(new ArrayList<Edge>());
  80. }
  81. used = new Boolean[szs];
  82. // initialize R[k][i][j]; 0 <= k <= n; 0 <= i, j < n;
  83. r = new ArrayList<ArrayList<ArrayList<String>>>();
  84. for (int k = 0; k < szs + 1; k++) {
  85. r.add(new ArrayList<ArrayList<String>>());
  86. for (int i = 0; i < szs; ++i) {
  87. r.get(k).add(new ArrayList<String>());
  88. for (int j = 0; j < szs; ++j) {
  89. r.get(k).get(i).add(new String());
  90. }
  91. }
  92. }
  93. // create a graph with nodes starting from 0
  94. for (int i = 1; i <= szs; ++i) this.stateToInt.put(this.states.get(i), i - 1);
  95. // validate transitions
  96. for (int i = 1; i < this.transitions.size(); ++i) {
  97. String[] cur = this.transitions.get(i).split(">");
  98. if (cur.length != 3)
  99. error("E0: Input file is malformed");
  100. }
  101. for (int i = 1; i < this.finalState.size(); ++i) {
  102. if (this.stateToInt.containsKey(this.finalState.get(i)))
  103. isFinal.add(this.stateToInt.get(this.finalState.get(i)));
  104. else
  105. error("E1: A state '" + this.finalState.get(i) + "' is not in the set of states");
  106. }
  107. for (int i = 1; i <= sza; ++i) alphaToInt.put(this.alpha.get(i), i - 1);
  108. for (int i = 1; i < this.transitions.size(); ++i) {
  109. String[] cur = this.transitions.get(i).split(">");
  110. if (cur.length != 3)
  111. error("E0: Input file is malformed");
  112. if (!this.stateToInt.containsKey(cur[0]))
  113. error("E1: A state '" + cur[0] + "' is not in the set of states");
  114. if (!this.stateToInt.containsKey(cur[2]))
  115. error("E1: A state '" + cur[2] + "' is not in the set of states");
  116. if (!this.alphaToInt.containsKey(cur[1]))
  117. error("E3: A transition '" + cur[1] + "' is not represented in the alphabet");
  118. int l = stateToInt.get(cur[0]), m = alphaToInt.get(cur[1]), r = stateToInt.get(cur[2]);
  119. tr.get(l).add(new Edge(r, m));
  120. tr2way.get(l).add(new Edge(r, m));
  121. tr2way.get(r).add(new Edge(l, m));
  122. }
  123. int components = 0;
  124. for (int i = 0; i < szs; ++i) used[i] = false;
  125. for (int i = 0; i < szs; ++i) {
  126. if (!used[i]) {
  127. dfs2way(i);
  128. components++;
  129. }
  130. }
  131. if (components > 1)
  132. error("E2: Some states are disjoint");
  133. for (int i = 0; i < szs; ++i) used[i] = false;
  134. String[] temp = initialState.split("initial=\\[|\\]");
  135. if (temp.length <= 1)
  136. error("E4: Initial state is not defined");
  137. this.initialState = temp[1];
  138. if (stateToInt.containsKey(this.initialState))
  139. initialStateID = stateToInt.get(this.initialState);
  140. else
  141. error("E1: A state '" + this.initialState + "' is not in the set of states");
  142. Boolean isDet = true, isComplete = true;
  143. for (int i = 0; i < szs; ++i) {
  144. HashSet<Integer> st = new HashSet<Integer>();
  145. for (int j = 0; j < tr.get(i).size(); ++j) {
  146. int a = tr.get(i).get(j).a;
  147. if (st.contains(a))
  148. isDet = false;
  149. else
  150. st.add(a);
  151. }
  152. if (st.size() != sza)
  153. isComplete = false;
  154. }
  155. if (!isDet)
  156. error("E5: FSA is nondeterministic");
  157. for (int i = 0; i < szs; ++i) {
  158. for (int j = 0; j < tr.get(i).size(); ++j) {
  159. String curAlpha;
  160. int cur = tr.get(i).get(j).s;
  161. if (r.get(0).get(i).get(cur).isEmpty())
  162. curAlpha = this.alpha.get(tr.get(i).get(j).a + 1);
  163. else
  164. curAlpha = r.get(0).get(i).get(cur) + "|" + this.alpha.get(tr.get(i).get(j).a + 1);
  165. r.get(0).get(i).set(cur, curAlpha);
  166. }
  167. for (int j = 0; j < szs; ++j) {
  168. if (i == j) {
  169. String curAlpha;
  170. if (r.get(0).get(i).get(j).isEmpty())
  171. curAlpha = "eps";
  172. else
  173. curAlpha = r.get(0).get(i).get(j) + "|eps";
  174. r.get(0).get(i).set(j, curAlpha);
  175. } else if (r.get(0).get(i).get(j).isEmpty()) {
  176. String curAlpha = "{}";
  177. r.get(0).get(i).set(j, curAlpha);
  178. }
  179. }
  180. }
  181. for (int k = 1; k <= szs; ++k) {
  182. for (int i = 0; i < szs; ++i) {
  183. for (int j = 0; j < szs; ++j) {
  184. String cur = "(" + r.get(k-1).get(i).get(k-1) + ")(" + r.get(k-1).get(k-1).get(k-1) + ")*(" + r.get(k-1).get(k-1).get(j) + ")|(" + r.get(k-1).get(i).get(j) + ")";
  185. r.get(k).get(i).set(j, cur);
  186. }
  187. }
  188. }
  189. String ans = new String();
  190. for (int i = 0; i < szs; ++i) {
  191. if (isFinal.contains(i)) {
  192. if(ans.isEmpty())
  193. ans = r.get(szs).get(initialStateID).get(i);
  194. else
  195. ans = ans + "|" + r.get(szs).get(initialStateID).get(i);
  196. }
  197. }
  198. if(ans.isEmpty())
  199. ans = "{}";
  200. out.write(ans);
  201. out.close();
  202. }
  203. }
  204. public class FSAtoREGEX {
  205. public static void main(String[] args) throws IOException {
  206. FileReader inp = new FileReader("input.txt");
  207. FileWriter out = new FileWriter("output.txt");
  208. Scanner in = new Scanner(inp);
  209. String states = in.nextLine();
  210. String alpha = in.nextLine();
  211. String initialState = in.nextLine();
  212. String finalState = in.nextLine();
  213. String transitions = in.nextLine();
  214. FSM fsm = new FSM(states, alpha, initialState, finalState, transitions, out);
  215. }
  216. }