-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdfa.pl
424 lines (351 loc) Β· 14 KB
/
dfa.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
% ----------------------------------AUTHOR--------------------------------------
% University Of Warsaw
% Kamil Jankowski
% kj418271
% --------------------------------DESCRIPTION-----------------------------------
% The internal structure used for computations is based on Binary Search Trees.
% What is later called NodeBST is a BST with a triplet as a node.
% The triplet is (Q, D, F), where:
% Q - State
% D - FpBST containing all outgoing edges from Q in automaton
% F - 0/1, describing wheter Q is a final state
% Further explaining, FpBST is made up of nodes represented as p(A, Q), where:
% A - Letter from the alphabet
% Q - State
% Predicate r(W, E) stands for representation of some automaton, where W is
% a NodeBST and E is a normal BST containing alphabet letters.
% The state stored in the root of NodeBST is the initial state of automaton.
% -----------------------------------BST----------------------------------------
% fillUniqueBST(+BST, +Elements, -NewBST)
% --- true iff NewBST is BST with inserted distinct Elements list
% --- and none of the elements appeared in BST previously
fillUniqueBST(ND, [], ND).
fillUniqueBST(D, [H|T], D3) :-
insertUniqueBST(D, H, D2),
fillUniqueBST(D2, T, D3).
% insertUniqueBST(+BST, +Element, -NewBST)
% --- true iff Element does not appear in BST
% --- and NewBST is BST with inserted Element
insertUniqueBST(nil, X, node(nil, X, nil)).
insertUniqueBST(node(L, Y, R), X, node(NL, Y, R)) :-
X@<Y,
insertUniqueBST(L, X, NL).
insertUniqueBST(node(L, Y, R), X, node(L, Y, NR)) :-
X@>Y,
insertUniqueBST(R, X, NR).
% createBST(+List, -BST)
% --- true iff BST is BST with inserted Element
createBST(L, D) :-
createBST(L, nil, D).
createBST([], D, D).
createBST([H | T], A, D) :-
insertBST(A, H, AH),
createBST(T, AH, D).
% insertBST(+BST, +Element, -NewBST)
% --- true iff NewBST is BST with inserted Element
insertBST(nil, X, node(nil, X, nil)).
insertBST(node(L, X, R), X, node(L, X, R)).
insertBST(node(L, Y, R), X, node(NL, Y, R)) :-
X@<Y,
insertBST(L, X, NL).
insertBST(node(L, Y, R), X, node(L, Y, NR)) :-
X@>Y,
insertBST(R, X, NR).
% createFlatBST(+List, -BST)
% --- true iff BST is made from List of elements in inorder
createFlatBST([], nil).
createFlatBST(L, node(D1, X, D2)) :-
length(L, Len),
Len \= 0, % length is not 0
Y is (Len + 1) // 2 - 1, % calculate length of left subtree
length(P, Y),
append(P, [X|S], L),
createFlatBST(P, D1),
createFlatBST(S, D2).
% lenBST(+BST, -Length)
% --- true iff Length is BST's size
lenBST(nil, 0).
lenBST(node(L, _, R), Len) :-
lenBST(L, A),
lenBST(R, B),
Len is A+B+1.
% listBST(+BST, -List)
% --- true iff List represents BST's inorder traversal
listBST(D, L) :-
listBST(D, [], L).
listBST(nil, L, L).
listBST(node(L, X, R), A, S) :-
listBST(R, A, SR),
listBST(L, [X|SR], S).
% listPreorderBST(+BST, -List)
% --- true iff List represents BST's preorder traversal
listPreorderBST(D, L) :-
listPreorderBST(D, L, []).
listPreorderBST(nil, L, L).
listPreorderBST(node(L, X, R), [X|A], S) :-
listPreorderBST(L, A, SL),
listPreorderBST(R, SL, S).
% ---------------------------------correct--------------------------------------
% correct(+Automaton, -Representation)
% --- true iff Automaton is a correct deterministic automaton
% --- Representation is Automaton's internal structure
correct(dfa(FP, I, F), r(W3, E)) :-
fillUniqueBST(nil, F, _), % check if final states are distinct
states(dfa(FP, I, F), S), % BST tree of states
alphabet(dfa(FP, I, F), E), % BST tree of alphabet
lenBST(E, Len), % the length of alphabet
Len \= 0, % alphabet cannot be empty
nodeBST(S, W), % main structure
fillFP(W, FP, W2), % fill main structure with transitions
setFinals(W2, F, W3), % set final states
fpSize(W3, Len). % assert all states have all transitions
% alphabet(+Automaton, -BST)
% --- true iff BST is Automaton's state BST Tree
states(dfa(FP, I, F), S) :-
createBST([I|F], D),
states(FP, D, S).
states([], S, S).
states([fp(X, _, Z)|T], D, S) :-
insertBST(D, X, D2),
insertBST(D2, Z, D3),
states(T, D3, S).
% alphabet(+Automaton, -BST)
% --- true iff BST is Automaton's alphabet BST Tree
alphabet(dfa(FP, _, _), S) :-
alphabet(FP, nil, S).
alphabet([], S, S).
alphabet([fp(_, X, _)|T], D, S) :-
insertBST(D, X, D2),
alphabet(T, D2, S).
% fillFP(+NodeBST, +FpList, -NewNodeBST)
% --- true iff NewNodeBST is NodeBST with
fillFP(D, [], D).
fillFP(D, [H|T], D3) :-
insertFP(D, H, D2),
fillFP(D2, T, D3).
% insertFP(+FpBST, +Fp, -NewFpBST)
% --- true iff NewFpBST is FpBST with transition stored in Fp
insertFP(node(L, (Q, D, F), R), fp(Q, Y, Q2), node(L, (Q, D2, F), R)) :-
insertUniqueBST(D, p(Y, Q2), D2).
insertFP(node(L, (S, D, F), R), fp(Q, Y, Q2), node(NL, (S, D, F), R)) :-
Q@<S,
insertFP(L, fp(Q, Y, Q2), NL).
insertFP(node(L, (S, D, F), R), fp(Q, Y, Q2), node(L, (S, D, F), NR)) :-
Q@>S,
insertFP(R, fp(Q, Y, Q2), NR).
% nodeBST(+StateBST, -NodeBST)
% --- true iff NodeBST is StateBST with nodes
% --- converted to triples (State, nil, 0)
nodeBST(nil, nil).
nodeBST(node(L, X, R), node(L2, (X, nil, 0), R2)) :-
nodeBST(L, L2),
nodeBST(R, R2).
% setFinal(+NodeBST, +FinalState, -NewNodeBST)
% --- true iff NewNodeBST is NodeBST with FinalState marked as final
setFinal(node(L, (Q, D, _), R), Q, node(L, (Q, D, 1), R)).
setFinal(node(L, (Q, D, F), R), X, node(L2, (Q, D, F), R)) :-
X@<Q,
setFinal(L, X, L2).
setFinal(node(L, (Q, D, F), R), X, node(L, (Q, D, F), R2)) :-
X@>Q,
setFinal(R, X, R2).
% setFinals(+NodeBST, +FinalStateList, -NewNodeBST)
% --- true iff NewNodeBST is NodeBST with FinalStateList states marked as final
setFinals(D, [], D).
setFinals(D, [H|T], D3) :-
setFinal(D, H, D2),
setFinals(D2, T, D3).
% fpSize(+NodeBST, +FpSize)
% --- true iff FpBST in every NodeBST's node is of size FpSize
fpSize(nil, _).
fpSize(node(L, (_, D, _), R), S) :-
lenBST(D, S),
fpSize(L, S),
fpSize(R, S).
% --------------------------------complement------------------------------------
% complement(+Representation, -NewRepresentation)
% --- true iff NewRepresentation is the complement of automaton's Representation
% --- and their alphabets are equal
complement(r(W, E), r(W2, E)) :-
swapFinal(W, W2).
% swapFinal(+NodeBST, -NewNodeBST)
% --- true iff NewNodeBST is NodeBST with swapped final states
swapFinal(nil, nil).
swapFinal(node(L, (Q, D, F), R), node(L2, (Q, D, F2), R2)) :-
F2 is 1-F, % final states are marked as 0/1
swapFinal(L, L2),
swapFinal(R, R2).
% -------------------------------intersection-----------------------------------
% intersection(+Representation1, +Representation2, -Intersection)
% --- true iff Intersection is the representation of automata
intersection(r(W1, E), r(W2, E2), r(W, E)) :-
listBST(E, L),
listBST(E2, L), % check if alphabets are equal
listPreorderBST(W1, Lst1),
listPreorderBST(W2, Lst2), % change BSTs to lists
product(Lst1, Lst2, Lst3), % cartesian product of automata
createNodes(Lst3, WLst), % list of nodes for NodeBST
createBST(WLst, W). % NodeBST of intersection
% product(+List1, +List2, -Product)
% --- true iff Product is the cartesian product of elements in List1 and List2
product(L, L2, L3) :-
product(L, L2, L3, L).
product(_, [], [], _).
product([], [_|T2], List3, L) :-
product(L, T2, List3, L).
product([H|T], [H2|T2], [[H,H2]|T3], L):-
product(T, [H2|T2], T3, L).
% createNodes(+List, -NodeList)
% --- true iff NodeList is a list of NodeBST's node structure made from List
createNodes([], []).
createNodes([[(X, D, F),(Y, D2, F2)]|T], [([X,Y], D3, F3)|A]) :-
F3 is F*F2, % both states must be final
merge(D, D2, D3), % merge FpBSTs of both nodes into one
createNodes(T, A).
% merge(+FpBST1, +FpBST2, -NewFpBST)
% --- true iff NewFpBST is a merged BST of
% --- transitions from FpBST1 and FpBST2
merge(D1, D2, D3) :-
listBST(D1, L1),
listBST(D2, L2),
mergeFpLists(L1, L2, L3),
createFlatBST(L3, D3). % create balanced BST
% mergeFpLists(+List1, +List2, -NewList)
% --- true iff NewList is a list of transitions with
% --- merged states from List1 and List2
mergeFpLists(L1, L2, L3) :-
mergeFpLists(L1, L2, [], L3).
mergeFpLists([], [], L, L).
mergeFpLists([p(X, Y)|T], [p(X, Z)|T2], A, L) :-
mergeFpLists(T, T2, [p(X, [Y,Z])|A], L).
% ----------------------------------accept--------------------------------------
% accept(+Automaton, ?Word)
% --- true iff Automaton accepts Word
accept(A, S) :-
var(S), % S is a variable
correct(A, r(W, _)),
infinite(W), % A is inifinite
acceptGen(W, 0, S). % generate infinite language
accept(A, S) :-
var(S), % S is a variable
correct(A, r(W, _)),
\+ infinite(W), % A is finite
lenBST(W, N), % N states in A
acceptLimit(W, 0, N, S). % generate words up to length N
accept(A, S) :-
\+ var(S), % S is not a variable
acceptList(A, S).
% acceptGen(+NodeBST, +Length, -Word)
% --- true iff Word is a word of length >= Length and
% --- Automaton represented by NodeBST accepts it
acceptGen(W, K, S) :-
acceptK(W, K, S).
acceptGen(W, K, S) :-
K2 is K + 1,
acceptGen(W, K2, S).
% acceptLimit(+NodeBST, +Length, +Limit, -Word)
% --- true iff Word is a word of length >= Length, length < Limit and
% --- Automaton represented by NodeBST accepts it
acceptLimit(W, K, _, S) :-
acceptK(W, K, S).
acceptLimit(W, K, Lim, S) :-
K2 is K + 1,
K2 < Lim,
acceptLimit(W, K2, Lim, S).
% acceptList(+Automaton, -Word)
% --- true iff Word is a list of letters from Automaton's alphabet and
% --- is a word accepted by Automaton
acceptList(A, S) :-
correct(A, r(node(L, (I, D, F), R), _)),
acceptList(node(L, (I, D, F), R), I, S).
acceptList(W, Q, [H|T]) :-
findNodeBST(W, Q, (Q, D, _)), % find state in NodeBST
getBST(D, p(H, Q2)), % get all transitions
acceptList(W, Q2, T).
acceptList(W, Q, []) :-
findNodeBST(W, Q, (Q, _, 1)).
% acceptK(+NodeBST, +Length, -Word)
% --- true iff Word is a word of length Length and
% --- Automaton represented by NodeBST accepts it
acceptK(node(L, (I, D, F), R), K, S) :-
acceptK(node(L, (I, D, F), R), I, K, S).
acceptK(W, Q, 0, []) :-
findNodeBST(W, Q, (Q, _, 1)).
acceptK(W, Q, K, [H|T]) :-
K>0,
K2 is K-1,
findNodeBST(W, Q, (Q, D, _)), % find state in NodeBST
getBST(D, p(H, Q2)), % get all transitions
acceptK(W, Q2, K2, T).
% infinite(+NodeBST)
% --- true iff the language of automaton represented by NodeBST is infinite
%
% --- the language accepted by a DFA M with n states is infinite if and only if
% --- M accepts a string of length k, where n <= k < 2n
infinite(W) :-
lenBST(W, N),
N2 is N*2,
infinite(W, N, N2).
infinite(W, K, _) :-
acceptK(W, K, _), !. % need one success to prove the infinity of language
infinite(W, K, N2) :-
K2 is K + 1,
K2 < N2,
infinite(W, K2, N2).
% getBST(+BST, -Node)
% --- true iff Node is a node in BST
getBST(node(_, X, _), X).
getBST(node(L, _, _), X) :-
getBST(L, X).
getBST(node(_, _, R), X) :-
getBST(R, X).
% ----------------------------------empty---------------------------------------
% empty(+Automaton)
% --- true iff the language of Automaton is empty
empty(A) :-
correct(A, r(W, _)),
\+ nonEmpty(W).
% nonEmpty(+NodeBST)
% --- true iff the language of automaton stored in NodeBST is non-empty
% --- true iff any final state is reachable from initial state
nonEmpty(node(L, (I, D, F), R)) :-
nonEmpty(node(L, (I, D, F), R), I, nil).
nonEmpty(W, X, V) :- % V - Visited
insertUniqueBST(V, X, _), % check if X was not previously visited
findNodeBST(W, X, (X, _, 1)). % check if X is a final state
nonEmpty(W, X, V) :-
insertUniqueBST(V, X, V2), % mark X as visited
findNodeBST(W, X, (X, D, 0)), % check if X is not a final state
traverseTree(D, V2, W). % traverse X's FpBST
% traverseTree(+FpBST, +VisitedBST, +NodeBST)
% --- true iff any state from FpBST is nonEmpty
traverseTree(node(_, p(_, Q), _), V, W) :- nonEmpty(W, Q, V).
traverseTree(node(L, _, _), V, W) :- traverseTree(L, V, W).
traverseTree(node(_, _, R), V, W) :- traverseTree(R, V, W).
% findNodeBST(+NodeBST, +State, -Node)
% --- true iff Node is a node in NodeBST whose state matches State
findNodeBST(node(_, (Q, D, F), _), Q, (Q, D, F)).
findNodeBST(node(L, (Y, _, _), _), X, Z) :-
X@<Y,
findNodeBST(L, X, Z).
findNodeBST(node(_, (Y, _, _), R), X, Z) :-
X@>Y,
findNodeBST(R, X, Z).
% --------------------------------subsetEq--------------------------------------
% subsetEq(+Automaton1, +Automaton2)
% --- true iff the language of Automaton1 is a subset of
% --- Automaton2's language and their alphabets are equal
subsetEq(A1, A2) :-
correct(A1, R1),
correct(A2, R2),
complement(R2, C2), % calculate the complement of A2
intersection(R1, C2, r(W, _)), % the intersection of A1 and the
\+ nonEmpty(W). % complement of A2 should be empty
% ----------------------------------equal---------------------------------------
% equal(+Automaton1, +Automaton2)
% --- true iff the languages of Automaton1 and Automaton2 are equal
% --- and their alphabets are equal
equal(A1, A2) :-
subsetEq(A1, A2),
subsetEq(A2, A1).
% ------------------------------------------------------------------------------