product.cc 4.43 KB
Newer Older
1
// -*- coding: utf-8 -*-
2
// Copyright (C) 2014, 2015 Laboratoire de Recherche et
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
//
// Spot is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// Spot is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

20
21
22
#include <spot/twaalgos/product.hh>
#include <spot/twa/twagraph.hh>
#include <spot/twaalgos/complete.hh>
23
24
#include <deque>
#include <unordered_map>
25
#include <spot/misc/hash.hh>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

namespace spot
{
  namespace
  {
    typedef std::pair<unsigned, unsigned> product_state;

    struct product_state_hash
    {
      size_t
      operator()(product_state s) const
      {
        return wang32_hash(s.first ^ wang32_hash(s.second));
      }
    };

42
43
44
45
46
47
48
49
50
    static
    twa_graph_ptr product_aux(const const_twa_graph_ptr& left,
			      const const_twa_graph_ptr& right,
			      unsigned left_state,
			      unsigned right_state,
			      bool and_acc)
    {
      std::unordered_map<product_state, unsigned, product_state_hash> s2n;
      std::deque<std::pair<product_state, unsigned>> todo;
51

52
53
54
55
56
      assert(left->get_dict() == right->get_dict());
      auto res = make_twa_graph(left->get_dict());
      res->copy_ap_of(left);
      res->copy_ap_of(right);
      auto left_num = left->num_sets();
57
      auto right_acc = right->get_acceptance() << left_num;
58
      if (and_acc)
59
	right_acc &= left->get_acceptance();
60
      else
61
	right_acc |= left->get_acceptance();
62
      res->set_acceptance(left_num + right->num_sets(), right_acc);
63

64
65
      auto v = new product_states;
      res->set_named_prop("product-states", v);
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
      auto new_state =
	[&](unsigned left_state, unsigned right_state) -> unsigned
	{
	  product_state x(left_state, right_state);
	  auto p = s2n.emplace(x, 0);
	  if (p.second)		// This is a new state
	    {
	      p.first->second = res->new_state();
	      todo.emplace_back(x, p.first->second);
	      assert(p.first->second == v->size());
	      v->push_back(x);
	    }
	  return p.first->second;
	};
81

82
      res->set_init_state(new_state(left_state, right_state));
83
      if (right_acc.is_f())
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
	// Do not bother doing any work if the resulting acceptance is
	// false.
	return res;
      while (!todo.empty())
	{
	  auto top = todo.front();
	  todo.pop_front();
	  for (auto& l: left->out(top.first.first))
	    for (auto& r: right->out(top.first.second))
	      {
		auto cond = l.cond & r.cond;
		if (cond == bddfalse)
		  continue;
		auto dst = new_state(l.dst, r.dst);
		res->new_edge(top.second, dst, cond,
			      res->acc().join(left->acc(), l.acc,
					      right->acc(), r.acc));
		// If right is deterministic, we can abort immediately!
	      }
	}
104

105
106
107
108
109
110
111
112
      res->prop_deterministic(left->prop_deterministic()
			      && right->prop_deterministic());
      res->prop_stutter_invariant(left->prop_stutter_invariant()
				  && right->prop_stutter_invariant());
      res->prop_stutter_sensitive(left->prop_stutter_sensitive()
				  && right->prop_stutter_sensitive());
      res->prop_state_acc(left->prop_state_acc()
				&& right->prop_state_acc());
113
      return res;
114
115
    }
  }
116

117
118
119
120
121
122
  twa_graph_ptr product(const const_twa_graph_ptr& left,
			const const_twa_graph_ptr& right,
			unsigned left_state,
			unsigned right_state)
  {
    return product_aux(left, right, left_state, right_state, true);
123
124
  }

125
  twa_graph_ptr product(const const_twa_graph_ptr& left,
126
			const const_twa_graph_ptr& right)
127
128
129
130
131
132
  {
    return product(left, right,
		   left->get_init_state_number(),
		   right->get_init_state_number());
  }

133
134
135
136
137
  twa_graph_ptr product_or(const const_twa_graph_ptr& left,
			   const const_twa_graph_ptr& right,
			   unsigned left_state,
			   unsigned right_state)
  {
138
139
    return product_aux(complete(left),
		       complete(right),
140
141
142
143
144
145
146
147
148
149
150
		       left_state, right_state, false);
  }

  twa_graph_ptr product_or(const const_twa_graph_ptr& left,
			   const const_twa_graph_ptr& right)
  {
    return product_or(left, right,
		      left->get_init_state_number(),
		      right->get_init_state_number());
  }

151
}