Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
has-twins-property.hh
Go to the documentation of this file.
1 #ifndef VCSN_ALGOS_HAS_TWINS_PROPERTY_HH
2 # define VCSN_ALGOS_HAS_TWINS_PROPERTY_HH
3 
4 # include <stack>
5 
6 # include <vcsn/algos/accessible.hh> // vcsn::trim
7 # include <vcsn/algos/is-ambiguous.hh> // is_cycle_ambiguous
8 # include <vcsn/algos/product.hh>
9 # include <vcsn/algos/scc.hh>
10 # include <vcsn/dyn/automaton.hh>
11 # include <vcsn/dyn/fwd.hh>
12 # include <vcsn/labelset/tupleset.hh>
13 # include <vcsn/misc/unordered_map.hh> // vcsn::has
14 
15 namespace vcsn
16 {
17 
18  /*-----------------.
19  | cycle_identity. |
20  `-----------------*/
21 
22  namespace detail
23  {
31  template <typename Aut>
33  {
34  public:
39 
42  bool check(const component_t& component, const Aut& aut)
43  {
44  // FIXME: check ordered_map, or even polynomial of state.
45  std::unordered_map<state_t, weight_t> wm;
46  // Double-tape weightset.
47  const auto& ws = *aut->weightset();
48  // Single-tape weightset.
49  auto ws1 = ws.template set<0>();
50  auto s0 = *component.begin();
51  std::stack<state_t> todo;
52  todo.push(s0);
53  wm[s0] = ws.one();
54  while (!todo.empty())
55  {
56  auto s = todo.top();
57  todo.pop();
58 
59  for (auto t : aut->all_out(s))
60  {
61  auto dst = aut->dst_of(t);
62  if (has(component, dst))
63  {
64  auto w = ws.mul(wm[s], aut->weight_of(t));
65  if (!has(wm, dst))
66  {
67  todo.push(dst);
68  wm.emplace(dst, w);
69  }
70  else
71  {
72  auto w2 = ws.mul(wm[dst], w);
73  // FIXME: return the counter example?
74  if (!ws1.equals(std::get<0>(w2), std::get<1>(w2)))
75  return false;
76  }
77  }
78  }
79  }
80  return true;
81  }
82  };
83  }
84 
86  template <typename Aut>
88  const Aut& aut)
89  {
91  return ci.check(c, aut);
92  }
93 
94 
95  /*---------------------.
96  | has_twins_property. |
97  `---------------------*/
98 
102  template <typename InAut, typename OutAut>
103  void create_states_and_trans_(const InAut& aut,
104  OutAut& naut1, OutAut& naut2)
105  {
106  using state_t = state_t_of<InAut>;
107  std::unordered_map<state_t, state_t> ms;
108 
109  ms[aut->pre()] = naut1->pre();
110  ms[aut->post()] = naut1->post();
111  for (auto s : aut->states())
112  {
113  ms[s] = naut1->new_state();
114  naut2->new_state();
115  }
116 
117  const auto& ws = *aut->weightset();
118  for (auto t : aut->all_transitions())
119  {
120  auto src = aut->src_of(t);
121  auto dst = aut->dst_of(t);
122  auto w = aut->weight_of(t);
123  auto l = aut->label_of(t);
124  auto nw1 = std::make_tuple(w, ws.one());
125  auto nw2 = std::make_tuple(ws.one(), w);
126  naut1->new_transition(ms[src], ms[dst], l, nw1);
127  naut2->new_transition(ms[src], ms[dst], l, nw2);
128  }
129  }
130 
132  template <typename Aut>
133  bool has_twins_property(const Aut& aut)
134  {
136  "has_twins_property: requires a cycle-unambiguous automaton");
137 
138  // Create new weightset lat<ws, ws> from weightset ws of aut.
139  auto ws = *aut->weightset();
140  auto nt = std::make_tuple(ws, ws);
142 
143  auto nctx = make_context(*aut->labelset(), nws);
144  auto naut1 = make_mutable_automaton(nctx);
145  auto naut2 = make_mutable_automaton(nctx);
146 
147  auto trim = ::vcsn::trim(aut);
148  create_states_and_trans_(trim, naut1, naut2);
149 
150  auto a = product(naut1, naut2);
151 
152  // Find all components of automate a.
153  auto cs = scc(a);
154 
155  // Check unique weight of two states on each component.
156  for (auto c : cs)
157  if (!cycle_identity(c, a))
158  return false;
159 
160  return true;
161  }
162 
163  namespace dyn
164  {
165  namespace detail
166  {
167  // Bridge.
168  template <typename Aut>
169  bool has_twins_property(const automaton& aut)
170  {
171  const auto& a = aut->as<Aut>();
173  }
174 
176  (const automaton&) -> bool);
177  }
178  }
179 }
180 #endif // !VCSN_ALGOS_HAS_TWINS_PROPERTY_HH
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
auto product(const Auts &...as) -> product_automaton< decltype(meet_automata(as...)), Auts...>
Build the (accessible part of the) product.
Definition: product.hh:445
A ValueSet which is a Cartesian product of ValueSets.
Definition: fwd.hh:20
bool has_twins_property(const automaton &aut)
Whether all the paths between any two states have the same weight (i.e., for all s0, s1, any two paths p0, p1 between s0 and s1 have the same weight w_{s0,s1}).
std::set< state_t_of< Aut >> component_t
An strongly-connected component: list of states.
Definition: scc.hh:24
void create_states_and_trans_(const InAut &aut, OutAut &naut1, OutAut &naut2)
Create states and the transitions two new automata naut1 and naut2 with weight of transition <(w...
bool cycle_identity(const detail::component_t< Aut > &c, const Aut &aut)
Check the weight of two states on this component is unique.
filter_automaton< Aut > trim(const Aut &a)
Definition: accessible.hh:141
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:36
const detail::components_t< Aut > scc(const Aut &aut, SCC_ALGO algo=SCC_ALGO::TARJAN)
Find all strongly connected components of aut.
Definition: scc.hh:229
bool check(const component_t &component, const Aut &aut)
By DFS starting in s0, check that all the states are reached with a single weight.
bool has_twins_property(const Aut &aut)
Whether aut has the twins property.
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:37
bool is_cycle_ambiguous(const Aut &aut)
Whether aut is cycle-ambiguous.
detail::component_t< Aut > component_t
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:35
Ctx make_context(const std::string &name)
Definition: make-context.hh:22
bool has(const std::map< Key, Value, Compare, Alloc > &s, const Key &e)
Definition: map.hh:35
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39