|
| 1 | +(** Epsilonsulundi näide "Introduction to Compiler Design" õpikust, peatükk 1.5.1. *) |
| 2 | +open OUnit2 |
| 3 | +open Fixpoint |
| 4 | + |
| 5 | +module IntSet = |
| 6 | +struct |
| 7 | + include Set.Make (Int) (* Taaskasutame standardset hulga moodulit. *) |
| 8 | + (* Aga lisame mõne funktsiooni juurde. *) |
| 9 | + |
| 10 | + let show is = [%show: int list] (elements is) |
| 11 | +end |
| 12 | + |
| 13 | +(** Epsilonsammude funktsioon, joonis 1.5. *) |
| 14 | +let nfa_eps = function |
| 15 | + | 1 -> [2; 5] |
| 16 | + | 5 -> [6; 7] |
| 17 | + | 8 -> [1] |
| 18 | + | _ -> [] |
| 19 | + |
| 20 | +(** Epsilonsammude funktsioon hulgal. *) |
| 21 | +let nfa_eps_set states = |
| 22 | + IntSet.elements states |
| 23 | + |> List.concat_map nfa_eps |
| 24 | + |> IntSet.of_list |
| 25 | + |
| 26 | +module IntSetFP = MakeSet (IntSet) |
| 27 | + |
| 28 | +let assert_equal = assert_equal ~cmp:IntSet.equal ~printer:IntSet.show |
| 29 | + |
| 30 | +(** Generaatorid omaduspõhiseks testimiseks. *) |
| 31 | +let arbitrary_state = QCheck.int_range 1 10 |
| 32 | +let arbitrary_states = QCheck.(map ~rev:IntSet.elements IntSet.of_list (list_small arbitrary_state)) |
| 33 | + |
| 34 | + |
| 35 | +(** Omaduspõhine test, mis kontrollib püsipunkti funktsiooni monotoonsust. *) |
| 36 | +let test_fp_f_mono = |
| 37 | + QCheck.Test.make ~name:"f_mono" |
| 38 | + (QCheck.triple arbitrary_states arbitrary_states arbitrary_states) |
| 39 | + (fun (initial, states1, states2) -> |
| 40 | + QCheck.assume (IntSet.subset states1 states2); |
| 41 | + let f x = IntSet.union initial (nfa_eps_set x) in |
| 42 | + IntSet.subset (f states1) (f states2) |
| 43 | + ) |
| 44 | + |> QCheck_ounit.to_ounit2_test |
| 45 | + |
| 46 | +let test_fp _ = |
| 47 | + (* Olekust 1. *) |
| 48 | + let f1 x = IntSet.union (IntSet.singleton 1) (nfa_eps_set x) in |
| 49 | + assert_equal (IntSet.of_list [1; 2; 5; 6; 7]) (IntSetFP.fp f1 IntSet.empty); |
| 50 | + (* Olekust 2. *) |
| 51 | + let f2 x = IntSet.union (IntSet.singleton 2) (nfa_eps_set x) in |
| 52 | + assert_equal (IntSet.of_list [2]) (IntSetFP.fp f2 IntSet.empty); |
| 53 | + (* Olekust 8. *) |
| 54 | + let f8 x = IntSet.union (IntSet.singleton 8) (nfa_eps_set x) in |
| 55 | + assert_equal (IntSet.of_list [1; 2; 5; 6; 7; 8]) (IntSetFP.fp f8 IntSet.empty) |
| 56 | + |
| 57 | +let test_lfp _ = |
| 58 | + (* Olekust 1. *) |
| 59 | + let f1 x = IntSet.union (IntSet.singleton 1) (nfa_eps_set x) in |
| 60 | + assert_equal (IntSet.of_list [1; 2; 5; 6; 7]) (IntSetFP.lfp f1); |
| 61 | + (* Olekust 2. *) |
| 62 | + let f2 x = IntSet.union (IntSet.singleton 2) (nfa_eps_set x) in |
| 63 | + assert_equal (IntSet.of_list [2]) (IntSetFP.lfp f2); |
| 64 | + (* Olekust 8. *) |
| 65 | + let f8 x = IntSet.union (IntSet.singleton 8) (nfa_eps_set x) in |
| 66 | + assert_equal (IntSet.of_list [1; 2; 5; 6; 7; 8]) (IntSetFP.lfp f8) |
| 67 | + |
| 68 | + |
| 69 | +(** Omaduspõhine test, mis kontrollib sulundi funktsiooni monotoonsust. *) |
| 70 | +let test_closure_f_mono = |
| 71 | + QCheck.Test.make ~name:"f_mono" |
| 72 | + (QCheck.pair arbitrary_states arbitrary_states) |
| 73 | + (fun (states1, states2) -> |
| 74 | + QCheck.assume (IntSet.subset states1 states2); |
| 75 | + IntSet.subset (nfa_eps_set states1) (nfa_eps_set states2) |
| 76 | + ) |
| 77 | + |> QCheck_ounit.to_ounit2_test |
| 78 | + |
| 79 | +let test_closure _ = |
| 80 | + (* Olekust 1. *) |
| 81 | + assert_equal (IntSet.of_list [1; 2; 5; 6; 7]) (IntSetFP.closure nfa_eps_set (IntSet.singleton 1)); |
| 82 | + (* Olekust 2. *) |
| 83 | + assert_equal (IntSet.of_list [2]) (IntSetFP.closure nfa_eps_set (IntSet.singleton 2)); |
| 84 | + (* Olekust 8. *) |
| 85 | + assert_equal (IntSet.of_list [1; 2; 5; 6; 7; 8]) (IntSetFP.closure nfa_eps_set (IntSet.singleton 8)) |
| 86 | + |
| 87 | +(** Test, mis kontrollib sulundi funktsiooni agarust. *) |
| 88 | +let test_closure_f_strict _ = |
| 89 | + assert_equal IntSet.empty (nfa_eps_set IntSet.empty) |
| 90 | + |
| 91 | +(** Omaduspõhine test, mis kontrollib sulundi funktsiooni distributiivsust. *) |
| 92 | +let test_closure_f_distr = |
| 93 | + QCheck.Test.make ~name:"f_distr" |
| 94 | + (QCheck.pair arbitrary_states arbitrary_states) |
| 95 | + (fun (states1, states2) -> |
| 96 | + IntSet.equal (nfa_eps_set (IntSet.union states1 states2)) (IntSet.union (nfa_eps_set states1) (nfa_eps_set states2)) |
| 97 | + ) |
| 98 | + |> QCheck_ounit.to_ounit2_test |
| 99 | + |
| 100 | +let test_closure_strict_distr _ = |
| 101 | + (* Olekust 1. *) |
| 102 | + assert_equal (IntSet.of_list [1; 2; 5; 6; 7]) (IntSetFP.closure_strict_distr nfa_eps_set (IntSet.singleton 1)); |
| 103 | + (* Olekust 2. *) |
| 104 | + assert_equal (IntSet.of_list [2]) (IntSetFP.closure_strict_distr nfa_eps_set (IntSet.singleton 2)); |
| 105 | + (* Olekust 8. *) |
| 106 | + assert_equal (IntSet.of_list [1; 2; 5; 6; 7; 8]) (IntSetFP.closure_strict_distr nfa_eps_set (IntSet.singleton 8)) |
| 107 | + |
| 108 | +(** Omaduspõhine test, mis kontrollib kahe sulundi samaväärsust. *) |
| 109 | +let test_closure_equivalent = |
| 110 | + QCheck.Test.make ~name:"equivalent" |
| 111 | + arbitrary_states |
| 112 | + (fun initial -> |
| 113 | + IntSet.equal (IntSetFP.closure nfa_eps_set initial) (IntSetFP.closure_strict_distr nfa_eps_set initial) |
| 114 | + ) |
| 115 | + |> QCheck_ounit.to_ounit2_test |
| 116 | + |
| 117 | + |
| 118 | +let tests = |
| 119 | + "nfa_eps" >::: [ |
| 120 | + "fp" >::: [ |
| 121 | + test_fp_f_mono; |
| 122 | + "fp" >:: test_fp; |
| 123 | + "lfp" >:: test_lfp; |
| 124 | + ]; |
| 125 | + "closure" >::: [ |
| 126 | + test_closure_f_mono; |
| 127 | + "closure" >:: test_closure; |
| 128 | + "f_strict" >:: test_closure_f_strict; |
| 129 | + test_closure_f_distr; |
| 130 | + "closure_strict_distr" >:: test_closure_strict_distr; |
| 131 | + test_closure_equivalent; |
| 132 | + ]; |
| 133 | + ] |
0 commit comments