spot  2.3.3.dev
ec.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2015, 2016 Laboratoire de Recherche et
3 // Developpement de l'Epita
4 //
5 // This file is part of Spot, a model checking library.
6 //
7 // Spot is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // Spot is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
20 #pragma once
21 
22 #include <spot/twa/acc.hh>
23 #include <spot/mc/unionfind.hh>
24 #include <spot/mc/intersect.hh>
25 
26 namespace spot
27 {
33  template<typename State, typename SuccIterator,
34  typename StateHash, typename StateEqual>
35  class ec_renault13lpar : public intersect<State, SuccIterator,
36  StateHash, StateEqual,
37  ec_renault13lpar<State, SuccIterator,
38  StateHash, StateEqual>>
39  {
40  // Ease the manipulation
41  using typename intersect<State, SuccIterator, StateHash, StateEqual,
42  ec_renault13lpar<State, SuccIterator,
43  StateHash,
44  StateEqual>>::product_state;
45 
46  public:
48  twacube_ptr twa, unsigned tid, bool stop)
49  : intersect<State, SuccIterator, StateHash, StateEqual,
50  ec_renault13lpar<State, SuccIterator,
51  StateHash, StateEqual>>(sys, twa, tid, stop),
52  acc_(twa->acc()), sccs_(0U)
53  {
54  }
55 
56  virtual ~ec_renault13lpar()
57  {
58 
59  }
60 
63  void setup()
64  {
65  }
66 
72  bool push_state(product_state, unsigned dfsnum, acc_cond::mark_t cond)
73  {
74  uf_.makeset(dfsnum);
75  roots_.push_back({dfsnum, cond, 0U});
76  return true;
77  }
78 
86  bool pop_state(product_state, unsigned top_dfsnum, bool,
87  product_state, unsigned)
88  {
89  if (top_dfsnum == roots_.back().dfsnum)
90  {
91  roots_.pop_back();
92  ++sccs_;
93  uf_.markdead(top_dfsnum);
94  }
95  dfs_ = this->todo.size() > dfs_ ? this->todo.size() : dfs_;
96  return true;
97  }
98 
101  bool update(product_state, unsigned,
102  product_state, unsigned dst_dfsnum,
103  acc_cond::mark_t cond)
104  {
105  if (uf_.isdead(dst_dfsnum))
106  return false;
107 
108  while (!uf_.sameset(dst_dfsnum, roots_.back().dfsnum))
109  {
110  auto& el = roots_.back();
111  roots_.pop_back();
112  uf_.unite(dst_dfsnum, el.dfsnum);
113  cond |= el.acc | el.ingoing;
114  }
115  roots_.back().acc |= cond;
116  found_ = acc_.accepting(roots_.back().acc);
117  if (SPOT_UNLIKELY(found_))
118  this->stop_ = true;
119  return found_;
120  }
121 
122  bool counterexample_found()
123  {
124  return found_;
125  }
126 
127  std::string trace()
128  {
129  SPOT_ASSERT(counterexample_found());
130  std::string res = "Prefix:\n";
131 
132  // Compute the prefix of the accepting run
133  for (auto& s : this->todo)
134  res += " " + std::to_string(s.st.st_prop) +
135  + "*" + this->sys_.to_string(s.st.st_kripke) + "\n";
136 
137  // Compute the accepting cycle
138  res += "Cycle:\n";
139 
140  struct ctrx_element
141  {
142  const product_state* prod_st;
143  ctrx_element* parent_st;
144  SuccIterator* it_kripke;
145  std::shared_ptr<trans_index> it_prop;
146  };
147  std::queue<ctrx_element*> bfs;
148 
149  acc_cond::mark_t acc = 0U;
150 
151  bfs.push(new ctrx_element({&this->todo.back().st, nullptr,
152  this->sys_.succ(this->todo.back().st.st_kripke, this->tid_),
153  this->twa_->succ(this->todo.back().st.st_prop)}));
154  while (true)
155  {
156  here:
157  auto* front = bfs.front();
158  bfs.pop();
159  // PUSH all successors of the state.
160  while (!front->it_kripke->done())
161  {
162  while (!front->it_prop->done())
163  {
164  if (this->twa_->get_cubeset().intersect
165  (this->twa_->trans_data(front->it_prop, this->tid_).cube_,
166  front->it_kripke->condition()))
167  {
168  const product_state dst = {
169  front->it_kripke->state(),
170  this->twa_->trans_storage(front->it_prop).dst
171  };
172 
173  // Skip Unknown states or not same SCC
174  auto it = this->map.find(dst);
175  if (it == this->map.end() ||
176  !uf_.sameset(it->second,
177  this->map[this->todo.back().st]))
178  {
179  front->it_prop->next();
180  continue;
181  }
182 
183  // This is a valid transition. If this transition
184  // is the one we are looking for, update the counter-
185  // -example and flush the bfs queue.
186  auto mark = this->twa_->trans_data(front->it_prop,
187  this->tid_).acc_;
188  if (!(acc & mark))
189  {
190  ctrx_element* current = front;
191  while (current != nullptr)
192  {
193  // FIXME also display acc?
194  res = res + " " +
195  std::to_string(current->prod_st->st_prop) +
196  + "*" +
197  this->sys_. to_string(current->prod_st
198  ->st_kripke) +
199  "\n";
200  current = current->parent_st;
201  }
202 
203  // empty the queue
204  while (!bfs.empty())
205  {
206  auto* e = bfs.front();
207  bfs.pop();
208  delete e;
209  }
210 
211  // update acceptance
212  acc |= mark;
213  if (this->twa_->acc().accepting(acc))
214  return res;
215 
216  const product_state* q = &(it->first);
217  ctrx_element* root = new ctrx_element({
218  q , nullptr,
219  this->sys_.succ(q->st_kripke, this->tid_),
220  this->twa_->succ(q->st_prop)
221  });
222  bfs.push(root);
223  goto here;
224  }
225 
226  // Otherwise increment iterator and push successor.
227  const product_state* q = &(it->first);
228  ctrx_element* root = new ctrx_element({
229  q , nullptr,
230  this->sys_.succ(q->st_kripke, this->tid_),
231  this->twa_->succ(q->st_prop)
232  });
233  bfs.push(root);
234  }
235  front->it_prop->next();
236  }
237  front->it_prop->reset();
238  front->it_kripke->next();
239  }
240  }
241 
242  // never reach here;
243  return res;
244  }
245 
246  virtual istats stats() override
247  {
248  return {this->states(), this->trans(), sccs_,
249  (unsigned) roots_.size(), dfs_, found_};
250  }
251 
252  private:
253 
254  bool found_ = false;
255 
256  struct root_element {
257  unsigned dfsnum;
258  acc_cond::mark_t ingoing;
259  acc_cond::mark_t acc;
260  };
261 
263  std::vector<root_element> roots_;
264  int_unionfind uf_;
265  acc_cond acc_;
266  unsigned sccs_;
267  unsigned dfs_;
268  };
269 }
void setup()
This method is called at the begining of the exploration. here we do not need to setup any informatio...
Definition: ec.hh:63
Definition: graph.hh:33
bool update(product_state, unsigned, product_state, unsigned dst_dfsnum, acc_cond::mark_t cond)
This method is called for every closing, back, or forward edge. Return true if a counterexample has b...
Definition: ec.hh:101
A Transition-based ω-Automaton.
Definition: twa.hh:622
This class explores (with a DFS) a product between a system and a twa. This exploration is performed ...
Definition: intersect.hh:59
This class is a template representation of a Kripke structure. It is composed of two template paramet...
Definition: kripke.hh:37
bool pop_state(product_state, unsigned top_dfsnum, bool, product_state, unsigned)
This method is called to notify the emptiness checks that a state will be popped. If the method retur...
Definition: ec.hh:86
This Union-Find data structure is a particular union-find, dedicated for emptiness checks below...
Definition: unionfind.hh:33
This class implements the sequential emptiness check as presented in "Three SCC-based Emptiness Check...
Definition: ec.hh:35
Wrapper to accumulate results from intersection and emptiness checks.
Definition: intersect.hh:30
Definition: acc.hh:31
bool push_state(product_state, unsigned dfsnum, acc_cond::mark_t cond)
This method is called to notify the emptiness checks that a new state has been discovered. If this method return false, the state will not be explored. The parameter dfsnum specify an unique id for the state s. Parameter cond represents The value on the ingoing edge to s.
Definition: ec.hh:72
Definition: acc.hh:34

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Tue Apr 18 2017 14:42:56 for spot by doxygen 1.8.13