-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
automaton.ml
1855 lines (1715 loc) · 67.7 KB
/
automaton.ml
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
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
let id_aut = ref (-1)
type search = | Mod | Less
open Format
let print_debug _ = ()
(* let print_debug x = print_endline x *)
(**
We must simultaneously define the state, the strongly connected component (scc) and the automaton, since each link to each other. We also provide some function on it.
*)
module U2M = Pair.Map (Subset)(Subset)
module UHmap = Pair.OrderedType (Subset)(Subset)
module UUUHmap = Pair.OrderedType (UHmap)(UHmap)
module U5M = Pair.Map (Subset)(UUUHmap)
(* Input of type (i, (d1l,d2l), (d1g,d2g)) *)
type iota = Ignore | Important
module rec
Type:
sig
type
(**
the type of a state
id an unique id
final is true if the state is final
delta is the transition function.
automaton is its automaton.
scc gives its strongly connected compontent, a dummy one if there is no cycle.
oop associate to each element its 0 orderered partition. A dummy one if there are no cycle.
eq its equivalence class for ~
visited and visted' are variable used by many function to temporary mark the states, the automaton must be unmarked at the end of the loop.
step[i] is true if there is a path of size i from the initial state with acyclic state
kappa[q][q'] correspond to kapa_q(q') of the paper, that is the lexicographicaly minimal words from q to q' if it exists
zeros: a function that takes a scc and return a state in it if it exists
rel : a function from i,d1<, d2<,d1>,d2> to the set of states equivalent to it
usable : true if there is no Z and no B.
*)
state = { id: int ;
final : bool ;
mutable delta : state Transition.t;
nameS : string ;
automaton : automaton ;
mutable scc : scc ;
mutable oop : Oop.t;
mutable eq : eq;
mutable cyclic : bool;
mutable visited :bool;
mutable visited' : bool;
mutable step : Int.S.t;
mutable kappa : int array SM.t ;
mutable zeros : state CM.t;
mutable formula : Formula.t option;
(*i, d1l, d2l, d1g, d2g*)
mutable rel :bool array U5M.t;
}
and
(**
The type of a strongly connected component
idS an unique id
statesS the list of its states, in the same order as in the automaton array
op its 0 partition
ku is a function from U unions of U_{C,i} to the size of the [U]-loop
k is the lcm of the ku
If the B-class is empty:
eqs : its set of equivalence class; a parition of statesS if the B class is empty, else nil
rewritting : a rule of rewritting rule to apply, in the order of Subsets.t, hence they must be applied in reverse order
a rule is (U,(i, is)) if U^i is equivalent to is
*)
scc = { mutable idS : int;
mutable statesS : state list;
a_state : state;
mutable ku : (Subset.t_node,int) Hmap.t;
mutable k : int;
mutable seen : bool;
mutable eqs : eq list;
mutable rewriting : (Subset.t_node,(int * int array)) Hmap.t
}
and
(**
The type of an equivalence class according to ~
idE an unique id
statesE the set of states
(*sccE a function from the scc to its state in scc inter eq*)
*)
eq = { idE : int;
mutable statesE : State_oop_set.t;
iota : iota array array;
}
and
(** The type of the automaton
name : a description
idA : an unique id
size is the number of states
base is the basis in which the automaton is written
dimension is the number of integer in a letter
var the set of free variables
states the set of state, 0 is initial, otherwise no order
sccs is the array of scc in topological order; the first has no successor, the last no predecessor
cycles the states with a cycle
b_less the states whose b class is empty
b_less_scc their scc
use_suc if +1 is needed
use_less if < is needed
use_zero if =0 is needed
use_equal if = is needed
*)
automaton =
{ name: string ;
idA : int ;
simple : Simple.automaton ;
alphabet : IntAr.t list;
size : int ;
base : int;
dimension : int ;
var : Formula.var array ;
states : state array;
mutable sccs : scc array;
mutable cycles : state list;
mutable b_less : state list;
mutable b_less_scc : scc list;
mutable use_suc : bool;
mutable use_less: bool;
mutable use_zero : bool;
mutable use_equal: bool;
mutable use_mod: bool;
}
end
=
struct
type
state = { id: int ;
final : bool ;
mutable delta : state Transition.t;
nameS : string ;
automaton : automaton ;
mutable scc : scc ;
mutable oop : Oop.t;
mutable eq : eq;
mutable cyclic : bool;
mutable visited :bool;
mutable visited' : bool;
mutable step : Int.S.t;
mutable kappa : int array SM.t ;
mutable zeros : state CM.t;
mutable formula : Formula.t option;
mutable rel :bool array U5M.t;
}
and
scc = { mutable idS : int;
mutable statesS : state list;
a_state : state;
mutable ku : (Subset.t_node,int) Hmap.t;
mutable k : int;
mutable seen : bool;
mutable eqs : eq list;
mutable rewriting : (Subset.t_node,(int * int array)) Hmap.t
}
and
eq = { idE : int;
mutable statesE : State_oop_set.t;
iota : iota array array;
}
and
automaton =
{ name: string ;
idA : int ;
simple : Simple.automaton ;
alphabet : IntAr.t list;
size : int ;
base : int;
dimension : int ;
var : Formula.var array ;
states : state array;
mutable sccs : scc array;
mutable cycles : state list;
mutable b_less : state list;
mutable b_less_scc : scc list;
mutable use_suc : bool;
mutable use_less: bool;
mutable use_zero : bool;
mutable use_equal: bool;
mutable use_mod: bool;
}
end
and
CompS : sig
type t = Type.state
val compare : t -> t -> int
end
= struct
type t = Type.state
let compare {Type.id=x} {Type.id=y} = x-y
end
and
SM : Map.S with type key = Type.state = Map.Make (CompS)
and
SS : Set.S with type elt = Type.state = Set.Make (CompS)
and
State_oop_comp :
sig
type t = Type.state
val compare : t -> t-> int
end
=
struct
type t= Type.state
let compare s t = Oop.compare s.Type.oop t.Type.oop
end
and
State_oop_set :
Set.S with type elt = Type.state
= Set.Make (State_oop_comp)
and
CompE : sig
type t = Type.eq
val compare : t -> t -> int
end
=
struct
type t = Type.eq
let compare {Type.idE=x} {Type.idE=y} = x-y
end
and
CompC : sig
type t = Type.scc
val compare : t -> t -> int
end
=
struct
type t = Type.scc
let compare {Type.idS=x} {Type.idS=y} = x-y
end
and
CM: Map.S with type key = Type.scc = Map.Make (CompC)
include Type
let state_print_id ppf state = fprintf ppf "%d" state.id
let state_print_name ppf state = fprintf ppf "%s" state.nameS
let scc_print_id ppf state = fprintf ppf "%d" state.idS
let trans_printf =
Transition.printf state_print_id
let eq_printf ppf eq =
fprintf ppf "eq of id:%d, and states: " eq.idE ;
State_oop_set.iter (fun state -> fprintf ppf "%a, " state_print_id state) eq.statesE
let scc_printf ppf scc =
fprintf ppf "scc of id:%d,@ k:%d@,;" scc.idS scc.k ;
Pretty.print_list ppf "ku=@[{" ",@," "}@]" (Hmap.bindings scc.ku) (fun ppf (u,ku) -> fprintf ppf "(%a,%d)" Subset.printf u ku);
Pretty.print_list ppf ",@,states:@[[" "," "]@]" scc.statesS state_print_id;
fprintf ppf " and eq : ";
Pretty.print_list ppf "@[ <" ";@," ">@]@." scc.eqs eq_printf
(*a list of getter *)
(** O(1) *)
let get_name {name = n} = n
(** O(1) *)
let state_oop {oop=oop}= oop
(** O(1) *)
let state_scc {scc=scc}= scc
(** O(1) *)
let state_automaton {automaton= aut} = aut
(** O(d* size*log(size))*)
let successor state letter =
Transition.successor letter state.delta
(** take a word as a list of letter, return the successor by this
word; O(d* size*log(size)*list zie) *)
let successors =
List.fold_left successor
(** add a transition. O(d*log(size)) *)
let add_transition state letter suc =
state.delta <- Transition.add state.delta letter suc
module NotReg =
struct
(* type state = state
type scc = int
type eq = int*)
(* we can not directly use scc or state since that would create a
loop, so we give its the id of the state (of an element of the scc/eq) instead *)
type t =
(** The automaton is not a relative set because of the initial state*)
| Prop_rel_init
(** The automaton is not a relative set because of the successor of the state by the letter*)
| Prop_rel of (int * IntAr.t)
(**(q) and its successor by 0 are not both final/not final *)
| Prop00 of (state)
(** (q,l,q') delta(q,l)=q', q has a cycle, not q' *)
| Prop01 of (state* Letter.t * state)
(** (q) if it has no state B*)
| Prop02exists of state
(** (q) if the intersection of the B that stay in the same scc does
not stay in the same scc *)
| Prop02array of (state )
(** (q,q') are in the same scc, but B is different*)
| Prop02state of (state * state)
(** (q,s) if s is an intersection of some U, but not an U *)
| Prop03array of (state * Subset.t )
(** (q,q') are in the same scc, but their U is different*)
| Prop03state of (state * state)
(** (q,u) u is a union of u_i, but does not respect the definition*)
| Prop03union of (scc * Subset.t)
(** (q, I,K) if the successor of q by (I,K) is not ({},K) cyclic *)
| Prop04 of (state * Subset.t * Subset.t)
(** (q, I,K) if the successor of q by [I,K] is not [I,K] cyclic *)
| Prop05 of (state * Subset.t * Subset.t)
(** (q,U) if there is q' in the same scc has q and their [U,B_C]
cycle have different size *)
| Prop06 of (state* Subset.t)
(** (q,U,B) if q in N(C,U,B) has a [U,B]-cycle not prime with b *)
| Prop06Prime of (state* Subset.t* Subset.t)
(** (s, us) if k_us does not divides the lcm of the k_u*)
| Prop07 of (scc* Subset.t )
(** (q,letter) if letter makes q change z or b but incorrectly *)
| Prop08 of (state * IntAr.t* state * state)
(** (q,letter) if letter makes q does not change z or b and incorrectly *)
| Prop09 of (state * IntAr.t* state * state)
(** (q,N) if the set q does not respect the N hypothesis *)
| Prop10 of (state* Subset.t)
(** (q,letter) if delta(q,letter) is not less than delta(q).letter *)
| Prop11 of (state* Letter.t)
(** (q,D,I) if the equality of 12 is not respected *)
| Prop12 of (state* Subset.t* Subset.t)
(** (q) if the equality of 13 is not respected *)
| Prop13 of (state)
(** (q,D,I,K) if the equality of 14 is not respected *)
| Prop14 of (state* Subset.t* Subset.t* Subset.t)
(** (q,D,I,K) if the equality of 15 is not respected *)
| Prop15 of (state* Subset.t* Subset.t* Subset.t)
(** (q,I) if equality 16 is not respected *)
| Prop16 of (state * Subset.t)
(** (q,i,j) if (i,j) is ignored, i<_q j and there are no k between them *)
| Prop17 of (state* int*int)
(** This is not in the paper, but it helps to consider this case.
(q,u) if q is not accessible from delta(q,<U>) by <.> *)
| Prop18bis of (state* Subset.t)
(** (q,q') if q equiv q' and their oop are identic *)
| Prop18 of (state * state )
(** (q,i) if the equality of prop 19 is not respected*)
| Prop19 of (state* Subset.t)
(** (q,I) if the equality of 20 is not respected *)
| Prop20 of (state* Subset.t)
(** (q,I,K) if the equality of 21 is not respected *)
| Prop21 of (state* Subset.t* Subset.t)
(** (q,I,K) if the equality of 22 is not respected *)
| Prop22 of (state* Subset.t* Subset.t)
exception T of t
let printf ppf p=
(match p with
| Prop_rel_init ->
fprintf ppf "The automaton is not even a correct relative one, its initial state is accepting.@."
| Prop_rel (i, a) ->
fprintf ppf "The automaton is not even a correct relative one, the successor of state %d by %a is accepting.@." i IntAr.printf a
| Prop00 (state) ->
fprintf ppf "The automaton is not even correct, as only one between state %s and its successor by 0...0 is accepting.@." state.nameS
| Prop01 (state, letter, succ) ->
fprintf ppf "Property 1 is not respected, as state %s,@, has a cycle and the letter " state.nameS;
Letter.printf ppf letter;
fprintf ppf " leads to %s which has no cycle" state.nameS
| Prop02exists state->
fprintf ppf " Property 2exists"
| Prop02array (state )->
fprintf ppf " Property 2array: the intersection of the Uc of %s is not in Uc " state.nameS
| Prop02state (state, state2)->
fprintf ppf " Property 2state: %s's b-class is %a and %s's is %a" state.nameS Subset.printf state.oop.Oop.b state2.nameS Subset.printf state2.oop.Oop.b
| Prop03array (state, u )->
fprintf ppf "Prop03 is false for state %s, with u=%a" state.nameS Subset.printf u
| Prop03state (state , state2)->
fprintf ppf " Property 3state"
| Prop03union (scc , sub)->
fprintf ppf " Property 3union"
| Prop04 (state, i,k)->
fprintf ppf " Property 4: delta(%s,(%a,%a)) is not in a ({},%a)-cycle" state.nameS Subset.printf i Subset.printf k Subset.printf k
| Prop05 (state, i,k)->
fprintf ppf " Property 5: delta(%s,[%a,%a]) is not in a [%a,%a]-cycle" state.nameS Subset.printf i Subset.printf k Subset.printf i Subset.printf k
| Prop06 (state2, u)->
fprintf ppf " Property6 is not respected, for u=%a, the loop on states ? and %s are different" Subset.printf u state2.nameS
| Prop06Prime (state, u, b)->
fprintf ppf " Property 6 prime"
| Prop07 (scc, us )->
fprintf ppf " Property 07"
| Prop08 (state , ints, left, right)->
fprintf ppf " Property 08 is not respected, delta(%s,%a)=%s and should be %s" state.nameS
IntAr.printf ints
left.nameS right.nameS
| Prop09 (state , ints, left, right)->
fprintf ppf " Property 09 is not respected, delta(%s,%a)=%s and should be %s" state.nameS
IntAr.printf ints
left.nameS right.nameS
| Prop10 (s,n )->
fprintf ppf " Property 10"
| Prop11 (state, letter)->
let suc = successor state letter in
(** (q,letter) if delta(q,letter) is not less than delta(q).letter *)
fprintf ppf " Property 11: state q=%s has op @.%a, its successor @.%s by @.%a has op @.%a which is not less than the concatenation @.%a."
state.nameS Oop.printf state.oop suc.nameS Letter.printf letter Oop.printf suc.oop Oop.printf (Oop.concat state.oop state.automaton.dimension letter)
| Prop12 (state, d, i)->
fprintf ppf " Property 12"
| Prop13 (state)->
fprintf ppf " Property 13"
| Prop14 (state, d,i,k)->
fprintf ppf " Property 14: delta(%s,[%a,%a][%a]) is not equal to delta(%s,[%a][%a]<%a cup %a>)" state.nameS Subset.printf k Subset.printf d Subset.printf i state.nameS Subset.printf i Subset.printf k Subset.printf i Subset.printf d
| Prop15 (state, d, i,k)->
fprintf ppf " Property 15"
| Prop16 (state, i)->
fprintf ppf " Property 16: for I=%a, delta(%s,[I])=%s, delta(%s,<I>[I])=%s, delta(%s,[I]<I>)=%s should be identic" Subset.printf i
state.nameS (successor state (Letter.CrochetD i)).nameS
state.nameS (successor (successor state (Letter.ChevronD i)) (Letter.CrochetD i)).nameS
state.nameS (successor (successor state (Letter.CrochetD i)) (Letter.ChevronD i)).nameS
| Prop17 (state, i,j)->
fprintf ppf " Property 17"
| Prop18 (q,q')->
fprintf ppf " Property 18: %a's op:@.%a@. and %a's op:@.%[email protected] comparable" state_print_name q Oop.printf q.oop state_print_name q' Oop.printf q'.oop
| Prop18bis (state, u)->
fprintf ppf " Property 18bis"
| Prop19 (state, i)->
fprintf ppf " Property 19"
| Prop20 (state, i)->
fprintf ppf " Property 20"
| Prop21 (state, i,k)->
fprintf ppf " Property 21"
| Prop22 (state, i,k)->
fprintf ppf " Property 22");
fprintf ppf "@."
let count = function
| Prop_rel_init -> 30
| Prop_rel _ -> 31
| Prop00 _ -> 0
| Prop01 _ -> 1
| Prop02exists state-> 2
| Prop02array _-> 2
| Prop02state _->2
| Prop03array _->3
| Prop03state _->3
| Prop03union _->3
| Prop04 _->4
| Prop05 _ -> 5
| Prop06Prime _
| Prop06 _ -> 6
| Prop07 _-> 7
| Prop08 _ -> 8
| Prop09 _ -> 9
| Prop10 _ -> 10
| Prop11 _-> 11
| Prop12 _-> 12
| Prop13 _-> 13
| Prop14 _-> 14
| Prop15 _-> 15
| Prop16 _-> 16
| Prop17 _-> 17
| Prop18 _-> 18
| Prop19 _-> 19
| Prop18bis _-> 18
| Prop20 _ -> 20
| Prop21 _-> 21
| Prop22 _-> 22
end
let aut_base {base =base} = base
let aut_dimension {dimension =dimension} = dimension
let aut_states {states =states} = states
let rec state_dummy =
{oop= Oop.init 0;
scc= scc_dummy;
nameS= "dummy" ;
zeros =CM.empty;
step = Int.S.empty;
formula = None;
kappa = SM.empty;
delta= Transition.empty ;
id = -1;
automaton = automaton_dummy ;
final = false;
eq=eq_dummy;
visited=false;
visited'=false;
cyclic =false;
rel = U5M.empty;}
and scc_dummy =
{ idS = -1;
a_state = state_dummy;
rewriting = Hmap.empty;
ku =Hmap.empty;
k=1;
eqs =[];
statesS=[];
seen = false;
}
and eq_dummy =
{idE = -1;
statesE = State_oop_set.empty;
iota = [||];
}
and automaton_dummy =
{idA= -1;
simple = Simple.automaton_dummy;
alphabet = [];
size = 0;
base = 0;
name = "";
b_less = [];
var = [||];
b_less_scc = [];
dimension = 0;
sccs = [||] ;
states = [||];
cycles = [];
use_suc = false;
use_less = false;
use_zero = false;
use_equal = false;
use_mod = false;
}
let state_printf ppf state =
fprintf ppf "@[%s state q%d=%s@, scc: %d, eq: %d, %s cycle, transitions:@ %a@,, its 0op is:%a@, its formula is %a@]"
(if state.final then "accepting" else "rejecting")
state.id
state.nameS
state.scc.idS state.eq.idE
(if state.cyclic then "a" else "no")
(Transition.printf (fun ppf state -> fprintf ppf "%d" state.id)) state.delta
Oop.printf state.oop
(Pretty.some Formula.printf) state.formula
(* rel_printf state *)
let aut_printf ppf aut =
fprintf ppf "Automaton %s:@ Base: %d; Dimension: %d; size: %d;using %s%s%s%s%s;.@ "
aut.name aut.base aut.dimension aut.size
(if aut.use_suc then "+1 "else "")
(if aut.use_less then "< "else "")
(if aut.use_zero then "=0 "else "")
(if aut.use_equal then "= "else "")
(if aut.use_mod then "mod "else "");
Pretty.print_array ppf "@[ <" ";@." ">@]" aut.states
(fun ppf _ elt ->
state_printf ppf elt);
fprintf ppf " and scc :@. ";
Pretty.print_array ppf "@[ <" ";@." ">@]" aut.sccs (fun ppf _ s -> scc_printf ppf s);
fprintf ppf "@."
let printf = aut_printf
(** Translate a simple automaton into an automaton.
O(size*b^d*log (b) * d )
*)
let of_simple simple=
let simple = Simple.correct simple in
let b = simple.Simple.base
and d = simple.Simple.dimension
and ss = simple.Simple.states
and name = simple.Simple.name in
let abd = simple.Simple.alphabet in
let size = Array.length ss in
let x = Formula.free d in
let states = Array.make size state_dummy in
let rec automaton =
{automaton_dummy with simple = simple;
size = size ;
base = b;
name = name;
dimension = d;
states = states;
var = x ;
alphabet = abd ;
}
in
(* putting states in the array *)
for i=0 to (size -1) do
states.(i) <-
{state_dummy with id = i;
oop = Oop.init d;
automaton = automaton ;
final = ss.(i).Simple.final;
nameS= ss.(i).Simple.nameS ;
}
done;
(* adding transition for each letter *)
for i=0 to size -1 do
IntAr.M.iter
(fun letter suc ->
let letter = (Letter.Letter letter) in
add_transition states.(i) letter states.(suc)
) ss.(i).Simple.delta
done;
automaton
exception N of (NotReg.t * automaton )
exception E of (exn * automaton)
module Exists:
sig
val exists : search -> automaton -> NotReg.t option
end =
struct
(** Verify that when adding a 0 the state remain (not) final*)
let check0 aut =
let zero = Letter.zero aut.base aut.dimension in
Array.iter
(fun state ->
let suc = successor state zero in
if suc.final <> state.final
then raise (NotReg.T (NotReg.Prop00 (state)))
) aut.states
(** Takes an automaton without sccs, add its sccs using Tarjan
algorithm. Not neccessary in any order *)
let tarjan aut =
let sccs = ref [] in
let size = aut.size in
let lowLink = Array.make size None in
let tar_index = Array.make size (-1) in
let cur_index = ref 0 (* Number of seen state *)
and cur_scc = ref 0 (*Number of scc *)
and s = ref [] in (* A FILO with the visited states not yet in an scc. *)
let rec aux state =
if tar_index.(state.id) = -1
then
(tar_index.(state.id)<- !cur_index;
incr cur_index;
s := state:: !s;
state.visited <- true;
Transition.iter
(fun _ suc ->
if tar_index.(suc.id) = -1
then( (*if this successor has never been visited yet *)
aux suc;
lowLink.(state.id) <-
(match (lowLink.(state.id), lowLink.(suc.id)) with
| None, None -> None (*If neither us nor the successor has cycle *)
| None, Some i -> if i <= tar_index.(state.id) then Some i else None
| Some i, None-> Some i(*if one of us have a cycle *)
| Some i, Some j -> Some (if i<j then i else j)) (*If both have a cycle *)
) else
if suc.visited (* If the successor is also an ancester *)
then lowLink.(state.id) <-
Some (match (lowLink.(state.id), tar_index.(suc.id)) with
| None, i -> i
| Some i,j -> if i<j then i else j)
) state.delta ;
match lowLink.(state.id) with
| None -> (* If we have seen no path to an ancestor; hence no cycle *)
s := List.tl !s
| Some i when i = tar_index.(state.id) -> (* if we have seen a path to ourself and none to an ancestor*)
let fin = ref false in
let scc = {scc_dummy with idS = !cur_scc; a_state = state} in
incr cur_scc;
sccs := scc :: !sccs;
while not !fin do
match !s with
| [] ->
failwith "We should never see the end of the list without seeing state as state2"
| state2::t->
s := t;
state2.scc <- scc ;
state2.cyclic <- true;
if state2 == state then fin := true;
aut.cycles <- state2 :: aut.cycles;
scc.statesS <- state2 :: scc.statesS
done ;
| _ -> ()(* If there is a path to an ancester, there is nothing to do*)
); (*end of the if *)
state.visited <- false
in
Array.iter aux aut.states;
aut.sccs <- Array.of_list ( !sccs)
(** Verify property1, after Tarjan algorithm is done, so state.cycle
are correct *)
let prop01 aut =
List.iter (
fun state->
Transition.iter
(fun letter suc ->
if not suc.cyclic then
raise (NotReg.T (NotReg.Prop01 (state,letter, suc)))
)state.delta;
) aut.cycles
(** add every successor of the form (U,B) and (U)*)
let addParen aut=
List.iter (* looping on each U*)
(fun u ->
List.iter (* looping on each B*)
(fun b ->
List.iter (* looping on each state with a cycle *)
(fun state->
let letter= IntAr.of_par2 aut.base aut.dimension u b in
let parenthesis = Letter.ParenT (u,b) in
let letter = Letter.Letter letter in
let succ = successor state letter in
add_transition state parenthesis succ;
if Subset.is_empty b
then
(let parenthesis = Letter.ParenD u in
add_transition state parenthesis succ);
if Subset.is_empty u
then
(let parenthesis = Letter.ParenG b in
add_transition state parenthesis succ)
) aut.cycles
) (Subset.enumerate_sub (Subset.comp u)) ;
)(Subset.enumerate aut.dimension)
(** Check property 2, after the parenthesis were added; computes the B *)
let prop02 aut =
List.iter (
fun state ->
let bs= (* the B such that delta(q,(0,b)) is in the same scc as q*)
List.filter
(fun b ->
let letter = Letter.ParenG b in
let suc = successor state letter in
state.scc == suc.scc
) (Subset.enumerate aut.dimension)
in
match bs with
|[] ->
raise (NotReg.T (NotReg.Prop02exists state))
| b:: bs ->
let b_inter=(* the intersection of every element of bs *)
List.fold_left Subset.inter b bs in
(* we check if the intersection lead to the same scc *)
let letter = Letter.ParenG b_inter in
let suc = successor state letter in
if suc.scc != state.scc then
raise (NotReg.T (NotReg.Prop02array (state)));
state.oop.Oop.b <- b_inter;
Subset.iter
(fun b ->
Subset.iter
(fun u ->
Oop.lower state.oop u b Oop.Les
) (Subset.comp b_inter)
)b_inter;
(* if the b class is empty, it goes into b_less *)
if Subset.is_empty b_inter
then aut.b_less <- state :: aut.b_less
) aut.cycles;
(*Finally, we must check that for each element of an scc, we have
the same B. *)
Array.iter (
fun scc ->
let state2 = List.hd scc.statesS and
t = List.tl scc.statesS in
let b = state2.oop.Oop.b in
if Subset.is_empty b
then aut.b_less_scc <- scc :: aut.b_less_scc;
List.iter (
function state ->
if b<> state.oop.Oop.b then
raise (NotReg.T (NotReg.Prop02state (state2, state)))
) t;
(* Furthemore if there is a non empty b, we put +1 and = at
true *)
if not (Subset.is_empty b) then
(aut.use_equal <- true;
aut.use_suc <- true;
aut.use_zero <- true )
) aut.sccs
(** Check property3 after the 2. Compute the Us and the Z *)
let prop03 aut =
List.iter (* We must do the same verification on each state *)
(fun state ->
let b = state.oop.Oop.b in
let ucs = Subset.enumerate_sub (Subset.comp b) in(* the sets disjoint from Bc *)
let ucs = (* such that delta(state,(U,Bc)) is in the same scc as state*)
List.filter (
fun u ->
let letter = Letter.ParenT (u, b) in
let suc = successor state letter in
state.scc == suc.scc
) ucs in
let cut = Subsets.cut ucs aut.dimension in (*the subsets Uc *)
(*we check if every element lead to the scc of state. We
could also check if cut is a subet of ucs*)
Subsets.iter (
fun u ->
let letter = Letter.ParenT (u, b) in
let suc = successor state letter in
if state.scc != suc.scc then
raise (NotReg.T (NotReg.Prop03array (state,u)))
) cut;
state.oop.Oop.u <- cut;
let z= Subset.comp (Subset.union (Subsets.union cut) b) in
state.oop.Oop.z <- z;
Subset.iter
(fun elt_z ->
Subset.iter
(fun i ->
Oop.lower state.oop elt_z i Oop.Les
) (Subset.comp z)
)z;
if not (Subset.is_empty z)
then ( aut.use_zero <- true)
) aut.cycles ;
(* Finally, we must check that for each element of an scc, there are
the same Ucs. Hence they are equal*)
Array.iter (
fun scc ->
let h = List.hd scc.statesS in
let t = List.tl scc.statesS in
List.iter (
function state ->
if state.oop.Oop.z <> h.oop.Oop.z || state.oop.Oop.u <> h.oop.Oop.u then
raise (NotReg.T (NotReg.Prop03state (h, state)))
) t
) aut.sccs
(** This function put the visited of every state of a scc to false. *)
let unvisit aut =
List.iter (fun state -> state.visited <- false) aut.cycles
(** Assuming: on each cycle, visited is all true or all false.
State.visited is false.
visited become true on the cycle of state.
inv letter are added as inverse on the cycle.
return true if there a cycle, and the size of the cycle
*)
let is_cyclic state letter inv inf sup=
let rec aux state2 size=
if state2.visited
then (false, -1)
else (state2.visited <- true;
let suc = successor state2 letter in
add_transition suc inv state2 ;
Subset.iter
(fun i ->
Subset.iter
(fun j ->
Oop.lower state2.oop i j Oop.Les
) sup
) inf;
if suc == state
then (true, size+1)
else aux suc (size + 1)
)
in aux state 0
(** Check that delta(q, (I,B}) is ({},B} cyclic; add inverse (emptyset,B)^-1 *)
let prop04 aut =
let d = aut.dimension in
List.iter
(fun i->
List.iter
(fun k ->
List.iter
(fun state ->
let letter = Letter.ParenG k
and inv = Letter.ParenI k in
let suc = successor state (Letter.ParenT (i,k)) in
if not suc.visited then
if not (fst (is_cyclic suc letter inv i k)) then
raise (NotReg.T (NotReg.Prop04 (state, i,k)))
) aut.cycles;
unvisit aut
) (Subset.enumerate_sub (Subset.comp i))
) (Subset.enumerate d)
(** add every successor of the form [U,B] and [U]*)
let addCrochet aut=
List.iter (* looping on each U*)
(fun u ->
List.iter (* looping on each B to add [U,B]*)
(fun b ->
List.iter (* looping on each state with a cycle *)
(fun state->
let crochet = Letter.CrochetT (u,b)
and paren = Letter.ParenT (u,b)
and inv = Letter.ParenI b in
let succ1 = successor state paren in
let succ = successor succ1 inv in
add_transition state crochet succ;
if Subset.is_empty b then
let crochet = Letter.CrochetD u in
add_transition state crochet succ
) aut.cycles
) (Subset.enumerate_sub (Subset.comp u))
)(Subset.enumerate aut.dimension)
(** Check that delta(q, [I,B]) is [I,B] cyclic; add inverse [I,B]^-1 *)
let prop05_06 aut =
Array.iter
(fun scc ->
List.iter
(fun k'->
let k = Subset.union k' scc.a_state.oop.Oop.b in
List.iter
(fun i ->
let letter = Letter.CrochetT (i,k)
and inv = Letter.CrochetI (i,k) in
(* fprintf std_formatter "05 on %a, scc=%d@." Letter.printf letter scc.idS; *)
List.iter
(fun state ->
let suc = successor state letter in
if not suc.visited then(
(* fprintf std_formatter "working on delta(%a,%a)=%a, adding %a@." state_print_name state Letter.printf letter state_print_name suc Letter.printf inv; *)
let cyclic, size = is_cyclic suc letter inv i k in
if not cyclic then
raise (NotReg.T (NotReg.Prop05 (state, i, k)))
else
try
if size <> Hmap.find i suc.scc.ku
then raise (NotReg.T (NotReg.Prop06 (suc, i)))
with
| Not_found ->
(suc.scc.ku <- Hmap.add i size suc.scc.ku;
if (Math.gcd size aut.base)>1
then raise (NotReg.T (NotReg.Prop06Prime (state, i,k)))
)
)
)scc.statesS ;
unvisit aut
)(Subset.enumerate_sub (Subset.comp k));
) (Subset.enumerate_sub (Subset.comp scc.a_state.oop.Oop.b))
) aut.sccs
(** add every successor of the form <U,B> and <U>*)
let addChevron aut=
List.iter (* looping on each state with a cycle *)
(fun state->
List.iter (* looping on each B to add <U,B> and <U>*)
(fun bs ->
let b = Subset.union (Subsets.union bs ) state.oop.Oop.b in
List.iter (* looping on each U*)
(fun u ->
let chevron = Letter.ChevronT (u,b)
and crochet = Letter.CrochetT (u,b)
and inv = Letter.CrochetI (u,b) in
let succ = successor state crochet in
let succ2 = successor succ inv in
add_transition state chevron succ2;
if Subset.is_empty b