PPL  1.2
BHRZ03_Certificate.cc
Go to the documentation of this file.
1 /* BHRZ03_Certificate class implementation (non-inline member 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 #include "ppl-config.h"
26 #include "Polyhedron_defs.hh"
27 #include "assertions.hh"
28 #include <iostream>
29 
30 namespace PPL = Parma_Polyhedra_Library;
31 
33  : affine_dim(0), lin_space_dim(0), num_constraints(0), num_points(0),
34  num_rays_null_coord(ph.space_dimension(), 0) {
35  // TODO: provide a correct and reasonably efficient
36  // implementation for NNC polyhedra.
37 
38  // The computation of the certificate requires both the
39  // constraint and the generator systems in minimal form.
40  ph.minimize();
41  // It is assumed that `ph' is not an empty polyhedron.
42  PPL_ASSERT(!ph.marked_empty());
43 
44  // The dimension of the polyhedron is obtained by subtracting
45  // the number of equalities from the space dimension.
46  // When counting constraints, for a correct reasoning, we have
47  // to disregard the low-level constraints (i.e., the positivity
48  // constraint and epsilon bounds).
49  const dimension_type space_dim = ph.space_dimension();
50  affine_dim = space_dim;
51  PPL_ASSERT(num_constraints == 0);
54  cs_end = cs.end(); i != cs_end; ++i) {
56  if (i->is_equality()) {
57  --affine_dim;
58  }
59  }
60 
61  PPL_ASSERT(lin_space_dim == 0);
62  PPL_ASSERT(num_points == 0);
63  const Generator_System& gs = ph.minimized_generators();
65  gs_end = gs.end(); i != gs_end; ++i) {
66  switch (i->type()) {
67  case Generator::POINT:
68  // Intentionally fall through.
70  ++num_points;
71  break;
72  case Generator::RAY:
73  // For each i such that 0 <= j < space_dim,
74  // `num_rays_null_coord[j]' will be the number of rays
75  // having exactly `j' coordinates equal to 0.
76  ++num_rays_null_coord[i->expression().num_zeroes(1, space_dim + 1)];
77  break;
78  case Generator::LINE:
79  // Since the generator systems is minimized, the dimension of
80  // the lineality space is equal to the number of lines.
81  ++lin_space_dim;
82  break;
83  }
84  }
85  PPL_ASSERT(OK());
86 
87  // TODO: this is an inefficient workaround.
88  // For NNC polyhedra, constraints might be no longer up-to-date
89  // (and hence, neither minimized) due to the strong minimization
90  // process applied to generators when constructing the certificate.
91  // We have to reinforce the (normal) minimization of the constraint
92  // system. The future, lazy implementation of the strong minimization
93  // process will solve this problem.
94  if (!ph.is_necessarily_closed()) {
95  ph.minimize();
96  }
97 }
98 
99 int
101  PPL_ASSERT(OK() && y.OK());
102  if (affine_dim != y.affine_dim) {
103  return (affine_dim > y.affine_dim) ? 1 : -1;
104  }
105  if (lin_space_dim != y.lin_space_dim) {
106  return (lin_space_dim > y.lin_space_dim) ? 1 : -1;
107  }
108  if (num_constraints != y.num_constraints) {
109  return (num_constraints > y.num_constraints) ? 1 : -1;
110  }
111  if (num_points != y.num_points) {
112  return (num_points > y.num_points) ? 1 : -1;
113  }
114  const dimension_type space_dim = num_rays_null_coord.size();
115  PPL_ASSERT(num_rays_null_coord.size() == y.num_rays_null_coord.size());
116  // Note: iterating upwards, because we have to check first
117  // the number of rays having more NON-zero coordinates.
118  for (dimension_type i = 0; i < space_dim; ++i) {
119  if (num_rays_null_coord[i] != y.num_rays_null_coord[i]) {
120  return (num_rays_null_coord[i] > y.num_rays_null_coord[i]) ? 1 : -1;
121  }
122  }
123  // All components are equal.
124  return 0;
125 }
126 
127 int
129  PPL_ASSERT(ph.space_dimension() == num_rays_null_coord.size());
130 
131  // TODO: provide a correct and reasonably efficient
132  // implementation for NNC polyhedra.
133 
134  // The computation of the certificate requires both the
135  // constraint and the generator systems in minimal form.
136  ph.minimize();
137  // It is assumed that `ph' is a polyhedron containing the
138  // polyhedron described by `*this': hence, it cannot be empty.
139  PPL_ASSERT(!ph.marked_empty());
140 
141  // The dimension of the polyhedron is obtained by subtracting
142  // the number of equalities from the space dimension.
143  // When counting constraints, for a correct reasoning, we have
144  // to disregard the low-level constraints (i.e., the positivity
145  // constraint and epsilon bounds).
146  const dimension_type space_dim = ph.space_dimension();
147  dimension_type ph_affine_dim = space_dim;
148  dimension_type ph_num_constraints = 0;
149  const Constraint_System& cs = ph.minimized_constraints();
151  cs_end = cs.end(); i != cs_end; ++i) {
152  ++ph_num_constraints;
153  if (i->is_equality()) {
154  --ph_affine_dim;
155  }
156  }
157  // TODO: this is an inefficient workaround.
158  // For NNC polyhedra, constraints might be no longer up-to-date
159  // (and hence, neither minimized) due to the strong minimization
160  // process applied to generators when constructing the certificate.
161  // We have to reinforce the (normal) minimization of the constraint
162  // system. The future, lazy implementation of the strong minimization
163  // process will solve this problem.
164  if (!ph.is_necessarily_closed()) {
165  ph.minimize();
166  }
167  // If the dimension of `ph' is increasing, the chain is stabilizing.
168  if (ph_affine_dim > affine_dim) {
169  return 1;
170  }
171  // At this point the two polyhedra must have the same dimension.
172  PPL_ASSERT(ph_affine_dim == affine_dim);
173 
174  // Speculative optimization: in order to better exploit the incrementality
175  // of the comparison, we do not compute information about rays here,
176  // hoping that the other components will be enough.
177  dimension_type ph_lin_space_dim = 0;
178  dimension_type ph_num_points = 0;
179  const Generator_System& gs = ph.minimized_generators();
181  gs_end = gs.end(); i != gs_end; ++i) {
182  switch (i->type()) {
183  case Generator::POINT:
184  // Intentionally fall through.
186  ++ph_num_points;
187  break;
188  case Generator::RAY:
189  break;
190  case Generator::LINE:
191  // Since the generator systems is minimized, the dimension of
192  // the lineality space is equal to the number of lines.
193  ++ph_lin_space_dim;
194  break;
195  }
196  }
197  // TODO: this is an inefficient workaround.
198  // For NNC polyhedra, constraints might be no longer up-to-date
199  // (and hence, neither minimized) due to the strong minimization
200  // process applied to generators when constructing the certificate.
201  // We have to reinforce the (normal) minimization of the constraint
202  // system. The future, lazy implementation of the strong minimization
203  // process will solve this problem.
204  if (!ph.is_necessarily_closed()) {
205  ph.minimize();
206  }
207  // If the dimension of the lineality space is increasing,
208  // then the chain is stabilizing.
209  if (ph_lin_space_dim > lin_space_dim) {
210  return 1;
211  }
212  // At this point the lineality space of the two polyhedra must have
213  // the same dimension.
214  PPL_ASSERT(ph_lin_space_dim == lin_space_dim);
215 
216  // If the number of constraints of `ph' is decreasing, then the chain
217  // is stabilizing. If it is increasing, the chain is not stabilizing.
218  // If they are equal, further investigation is needed.
219  if (ph_num_constraints != num_constraints) {
220  return (ph_num_constraints < num_constraints) ? 1 : -1;
221  }
222  // If the number of points of `ph' is decreasing, then the chain
223  // is stabilizing. If it is increasing, the chain is not stabilizing.
224  // If they are equal, further investigation is needed.
225  if (ph_num_points != num_points) {
226  return (ph_num_points < num_points) ? 1 : -1;
227  }
228  // The speculative optimization was not worth:
229  // compute information about rays.
230  std::vector<dimension_type> ph_num_rays_null_coord(ph.space_dim, 0);
232  gs_end = gs.end(); i != gs_end; ++i) {
233  if (i->is_ray()) {
234  ++ph_num_rays_null_coord[i->expression().num_zeroes(1, space_dim + 1)];
235  }
236  }
237  // Compare (lexicographically) the two vectors:
238  // if ph_num_rays_null_coord < num_rays_null_coord the chain is stabilizing.
239  for (dimension_type i = 0; i < space_dim; ++i) {
240  if (ph_num_rays_null_coord[i] != num_rays_null_coord[i]) {
241  return (ph_num_rays_null_coord[i] < num_rays_null_coord[i]) ? 1 : -1;
242  }
243  }
244  // All components are equal.
245  return 0;
246 }
247 
248 bool
250 #ifndef NDEBUG
251  using std::endl;
252  using std::cerr;
253 #endif
254 
255  // The dimension of the vector space.
256  const dimension_type space_dim = num_rays_null_coord.size();
257 
258  if (affine_dim > space_dim) {
259 #ifndef NDEBUG
260  cerr << "In the BHRZ03 certificate about a non-empty polyhedron:"
261  << endl
262  << "the affine dimension is greater than the space dimension!"
263  << endl;
264 #endif
265  return false;
266  }
267 
268  if (lin_space_dim > affine_dim) {
269 #ifndef NDEBUG
270  cerr << "In the BHRZ03 certificate about a non-empty polyhedron:"
271  << endl
272  << "the lineality space dimension is greater than "
273  << "the affine dimension!"
274  << endl;
275 #endif
276  return false;
277  }
278 
279  if (num_constraints < space_dim - affine_dim) {
280 #ifndef NDEBUG
281  cerr << "In the BHRZ03 certificate about a non-empty polyhedron:"
282  << endl
283  << "in a vector space of dimension `n',"
284  << "any polyhedron of affine dimension `k'" << endl
285  << "should have `n-k' non-redundant constraints at least."
286  << endl
287  << "Here space_dim = " << space_dim << ", "
288  << "affine_dim = " << affine_dim << ", "
289  << "but num_constraints = " << num_constraints << "!"
290  << endl;
291 #endif
292  return false;
293  }
294 
295  if (num_points == 0) {
296 #ifndef NDEBUG
297  cerr << "In the BHRZ03 certificate about a non-empty polyhedron:"
298  << endl
299  << "the generator system has no points!"
300  << endl;
301 #endif
302  return false;
303  }
304 
305  if (lin_space_dim == space_dim) {
306  // This was a universe polyhedron.
307  if (num_constraints > 0) {
308 #ifndef NDEBUG
309  cerr << "In the BHRZ03 certificate about a non-empty polyhedron:"
310  << endl
311  << "a universe polyhedron has non-redundant constraints!"
312  << endl;
313 #endif
314  return false;
315  }
316 
317  if (num_points != 1) {
318 #ifndef NDEBUG
319  cerr << "In the BHRZ03 certificate about a non-empty polyhedron:"
320  << endl
321  << "a universe polyhedron has more than one non-redundant point!"
322  << endl;
323 #endif
324  return false;
325  }
326  }
327 
328  // All tests passed.
329  return true;
330 }
dimension_type affine_dim
Affine dimension of the polyhedron.
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
bool OK() const
Check if gathered information is meaningful.
size_t dimension_type
An unsigned integral type for representing space dimensions.
dimension_type num_points
Number of non-redundant points in a generator system for the polyhedron.
dimension_type num_constraints
Cardinality of a non-redundant constraint system for the polyhedron.
dimension_type num_constraints(const Constraint_System &cs)
Helper returning number of constraints in system.
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
int compare(const BHRZ03_Certificate &y) const
The comparison function for certificates.
The base class for convex polyhedra.
std::vector< dimension_type > num_rays_null_coord
A vector containing, for each index `0 <= i < space_dim', the number of non-redundant rays in a gener...
const_iterator end() const
Returns the past-the-end const_iterator.
const Generator_System & minimized_generators() const
Returns the system of generators, with no redundant generator.
dimension_type lin_space_dim
Dimension of the lineality space of the polyhedron.
dimension_type num_constraints(const Constraint_System &cs)
bool minimize(const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.
The convergence certificate for the BHRZ03 widening operator.
The entire library is confined to this namespace.
Definition: version.hh:61
dimension_type space_dim
The number of dimensions of the enclosing vector space.
bool is_necessarily_closed() const
Returns true if and only if the polyhedron is necessarily closed.
const_iterator end() const
Returns the past-the-end const_iterator.
const_iterator begin() const
Returns the const_iterator pointing to the first generator, if *this is not empty; otherwise...
const Constraint_System & minimized_constraints() const
Returns the system of constraints, with no redundant constraint.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.