Limi
meta_automaton.h
1 /*
2  * Copyright 2016, IST Austria
3  *
4  * This file is part of Limi.
5  *
6  * Limi is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Limi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with Limi. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef LIMI_INTERNAL_META_AUTOMATON_H
21 #define LIMI_INTERNAL_META_AUTOMATON_H
22 
23 #include <memory>
24 
25 #include "../automaton.h"
26 #include "meta_state.h"
27 #include "helpers.h"
28 #include <iostream>
29 #include <cassert>
30 #include <stdexcept>
31 
32 namespace Limi {
33  namespace internal {
34 
35 
42 template <class InnerImplementationB, class Independence = independence<typename InnerImplementationB::Symbol_>>
43 class meta_automaton : public Limi::automaton<std::shared_ptr<meta_state<typename InnerImplementationB::State_, typename InnerImplementationB::Symbol_, Independence>>,typename InnerImplementationB::Symbol_,meta_automaton<InnerImplementationB, Independence>> {
44  using InnerStateB = typename InnerImplementationB::State_;
45  using Symbol = typename InnerImplementationB::Symbol_;
47 public:
48  typedef std::shared_ptr<StateB> StateI;
49 private:
51  typedef typename Limi::automaton<StateI,Symbol,meta_automaton<InnerImplementationB, Independence>>::Symbol_vector Symbol_vector;
52 
54 public:
55 
56  meta_automaton(const InnerAutomatonB& automaton, const Independence& independence = Independence()) :
58  inner(automaton), independence_(independence) {
59  if (!automaton.collapse_epsilon && !automaton.no_epsilon_produced) {
60  throw std::logic_error("For the automaton B in the language inclusion algorithm either collapse_epsilon must be true or no_epsilon_produced");
61  }
62  }
63 
64  bool int_is_final_state(const StateI& state) const {
65  return (state->early().size()==0 && state->late().size()==0 && inner.is_final_state(state->inner_state()));
66  }
67 
68  void int_initial_states(State_vector& states) const {
69  std::vector<InnerStateB> is;
70  inner.initial_states(is);
71  for (const auto& i:is) {
72  states.push_back(std::make_shared<StateB>(i));
73  }
74  }
75 
76 private:
77 
85  int check_independence(typename StateB::vector_iterator begin, const typename StateB::vector_iterator& end, const Symbol& symbol) const {
86  int counter = 0;
87  for (; begin!=end; ++begin) {
88  if (std::equal_to<Symbol>()(*begin, symbol)) return counter;
89  if (!independence_(*begin, symbol)) return -2;
90  ++counter;
91  }
92  return -1;
93  }
94 
95 
96  StateI successor(const StateI& state, const Symbol& sigmaA, const Symbol& sigmaB) const {
97  // check if the element we are about to add to early (sigmaB) can commute with everything in late. In the case it does not, then this state is dead
98  // if the element is already in late than it only needs to commute with all elements up to that
99  // furthermore we remove the element in late
100  int pos_early, pos_late;
101  if ((pos_late = check_independence(state->late().begin(), state->late().end(), sigmaB)) == -2) return StateI();
102 
103  // make a copy
104  StateI newst = std::make_shared<StateB>(*state);
105  // now delete if needed (and add otherwise)
106  if (pos_late!=-1)
107  newst->erase_late(pos_late);
108  else
109  newst->add_early(sigmaB, independence_);
110 
111  // now do it for the other one
112  if ((pos_early = check_independence(newst->early().begin(), newst->early().end(), sigmaA)) == -2) return StateI();
113  if (-1!=pos_early)
114  newst->erase_early(pos_early);
115  else
116  newst->add_late(sigmaA, independence_);
117  assert(newst->early().size() == newst->late().size());
118  //print_state(newst, std::cout); std::cout << std::endl;
119  return newst;
120  }
121 
122 public:
123 
124  void int_successors(const StateI& state, const Symbol& sigmaA, State_vector& successors) const {
125  for (const Symbol& sigmaB : inner.next_symbols(state->inner_state())) {
126  //print_state(state, std::cout); std::cout << std::endl;
127  //std::cout << sigmaA << std::endl;
128  //std::cout << sigmaB << std::endl;
129  StateI succ = successor(state, sigmaA, sigmaB);
130  if (succ) {
131  typename InnerAutomatonB::State_vector succs;
132  inner.successors(state->inner_state(),sigmaB, succs);
133  for(auto it = succs.begin(); it!=succs.end(); ++it) {
134  // make a copy if this is more than once needed
135  if (it!=succs.begin())
136  succ = std::make_shared<StateB>(*succ);
137  succ->inner_state(*it);
138 
139  successors.push_back(succ);
140  }
141 
142  }
143  }
144  }
145 
146  inline void int_next_symbols(const StateI& state, Symbol_vector& symbols) const {
147  throw std::logic_error("The meta-automaton cannot produce a set of next symbols");
148  }
149 
150  inline printer_base<StateI>* int_state_printer() const { return new printer<StateI>(inner.state_printer(), inner.symbol_printer()); }
151 
152  inline const printer_base<Symbol>& symbol_printer() const { return inner.symbol_printer(); }
153 
154  inline bool int_is_epsilon(const Symbol& symbol) const { return inner.is_epsilon(symbol); }
155 
156 private:
157  const InnerAutomatonB& inner;
158  const Independence& independence_;
159 };
160 
161  }
162 }
163 
164 #endif //LIMI_INTERNAL_META_AUTOMATON_H
The printer base is what custom printers need to inherit from.
Definition: generics.h:81
void next_symbols(const State &state, Symbol_vector &symbols) const
Returns possible successor symbols for a state.
Definition: automaton.h:256
The main namespace of the library.
Definition: antichain_algo.h:40
This automaton presents an automaton up to an independence relation.
Definition: meta_automaton.h:43
The template for the independence relation.
Definition: generics.h:53
A state in the meta-automaton.
Definition: meta_state.h:39
const printer_base< State > & state_printer() const
Returns a printer for states.
Definition: automaton.h:292
bool is_epsilon(const Symbol &symbol) const
Determines if a symbol should be considered an epsilon transition.
Definition: automaton.h:320
bool is_final_state(const State &state) const
This function determines if a specific state is final.
Definition: automaton.h:160
void successors(const std::shared_ptr< meta_state< InnerImplementationB::State_, InnerImplementationB::Symbol_, Independence > > &state, const InnerImplementationB::Symbol_ &sigma, State_vector &successors1) const
Returns the successor for a specific state.
Definition: automaton.h:201
bool no_epsilon_produced
Indicates that the implementation of next_symbols(const State&,Symbol_set&) const will never produce ...
Definition: automaton.h:350
const printer_base< Symbol > & symbol_printer() const
Returns a printer for symbols.
Definition: automaton.h:304
The default implementation of Limi::printer_base.
Definition: generics.h:104
void initial_states(State_vector &states) const
Returns the initial states.
Definition: automaton.h:167
bool collapse_epsilon
If true during exploration of the next state the epsilons will be fully explored. If false then epsil...
Definition: automaton.h:344
Automata need to inherit from this class and implement certain methods.
Definition: automaton.h:49