1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.

705 lines
23 KiB
C++
Executable File

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Christian Schulte <schulte@gecode.org>
* Guido Tack <tack@gecode.org>
*
* Contributing authors:
* Gabor Szokoli <szokoli@gecode.org>
*
* Copyright:
* Christian Schulte, 2002
* Guido Tack, 2004
* Gabor Szokoli, 2003
*
* This file is part of Gecode, the generic constraint
* development environment:
* http://www.gecode.org
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef GECODE_INT_REL_HH
#define GECODE_INT_REL_HH
#include <gecode/int.hh>
/**
* \namespace Gecode::Int::Rel
* \brief Simple relation propagators
*/
namespace Gecode { namespace Int { namespace Rel {
/*
* Equality propagators
*
*/
/**
* \brief Binary domain consistent equality propagator
*
* Uses staging by first performing bounds propagation and only
* then domain propagation.
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View0,class View1>
class EqDom :
public MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM> {
protected:
using MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>::x0;
using MixBinaryPropagator<View0,PC_INT_DOM,View1,PC_INT_DOM>::x1;
/// Constructor for cloning \a p
EqDom(Space& home, EqDom<View0,View1>& p);
public:
/// Constructor for posting
EqDom(Home home, View0 x0, View1 x1);
/// Constructor for rewriting \a p during cloning
EqDom(Space& home, Propagator& p, View0 x0, View1 x1);
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/**
* \brief Cost function
*
* If a view has been assigned, the cost is low unary.
* If in stage for bounds propagation, the cost is
* low binary. Otherwise it is high binary.
*/
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post domain consistent propagator \f$ x_0 = x_1\f$
static ExecStatus post(Home home, View0 x0, View1 x1);
};
/**
* \brief Binary value propagation equality propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View0, class View1>
class EqVal :
public MixBinaryPropagator<View0,PC_INT_VAL,View1,PC_INT_VAL> {
protected:
using MixBinaryPropagator<View0,PC_INT_VAL,View1,PC_INT_VAL>::x0;
using MixBinaryPropagator<View0,PC_INT_VAL,View1,PC_INT_VAL>::x1;
/// Constructor for cloning \a p
EqVal(Space& home, EqVal<View0,View1>& p);
public:
/// Constructor for posting
EqVal(Home home, View0 x0, View1 x1);
/// Constructor for rewriting \a p during cloning
EqVal(Space& home, Propagator& p, View0 x0, View1 x1);
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Cost function: low unary.
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post value propagation propagator \f$ x_0 = x_1\f$
static ExecStatus post(Home home, View0 x0, View1 x1);
};
/**
* \brief Binary bounds consistent equality propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View0, class View1>
class EqBnd :
public MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND> {
protected:
using MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>::x0;
using MixBinaryPropagator<View0,PC_INT_BND,View1,PC_INT_BND>::x1;
/// Constructor for cloning \a p
EqBnd(Space& home, EqBnd<View0,View1>& p);
public:
/// Constructor for posting
EqBnd(Home home, View0 x0, View1 x1);
/// Constructor for rewriting \a p during cloning
EqBnd(Space& home, Propagator& p, View0 x0, View1 x1);
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post bounds consistent propagator \f$ x_0 = x_1\f$
static ExecStatus post(Home home, View0 x0, View1 x1);
};
/**
* \brief n-ary domain consistent equality propagator
*
* Uses staging by first performing bounds propagation and only
* then domain propagation.
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View>
class NaryEqDom : public NaryPropagator<View,PC_INT_DOM> {
protected:
using NaryPropagator<View,PC_INT_DOM>::x;
/// Constructor for cloning \a p
NaryEqDom(Space& home, NaryEqDom<View>& p);
/// Constructor for posting
NaryEqDom(Home home, ViewArray<View>&);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/**
* \brief Cost function
*
* If a view has been assigned, the cost is low unary.
* If in stage for bounds propagation, the cost is
* low linear. Otherwise it is high linear.
*/
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post domain consistent propagator \f$ x_0 = x_1=\ldots =x_{|x|-1}\f$
static ExecStatus post(Home home, ViewArray<View>& x);
};
/**
* \brief n-ary bounds consistent equality propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View>
class NaryEqBnd : public NaryPropagator<View,PC_INT_BND> {
protected:
using NaryPropagator<View,PC_INT_BND>::x;
/// Constructor for cloning \a p
NaryEqBnd(Space& home, NaryEqBnd<View>& p);
/// Constructor for posting
NaryEqBnd(Home home, ViewArray<View>&);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/**
* \brief Cost function
*
* If a view has been assigned, the cost is low unary.
* Otherwise it is low linear.
*/
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post bounds consistent propagator \f$ x_0 = x_1=\ldots =x_{|x|-1}\f$
static ExecStatus post(Home home, ViewArray<View>& x);
};
/**
* \brief n-ary less and less or equal propagator
*
* If \a o is 0, less or equal is propagated, if \a o is 1 less is
* propagated.
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View, int o>
class NaryLqLe : public NaryPropagator<View,PC_INT_NONE> {
protected:
using NaryPropagator<View,PC_INT_NONE>::x;
/// %Advisors for views (by position in array)
class Index : public Advisor {
public:
/// The position of the view in the view array
int i;
/// Create index advisor
Index(Space& home, Propagator& p, Council<Index>& c, int i);
/// Clone index advisor \a a
Index(Space& home, Index& a);
};
/// The advisor council
Council<Index> c;
/// Positions in view array that have to be propagated
class Pos : public FreeList {
public:
/// Position of view in view array
int p;
/// \name Constructor
//@{
/// Initialize with position \a p and next position \a n
Pos(int p, Pos* n);
//@}
/// \name Linkage access
//@{
/// Return next position
Pos* next(void) const;
//@}
/// \name Memory management
//@{
/// Free memory for this position
void dispose(Space& home);
/// Allocate memory from space
static void* operator new(size_t s, Space& home);
/// No-op (for exceptions)
static void operator delete(void* p);
/// No-op (use dispose instead)
static void operator delete(void* p, Space& home);
//@}
};
/// Stack of positions
Pos* pos;
/// Whether no more positions must be propagated
bool empty(void) const;
/// Pop a position to be propagated and return it
int pop(Space& home);
/// Push a new position \a p to be propagated
void push(Space& home, int p);
/// Whether the propagator is currently running
bool run;
/// Number of already subsumed advisors (or views)
int n_subsumed;
/// Compact during cloning when more advisors than that are subsumed
static const int n_threshold = 7;
/// Constructor for cloning \a p
NaryLqLe(Space& home, NaryLqLe<View,o>& p);
/// Constructor for posting
NaryLqLe(Home home, ViewArray<View>&);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Cost function
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Schedule function
virtual void reschedule(Space& home);
/// Give advice to propagator
virtual ExecStatus advise(Space& home, Advisor& a, const Delta& d);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Delete propagator and return its size
virtual size_t dispose(Space& home);
/// Post propagator for \f$ x_0 +c\leq x_1+c\leq\cdots \leq x_{|x|-1}\f$
static ExecStatus post(Home home, ViewArray<View>& x);
};
/**
* \brief Nary disequality propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View>
class NaryNq : public NaryPropagator<View,PC_INT_VAL> {
protected:
using NaryPropagator<View,PC_INT_VAL>::x;
/// Constructor for posting
NaryNq(Home home, ViewArray<View>& x);
/// Constructor for cloning \a p
NaryNq(Space& home, NaryNq<View>& p);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Cost function
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post propagator \f$ \neg\left(x_0=x_1=\cdots=x_{|x|-1}\right)\f$
static ExecStatus post(Home home, ViewArray<View>& x);
/// Delete propagator and return its size
virtual size_t dispose(Space& home);
};
/**
* \brief Reified binary domain consistent equality propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View, class CtrlView, ReifyMode rm>
class ReEqDom : public ReBinaryPropagator<View,PC_INT_DOM,CtrlView> {
protected:
using ReBinaryPropagator<View,PC_INT_DOM,CtrlView>::x0;
using ReBinaryPropagator<View,PC_INT_DOM,CtrlView>::x1;
using ReBinaryPropagator<View,PC_INT_DOM,CtrlView>::b;
/// Constructor for cloning \a p
ReEqDom(Space& home, ReEqDom& p);
/// Constructor for posting
ReEqDom(Home home, View x0, View x1, CtrlView b);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post domain consistent propagator \f$ (x_0 = x_1)\Leftrightarrow b\f$
static ExecStatus post(Home home, View x0, View x1, CtrlView b);
};
/**
* \brief Reified binary bounds consistent equality propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View, class CtrlView, ReifyMode rm>
class ReEqBnd : public ReBinaryPropagator<View,PC_INT_BND,CtrlView> {
protected:
using ReBinaryPropagator<View,PC_INT_BND,CtrlView>::x0;
using ReBinaryPropagator<View,PC_INT_BND,CtrlView>::x1;
using ReBinaryPropagator<View,PC_INT_BND,CtrlView>::b;
/// Constructor for cloning \a p
ReEqBnd(Space& home, ReEqBnd& p);
/// Constructor for posting
ReEqBnd(Home home, View x0, View x1, CtrlView b);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post bounds consistent propagator \f$ (x_0 = x_1)\Leftrightarrow b\f$
static ExecStatus post(Home home, View x0, View x1, CtrlView b);
};
/**
* \brief Reified domain consistent equality with integer propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View, class CtrlView, ReifyMode rm>
class ReEqDomInt : public ReUnaryPropagator<View,PC_INT_DOM,CtrlView> {
protected:
using ReUnaryPropagator<View,PC_INT_DOM,CtrlView>::x0;
using ReUnaryPropagator<View,PC_INT_DOM,CtrlView>::b;
/// Integer constant to check
int c;
/// Constructor for cloning \a p
ReEqDomInt(Space& home, ReEqDomInt& p);
/// Constructor for posting
ReEqDomInt(Home home, View x, int c, CtrlView b);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post domain consistent propagator \f$ (x = c)\Leftrightarrow b\f$
static ExecStatus post(Home home, View x, int c, CtrlView b);
};
/**
* \brief Reified bounds consistent equality with integer propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View, class CtrlView, ReifyMode rm>
class ReEqBndInt : public ReUnaryPropagator<View,PC_INT_BND,CtrlView> {
protected:
using ReUnaryPropagator<View,PC_INT_BND,CtrlView>::x0;
using ReUnaryPropagator<View,PC_INT_BND,CtrlView>::b;
/// Integer constant to check
int c;
/// Constructor for cloning \a p
ReEqBndInt(Space& home, ReEqBndInt& p);
/// Constructor for posting
ReEqBndInt(Home home, View x, int c, CtrlView b);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post bounds consistent propagator \f$ (x = c)\Leftrightarrow b\f$
static ExecStatus post(Home home, View x, int c, CtrlView b);
};
/*
* Disequality propagators
*
*/
/**
* \brief Binary disequality propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class V0, class V1>
class Nq : public MixBinaryPropagator<V0,PC_INT_VAL,V1,PC_INT_VAL> {
protected:
using MixBinaryPropagator<V0,PC_INT_VAL,V1,PC_INT_VAL>::x0;
using MixBinaryPropagator<V0,PC_INT_VAL,V1,PC_INT_VAL>::x1;
/// Constructor for cloning \a p
Nq(Space& home, Nq<V0,V1>& p);
/// Constructor for posting
Nq(Home home, V0 x0, V1 x1);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Cost function (defined as low unary)
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post propagator \f$x_0\neq x_1\f$
static ExecStatus post(Home home, V0 x0, V1 x1);
};
/*
* Order propagators
*
*/
/**
* \brief Less or equal propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class V0, class V1>
class Lq : public MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND> {
protected:
using MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>::x0;
using MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>::x1;
/// Constructor for cloning \a p
Lq(Space& home, Lq& p);
/// Constructor for posting
Lq(Home home, V0 x0, V1 x1);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post propagator \f$x_0 \leq x_1\f$
static ExecStatus post(Home home, V0 x0, V1 x1);
};
/**
* \brief Less propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class V0, class V1>
class Le : public MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND> {
protected:
using MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>::x0;
using MixBinaryPropagator<V0,PC_INT_BND,V1,PC_INT_BND>::x1;
/// Constructor for cloning \a p
Le(Space& home, Le& p);
/// Constructor for posting
Le(Home home, V0 x0, V1 x1);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post propagator \f$x_0 \le x_1\f$
static ExecStatus post(Home home, V0 x0, V1 x1);
};
/*
* Reified order propagators
*
*/
/**
* \brief Reified less or equal propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View, class CtrlView, ReifyMode rm>
class ReLq : public ReBinaryPropagator<View,PC_INT_BND,CtrlView> {
protected:
using ReBinaryPropagator<View,PC_INT_BND,CtrlView>::x0;
using ReBinaryPropagator<View,PC_INT_BND,CtrlView>::x1;
using ReBinaryPropagator<View,PC_INT_BND,CtrlView>::b;
/// Constructor for cloning \a p
ReLq(Space& home, ReLq& p);
/// Constructor for posting
ReLq(Home home, View x0, View x1, CtrlView b);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post propagator for \f$ (x_0 \leq x_1)\Leftrightarrow b\f$
static ExecStatus post(Home home, View x0, View x1, CtrlView b);
};
/**
* \brief Reified less or equal with integer propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class View, class CtrlView, ReifyMode rm>
class ReLqInt : public ReUnaryPropagator<View,PC_INT_BND,CtrlView> {
protected:
using ReUnaryPropagator<View,PC_INT_BND,CtrlView>::x0;
using ReUnaryPropagator<View,PC_INT_BND,CtrlView>::b;
/// Integer constant to check
int c;
/// Constructor for cloning \a p
ReLqInt(Space& home, ReLqInt& p);
/// Constructor for posting
ReLqInt(Home home, View x, int c, CtrlView b);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post propagator for \f$ (x \leq c)\Leftrightarrow b\f$
static ExecStatus post(Home home, View x, int c, CtrlView b);
};
/**
* \brief Lexical ordering propagator
*
* The propagator uses the algorithm (and also the automaton)
* from:
* Mats Carlsson, Nicolas Beldiceanu, Revisiting the
* Lexicographic Ordering Constraint. SICS Technical
* Report T2002:17, SICS, Sweden, 2002.
*
* It deviates in the following two main aspects:
* - Assigned variables are eagerly eliminated
* This yields the same incremental behaviour with
* respect to states 1 and 2 of the automaton.
* With respect to the values of \a q and \a r in the report:
* - \a q is always 0 after elimination
* - \a r is always 1 after elimination
*
* - It is not incremental with respect to states 3 and 4
* as no propagation event information is available
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class VX, class VY>
class LexLqLe : public Propagator {
protected:
/// View arrays
ViewArray<VX> x;
ViewArray<VY> y;
/// Determines whether propagator is strict or not
bool strict;
/// Constructor for cloning \a p
LexLqLe(Space& home, LexLqLe<VX,VY>& p);
/// Constructor for posting
LexLqLe(Home home, ViewArray<VX>& x, ViewArray<VY>& y, bool strict);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Cost function (defined as low linear)
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Schedule function
virtual void reschedule(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post propagator for lexical order between \a x and \a y
static ExecStatus post(Home home, ViewArray<VX>& x, ViewArray<VY>& y,
bool strict);
/// Delete propagator and return its size
virtual size_t dispose(Space& home);
};
/**
* \brief Lexical disequality propagator
*
* Requires \code #include <gecode/int/rel.hh> \endcode
* \ingroup FuncIntProp
*/
template<class VX, class VY>
class LexNq : public Propagator {
protected:
/// View currently subscribed to
VX x0;
/// View currently subscribed to
VY y0;
/// View currently subscribed to
VX x1;
/// View currently subscribed to
VY y1;
/// Views not yet subscribed to
ViewArray<VX> x;
/// Views not yet subscribed to
ViewArray<VY> y;
/// Update subscription
ExecStatus resubscribe(Space& home,
RelTest rt, VX& x0, VY& y0, VX x1, VY y1);
/// Constructor for posting
LexNq(Home home, ViewArray<VX>& x, ViewArray<VY>& y);
/// Constructor for cloning \a p
LexNq(Space& home, LexNq<VX,VY>& p);
public:
/// Copy propagator during cloning
virtual Actor* copy(Space& home);
/// Cost function
virtual PropCost cost(const Space& home, const ModEventDelta& med) const;
/// Schedule function
virtual void reschedule(Space& home);
/// Perform propagation
virtual ExecStatus propagate(Space& home, const ModEventDelta& med);
/// Post propagator \f$ x\neq y\f$
static ExecStatus post(Home home, ViewArray<VX>& x, ViewArray<VY>& y);
/// Delete propagator and return its size
virtual size_t dispose(Space& home);
};
}}}
#include <gecode/int/rel/eq.hpp>
#include <gecode/int/rel/nq.hpp>
#include <gecode/int/rel/lq-le.hpp>
#include <gecode/int/rel/lex.hpp>
#endif
// STATISTICS: int-prop