00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <ppl-config.h>
00025
00026 #include "Constraint.defs.hh"
00027 #include "Variable.defs.hh"
00028 #include "Congruence.defs.hh"
00029 #include <iostream>
00030 #include <sstream>
00031 #include <stdexcept>
00032
00033 namespace PPL = Parma_Polyhedra_Library;
00034
00035 void
00036 PPL::Constraint::throw_invalid_argument(const char* method,
00037 const char* message) const {
00038 std::ostringstream s;
00039 s << "PPL::Constraint::" << method << ":" << std::endl
00040 << message;
00041 throw std::invalid_argument(s.str());
00042 }
00043
00044 void
00045 PPL::Constraint::throw_dimension_incompatible(const char* method,
00046 const char* name_var,
00047 const Variable v) const {
00048 std::ostringstream s;
00049 s << "PPL::Constraint::" << method << ":" << std::endl
00050 << "this->space_dimension() == " << space_dimension() << ", "
00051 << name_var << ".space_dimension() == " << v.space_dimension() << ".";
00052 throw std::invalid_argument(s.str());
00053 }
00054
00055 PPL::Constraint
00056 PPL::Constraint::construct_epsilon_geq_zero() {
00057 Linear_Expression e = Variable(0);
00058 Constraint c(e, NONSTRICT_INEQUALITY, NOT_NECESSARILY_CLOSED);
00059 return c;
00060 }
00061
00062 PPL::Constraint::Constraint(const Congruence& cg)
00063 : Linear_Row(cg.is_equality()
00064
00065 ? cg.space_dimension() + 1
00066 : (throw_invalid_argument("Constraint(cg)",
00067 "congruence cg must be an equality."),
00068 0),
00069
00070 compute_capacity(cg.space_dimension() + 2, Row::max_size()),
00071 Flags(NECESSARILY_CLOSED, LINE_OR_EQUALITY)) {
00072 Constraint& c = *this;
00073
00074 for (dimension_type i = cg.space_dimension() + 1; i-- > 0; )
00075 c[i] = cg[i];
00076
00077 strong_normalize();
00078 }
00079
00080 PPL::Constraint::Constraint(const Congruence& cg,
00081 dimension_type sz,
00082 dimension_type capacity)
00083 : Linear_Row(cg.is_equality()
00084 ? sz
00085 : (throw_invalid_argument("Constraint(cg, sz, c)",
00086 "congruence cg must be an equality."),
00087 0),
00088 capacity,
00089 Flags(NECESSARILY_CLOSED, LINE_OR_EQUALITY)) {
00090 Constraint& c = *this;
00091
00092 PPL_ASSERT(sz > 0);
00093 while (sz-- > 0)
00094 c[sz] = cg[sz];
00095 }
00096
00097 bool
00098 PPL::Constraint::is_tautological() const {
00099 PPL_ASSERT(size() > 0);
00100 const Constraint& x = *this;
00101 if (x.all_homogeneous_terms_are_zero())
00102 if (is_equality())
00103 return x[0] == 0;
00104 else
00105
00106 return x[0] >= 0;
00107 else
00108
00109 if (is_necessarily_closed())
00110 return false;
00111 else {
00112
00113 const dimension_type eps_index = size() - 1;
00114 const int eps_sign = sgn(x[eps_index]);
00115 if (eps_sign > 0)
00116
00117 return true;
00118 if (eps_sign == 0)
00119
00120 return false;
00121 else {
00122
00123 if (x[0] <= 0)
00124
00125
00126 return false;
00127
00128 for (dimension_type i = eps_index; --i > 0; )
00129 if (x[i] != 0)
00130 return false;
00131
00132
00133 return true;
00134 }
00135 }
00136 }
00137
00138 bool
00139 PPL::Constraint::is_inconsistent() const {
00140 PPL_ASSERT(size() > 0);
00141 const Constraint& x = *this;
00142 if (x.all_homogeneous_terms_are_zero())
00143
00144 if (is_equality())
00145 return x[0] != 0;
00146 else
00147
00148 return x[0] < 0;
00149 else
00150
00151 if (is_necessarily_closed())
00152 return false;
00153 else {
00154
00155 const dimension_type eps_index = size() - 1;
00156 if (x[eps_index] >= 0)
00157
00158
00159
00160 return false;
00161 else {
00162
00163 if (x[0] > 0)
00164
00165
00166 return false;
00167
00168 for (dimension_type i = eps_index; --i > 0; )
00169 if (x[i] != 0)
00170 return false;
00171
00172
00173 return true;
00174 }
00175 }
00176 }
00177
00178 bool
00179 PPL::Constraint::is_equivalent_to(const Constraint& y) const {
00180 const Constraint& x = *this;
00181 const dimension_type x_space_dim = x.space_dimension();
00182 if (x_space_dim != y.space_dimension())
00183 return false;
00184
00185 const Type x_type = x.type();
00186 if (x_type != y.type()) {
00187
00188 if (x.is_tautological())
00189 return y.is_tautological();
00190 else
00191 return x.is_inconsistent() && y.is_inconsistent();
00192 }
00193
00194 if (x_type == STRICT_INEQUALITY) {
00195
00196
00197
00198
00199 Linear_Expression x_expr(x);
00200 Linear_Expression y_expr(y);
00201
00202 x_expr.normalize();
00203 y_expr.normalize();
00204
00205 for (dimension_type i = x_space_dim + 1; i-- > 0; )
00206 if (x_expr[i] != y_expr[i])
00207 return false;
00208 return true;
00209 }
00210
00211
00212
00213
00214 for (dimension_type i = x_space_dim + 1; i-- > 0; )
00215 if (x[i] != y[i])
00216 return false;
00217 return true;
00218 }
00219
00220 const PPL::Constraint* PPL::Constraint::zero_dim_false_p = 0;
00221 const PPL::Constraint* PPL::Constraint::zero_dim_positivity_p = 0;
00222 const PPL::Constraint* PPL::Constraint::epsilon_geq_zero_p = 0;
00223 const PPL::Constraint* PPL::Constraint::epsilon_leq_one_p = 0;
00224
00225 void
00226 PPL::Constraint::initialize() {
00227 PPL_ASSERT(zero_dim_false_p == 0);
00228 zero_dim_false_p
00229 = new Constraint(Linear_Expression::zero() == Coefficient_one());
00230
00231 PPL_ASSERT(zero_dim_positivity_p == 0);
00232 zero_dim_positivity_p
00233 = new Constraint(Linear_Expression::zero() <= Coefficient_one());
00234
00235 PPL_ASSERT(epsilon_geq_zero_p == 0);
00236 epsilon_geq_zero_p
00237 = new Constraint(construct_epsilon_geq_zero());
00238
00239 PPL_ASSERT(epsilon_leq_one_p == 0);
00240 epsilon_leq_one_p
00241 = new Constraint(Linear_Expression::zero() < Coefficient_one());
00242 }
00243
00244 void
00245 PPL::Constraint::finalize() {
00246 PPL_ASSERT(zero_dim_false_p != 0);
00247 delete zero_dim_false_p;
00248 zero_dim_false_p = 0;
00249
00250 PPL_ASSERT(zero_dim_positivity_p != 0);
00251 delete zero_dim_positivity_p;
00252 zero_dim_positivity_p = 0;
00253
00254 PPL_ASSERT(epsilon_geq_zero_p != 0);
00255 delete epsilon_geq_zero_p;
00256 epsilon_geq_zero_p = 0;
00257
00258 PPL_ASSERT(epsilon_leq_one_p != 0);
00259 delete epsilon_leq_one_p;
00260 epsilon_leq_one_p = 0;
00261 }
00262
00264 std::ostream&
00265 PPL::IO_Operators::operator<<(std::ostream& s, const Constraint& c) {
00266 const dimension_type num_variables = c.space_dimension();
00267 PPL_DIRTY_TEMP_COEFFICIENT(cv);
00268 bool first = true;
00269 for (dimension_type v = 0; v < num_variables; ++v) {
00270 cv = c.coefficient(Variable(v));
00271 if (cv != 0) {
00272 if (!first) {
00273 if (cv > 0)
00274 s << " + ";
00275 else {
00276 s << " - ";
00277 neg_assign(cv);
00278 }
00279 }
00280 else
00281 first = false;
00282 if (cv == -1)
00283 s << "-";
00284 else if (cv != 1)
00285 s << cv << "*";
00286 s << PPL::Variable(v);
00287 }
00288 }
00289 if (first)
00290 s << Coefficient_zero();
00291 const char* relation_symbol = 0;
00292 switch (c.type()) {
00293 case Constraint::EQUALITY:
00294 relation_symbol = " = ";
00295 break;
00296 case Constraint::NONSTRICT_INEQUALITY:
00297 relation_symbol = " >= ";
00298 break;
00299 case Constraint::STRICT_INEQUALITY:
00300 relation_symbol = " > ";
00301 break;
00302 }
00303 s << relation_symbol << -c.inhomogeneous_term();
00304 return s;
00305 }
00306
00308 std::ostream&
00309 PPL::IO_Operators::operator<<(std::ostream& s, const Constraint::Type& t) {
00310 const char* n = 0;
00311 switch (t) {
00312 case Constraint::EQUALITY:
00313 n = "EQUALITY";
00314 break;
00315 case Constraint::NONSTRICT_INEQUALITY:
00316 n = "NONSTRICT_INEQUALITY";
00317 break;
00318 case Constraint::STRICT_INEQUALITY:
00319 n = "STRICT_INEQUALITY";
00320 break;
00321 }
00322 s << n;
00323 return s;
00324 }
00325
00326 PPL_OUTPUT_DEFINITIONS(Constraint)
00327
00328 bool
00329 PPL::Constraint::OK() const {
00330
00331 if (!Linear_Row::OK())
00332 return false;
00333
00334
00335 const dimension_type min_size = is_necessarily_closed() ? 1 : 2;
00336 if (size() < min_size) {
00337 #ifndef NDEBUG
00338 std::cerr << "Constraint has fewer coefficients than the minimum "
00339 << "allowed by its topology:"
00340 << std::endl
00341 << "size is " << size()
00342 << ", minimum is " << min_size << "."
00343 << std::endl;
00344 #endif
00345 return false;
00346 }
00347
00348 if (is_equality() && !is_necessarily_closed() && (*this)[size() - 1] != 0) {
00349 #ifndef NDEBUG
00350 std::cerr << "Illegal constraint: an equality cannot be strict."
00351 << std::endl;
00352 #endif
00353 return false;
00354 }
00355
00356
00357 Constraint tmp = *this;
00358 tmp.strong_normalize();
00359 if (tmp != *this) {
00360 #ifndef NDEBUG
00361 std::cerr << "Constraint is not strongly normalized as it should be."
00362 << std::endl;
00363 #endif
00364 return false;
00365 }
00366
00367
00368 return true;
00369 }