1 package org.thegalactic.rule;
2
3
4
5
6
7
8
9
10
11
12
13
14 import java.io.IOException;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.Iterator;
18 import java.util.SortedSet;
19 import java.util.StringTokenizer;
20 import java.util.TreeMap;
21 import java.util.TreeSet;
22
23 import org.thegalactic.dgraph.ConcreteDGraph;
24 import org.thegalactic.dgraph.Edge;
25 import org.thegalactic.dgraph.Node;
26 import org.thegalactic.io.Filer;
27 import org.thegalactic.lattice.ClosureSystem;
28 import org.thegalactic.lattice.io.ImplicationalSystemIOFactory;
29 import org.thegalactic.util.ComparableSet;
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 public class ImplicationalSystem extends ClosureSystem {
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 public static ImplicationalSystem random(int nbS, int nbR) {
88 ImplicationalSystem sigma = new ImplicationalSystem();
89
90 for (int i = 0; i < nbS; i++) {
91 sigma.addElement(Integer.valueOf(i));
92 }
93
94
95 while (sigma.getRules().size() < nbR) {
96 ComparableSet conclusion = new ComparableSet();
97 int choice = (int) Math.rint(nbS * Math.random());
98 int j = 1;
99 for (Comparable c : sigma.getSet()) {
100 if (j == choice) {
101 conclusion.add(c);
102 }
103 j++;
104 }
105 ComparableSet premisse = new ComparableSet();
106 for (Comparable c : sigma.getSet()) {
107 choice = (int) Math.rint(nbS * Math.random());
108 if (choice < nbS / 5) {
109 premisse.add(c);
110 }
111 }
112
113 sigma.addRule(new Rule(premisse, conclusion));
114
115 }
116 return sigma;
117 }
118
119
120
121
122 private TreeSet<Rule> sigma;
123
124
125
126
127 private TreeSet<Comparable> set;
128
129
130
131
132
133
134
135 public ImplicationalSystem() {
136 this.init();
137 }
138
139
140
141
142
143
144 public ImplicationalSystem(Collection<Rule> sigma) {
145 this.sigma = new TreeSet<Rule>(sigma);
146 this.set = new TreeSet<Comparable>();
147 for (Rule rule : this.sigma) {
148 set.addAll(rule.getPremise());
149 set.addAll(rule.getConclusion());
150 }
151 }
152
153
154
155
156
157
158
159
160
161 public ImplicationalSystem(ImplicationalSystem is) {
162 this.sigma = new TreeSet<Rule>(is.getRules());
163 this.set = new TreeSet<Comparable>(is.getSet());
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 public ImplicationalSystem(String filename) throws IOException {
189 this.parse(filename);
190 }
191
192
193
194
195
196
197 public ImplicationalSystem init() {
198 this.sigma = new TreeSet<Rule>();
199 this.set = new TreeSet<Comparable>();
200 return this;
201 }
202
203
204
205
206
207
208
209
210
211 public SortedSet<Rule> getRules() {
212 return Collections.unmodifiableSortedSet((SortedSet<Rule>) this.sigma);
213 }
214
215
216
217
218
219
220 public SortedSet<Comparable> getSet() {
221 return Collections.unmodifiableSortedSet((SortedSet<Comparable>) this.set);
222 }
223
224
225
226
227
228
229 public int sizeElements() {
230 return this.set.size();
231 }
232
233
234
235
236
237
238 public int sizeRules() {
239 return this.sigma.size();
240 }
241
242
243
244
245
246
247
248
249
250
251
252 public boolean addElement(Comparable e) {
253 return set.add(e);
254 }
255
256
257
258
259
260
261
262
263 public boolean addAllElements(TreeSet<Comparable> x) {
264 boolean all = true;
265 for (Comparable e : x) {
266 if (!set.add(e)) {
267 all = false;
268 }
269 }
270 return all;
271 }
272
273
274
275
276
277
278
279
280
281 public boolean deleteElement(Comparable e) {
282 if (set.contains(e)) {
283 set.remove(e);
284 ImplicationalSystem save = new ImplicationalSystem(this);
285 for (Rule rule : save.sigma) {
286 Rule newR = new Rule(rule.getPremise(), rule.getConclusion());
287 newR.removeFromPremise(e);
288 newR.removeFromConclusion(e);
289 if (!rule.equals(newR)) {
290 if (newR.getConclusion().size() != 0) {
291 this.replaceRule(rule, newR);
292 } else {
293 this.removeRule(rule);
294 }
295 }
296 }
297 return true;
298 }
299 return false;
300 }
301
302
303
304
305
306
307
308
309
310 public boolean checkRuleElements(Rule rule) {
311 for (Object e : rule.getPremise()) {
312 if (!set.contains(e)) {
313 return false;
314 }
315 }
316 for (Object e : rule.getConclusion()) {
317 if (!set.contains(e)) {
318 return false;
319 }
320 }
321 return true;
322 }
323
324
325
326
327
328
329
330
331
332
333 public boolean containsRule(Rule rule) {
334 return this.sigma.contains(rule);
335 }
336
337
338
339
340
341
342
343
344 public boolean addRule(Rule rule) {
345 if (!this.containsRule(rule) && this.checkRuleElements(rule)) {
346 return this.sigma.add(rule);
347 }
348 return false;
349 }
350
351
352
353
354
355
356
357
358 public boolean removeRule(Rule rule) {
359 return this.sigma.remove(rule);
360 }
361
362
363
364
365
366
367
368
369
370 public boolean replaceRule(Rule rule1, Rule rule2) {
371 return this.removeRule(rule1) && this.addRule(rule2);
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 @Override
397 public String toString() {
398 StringBuilder s = new StringBuilder();
399
400
401
402 for (Comparable e : this.set) {
403 StringTokenizer st = new StringTokenizer(e.toString());
404 while (st.hasMoreTokens()) {
405 s.append(st.nextToken());
406 }
407 s.append(" ");
408 }
409 String newLine = System.getProperty("line.separator");
410 s.append(newLine);
411
412
413 for (Rule rule : this.sigma) {
414 s.append(rule.toString()).append(newLine);
415 }
416 return s.toString();
417 }
418
419
420
421
422
423
424
425
426 public void save(final String filename) throws IOException {
427 Filer.getInstance().save(this, ImplicationalSystemIOFactory.getInstance(), filename);
428 }
429
430
431
432
433
434
435
436
437
438
439
440 public ImplicationalSystem parse(final String filename) throws IOException {
441 this.init();
442 Filer.getInstance().parse(this, ImplicationalSystemIOFactory.getInstance(), filename);
443 return this;
444 }
445
446
447
448
449
450
451
452
453
454
455
456
457 public boolean isProper() {
458 for (Rule rule : this.sigma) {
459 for (Object c : rule.getConclusion()) {
460 if (rule.getPremise().contains(c)) {
461 return false;
462 }
463 }
464 }
465 return true;
466 }
467
468
469
470
471
472
473
474
475 public boolean isUnary() {
476 for (Rule rule : this.sigma) {
477 if (rule.getConclusion().size() > 1) {
478 return false;
479 }
480 }
481 return true;
482 }
483
484
485
486
487
488
489
490
491
492 public boolean isCompact() {
493 for (Rule rule1 : this.sigma) {
494 for (Rule rule2 : this.sigma) {
495 if (!rule1.equals(rule2) && rule1.getPremise().equals(rule2.getPremise())) {
496 return false;
497 }
498 }
499 }
500 return true;
501 }
502
503
504
505
506
507
508
509
510 public boolean isRightMaximal() {
511 for (Rule rule : this.sigma) {
512 if (!rule.getConclusion().containsAll(this.closure(rule.getConclusion()))) {
513 return false;
514 }
515 }
516 return true;
517 }
518
519
520
521
522
523
524
525
526
527 public boolean isLeftMinimal() {
528 for (Rule rule1 : this.sigma) {
529 for (Rule rule2 : this.sigma) {
530 if (!rule1.equals(rule2)
531 && rule1.getPremise().containsAll(rule2.getPremise())
532 && rule1.getConclusion().equals(rule2.getConclusion())) {
533 return false;
534 }
535 }
536 }
537 return true;
538 }
539
540
541
542
543
544
545
546
547
548
549 public boolean isDirect() {
550 for (Rule rule1 : this.sigma) {
551 TreeSet<Comparable> onePass = new TreeSet(rule1.getPremise());
552 for (Rule rule2 : this.sigma) {
553 if (rule1.getPremise().containsAll(rule2.getPremise())) {
554 onePass.addAll(rule2.getConclusion());
555 }
556 }
557 if (!onePass.equals(this.closure(rule1.getPremise()))) {
558 return false;
559 }
560 }
561 return true;
562 }
563
564
565
566
567
568
569
570
571
572
573 public boolean isMinimum() {
574 ImplicationalSystem tmp = new ImplicationalSystem(this);
575 tmp.makeRightMaximal();
576 for (Rule rule : sigma) {
577 ImplicationalSystem epsilon = new ImplicationalSystem(tmp);
578 epsilon.removeRule(rule);
579 TreeSet<Comparable> clThis = this.closure(rule.getPremise());
580 TreeSet<Comparable> clEpsilon = epsilon.closure(rule.getPremise());
581 if (clThis.equals(clEpsilon)) {
582 return false;
583 }
584 }
585 return true;
586 }
587
588
589
590
591
592
593
594
595
596
597
598
599
600 public boolean isCanonicalDirectBasis() {
601 ImplicationalSystem cdb = new ImplicationalSystem(this);
602 cdb.makeCanonicalDirectBasis();
603 return this.isIncludedIn(cdb) && cdb.isIncludedIn(this);
604 }
605
606
607
608
609
610
611
612
613
614
615
616 public boolean isCanonicalBasis() {
617 ImplicationalSystem cb = new ImplicationalSystem(this);
618 cb.makeCanonicalBasis();
619 return this.isIncludedIn(cb) && cb.isIncludedIn(this);
620 }
621
622
623
624
625
626
627
628
629
630 public boolean isIncludedIn(ImplicationalSystem is) {
631 ImplicationalSystem tmp = new ImplicationalSystem(this);
632 tmp.makeProper();
633 tmp.makeUnary();
634 is.makeProper();
635 is.makeUnary();
636 for (Rule rule : tmp.sigma) {
637 if (!is.containsRule(rule)) {
638 return false;
639 }
640 }
641 return true;
642 }
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659 public int makeProper() {
660 ImplicationalSystem save = new ImplicationalSystem(this);
661 for (Rule rule : save.sigma) {
662
663 Rule newR = new Rule(rule.getPremise(), rule.getConclusion());
664 for (Object e : rule.getConclusion()) {
665 if (newR.getPremise().contains(e)) {
666 newR.removeFromConclusion(e);
667 }
668 }
669
670 if (!rule.equals(newR)) {
671 this.replaceRule(rule, newR);
672 }
673
674 if (newR.getConclusion().isEmpty()) {
675 this.removeRule(newR);
676 }
677 }
678 return save.sizeRules() - this.sizeRules();
679 }
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694 public int makeUnary() {
695 ImplicationalSystem save = new ImplicationalSystem(this);
696 for (Rule rule : save.sigma) {
697 if (rule.getConclusion().size() > 1) {
698 this.removeRule(rule);
699 TreeSet<Comparable> conclusion = rule.getConclusion();
700 TreeSet<Comparable> premise = rule.getPremise();
701 for (Comparable e : conclusion) {
702 TreeSet<Comparable> newC = new TreeSet();
703 newC.add(e);
704 Rule newRule = new Rule(premise, newC);
705 this.addRule(newRule);
706 }
707 }
708 }
709 return save.sizeRules() - this.sizeRules();
710 }
711
712
713
714
715
716
717
718
719
720 public int makeCompact() {
721 ImplicationalSystem save = new ImplicationalSystem(this);
722 int before = this.sigma.size();
723 this.sigma = new TreeSet();
724
725 while (save.sigma.size() > 0) {
726 Rule rule1 = save.sigma.first();
727 ComparableSet newConc = new ComparableSet();
728 Iterator<Rule> it2 = save.sigma.iterator();
729 while (it2.hasNext()) {
730 Rule rule2 = it2.next();
731 if (!rule1.equals(rule2) && rule1.getPremise().equals(rule2.getPremise())) {
732 newConc.addAll(rule2.getConclusion());
733 it2.remove();
734 }
735 }
736 if (newConc.size() > 0) {
737 newConc.addAll(rule1.getConclusion());
738 Rule newR = new Rule(rule1.getPremise(), newConc);
739 this.addRule(newR);
740 } else {
741 this.addRule(rule1);
742 }
743 save.removeRule(rule1);
744 }
745 return before - this.sigma.size();
746 }
747
748
749
750
751
752
753
754
755
756
757 public int makeCompactAssociation() {
758 ImplicationalSystem save = new ImplicationalSystem(this);
759 int before = this.sigma.size();
760 this.sigma = new TreeSet();
761
762 while (save.sigma.size() > 0) {
763 AssociationRule rule1 = (AssociationRule) save.sigma.first();
764 ComparableSet newConc = new ComparableSet();
765 Iterator<Rule> it2 = save.sigma.iterator();
766 while (it2.hasNext()) {
767 AssociationRule rule2 = (AssociationRule) it2.next();
768 if (!rule1.equals(rule2) && rule1.getPremise().equals(rule2.getPremise())
769 && rule1.getConfidence() == rule2.getConfidence() && rule1.getSupport() == rule2.getSupport()) {
770 newConc.addAll(rule2.getConclusion());
771 it2.remove();
772 }
773 }
774 if (newConc.size() > 0) {
775 newConc.addAll(rule1.getConclusion());
776 AssociationRule newR = new AssociationRule(rule1.getPremise(), newConc, rule1.getSupport(), rule1.getConfidence());
777 this.addRule(newR);
778 } else {
779 this.addRule(rule1);
780 }
781 save.removeRule(rule1);
782 }
783 return before - this.sigma.size();
784 }
785
786
787
788
789
790
791
792
793
794
795 public int makeRightMaximal() {
796 int s = this.sizeRules();
797 this.makeCompact();
798 ImplicationalSystem save = new ImplicationalSystem(this);
799 for (Rule rule : save.sigma) {
800 Rule newR = new Rule(rule.getPremise(), this.closure(rule.getPremise()));
801 if (!rule.equals(newR)) {
802 this.replaceRule(rule, newR);
803 }
804 }
805 return s - this.sizeRules();
806 }
807
808
809
810
811
812
813
814
815
816
817
818
819
820 public int makeLeftMinimal() {
821 this.makeUnary();
822 ImplicationalSystem save = new ImplicationalSystem(this);
823 for (Rule rule1 : save.sigma) {
824 for (Rule rule2 : save.sigma) {
825 if (!rule1.equals(rule2)
826 && rule2.getPremise().containsAll(rule1.getPremise())
827 && rule1.getConclusion().equals(rule2.getConclusion())) {
828 this.sigma.remove(rule2);
829 }
830 }
831 }
832 this.makeCompact();
833 return save.sizeRules() - this.sizeRules();
834 }
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853 public int makeDirect() {
854 this.makeUnary();
855 this.makeProper();
856 int s = this.sizeRules();
857 boolean ok = true;
858 while (ok) {
859 ImplicationalSystem save = new ImplicationalSystem(this);
860 for (Rule rule1 : save.sigma) {
861 for (Rule rule2 : save.sigma) {
862 if (!rule1.equals(rule2) && !rule1.getPremise().containsAll(rule2.getConclusion())) {
863 ComparableSet c = new ComparableSet(rule2.getPremise());
864 c.removeAll(rule1.getConclusion());
865 c.addAll(rule1.getPremise());
866 if (!c.containsAll(rule2.getPremise())) {
867 Rule newR = new Rule(c, rule2.getConclusion());
868
869
870
871
872 this.addRule(newR);
873 }
874 }
875 }
876 }
877 if (this.sizeRules() == save.sizeRules()) {
878 ok = false;
879 }
880 }
881 this.makeCompact();
882 return s - this.sizeRules();
883 }
884
885
886
887
888
889
890
891
892
893
894
895
896
897 public int makeMinimum() {
898 this.makeRightMaximal();
899 ImplicationalSystem save = new ImplicationalSystem(this);
900 for (Rule rule : save.sigma) {
901 ImplicationalSystem epsilon = new ImplicationalSystem(this);
902 epsilon.removeRule(rule);
903 if (epsilon.closure(rule.getPremise()).equals(this.closure(rule.getPremise()))) {
904 this.removeRule(rule);
905 }
906 }
907 return save.sizeRules() - this.sizeRules();
908 }
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924 public int makeCanonicalDirectBasis() {
925 int s = this.sizeRules();
926 this.makeProper();
927 this.makeLeftMinimal();
928 this.makeDirect();
929 this.makeLeftMinimal();
930 this.makeCompact();
931 return s - this.sizeRules();
932 }
933
934
935
936
937
938
939
940
941
942
943
944
945 public int makeCanonicalBasis() {
946 this.makeMinimum();
947 ImplicationalSystem save = new ImplicationalSystem(this);
948 for (Rule rule : save.sigma) {
949 ImplicationalSystem epsilon = new ImplicationalSystem(this);
950 epsilon.removeRule(rule);
951 Rule tmp = new Rule(epsilon.closure(rule.getPremise()), rule.getConclusion());
952 if (!rule.equals(tmp)) {
953 this.replaceRule(rule, tmp);
954 }
955 }
956 this.makeProper();
957 return save.sizeRules() - this.sizeRules();
958 }
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973 public ConcreteDGraph representativeGraph() {
974 ImplicationalSystem tmp = new ImplicationalSystem(this);
975 tmp.makeUnary();
976
977 ConcreteDGraph pred = new ConcreteDGraph();
978 TreeMap<Comparable, Node> nodeCreated = new TreeMap<Comparable, Node>();
979 for (Comparable x : tmp.getSet()) {
980 Node node = new Node(x);
981 pred.addNode(node);
982 nodeCreated.put(x, node);
983 }
984
985 for (Rule rule : tmp.getRules()) {
986 for (Object a : rule.getPremise()) {
987 ComparableSet diff = new ComparableSet(rule.getPremise());
988 diff.remove(a);
989 Node source = nodeCreated.get(rule.getConclusion().first());
990 Node target = nodeCreated.get(a);
991 Edge ed;
992 if (pred.containsEdge(source, target)) {
993 ed = pred.getEdge(source, target);
994 } else {
995 ed = new Edge(source, target, new TreeSet<ComparableSet>());
996 pred.addEdge(ed);
997 }
998 ((TreeSet<ComparableSet>) ed.getContent()).add(diff);
999 }
1000 }
1001 return pred;
1002 }
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 public ConcreteDGraph dependencyGraph() {
1017 ImplicationalSystem bcd = new ImplicationalSystem(this);
1018 bcd.makeCanonicalDirectBasis();
1019 bcd.makeUnary();
1020 return bcd.representativeGraph();
1021 }
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033 public TreeMap<Comparable, TreeSet<Comparable>> reduction() {
1034
1035 TreeMap red = this.getReducibleElements();
1036
1037 TreeSet<Comparable> truth = this.closure(new TreeSet<Comparable>());
1038
1039 for (Object x : red.keySet()) {
1040 TreeSet<Rule> rules = this.sigma;
1041 rules = (TreeSet<Rule>) rules.clone();
1042 for (Rule rule : rules) {
1043 Rule rule2 = new Rule();
1044 boolean modif = false;
1045
1046 TreeSet premise = rule.getPremise();
1047 premise = (TreeSet) premise.clone();
1048 if (premise.contains(x)) {
1049 premise.remove(x);
1050 premise.addAll((TreeSet) red.get(x));
1051 rule2.addAllToPremise(premise);
1052 modif = true;
1053 } else {
1054 rule2.addAllToPremise(premise);
1055 }
1056
1057 TreeSet conclusion = rule.getConclusion();
1058 conclusion = (TreeSet) conclusion.clone();
1059 if (conclusion.contains(x)) {
1060 conclusion.remove(x);
1061 conclusion.addAll((TreeSet) red.get(x));
1062 rule2.addAllToConclusion(conclusion);
1063 modif = true;
1064 } else {
1065 rule2.addAllToConclusion(conclusion);
1066 }
1067
1068 if (modif) {
1069 if (truth.containsAll(rule2.getConclusion())) {
1070 this.removeRule(rule);
1071 } else {
1072 this.replaceRule(rule, rule2);
1073 }
1074 } else if (truth.containsAll(rule.getConclusion())) {
1075 this.removeRule(rule);
1076 }
1077 }
1078
1079 this.deleteElement((Comparable) x);
1080 }
1081 return red;
1082 }
1083
1084
1085
1086
1087
1088
1089 public boolean isReduced() {
1090
1091 ImplicationalSystem tmp = new ImplicationalSystem(this);
1092 return tmp.reduction().isEmpty();
1093 }
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116 public TreeSet<Comparable> closure(TreeSet<Comparable> x) {
1117 TreeSet<Comparable> oldES = new TreeSet<Comparable>();
1118
1119 TreeSet<Comparable> newES = new TreeSet<Comparable>(x);
1120 do {
1121 oldES.addAll(newES);
1122 for (Rule rule : this.sigma) {
1123 if (newES.containsAll(rule.getPremise()) || rule.getPremise().isEmpty()) {
1124 newES.addAll(rule.getConclusion());
1125 }
1126 }
1127 } while (!oldES.equals(newES));
1128 return newES;
1129 }
1130 }