/* Constraint class declaration.
Copyright (C) 2001-2004 Roberto Bagnara <bagnara@cs.unipr.it>
This file is part of the Parma Polyhedra Library (PPL).
The PPL 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 2 of the License, or (at your
option) any later version.
The PPL 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.
For the most up-to-date information see the Parma Polyhedra Library
site: http://www.cs.unipr.it/ppl/ . */
#ifndef PPL_Constraint_defs_hh
#define PPL_Constraint_defs_hh 1
#include "Constraint.types.hh"
#include "Row.defs.hh"
#include "Variable.defs.hh"
#include "LinExpression.defs.hh"
#include "ConSys.defs.hh"
#include "Polyhedron.types.hh"
#include <iosfwd>
namespace Parma_Polyhedra_Library {
namespace IO_Operators {
//! Output operator.
/*! \relates Parma_Polyhedra_Library::Constraint */
std::ostream& operator<<(std::ostream& s, const Constraint& c);
} // namespace IO_Operators
// Put them in the namespace here to declare them friend later.
//! Returns the constraint \p e1 = \p e2.
/*! \relates Constraint */
Constraint operator==(const LinExpression& e1, const LinExpression& e2);
//! Returns the constraint \p e = \p n.
/*! \relates Constraint */
Constraint operator==(const LinExpression& e, const Integer& n);
//! Returns the constraint \p n = \p e.
/*! \relates Constraint */
Constraint operator==(const Integer& n, const LinExpression& e);
//! Returns the constraint \p e1 \<= \p e2.
/*! \relates Constraint */
Constraint operator<=(const LinExpression& e1, const LinExpression& e2);
//! Returns the constraint \p e \<= \p n.
/*! \relates Constraint */
Constraint operator<=(const LinExpression& e, const Integer& n);
//! Returns the constraint \p n \<= \p e.
/*! \relates Constraint */
Constraint operator<=(const Integer& n, const LinExpression& e);
//! Returns the constraint \p e1 \>= \p e2.
/*! \relates Constraint */
Constraint operator>=(const LinExpression& e1, const LinExpression& e2);
//! Returns the constraint \p e \>= \p n.
/*! \relates Constraint */
Constraint operator>=(const LinExpression& e, const Integer& n);
//! Returns the constraint \p n \>= \p e.
/*! \relates Constraint */
Constraint operator>=(const Integer& n, const LinExpression& e);
//! Returns the constraint \p e1 \< \p e2.
/*! \relates Constraint */
Constraint operator<(const LinExpression& e1, const LinExpression& e2);
//! Returns the constraint \p e \< \p n.
/*! \relates Constraint */
Constraint operator<(const LinExpression& e, const Integer& n);
//! Returns the constraint \p n \< \p e.
/*! \relates Constraint */
Constraint operator<(const Integer& n, const LinExpression& e);
//! Returns the constraint \p e1 \> \p e2.
/*! \relates Constraint */
Constraint operator>(const LinExpression& e1, const LinExpression& e2);
//! Returns the constraint \p e \> \p n.
/*! \relates Constraint */
Constraint operator>(const LinExpression& e, const Integer& n);
//! Returns the constraint \p n \> \p e.
/*! \relates Constraint */
Constraint operator>(const Integer& n, const LinExpression& e);
} // namespace Parma_Polyhedra_Library
namespace std {
//! Specializes <CODE>std::swap</CODE>.
/*! \relates Parma_Polyhedra_Library::Constraint */
void swap(Parma_Polyhedra_Library::Constraint& x,
Parma_Polyhedra_Library::Constraint& y);
} // namespace std
//! A linear equality or inequality.
/*!
An object of the class Constraint is either:
- an equality: \f$\sum_{i=0}^{n-1} a_i x_i + b = 0\f$;
- a non-strict inequality: \f$\sum_{i=0}^{n-1} a_i x_i + b \geq 0\f$; or
- a strict inequality: \f$\sum_{i=0}^{n-1} a_i x_i + b > 0\f$;
where \f$n\f$ is the dimension of the space,
\f$a_i\f$ is the integer coefficient of variable \f$x_i\f$
and \f$b\f$ is the integer inhomogeneous term.
\par How to build a constraint
Constraints are typically built by applying a relation symbol
to a pair of linear expressions.
Available relation symbols are equality (<CODE>==</CODE>),
non-strict inequalities (<CODE>\>=</CODE> and <CODE>\<=</CODE>) and
strict inequalities (<CODE>\<</CODE> and <CODE>\></CODE>).
The space-dimension of a constraint is defined as the maximum
space-dimension of the arguments of its constructor.
\par
In the following examples it is assumed that variables
<CODE>x</CODE>, <CODE>y</CODE> and <CODE>z</CODE>
are defined as follows:
\code
Variable x(0);
Variable y(1);
Variable z(2);
\endcode
\par Example 1
The following code builds the equality constraint
\f$3x + 5y - z = 0\f$, having space-dimension \f$3\f$:
\code
Constraint eq_c(3*x + 5*y - z == 0);
\endcode
The following code builds the (non-strict) inequality constraint
\f$4x \geq 2y - 13\f$, having space-dimension \f$2\f$:
\code
Constraint ineq_c(4*x >= 2*y - 13);
\endcode
The corresponding strict inequality constraint
\f$4x > 2y - 13\f$ is obtained as follows:
\code
Constraint strict_ineq_c(4*x > 2*y - 13);
\endcode
An unsatisfiable constraint on the zero-dimension space \f$\Rset^0\f$
can be specified as follows:
\code
Constraint false_c = Constraint::zero_dim_false();
\endcode
Equivalent, but more involved ways are the following:
\code
Constraint false_c1(LinExpression::zero() == 1);
Constraint false_c2(LinExpression::zero() >= 1);
Constraint false_c3(LinExpression::zero() > 0);
\endcode
In contrast, the following code defines an unsatisfiable constraint
having space-dimension \f$3\f$:
\code
Constraint false_c(0*z == 1);
\endcode
\par How to inspect a constraint
Several methods are provided to examine a constraint and extract
all the encoded information: its space-dimension, its type
(equality, non-strict inequality, strict inequality) and
the value of its integer coefficients.
\par Example 2
The following code shows how it is possible to access each single
coefficient of a constraint. Given an inequality constraint
(in this case \f$x - 5y + 3z <= 4\f$), we construct a new constraint
corresponding to its complement (thus, in this case we want to obtain
the strict inequality constraint \f$x - 5y + 3z > 4\f$).
\code
Constraint c1(x - 5*y + 3*z <= 4);
cout << "Constraint c1: " << c1 << endl;
if (c1.is_equality())
cout << "Constraint c1 is not an inequality." << endl;
else {
LinExpression e;
for (int i = c1.space_dimension() - 1; i >= 0; i--)
e += c1.coefficient(Variable(i)) * Variable(i);
e += c1.inhomogeneous_term();
Constraint c2 = c1.is_strict_inequality() ? (e <= 0) : (e < 0);
cout << "Complement c2: " << c2 << endl;
}
\endcode
The actual output is the following:
\code
Constraint c1: -A + 5*B - 3*C >= -4
Complement c2: A - 5*B + 3*C > 4
\endcode
Note that, in general, the particular output obtained can be
syntactically different from the (semantically equivalent)
constraint considered.
*/
class Parma_Polyhedra_Library::Constraint : private Row {
public:
//! Ordinary copy-constructor.
Constraint(const Constraint& c);
//! Destructor.
~Constraint();
//! Assignment operator.
Constraint& operator=(const Constraint& c);
//! Returns the dimension of the vector space enclosing \p *this.
dimension_type space_dimension() const;
//! The constraint type.
enum Type {
/*! The constraint is an equality. */
EQUALITY,
/*! The constraint is a non-strict inequality. */
NONSTRICT_INEQUALITY,
/*! The constraint is a strict inequality. */
STRICT_INEQUALITY
};
//! Returns the constraint type of \p *this.
Type type() const;
//! \brief
//! Returns <CODE>true</CODE> if and only if
//! \p *this is an equality constraint.
bool is_equality() const;
//! \brief
//! Returns <CODE>true</CODE> if and only if
//! \p *this is an inequality constraint (either strict or non-strict).
bool is_inequality() const;
//! \brief
//! Returns <CODE>true</CODE> if and only if
//! \p *this is a non-strict inequality constraint.
bool is_nonstrict_inequality() const;
//! \brief
//! Returns <CODE>true</CODE> if and only if
//! \p *this is a strict inequality constraint.
bool is_strict_inequality() const;
//! Returns the coefficient of \p v in \p *this.
/*!
\exception std::invalid_argument thrown if the index of \p v
is greater than or equal to the space-dimension of \p *this.
*/
const Integer& coefficient(Variable v) const;
//! Returns the inhomogeneous term of \p *this.
const Integer& inhomogeneous_term() const;
//! The unsatisfiable (zero-dimension space) constraint \f$0 = 1\f$.
static const Constraint& zero_dim_false();
//! \brief
//! The true (zero-dimension space) constraint \f$0 \leq 1\f$,
//! also known as <EM>positivity constraint</EM>.
static const Constraint& zero_dim_positivity();
//! Checks if all the invariants are satisfied.
bool OK() const;
private:
friend class Parma_Polyhedra_Library::ConSys;
friend class Parma_Polyhedra_Library::ConSys::const_iterator;
friend class Parma_Polyhedra_Library::Polyhedron;
// FIXME: the following friend declaration is only to grant access to
// GenSys::satisfied_by_all_generators().
friend class Parma_Polyhedra_Library::GenSys;
friend const Integer&
Parma_Polyhedra_Library::operator*(const Constraint& c,
const Generator& g);
friend const Integer&
Parma_Polyhedra_Library::reduced_scalar_product(const Constraint& c,
const Generator& g);
friend
Parma_Polyhedra_Library::LinExpression::LinExpression(const Constraint& c);
friend void std::swap(Parma_Polyhedra_Library::Constraint& x,
Parma_Polyhedra_Library::Constraint& y);
//! Default constructor: private and not implemented.
Constraint();
//! \brief
//! Builds a constraint (of unspecified type) stealing
//! the coefficients from \p e.
explicit Constraint(LinExpression& e);
//! \brief
//! Builds a constraint, having type \p type, which is able
//! to store \p sz coefficients, whose values are left unspecified.
Constraint(Row::Type t, dimension_type sz);
//! Swaps \p *this with \p y.
void swap(Constraint& y);
//! \brief
//! Throws a <CODE>std::invalid_argument</CODE> exception
//! containing the appropriate error message.
void
throw_dimension_incompatible(const char* method,
const char* name_var,
Variable v) const;
friend Constraint
Parma_Polyhedra_Library::operator==(const LinExpression& e1,
const LinExpression& e2);
friend Constraint
Parma_Polyhedra_Library::operator==(const LinExpression& e,
const Integer& n);
friend Constraint
Parma_Polyhedra_Library::operator==(const Integer& n,
const LinExpression& e);
friend Constraint
Parma_Polyhedra_Library::operator>=(const LinExpression& e1,
const LinExpression& e2);
friend Constraint
Parma_Polyhedra_Library::operator>=(const LinExpression& e,
const Integer& n);
friend Constraint
Parma_Polyhedra_Library::operator>=(const Integer& n,
const LinExpression& e);
friend Constraint
Parma_Polyhedra_Library::operator<=(const LinExpression& e1,
const LinExpression& e2);
friend Constraint
Parma_Polyhedra_Library::operator<=(const LinExpression& e,
const Integer& n);
friend Constraint
Parma_Polyhedra_Library::operator<=(const Integer& n,
const LinExpression& e);
friend Constraint
Parma_Polyhedra_Library::operator>(const LinExpression& e1,
const LinExpression& e2);
friend Constraint
Parma_Polyhedra_Library::operator>(const LinExpression& e,
const Integer& n);
friend Constraint
Parma_Polyhedra_Library::operator>(const Integer& n,
const LinExpression& e);
friend Constraint
Parma_Polyhedra_Library::operator<(const LinExpression& e1,
const LinExpression& e2);
friend Constraint
Parma_Polyhedra_Library::operator<(const LinExpression& e,
const Integer& n);
friend Constraint
Parma_Polyhedra_Library::operator<(const Integer& n,
const LinExpression& e);
//! Copy-constructor with given size.
Constraint(const Constraint& c, dimension_type sz);
//! \brief
//! Builds a new copy of the zero-dimension space constraint
//! \f$\epsilon \geq 0\f$ (used to implement NNC polyhedra).
static Constraint construct_epsilon_geq_zero();
//! Returns the zero-dimension space constraint \f$\epsilon \geq 0\f$.
static const Constraint& epsilon_geq_zero();
//! \brief
//! The zero-dimension space constraint \f$\epsilon \leq 1\f$
//! (used to implement NNC polyhedra).
static const Constraint& epsilon_leq_one();
//! \brief
//! Returns <CODE>true</CODE> if and only if
//! \p *this is a trivially true constraint.
/*!
Trivially true constraints have either one of the following forms:
- an equality: \f$\sum_{i=0}^{n-1} 0 x_i + 0 = 0\f$; or
- a non-strict inequality: \f$\sum_{i=0}^{n-1} 0 x_i + b \geq 0\f$,
where \f$b \geq 0\f$; or
- a strict inequality: \f$\sum_{i=0}^{n-1} 0 x_i + b > 0\f$,
where \f$b > 0\f$.
*/
bool is_trivial_true() const;
//! \brief
//! Returns <CODE>true</CODE> if and only if
//! \p *this is a trivially false constraint.
/*!
Trivially false constraints have either one of the following forms:
- an equality: \f$\sum_{i=0}^{n-1} 0 x_i + b = 0\f$,
where \f$b \neq 0\f$; or
- a non-strict inequality: \f$\sum_{i=0}^{n-1} 0 x_i + b \geq 0\f$,
where \f$b < 0\f$; or
- a strict inequality: \f$\sum_{i=0}^{n-1} 0 x_i + b > 0\f$,
where \f$b \leq 0\f$.
*/
bool is_trivial_false() const;
//! Sets the constraint type to <CODE>EQUALITY</CODE>.
void set_is_equality();
//! Sets the constraint type to <CODE>INEQUALITY</CODE>.
void set_is_inequality();
};
#include "Constraint.inlines.hh"
#endif // !defined(PPL_Constraint_defs_hh)
syntax highlighted by Code2HTML, v. 0.9.1