libmonaa 0.5.2
Loading...
Searching...
No Matches
kmp_skip_value.hh
1#pragma once
2
3#include <numeric>
4#include <unordered_map>
5
6#include "intersection.hh"
7#include "ta2za.hh"
8#include "timed_automaton.hh"
9#include "zone_automaton.hh"
10
18private:
19 std::unordered_map<const TAState *, int> beta;
20
21public:
22 KMPSkipValue(const TimedAutomaton &TA, int m) {
23 ZoneAutomaton ZA2;
25 boost::unordered_map<std::pair<TAState *, TAState *>,
26 std::shared_ptr<TAState>>
27 toIState;
28 // A0 is the automaton in A_{+n}^* in the paper. What we do is: 1) construct
29 // a dummy accepting state, and 2) construct m-dummy states to the original
30 // initial states
32 std::unordered_map<TAState *, std::shared_ptr<TAState>> old2new0;
33 TA.deepCopy(A0, old2new0);
34 // Vector of extended initial states. if the accepting state is
35 // extendedInitialStates[n], the TA reads n-additional events.
36 std::vector<std::shared_ptr<TAState>> extendedInitialStates(m + 1);
37 std::generate(extendedInitialStates.begin(), extendedInitialStates.end(), std::make_shared<TAState>);
38
39 for (const auto& initialState : A0.initialStates) {
40 for (auto it = initialState->next.begin(); it != initialState->next.end();
41 it++) {
42 for (TATransition edge : it->second) {
43 // We can modify edge because it is copied
44 const Alphabet c = it->first;
45 widen(edge.guard);
46 extendedInitialStates[0]->next[c].push_back(std::move(edge));
47 }
48 }
49 }
50
51 std::vector<ClockVariables> allClocks(TA.clockSize());
52 std::iota(allClocks.begin(), allClocks.end(), 0);
53 for (int i = 1; i <= m; ++i) {
54 for (char c = 1; c < CHAR_MAX; ++c) {
55 extendedInitialStates[i]->next[c].push_back(
56 {extendedInitialStates[i - 1].get(), allClocks, {}});
57 }
58 }
59 auto dummyAcceptingState = std::make_shared<TAState>(true);
60 // add self loop
61 for (char c = 1; c < CHAR_MAX; ++c) {
62 dummyAcceptingState->next[c].push_back(
63 {dummyAcceptingState.get(), {}, {}});
64 }
65 for (auto &state : A0.states) {
66 for (auto & it : state->next) {
67 for (TATransition edge : it.second) {
68 const auto target = edge.target;
69 // We can modify edge because it is copied
70 if (target && target->isMatch) {
71 edge.target = dummyAcceptingState.get();
72 widen(edge.guard);
73 it.second.emplace_back(std::move(edge));
74 }
75 }
76 }
77 }
78 A0.states.reserve(A0.states.size() + 1 + (m + 1));
79 A0.states.push_back(dummyAcceptingState);
80 A0.states.insert(A0.states.end(), extendedInitialStates.begin(),
81 extendedInitialStates.end());
82
83 // As is the automaton in A_{s}^* in the paper. What we do is to construct a
84 // dummy state for each state s.
86 std::unordered_map<TAState *, std::shared_ptr<TAState>> old2newS;
87 old2newS.reserve(TA.states.size());
88 TA.deepCopy(As, old2newS);
89 std::unordered_map<std::shared_ptr<TAState>, std::shared_ptr<TAState>>
90 toDummyState;
91 toDummyState.reserve(TA.states.size());
92 for (const auto& state : As.states) {
93 toDummyState[state] = std::make_shared<TAState>();
94 state->next[0].push_back({toDummyState[state].get(), {}, {}});
95 // add self loop
96 for (char c = 1; c < CHAR_MAX; ++c) {
97 toDummyState[state]->next[c].push_back(
98 {toDummyState[state].get(), {}, {}});
99 }
100 }
101 As.states.reserve(As.states.size() * 2);
102 for (const auto& dummyState : toDummyState) {
103 As.states.push_back(dummyState.second);
104 }
105
106 intersectionTA(A0, As, A2, toIState);
107
108 // Calculate KMP-type skip value
109 for (const auto& origState : TA.states) {
110 for (auto &stateAs : As.states) {
111 stateAs->isMatch = stateAs == old2newS[origState.get()] ||
112 stateAs == toDummyState[old2newS[origState.get()]];
113 }
114 // Find the minimum n such that the intersection of the two languages is
115 // not empty.
116 for (int n = 1; n <= m; n++) {
117 A0.initialStates = {extendedInitialStates[n]};
118 updateInitAccepting(A0, As, A2, toIState);
119 std::sort(A2.initialStates.begin(), A2.initialStates.end());
120 ta2za(A2, ZA2);
122 if (!ZA2.empty()) {
123 beta[origState.get()] = n;
124 break;
125 }
126 }
127 // When the emptiness checking always failed, we set m
128 beta.insert(std::make_pair(origState.get(), m));
129 }
130 }
131
132 inline int at(const TAState *s) const { return beta.at(s); }
133 inline int operator[](const TAState *s) const { return beta.at(s); }
134 inline int at(const std::shared_ptr<TAState>& s) const { return beta.at(s.get()); }
135 inline int operator[](const std::shared_ptr<TAState>& s) const {
136 return beta.at(s.get());
137 }
138};
The skip value function based on the KMP algorithm for string matching.
Definition kmp_skip_value.hh:17
std::vector< std::shared_ptr< State > > states
The states of this automaton.
Definition common_types.hh:17
std::vector< std::shared_ptr< State > > initialStates
The initial states of this automaton.
Definition common_types.hh:19
A state of timed automata.
Definition timed_automaton.hh:19
A state of timed automata.
Definition timed_automaton.hh:42
A timed automaton.
Definition timed_automaton.hh:54
size_t clockSize() const
Returns the number of clock variables used in the timed automaton.
Definition timed_automaton.hh:95
void deepCopy(TimedAutomaton &dest, std::unordered_map< TAState *, std::shared_ptr< TAState > > &old2new) const
make a deep copy of this timed automaton.
Definition timed_automaton.hh:68
Definition zone_automaton.hh:55
void updateInitAccepting(const std::vector< std::shared_ptr< TAState > > taInitialStates)
Propagate accepting states from the original timed automaton.
Definition zone_automaton.hh:116
bool empty() const
emptiness check of the language
Definition zone_automaton.hh:136