PPL  1.2
Ask_Tell_templates.hh
Go to the documentation of this file.
1 /* Ask_Tell class implementation: non-inline template functions.
2  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_Ask_Tell_templates_hh
25 #define PPL_Ask_Tell_templates_hh 1
26 
27 #include <iostream>
28 
29 namespace Parma_Polyhedra_Library {
30 
31 template <typename D>
32 bool
34  for (const_iterator x_begin = begin(),
35  x_end = end(), xi = x_begin; xi != x_end; ++xi)
36  for (const_iterator yi = x_begin; yi != x_end; ++yi)
37  if (xi != yi) {
38  if (xi->tell().definitely_entails(yi->tell())) {
39  if (yi->ask().definitely_entails(xi->ask())) {
40  return false;
41  }
42  }
43  else if (xi->tell().definitely_entails(yi->ask())) {
44  return false;
45  }
46  if (xi->ask().definitely_entails(yi->ask())
47  && !xi->ask().definitely_entails(yi->tell())) {
48  return false;
49  }
50  }
51  return true;
52 }
53 
54 template <typename D>
55 bool
57  bool changed = false;
58  for (Sequence_iterator x_begin = sequence.begin(),
59  x_end = sequence.end(), xi = x_begin; xi != x_end; ++xi)
60  for (Sequence_iterator yi = x_begin; yi != x_end; ) {
61  if (xi != yi
62  && yi->ask().definitely_entails(xi->ask())
63  && xi->tell().definitely_entails(yi->tell())) {
64  yi = sequence.erase(yi);
65  x_begin = sequence.begin();
66  x_end = sequence.end();
67  changed = true;
68  }
69  else {
70  ++yi;
71  }
72  }
73  PPL_ASSERT_HEAVY(OK());
74  return changed;
75 }
76 
77 template <typename D>
78 bool
80  bool changed = false;
81  for (Sequence_iterator x_begin = sequence.begin(),
82  x_end = sequence.end(), xi = x_begin; xi != x_end; ++xi) {
83  D& xi_tell = xi->tell();
84  bool tell_changed;
85  do {
86  tell_changed = false;
87  for (Sequence_iterator yi = x_begin; yi != x_end; ++yi) {
88  if (xi != yi
89  && xi_tell.definitely_entails(yi->ask())
90  && !xi_tell.definitely_entails(yi->tell())) {
91  xi_tell.meet_assign(yi->tell());
92  changed = tell_changed = true;
93  }
94  }
95  } while (tell_changed);
96  }
97  if (changed) {
98  (void) reduce();
99  }
100  PPL_ASSERT_HEAVY(OK());
101  return changed;
102 }
103 
104 template <typename D>
105 bool
107  bool changed = false;
108  for (Sequence_iterator x_begin = sequence.begin(),
109  x_end = sequence.end(), xi = x_begin; xi != x_end; ) {
110  D& xi_ask = xi->ask();
111  D& xi_tell = xi->tell();
112  // We may strengthen the ask component of the pair referenced by `xi'.
113  // If we do it, the pair may become useless (i.e., with the ask
114  // component entailing the tell component) and thus to be
115  // discarded.
116  bool must_check_xi_pair = false;
117  bool ask_changed;
118  do {
119  ask_changed = false;
120  for (Sequence_iterator yi = x_begin; yi != x_end; ++yi) {
121  if (xi != yi) {
122  D& yi_ask = yi->ask();
123  D& yi_tell = yi->tell();
124  if (xi_ask.definitely_entails(yi_ask)
125  && !xi_ask.definitely_entails(yi_tell)) {
126  xi_ask.meet_assign(yi_tell);
127  must_check_xi_pair = true;
128  ask_changed = true;
129  }
130  }
131  }
132  } while (ask_changed);
133  if (must_check_xi_pair) {
134  changed = true;
135  if (xi_ask.definitely_entails(xi_tell)) {
136  xi = sequence.erase(xi);
137  x_begin = sequence.begin();
138  x_end = sequence.end();
139  }
140  else {
141  ++xi;
142  }
143  }
144  else {
145  ++xi;
146  }
147  }
148  if (changed) {
149  (void) reduce();
150  }
151  PPL_ASSERT_HEAVY(OK());
152  return changed;
153 }
154 
155 template <typename D>
156 void
158  if (D::has_nontrivial_weakening()) {
159  Sequence new_sequence;
160  for (Sequence_const_iterator x_begin = sequence.begin(),
161  x_end = sequence.end(), xi = x_begin; xi != x_end; ++xi)
162  for (Sequence_const_iterator yi = x_begin; yi != x_end; ++yi) {
163  if (xi != yi) {
164  const D& xi_ask = xi->ask();
165  const D& yi_ask = yi->ask();
166  if (xi_ask.definitely_entails(yi_ask)) {
167  D new_ask = xi_ask;
168  new_ask.weakening_assign(yi->tell());
169  new_ask.meet_assign(yi_ask);
170  if (!new_ask.definitely_entails(xi_ask)) {
171  new_sequence.push_back(Pair(new_ask, xi->tell()));
172  }
173  }
174  }
175  }
176  if (!new_sequence.empty()) {
177  Ask_Tell& x = const_cast<Ask_Tell&>(*this);
178  std::copy(new_sequence.begin(), new_sequence.end(),
179  back_inserter(x.sequence));
180  x.reduce();
181  x.deduce();
182  normalized = false;
183  }
184  }
185  else if (!normalized) {
186  Ask_Tell& x = const_cast<Ask_Tell&>(*this);
187  x.reduce();
188  x.deduce();
189  }
190  PPL_ASSERT_HEAVY(OK());
191 }
192 
193 template <typename D>
194 void
196  const Ask_Tell& x = *this;
197  x.deabsorb();
198  y.deabsorb();
199  Ask_Tell<D> z;
200  for (typename Ask_Tell<D>::const_iterator xi = x.begin(),
201  x_end = x.end(); xi != x_end; ++xi)
202  for (typename Ask_Tell<D>::const_iterator yi = y.begin(),
203  y_end = y.end(); yi != y_end; ++yi) {
204  D tell = xi->tell();
205  tell.upper_bound_assign(yi->tell());
206  D ask = xi->ask();
207  ask.meet_assign(yi->ask());
208  if (!ask.definitely_entails(tell)) {
209  z.pair_insert(ask, tell);
210  }
211  }
212  *this = z;
213  PPL_ASSERT_HEAVY(OK());
214 }
215 
216 template <typename D>
217 bool
219  for (typename Ask_Tell<D>::const_iterator xi = begin(),
220  x_end = end(); xi != x_end; ++xi) {
221  const Ask_Tell_Pair<D>& p = *xi;
222  if (!p.ask().OK()) {
223  return false;
224  }
225  if (!p.tell().OK()) {
226  return false;
227  }
228  if (p.ask().definitely_entails(p.tell())) {
229 #ifndef NDEBUG
230  using namespace IO_Operators;
231  std::cerr << "Illegal agent in ask-and-tell: "
232  << p.ask() << " -> " << p.tell()
233  << std::endl;
234 #endif
235  return false;
236  }
237  }
238  if (normalized && !check_normalized()) {
239 #ifndef NDEBUG
240  std::cerr << "Ask_Tell claims to be normalized, but it is not!"
241  << std::endl;
242 #endif
243  return false;
244  }
245  return true;
246 }
247 
248 namespace IO_Operators {
249 
250 template <typename D>
251 std::ostream&
252 operator<<(std::ostream& s, const Ask_Tell<D>& x) {
253  if (x.is_top()) {
254  s << "true";
255  }
256  else if (x.is_bottom()) {
257  s << "false";
258  }
259  else {
260  for (typename Ask_Tell<D>::const_iterator xi = x.begin(),
261  x_end = x.end(); xi != x_end; ++xi)
262  s << "(" << xi->ask() << " -> " << xi->tell() << ")";
263  }
264  return s;
265 }
266 
267 } // namespace IO_Operators
268 
269 } // namespace Parma_Polyhedra_Library
270 
271 #endif // !defined(PPL_Ask_Tell_templates_hh)
iterator begin()
Returns an iterator pointing to the first pair, if *this is not empty; otherwise, returns the past-th...
const D & ask() const
Const accessor to the ask component.
Sequence::iterator Sequence_iterator
Alias for the low-level iterator on the pairs.
iterator end()
Returns the past-the-end iterator.
Sequence sequence
The sequence container holding the pairs/.
std::list< Ask_Tell_Pair< D > > Sequence
An ask-tell agent is implemented as a sequence of ask-tell pairs.
void upper_bound_assign(const Ask_Tell &y)
Assigns to *this an upper bound of *this and y.
A const_iterator on a sequence of read-only objects.
The entire library is confined to this namespace.
Definition: version.hh:61
Sequence::const_iterator Sequence_const_iterator
Alias for the low-level const_iterator on the pairs.
const D & tell() const
Const accessor to the ask component.
bool check_normalized() const
Does the hard work of checking whether *this is normalized and returns true if and only if it is...
A pair of ask and tell descriptions.
void pair_insert(const D &a, const D &t)
The ask and tell construction on a base-level domain.
bool OK() const
Checks if all the invariants are satisfied.