ruby-sfst 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1131 @@
1
+
2
+ /*******************************************************************/
3
+ /* */
4
+ /* FILE operators.C */
5
+ /* MODULE operators */
6
+ /* PROGRAM SFST */
7
+ /* AUTHOR Helmut Schmid, IMS, University of Stuttgart */
8
+ /* */
9
+ /*******************************************************************/
10
+
11
+
12
+ #include "fst.h"
13
+
14
+ using std::pair;
15
+ using std::cerr;
16
+
17
+ static void compose_nodes( Node*, Node*, Node*, Transducer*, PairMapping& );
18
+
19
+
20
+ /*******************************************************************/
21
+ /* */
22
+ /* check_cyclicity */
23
+ /* */
24
+ /*******************************************************************/
25
+
26
+ static bool check_cyclicity( Node *node, NodeHashSet &visited,
27
+ const Alphabet &alphabet)
28
+ {
29
+
30
+ if (!visited.insert(node).second)
31
+ return true; // node was visited before
32
+
33
+ for( ArcsIter p(node->arcs()); p; p++ ) {
34
+ Arc *arc=p;
35
+ if (arc->label().upper_is_epsilon())
36
+ if (check_cyclicity(arc->target_node(), visited, alphabet)) {
37
+ cerr << alphabet.write_label(arc->label()) << "\n";
38
+ return true;
39
+ }
40
+ }
41
+ visited.erase(node);
42
+ return false;
43
+ }
44
+
45
+
46
+ /*******************************************************************/
47
+ /* */
48
+ /* Transducer::infinitely_ambiguous_node */
49
+ /* */
50
+ /*******************************************************************/
51
+
52
+ bool Transducer::infinitely_ambiguous_node( Node *node )
53
+
54
+ {
55
+ if (!node->was_visited( vmark )) {
56
+ NodeHashSet visited;
57
+ if (check_cyclicity(node, visited, alphabet))
58
+ return true;
59
+
60
+ // iterate over all outgoing arcs
61
+ for( ArcsIter p(node->arcs()); p; p++ ) {
62
+ Arc *arc=p;
63
+ if (infinitely_ambiguous_node( arc->target_node() ))
64
+ return true;
65
+ }
66
+ }
67
+ return false;
68
+ }
69
+
70
+
71
+ /*******************************************************************/
72
+ /* */
73
+ /* Transducer::is_infinitely_ambiguous */
74
+ /* */
75
+ /*******************************************************************/
76
+
77
+ bool Transducer::is_infinitely_ambiguous()
78
+
79
+ {
80
+ incr_vmark();
81
+ return infinitely_ambiguous_node(root_node());
82
+ }
83
+
84
+
85
+ /*******************************************************************/
86
+ /* */
87
+ /* Transducer::is_cyclic_node */
88
+ /* */
89
+ /*******************************************************************/
90
+
91
+ bool Transducer::is_cyclic_node( Node *node, NodeHashSet &previous )
92
+
93
+ {
94
+ if (!node->was_visited( vmark )) {
95
+ NodeHashSet visited;
96
+
97
+ NodeHashSet::iterator it=previous.insert(node).first;
98
+
99
+ // iterate over all outgoing arcs
100
+ for( ArcsIter p(node->arcs()); p; p++ ) {
101
+ Arc *arc=p;
102
+ if (previous.find(arc->target_node()) != previous.end() ||
103
+ is_cyclic_node( arc->target_node(), previous ))
104
+ return true;
105
+ }
106
+
107
+ previous.erase(it);
108
+ }
109
+ return false;
110
+ }
111
+
112
+
113
+ /*******************************************************************/
114
+ /* */
115
+ /* Transducer::is_cyclic */
116
+ /* */
117
+ /*******************************************************************/
118
+
119
+ bool Transducer::is_cyclic()
120
+
121
+ {
122
+ incr_vmark();
123
+ NodeHashSet previous;
124
+ return is_cyclic_node(root_node(), previous);
125
+ }
126
+
127
+
128
+
129
+ /*******************************************************************/
130
+ /* */
131
+ /* Transducer::is_automaton_node */
132
+ /* */
133
+ /*******************************************************************/
134
+
135
+ bool Transducer::is_automaton_node( Node *node )
136
+
137
+ {
138
+ if (!node->was_visited( vmark )) {
139
+ // iterate over all outgoing arcs
140
+ for( ArcsIter p(node->arcs()); p; p++ ) {
141
+ Arc *arc=p;
142
+ Label l=arc->label();
143
+ if (l.upper_char() != l.lower_char())
144
+ return false;
145
+ if (!is_automaton_node( arc->target_node()))
146
+ return false;
147
+ }
148
+ }
149
+ return true;
150
+ }
151
+
152
+
153
+ /*******************************************************************/
154
+ /* */
155
+ /* Transducer::is_automaton */
156
+ /* */
157
+ /*******************************************************************/
158
+
159
+ bool Transducer::is_automaton()
160
+
161
+ {
162
+ incr_vmark();
163
+ return is_automaton_node(root_node());
164
+ }
165
+
166
+
167
+ /*******************************************************************/
168
+ /* */
169
+ /* Transducer::is_empty */
170
+ /* */
171
+ /*******************************************************************/
172
+
173
+ bool Transducer::is_empty()
174
+
175
+ {
176
+ if (!minimised) {
177
+ Transducer *tmp=&minimise();
178
+ bool result=tmp->is_empty();
179
+ delete tmp;
180
+ return result;
181
+ }
182
+ if (root_node()->is_final())
183
+ return false;
184
+ return root_node()->arcs()->is_empty();
185
+ }
186
+
187
+
188
+ /*******************************************************************/
189
+ /* */
190
+ /* Transducer::generates_empty_string */
191
+ /* */
192
+ /*******************************************************************/
193
+
194
+ bool Transducer::generates_empty_string()
195
+
196
+ {
197
+ if (!minimised) {
198
+ Transducer *tmp=&minimise();
199
+ bool result=tmp->root_node()->is_final();
200
+ delete tmp;
201
+ return result;
202
+ }
203
+ return root_node()->is_final();
204
+ }
205
+
206
+
207
+ /*******************************************************************/
208
+ /* */
209
+ /* Transducer::reverse_node */
210
+ /* */
211
+ /*******************************************************************/
212
+
213
+ void Transducer::reverse_node( Node *node, Transducer *na )
214
+
215
+ {
216
+ if (!node->was_visited( vmark )) {
217
+
218
+ // create a new node
219
+ node->set_forward( na->new_node() );
220
+
221
+ if (node->is_final())
222
+ // add epsilon transition from new root to this node
223
+ na->root_node()->add_arc( Label(), node->forward(), na );
224
+
225
+ // iterate over all outgoing arcs
226
+ for( ArcsIter p(node->arcs()); p; p++ ) {
227
+ Arc *arc=p;
228
+
229
+ // reverse the subgraph headed by the target node
230
+ reverse_node( arc->target_node(), na );
231
+ Node *n = arc->target_node()->forward();
232
+
233
+ // create the reverse arc
234
+ n->add_arc( arc->label(), node->forward(), na );
235
+ }
236
+ }
237
+ }
238
+
239
+
240
+ /*******************************************************************/
241
+ /* */
242
+ /* Transducer::reverse */
243
+ /* */
244
+ /*******************************************************************/
245
+
246
+ Transducer &Transducer::reverse()
247
+
248
+ {
249
+ Transducer *na = new Transducer();
250
+ na->alphabet.copy(alphabet);
251
+
252
+ incr_vmark();
253
+ reverse_node(root_node(), na);
254
+ root_node()->forward()->set_final(1);
255
+ return *na;
256
+ }
257
+
258
+
259
+ /*******************************************************************/
260
+ /* */
261
+ /* Transducer::recode_label */
262
+ /* */
263
+ /*******************************************************************/
264
+
265
+ Label Transducer::recode_label( Label l, bool lswitch, bool recode,
266
+ Alphabet &al )
267
+ {
268
+ if (lswitch)
269
+ l = Label(l.upper_char(), l.lower_char());
270
+
271
+ if (recode) {
272
+ Character lc = al.add_symbol(alphabet.code2symbol(l.lower_char()));
273
+ Character uc = al.add_symbol(alphabet.code2symbol(l.upper_char()));
274
+ l = Label(lc, uc);
275
+ al.insert(l);
276
+ }
277
+
278
+ return l;
279
+ }
280
+
281
+
282
+ /*******************************************************************/
283
+ /* */
284
+ /* Transducer::copy_nodes */
285
+ /* */
286
+ /*******************************************************************/
287
+
288
+ Node *Transducer::copy_nodes( Node *node, Transducer *a,
289
+ bool lswitch, bool recode )
290
+ {
291
+ if (!node->was_visited(vmark)) {
292
+
293
+ node->set_forward(a->new_node());
294
+
295
+ // define final nodes
296
+ if (node->is_final())
297
+ node->forward()->set_final(1);
298
+
299
+ // iterate over all outgoing arcs of node
300
+ for( ArcsIter p(node->arcs()); p; p++ ) {
301
+ Arc *arc=p;
302
+ Node *tn = copy_nodes( arc->target_node(), a, lswitch, recode );
303
+
304
+ // Add a link to the new node
305
+ Label l=recode_label(arc->label(), lswitch, recode, a->alphabet);
306
+ node->forward()->add_arc( l, tn, a );
307
+ }
308
+ }
309
+
310
+ return node->forward();
311
+ }
312
+
313
+
314
+ /*******************************************************************/
315
+ /* */
316
+ /* Transducer::copy */
317
+ /* */
318
+ /*******************************************************************/
319
+
320
+ Transducer &Transducer::copy( bool lswitch, const Alphabet *al )
321
+
322
+ {
323
+ bool recode = false;
324
+ Transducer *na = new Transducer();
325
+ if (al == NULL)
326
+ al = &alphabet;
327
+ else
328
+ recode = true;
329
+
330
+ na->alphabet.utf8 = al->utf8;
331
+ if (lswitch) {
332
+ na->alphabet.insert_symbols(*al);
333
+ for( Alphabet::iterator it=al->begin(); it!=al->end(); it++ ) {
334
+ Character lc=it->lower_char();
335
+ Character uc=it->upper_char();
336
+ na->alphabet.insert(Label(uc,lc));
337
+ }
338
+ }
339
+ else
340
+ na->alphabet.copy(*al);
341
+
342
+ na->deterministic = deterministic;
343
+ na->minimised = minimised;
344
+ na->root_node()->set_final(root_node()->is_final());
345
+ incr_vmark();
346
+
347
+ root_node()->set_forward(na->root_node());
348
+ root_node()->was_visited(vmark);
349
+
350
+ for( ArcsIter p(root_node()->arcs()); p; p++ ) {
351
+ Arc *arc=p;
352
+ Node *target_node=copy_nodes(arc->target_node(), na, lswitch, recode);
353
+ Label l = recode_label(arc->label(), lswitch, recode, na->alphabet);
354
+ na->root_node()->add_arc( l, target_node, na);
355
+ }
356
+
357
+ return *na;
358
+ }
359
+
360
+
361
+ /*******************************************************************/
362
+ /* */
363
+ /* Transducer::operator | */
364
+ /* */
365
+ /*******************************************************************/
366
+
367
+ Transducer &Transducer::operator|( Transducer &a )
368
+
369
+ {
370
+ Transducer *na = new Transducer();
371
+ na->alphabet.copy(alphabet);
372
+ na->alphabet.copy(a.alphabet);
373
+
374
+ incr_vmark();
375
+ na->root_node()->add_arc( Label(), copy_nodes(root_node(), na), na);
376
+ a.incr_vmark();
377
+ na->root_node()->add_arc( Label(), a.copy_nodes(a.root_node(), na), na);
378
+
379
+ return *na;
380
+ }
381
+
382
+
383
+ /*******************************************************************/
384
+ /* */
385
+ /* Transducer::rec_cat_nodes */
386
+ /* */
387
+ /*******************************************************************/
388
+
389
+ void Transducer::rec_cat_nodes( Node *node, Node *node2 )
390
+
391
+ {
392
+ if (!node->was_visited( vmark )) {
393
+
394
+ // iterate over all outgoing arcs of node
395
+ for( ArcsIter p(node->arcs()); p; p++ ) {
396
+ Arc *arc=p;
397
+ rec_cat_nodes( arc->target_node(), node2 );
398
+ }
399
+
400
+ if (node->is_final()) {
401
+ // link this node to node2
402
+ node->set_final(0);
403
+ node->add_arc( Label(), node2, this );
404
+ }
405
+ }
406
+ }
407
+
408
+
409
+ /*******************************************************************/
410
+ /* */
411
+ /* Transducer::operator+ */
412
+ /* */
413
+ /*******************************************************************/
414
+
415
+ Transducer &Transducer::operator+( Transducer &a )
416
+
417
+ {
418
+ Transducer *na = new Transducer();
419
+ na->alphabet.copy(alphabet);
420
+ na->alphabet.copy(a.alphabet);
421
+
422
+ // copy Transducer1 to the new Transducer
423
+ incr_vmark();
424
+ Node *node=copy_nodes(root_node(), na);
425
+ na->root_node()->add_arc( Label(), node, na);
426
+
427
+ // copy Transducer2 to the new Transducer
428
+ a.incr_vmark();
429
+ node=a.copy_nodes(a.root_node(), na);
430
+
431
+ // catenate the two automata
432
+ na->incr_vmark();
433
+ na->rec_cat_nodes(na->root_node(), node);
434
+
435
+ return *na;
436
+ }
437
+
438
+
439
+ /*******************************************************************/
440
+ /* */
441
+ /* Transducer::kleene_star */
442
+ /* */
443
+ /*******************************************************************/
444
+
445
+ Transducer &Transducer::kleene_star()
446
+
447
+ {
448
+ Transducer *na = &copy();
449
+ na->alphabet.copy(alphabet);
450
+
451
+ // link back to the start node
452
+ na->incr_vmark();
453
+ na->rec_cat_nodes(na->root_node(), na->root_node());
454
+ na->root_node()->set_final(1);
455
+
456
+ na->deterministic = na->minimised = false;
457
+
458
+ return *na;
459
+ }
460
+
461
+
462
+ /*******************************************************************/
463
+ /* */
464
+ /* Transducer::negate_nodes */
465
+ /* */
466
+ /*******************************************************************/
467
+
468
+ void Transducer::negate_nodes( Node *node, Node *accept )
469
+
470
+ {
471
+ if (!node->was_visited(vmark)) {
472
+ node->set_final( !node->is_final() );
473
+
474
+ for( ArcsIter p(node->arcs()); p; p++ ) {
475
+ Arc *arc=p;
476
+ negate_nodes( arc->target_node(), accept );
477
+ }
478
+
479
+ for( Alphabet::iterator it=alphabet.begin(); it!=alphabet.end(); it++)
480
+ if (!node->target_node(*it))
481
+ node->add_arc( *it, accept, this );
482
+ }
483
+ }
484
+
485
+
486
+ /*******************************************************************/
487
+ /* */
488
+ /* Transducer::productive_node */
489
+ /* */
490
+ /*******************************************************************/
491
+
492
+ bool Transducer::productive_node( Node *node )
493
+
494
+ {
495
+ if (node->was_visited(vmark))
496
+ return (node->forward() != NULL);
497
+
498
+ bool productive;
499
+ if (node->is_final()) {
500
+ productive = true;
501
+ node->set_forward( node );
502
+ }
503
+ else {
504
+ productive = false;
505
+ node->set_forward( NULL );
506
+ }
507
+
508
+ for( ArcsIter p(node->arcs()); p; p++ ) {
509
+ Arc *arc=p;
510
+ if (productive_node( arc->target_node() ))
511
+ productive = true;
512
+ }
513
+
514
+ if (productive)
515
+ // use forwardp to indicate whether the node is productive
516
+ node->set_forward(node);
517
+ return productive;
518
+ }
519
+
520
+
521
+ /*******************************************************************/
522
+ /* */
523
+ /* Transducer::prune_nodes */
524
+ /* */
525
+ /*******************************************************************/
526
+
527
+ bool Transducer::prune_nodes( Node *node )
528
+
529
+ {
530
+ if (!node->was_visited(vmark)) {
531
+ for( ArcsIter p(node->arcs()); p; p++ ) {
532
+ Arc *arc=p;
533
+ if (prune_nodes( arc->target_node() ))
534
+ node->arcs()->remove_arc(arc);
535
+ }
536
+ if (!node->arcs()->is_empty())
537
+ node->set_forward(node);
538
+ }
539
+ return (node->forward() == NULL);
540
+ }
541
+
542
+
543
+ /*******************************************************************/
544
+ /* */
545
+ /* Transducer::prune */
546
+ /* */
547
+ /*******************************************************************/
548
+
549
+ void Transducer::prune()
550
+
551
+ {
552
+ incr_vmark();
553
+ productive_node( root_node() );
554
+ incr_vmark();
555
+ prune_nodes( root_node() );
556
+ }
557
+
558
+
559
+ /*******************************************************************/
560
+ /* */
561
+ /* Transducer::operator! */
562
+ /* */
563
+ /*******************************************************************/
564
+
565
+ Transducer &Transducer::operator!()
566
+
567
+ {
568
+ Transducer *na;
569
+
570
+ if (alphabet.size() == 0)
571
+ throw "Negation of Transducer with undefined alphabet attempted!";
572
+
573
+ if (minimised)
574
+ na = &copy();
575
+ else
576
+ na = &minimise();
577
+ na->alphabet.copy(alphabet);
578
+
579
+ Node *accept_node=na->new_node();
580
+ accept_node->set_final(1);
581
+ for( Alphabet::iterator it=alphabet.begin(); it!=alphabet.end(); it++)
582
+ accept_node->add_arc( *it, accept_node, na );
583
+
584
+ na->incr_vmark();
585
+ na->negate_nodes( na->root_node(), accept_node );
586
+ //na->prune();
587
+ na->minimised = na->deterministic = false;
588
+
589
+ return *na;
590
+ }
591
+
592
+
593
+ /*******************************************************************/
594
+ /* */
595
+ /* conjoin_nodes */
596
+ /* */
597
+ /*******************************************************************/
598
+
599
+ static void conjoin_nodes( Node *n1, Node *n2, Node *node,
600
+ Transducer *a, PairMapping &map )
601
+
602
+ {
603
+ // if both input nodes are final, so is the new one
604
+ if (n1->is_final() && n2->is_final())
605
+ node->set_final(1);
606
+
607
+ // iterate over all outgoing arcs of the first node
608
+ for( ArcsIter i(n1->arcs()); i; i++ ) {
609
+ Arc *arc=i;
610
+ Label l=arc->label();
611
+ Node *t1 = arc->target_node();
612
+ Node *t2 = n2->target_node(l);
613
+
614
+ // Does the second node have an outgoing arc with the same label?
615
+ if (t2) {
616
+ // Check whether this node pair has been encountered before
617
+ PairMapping::iterator it=map.find(t1, t2);
618
+
619
+ if (it == map.end()) {
620
+ // new node pair
621
+ // create a new node in the conjunction Transducer
622
+ Node *target_node = a->new_node();
623
+ // map the target node pair to the new node
624
+ map[pair<Node*,Node*>(t1,t2)] = target_node;
625
+ // add an arc to the new node
626
+ node->add_arc( l, target_node, a );
627
+ // recursion
628
+ conjoin_nodes( t1, t2, target_node, a, map );
629
+ }
630
+ else {
631
+ // add an arc to the already existing target node
632
+ node->add_arc( l, it->second, a );
633
+ }
634
+ }
635
+ }
636
+ }
637
+
638
+
639
+ /*******************************************************************/
640
+ /* */
641
+ /* Transducer::operator & */
642
+ /* */
643
+ /*******************************************************************/
644
+
645
+ Transducer &Transducer::operator&( Transducer &a )
646
+
647
+ {
648
+ Transducer *tmp1=NULL;
649
+ Transducer *tmp2=NULL;
650
+ Node *r1, *r2;
651
+
652
+ if (deterministic)
653
+ r1 = root_node();
654
+ else {
655
+ tmp1 = &determinise();
656
+ r1 = tmp1->root_node();
657
+ }
658
+
659
+ if (a.deterministic)
660
+ r2 = a.root_node();
661
+ else {
662
+ tmp2 = &a.determinise();
663
+ r2 = tmp2->root_node();
664
+ }
665
+
666
+ PairMapping map;
667
+
668
+ Transducer *na = new Transducer();
669
+ na->alphabet.copy(alphabet);
670
+ na->alphabet.copy(a.alphabet);
671
+
672
+ // map the two root nodes to the new root node
673
+ map[pair<Node*,Node*>(r1, r2)] = na->root_node();
674
+
675
+ // recursively conjoin the two automata
676
+ conjoin_nodes( r1, r2, na->root_node(), na, map);
677
+
678
+ na->deterministic = 1;
679
+ delete tmp1;
680
+ delete tmp2;
681
+
682
+ return *na;
683
+ }
684
+
685
+
686
+ /*******************************************************************/
687
+ /* */
688
+ /* add_composed_node */
689
+ /* */
690
+ /*******************************************************************/
691
+
692
+ static void add_composed_node( Label l, Node *n1, Node *n2, Node *node,
693
+ Transducer *a, PairMapping &map )
694
+
695
+ {
696
+ // Check whether this node pair has been encountered before
697
+ PairMapping::iterator it=map.find(n1, n2);
698
+
699
+ if (it != map.end()) {
700
+ // add an arc to the already existing target node
701
+ node->add_arc( l, it->second, a );
702
+ return;
703
+ }
704
+
705
+ // create a new node in the composed Transducer
706
+ Node *target_node = a->new_node();
707
+
708
+ // map the target node pair to the new node
709
+ map[pair<Node*,Node*>(n1,n2)] = target_node;
710
+
711
+ // add an arc to the new node
712
+ node->add_arc( l, target_node, a );
713
+
714
+ // recursion
715
+ compose_nodes( n1, n2, target_node, a, map );
716
+ }
717
+
718
+
719
+ /*******************************************************************/
720
+ /* */
721
+ /* compose_nodes */
722
+ /* */
723
+ /*******************************************************************/
724
+
725
+ static void compose_nodes( Node *n1, Node *n2, Node *node,
726
+ Transducer *a, PairMapping &map )
727
+ {
728
+ // if both input nodes are final, so is the new one
729
+ if (n1->is_final() && n2->is_final())
730
+ node->set_final(1);
731
+
732
+ // iterate over all outgoing arcs of the first node
733
+ for( ArcsIter i(n1->arcs()); i; i++ ) {
734
+ Arc *arc1=i;
735
+ Node *t1 = arc1->target_node();
736
+ Label l1=arc1->label();
737
+ Character uc1=l1.upper_char();
738
+ Character lc1=l1.lower_char();
739
+
740
+ if (uc1 == Label::epsilon)
741
+ add_composed_node( l1, t1, n2, node, a, map );
742
+
743
+ else {
744
+ for( ArcsIter k(n2->arcs()); k; k++ ) {
745
+ Arc *arc2=k;
746
+ Node *t2 = arc2->target_node();
747
+ Label l2=arc2->label();
748
+ Character lc2=l2.lower_char();
749
+ Character uc2=l2.upper_char();
750
+
751
+ if (uc1 == lc2)
752
+ add_composed_node( Label(lc1,uc2), t1, t2, node, a, map );
753
+ }
754
+ }
755
+ }
756
+
757
+ // epsilon input characters of the second Transducer
758
+ for( ArcsIter i(n2->arcs()); i; i++ ) {
759
+ Arc *arc=i;
760
+ Node *t = arc->target_node();
761
+ Label l=arc->label();
762
+ Character lc=l.lower_char();
763
+
764
+ if (lc == Label::epsilon)
765
+ add_composed_node( l, n1, t, node, a, map );
766
+ }
767
+ }
768
+
769
+
770
+ /*******************************************************************/
771
+ /* */
772
+ /* Transducer::operator || */
773
+ /* */
774
+ /*******************************************************************/
775
+
776
+ Transducer &Transducer::operator||( Transducer &a )
777
+
778
+ {
779
+ PairMapping map;
780
+
781
+ Transducer *na = new Transducer();
782
+ na->alphabet.compose(alphabet, a.alphabet);
783
+
784
+ // map the two root nodes to the new root node
785
+ map[pair<Node*,Node*>(root_node(), a.root_node())] = na->root_node();
786
+
787
+ // recursively compose the two automata
788
+ compose_nodes( root_node(), a.root_node(), na->root_node(), na, map );
789
+
790
+ return *na;
791
+ }
792
+
793
+
794
+
795
+ /*******************************************************************/
796
+ /* */
797
+ /* Transducer::operator / */
798
+ /* */
799
+ /*******************************************************************/
800
+
801
+ Transducer &Transducer::operator/( Transducer &a )
802
+
803
+ {
804
+ complete_alphabet();
805
+ a.alphabet.copy(alphabet);
806
+ Transducer *a1 = &(!a);
807
+ Transducer *a2 = &(*this & *a1);
808
+ delete a1;
809
+ return *a2;
810
+ }
811
+
812
+
813
+ /*******************************************************************/
814
+ /* */
815
+ /* Transducer::compare_nodes */
816
+ /* */
817
+ /*******************************************************************/
818
+
819
+ bool Transducer::compare_nodes( Node *node, Node *node2, Transducer &a2 )
820
+
821
+ {
822
+ if (node->was_visited( vmark )) {
823
+ if (node2->was_visited( a2.vmark ))
824
+ return (node->forward() == node2 && node2->forward() == node);
825
+ else
826
+ return false;
827
+ }
828
+ else if (node2->was_visited( a2.vmark ))
829
+ return false;
830
+
831
+ node->set_forward( node2 );
832
+ node2->set_forward( node );
833
+
834
+ if (node->is_final() != node2->is_final())
835
+ return false;
836
+
837
+ // iterate over all outgoing arcs
838
+ for( ArcsIter p(node->arcs()); p; p++ ) {
839
+ Arc *arc=p;
840
+ Node *t2=node2->target_node(arc->label());
841
+
842
+ if (t2 == NULL)
843
+ return false;
844
+ else if (!compare_nodes(arc->target_node(), t2, a2))
845
+ return false;
846
+ }
847
+ for( ArcsIter p(node2->arcs()); p; p++ ) {
848
+ Arc *arc=p;
849
+ if (node->target_node(arc->label()) == NULL)
850
+ return false;
851
+ }
852
+
853
+ return true;
854
+ }
855
+
856
+
857
+ /*******************************************************************/
858
+ /* */
859
+ /* Transducer::operator == */
860
+ /* */
861
+ /*******************************************************************/
862
+
863
+ bool Transducer::operator==( Transducer &a )
864
+
865
+ {
866
+ Transducer *p1 = (minimised)? this: &minimise();
867
+ Transducer *p2 = (a.minimised)? &a: &a.minimise();
868
+
869
+ p1->incr_vmark();
870
+ p2->incr_vmark();
871
+ bool result = p1->compare_nodes(p1->root_node(), p2->root_node(), *p2 );
872
+
873
+ if (p1 != this) delete p1;
874
+ if (p2 != &a) delete p2;
875
+
876
+ return result;
877
+ }
878
+
879
+
880
+
881
+ /*******************************************************************/
882
+ /* */
883
+ /* Transducer::map_nodes */
884
+ /* */
885
+ /*******************************************************************/
886
+
887
+ void Transducer::map_nodes( Node *node, Node *node2, Transducer *a, Level level)
888
+
889
+ {
890
+ if (!node->was_visited(vmark)) {
891
+
892
+ node->set_forward(node2);
893
+
894
+ // define final nodes
895
+ if (node->is_final())
896
+ node2->set_final(1);
897
+
898
+ // iterate over all outgoing arcs of node
899
+ for( ArcsIter p(node->arcs()); p; p++ ) {
900
+ Arc *arc=p;
901
+ Label l(arc->label().get_char(level));
902
+ Node *t2=NULL, *t=arc->target_node();
903
+
904
+ if (t->check_visited(vmark))
905
+ t2 = t->forward();
906
+ else
907
+ t2 = a->new_node(); // create a new node
908
+
909
+ node2->add_arc(l, t2, a); // add a link to the node
910
+
911
+ map_nodes( t, t2, a, level );
912
+ }
913
+ }
914
+ }
915
+
916
+
917
+ /*******************************************************************/
918
+ /* */
919
+ /* Transducer::level */
920
+ /* */
921
+ /*******************************************************************/
922
+
923
+ Transducer &Transducer::level( Level level )
924
+
925
+ {
926
+ Transducer *na = new Transducer();
927
+
928
+ for( Alphabet::iterator it=alphabet.begin(); it!=alphabet.end(); it++ ) {
929
+ Character c = it->get_char(level);
930
+ if (alphabet.code2symbol(c) != NULL)
931
+ na->alphabet.add_symbol( alphabet.code2symbol(c), c );
932
+ na->alphabet.insert(Label(c));
933
+ }
934
+
935
+ incr_vmark();
936
+ map_nodes(root_node(), na->root_node(), na, level );
937
+
938
+ return *na;
939
+ }
940
+
941
+
942
+ /*******************************************************************/
943
+ /* */
944
+ /* Transducer::freely_insert_at_node */
945
+ /* */
946
+ /*******************************************************************/
947
+
948
+ void Transducer::freely_insert_at_node( Node *node, Label l )
949
+
950
+ {
951
+ if (!node->was_visited(vmark)) {
952
+ node->add_arc(l, node, this); // add a recursive link labelled with l
953
+
954
+ // iterate over all outgoing arcs of node
955
+ for( ArcsIter p(node->arcs()); p; p++ ) {
956
+ Arc *arc=p;
957
+ freely_insert_at_node(arc->target_node(), l );
958
+ }
959
+ }
960
+ }
961
+
962
+
963
+ /*******************************************************************/
964
+ /* */
965
+ /* Transducer::freely_insert */
966
+ /* */
967
+ /*******************************************************************/
968
+
969
+ Transducer &Transducer::freely_insert( Label l )
970
+
971
+ {
972
+ Transducer *na = &copy();
973
+
974
+ na->incr_vmark();
975
+ na->freely_insert_at_node(na->root_node(), l );
976
+
977
+ return *na;
978
+ }
979
+
980
+
981
+ /*******************************************************************/
982
+ /* */
983
+ /* Transducer::splice_arc */
984
+ /* */
985
+ /*******************************************************************/
986
+
987
+ void Transducer::splice_arc( Node *node, Node *node2, Node *next_node,
988
+ Transducer *a )
989
+ {
990
+ if (node->is_final()) {
991
+ // link final node to the next node
992
+ node2->add_arc( Label(), next_node, a );
993
+ return;
994
+ }
995
+
996
+ // iterate over the outgoing arcs
997
+ for( ArcsIter p(node->arcs()); p; p++ ) {
998
+ Arc *arc=p;
999
+ Node *tn=a->new_node();
1000
+
1001
+ node2->add_arc( arc->label(), tn, a );
1002
+ splice_arc( arc->target_node(), tn, next_node, a );
1003
+ }
1004
+ }
1005
+
1006
+
1007
+ /*******************************************************************/
1008
+ /* */
1009
+ /* Transducer::splice_nodes */
1010
+ /* */
1011
+ /*******************************************************************/
1012
+
1013
+ void Transducer::splice_nodes(Node *node, Node *node2, Label sl,
1014
+ Transducer *sa, Transducer *a)
1015
+ {
1016
+ if (!node->was_visited(vmark)) {
1017
+
1018
+ node->set_forward(node2);
1019
+
1020
+ // define final nodes
1021
+ if (node->is_final())
1022
+ node2->set_final(1);
1023
+
1024
+ // iterate over all outgoing arcs of node
1025
+ for( ArcsIter p(node->arcs()); p; p++ ) {
1026
+ Arc *arc=p;
1027
+ Node *t2=NULL, *t=arc->target_node();
1028
+
1029
+ if (t->check_visited(vmark))
1030
+ t2 = t->forward();
1031
+ else
1032
+ t2 = a->new_node(); // create a new node
1033
+
1034
+ if (arc->label() == sl)
1035
+ // insert the transducer
1036
+ splice_arc(sa->root_node(), node2, t2, a);
1037
+ else
1038
+ // add a link to the node
1039
+ node2->add_arc(arc->label(), t2, a);
1040
+
1041
+ splice_nodes( t, t2, sl, sa, a );
1042
+ }
1043
+ }
1044
+ }
1045
+
1046
+
1047
+ /*******************************************************************/
1048
+ /* */
1049
+ /* Transducer::splice */
1050
+ /* */
1051
+ /*******************************************************************/
1052
+
1053
+ Transducer &Transducer::splice( Label sl, Transducer *sa )
1054
+
1055
+ {
1056
+ Alphabet::iterator it;
1057
+
1058
+ Transducer *na = new Transducer();
1059
+
1060
+ for( it=alphabet.begin(); it!=alphabet.end(); it++ ) {
1061
+ Label l = *it;
1062
+ if (l != sl)
1063
+ na->alphabet.insert(l);
1064
+ }
1065
+ for( it=sa->alphabet.begin(); it!=sa->alphabet.end(); it++ )
1066
+ na->alphabet.insert(*it);
1067
+
1068
+ incr_vmark();
1069
+ splice_nodes(root_node(), na->root_node(), sl, sa, na );
1070
+
1071
+ return *na;
1072
+ }
1073
+
1074
+
1075
+ /*******************************************************************/
1076
+ /* */
1077
+ /* Transducer::replace_char */
1078
+ /* */
1079
+ /*******************************************************************/
1080
+
1081
+ Transducer &Transducer::replace_char( Character c, Character nc )
1082
+
1083
+ {
1084
+ Alphabet::iterator it;
1085
+
1086
+ Transducer *na = new Transducer();
1087
+
1088
+ for( it=alphabet.begin(); it!=alphabet.end(); it++ ) {
1089
+ Label l = *it;
1090
+ na->alphabet.insert(l.replace_char(c,nc));
1091
+ }
1092
+
1093
+ incr_vmark();
1094
+ replace_char2(root_node(), na->root_node(), c, nc, na );
1095
+
1096
+ return *na;
1097
+ }
1098
+
1099
+
1100
+ /*******************************************************************/
1101
+ /* */
1102
+ /* Transducer::replace_char2 */
1103
+ /* */
1104
+ /*******************************************************************/
1105
+
1106
+ void Transducer::replace_char2(Node *node, Node *node2, Character c,
1107
+ Character nc, Transducer *a)
1108
+ {
1109
+ if (!node->was_visited(vmark)) {
1110
+
1111
+ node->set_forward(node2);
1112
+
1113
+ // define final nodes
1114
+ if (node->is_final())
1115
+ node2->set_final(1);
1116
+
1117
+ // iterate over all outgoing arcs of node
1118
+ for( ArcsIter p(node->arcs()); p; p++ ) {
1119
+ Arc *arc=p;
1120
+ Node *t2=NULL, *t=arc->target_node();
1121
+
1122
+ if (t->check_visited(vmark))
1123
+ t2 = t->forward();
1124
+ else
1125
+ t2 = a->new_node(); // create a new node
1126
+
1127
+ node2->add_arc(arc->label().replace_char(c, nc), t2, a);
1128
+ replace_char2( t, t2, c, nc, a );
1129
+ }
1130
+ }
1131
+ }