|
1 | 1 | /** |
2 | | - * Automata reduction and LTS-based simulation. |
3 | | - * - sim_reduce uses LTS build (simulation::translate_to_lts_downward, count_aut_states) and compute_down_sim. |
4 | | - * - Light reduce up/down, bottom-up reduce, reduce(), remove_useless(). |
5 | | - * - Helpers: reindex_aut_states, compact_aut, state_renumbering, fraction_simplification, k_unification. |
| 2 | + * Automata reduction: light reduce, bottom-up reduce, remove_useless, fraction_simplification, k_unification. |
| 3 | + * LTS-based sim_reduce is in reduce_sim.cc. Shared helpers in reduce_common.hh. |
6 | 4 | */ |
7 | 5 | #include <queue> |
8 | 6 |
|
|
11 | 9 | #include "autoq/symbol/symbolic.hh" |
12 | 10 | #include "autoq/symbol/predicate.hh" |
13 | 11 | #include "autoq/symbol/constrained.hh" |
14 | | -#include "autoq/simulation/explicit_lts.hh" |
15 | | -#include "autoq/simulation/automata_to_lts.hh" |
| 12 | +#include "autoq/reduce_common.hh" |
16 | 13 |
|
17 | 14 | using namespace AUTOQ; |
18 | 15 | using namespace AUTOQ::Util; |
19 | 16 |
|
20 | | -namespace { // anonymous namespace |
21 | | - |
22 | | - // --- LTS-based simulation (used by sim_reduce) --- |
23 | | - |
24 | | - template <typename Symbol> |
25 | | - typename Util::DiscontBinaryRelation<typename Automata<Symbol>::State> compute_down_sim(const AUTOQ::Automata<Symbol>& aut) |
26 | | - { |
27 | | - using State = typename Automata<Symbol>::State; |
28 | | - using StateToIndexMap = typename std::unordered_map<State, size_t>; |
29 | | - using StateToIndexTranslWeak = typename Util::TranslatorWeak<StateToIndexMap>; |
30 | | - using DiscontBinaryRelOnStates = typename Util::DiscontBinaryRelation<State>; |
31 | | - |
32 | | - StateToIndexMap translMap; |
33 | | - size_t stateCnt = 0; |
34 | | - StateToIndexTranslWeak transl(translMap, |
35 | | - [&stateCnt](const State&) {return stateCnt++;}); |
36 | | - |
37 | | - size_t num_states = simulation::count_aut_states(aut); |
38 | | - AUTOQ::ExplicitLTS lts = simulation::translate_to_lts_downward(aut, num_states, transl); |
39 | | - BinaryRelation ltsSim = lts.computeSimulation(num_states); |
40 | | - return DiscontBinaryRelOnStates(ltsSim, translMap); |
41 | | - } |
42 | | - |
43 | | - // --- Reindexing and compaction helpers --- |
44 | | - |
45 | | - template <class Index, typename Symbol> |
46 | | - void reindex_aut_states(Automata<Symbol>& aut, Index& index) |
47 | | - { |
48 | | - using State = typename Automata<Symbol>::State; |
49 | | - using StateVector = typename Automata<Symbol>::StateVector; |
50 | | - |
51 | | - StateVector newFinal; |
52 | | - |
53 | | - for (const State& state : aut.finalStates) { // process final states |
54 | | - if (newFinal.end() == std::find(newFinal.begin(), newFinal.end(), index[state])) { |
55 | | - newFinal.push_back(index[state]); |
56 | | - } |
57 | | - } |
58 | | - typename Automata<Symbol>::TopDownTransitions transitions_new; |
59 | | - for (const auto &t : aut.transitions) { |
60 | | - for (const auto &out_ins : t.second) { |
61 | | - const auto &out = out_ins.first; |
62 | | - for (auto in : out_ins.second) { |
63 | | - for (auto &e : in) { |
64 | | - e = index[e]; |
65 | | - } |
66 | | - transitions_new[t.first][index[out]].insert(in); |
67 | | - } |
68 | | - } |
69 | | - } |
70 | | - |
71 | | - aut.finalStates = newFinal; |
72 | | - aut.transitions = transitions_new; |
73 | | - } |
74 | | - |
75 | | - template <class T> |
76 | | - int findIndex(const std::vector<T> &arr, T item) { |
77 | | - for (int i = 0; i < static_cast<int>(arr.size()); ++i) { |
78 | | - if (arr[i] == item) |
79 | | - return i; |
80 | | - } |
81 | | - std::__throw_out_of_range("[ERROR] findIndex: item not found."); |
82 | | - } |
83 | | - |
84 | | - /// Checks that a state is at most once on the right-hand (parent) side of |
85 | | - /// any rule. |
86 | | - template <typename Symbol> |
87 | | - bool aut_is_single_occurrence(const Automata<Symbol>& aut) |
88 | | - { |
89 | | - using State = typename Automata<Symbol>::State; |
90 | | - |
91 | | - std::set<State> occurrences; |
92 | | - for (auto symbMapPair : aut.transitions) { |
93 | | - for (auto vecSetPair : symbMapPair.second) { |
94 | | - for (auto state : vecSetPair.second) { |
95 | | - auto itBoolPair = occurrences.insert(state); |
96 | | - if (!itBoolPair.second) { return false; } |
97 | | - } |
98 | | - } |
99 | | - } |
100 | | - |
101 | | - return true; |
102 | | - } |
103 | | - |
104 | | - // Makes a TA compact (states are renumbered to start from 0 and go consecutively up |
105 | | - template <typename Symbol> |
106 | | - void compact_aut(Automata<Symbol>& aut) |
107 | | - { |
108 | | - using State = typename Automata<Symbol>::State; |
109 | | - using StateToStateMap = typename std::unordered_map<State, State>; |
110 | | - using StateToStateTranslWeak = typename Util::TranslatorWeak<StateToStateMap>; |
111 | | - StateToStateMap translMap; |
112 | | - size_t stateCnt = 0; |
113 | | - StateToStateTranslWeak transl(translMap, |
114 | | - [&stateCnt](const State&) {return stateCnt++;}); |
115 | | - |
116 | | - // AUTOQ_DEBUG("Before compact stateNum = " + Convert::ToString(aut.stateNum)); |
117 | | - reindex_aut_states(aut, transl); |
118 | | - aut.stateNum = stateCnt; |
119 | | - // AUTOQ_DEBUG("After compact stateNum = " + Convert::ToString(aut.stateNum)); |
120 | | - } |
121 | | -} // anonymous namespace |
122 | | - |
123 | | -// --- Reduction API: sim_reduce, light_reduce_*, bottom_up_reduce, reduce --- |
124 | | - |
125 | | -template <typename Symbol> |
126 | | -void AUTOQ::Automata<Symbol>::sim_reduce() |
127 | | -{ |
128 | | - using State = typename Automata<Symbol>::State; |
129 | | - using DiscontBinaryRelOnStates = typename Util::DiscontBinaryRelation<State>; |
130 | | - using StateToStateMap = typename std::unordered_map<State, State>; |
131 | | - |
132 | | - DiscontBinaryRelOnStates sim = compute_down_sim(*this); |
133 | | - |
134 | | - // TODO: this is probably not optimal, we could probably get the mapping of |
135 | | - // states for collapsing in a faster way |
136 | | - sim.RestrictToSymmetric(); // sim is now an equivalence relation |
137 | | - |
138 | | - StateToStateMap collapseMap; |
139 | | - sim.GetQuotientProjection(collapseMap); |
140 | | - |
141 | | - // Automata old = *this; |
142 | | - reindex_aut_states(*this, collapseMap); |
143 | | - |
144 | | - // if (!check_equal_aut(*this, old)) { |
145 | | - // AUTOQ_DEBUG("wrong simulation result!"); |
146 | | - // AUTOQ_DEBUG("old: " + old.ToString()); |
147 | | - // AUTOQ_DEBUG("new: " + this->ToString()); |
148 | | - // AUTOQ_DEBUG("simulation: " + sim.ToString()); |
149 | | - // } |
150 | | -} |
| 17 | +// --- Reduction API: light_reduce_*, bottom_up_reduce, reduce, remove_useless, etc. --- |
151 | 18 |
|
152 | 19 | template <typename Symbol> |
153 | 20 | bool AUTOQ::Automata<Symbol>::light_reduce_up() |
@@ -194,7 +61,7 @@ bool AUTOQ::Automata<Symbol>::light_reduce_up() |
194 | 61 | // AUTOQ_DEBUG("index: " + Convert::ToString(index)); |
195 | 62 | if (changed) { |
196 | 63 | // Automata old = *this; |
197 | | - reindex_aut_states(*this, index); |
| 64 | + reduce_detail::reindex_aut_states(*this, index); |
198 | 65 | // assert(check_equal_aut(old, *this)); |
199 | 66 | } |
200 | 67 |
|
@@ -247,7 +114,7 @@ bool AUTOQ::Automata<Symbol>::light_reduce_down() |
247 | 114 |
|
248 | 115 | StateToStateTranslWeak transl(index, [](const State& state) {return state;}); |
249 | 116 |
|
250 | | - reindex_aut_states(*this, transl); |
| 117 | + reduce_detail::reindex_aut_states(*this, transl); |
251 | 118 | return true; |
252 | 119 | } |
253 | 120 |
|
@@ -333,7 +200,7 @@ bool AUTOQ::Automata<Symbol>::light_reduce_down() |
333 | 200 | } |
334 | 201 |
|
335 | 202 | StateToStateTranslWeak transl(index, [](const State& state) { return state; }); |
336 | | - reindex_aut_states(*this, transl); |
| 203 | + reduce_detail::reindex_aut_states(*this, transl); |
337 | 204 | return true; |
338 | 205 | } |
339 | 206 | } |
@@ -573,7 +440,7 @@ void AUTOQ::Automata<Symbol>::reduce() { |
573 | 440 | this->light_reduce_down_iter(); |
574 | 441 | // AUTOQ_DEBUG("after light_reduce_down: " + Convert::ToString(count_aut_states(*this))); |
575 | 442 |
|
576 | | - compact_aut(*this); |
| 443 | + reduce_detail::compact_aut(*this); |
577 | 444 | // assert(check_equal_aut(old, *this)); |
578 | 445 |
|
579 | 446 | auto a = transitions; //count_transitions(); |
|
0 commit comments