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.
Jip J. Dekker 1d9faf38de Squashed 'software/gecode/' content from commit 313e8764
git-subtree-dir: software/gecode
git-subtree-split: 313e87646da4fc2752a70e83df16d993121a8e40
2021-06-16 14:02:33 +10:00

506 lines
14 KiB
C++

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Guido Tack <tack@gecode.org>
* Gabor Szokoli <szokoli@gecode.org>
*
* Contributing authors:
* Christian Schulte <schulte@gecode.org>
*
* Copyright:
* Guido Tack, 2004
* Christian Schulte, 2004
* Gabor Szokoli, 2004
*
* 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.
*
*/
namespace Gecode { namespace Set {
/*
* Creation of new variable implementations
*
*/
forceinline
SetVarImp::SetVarImp(Space& home)
: SetVarImpBase(home), lub(home), glb(home) {
lub.card(Limits::card);
assert(lub.card()==lub.size());
}
forceinline
SetVarImp::SetVarImp(Space& home,int lbMin,int lbMax,int ubMin,int ubMax,
unsigned int cardMin, unsigned int cardMax)
: SetVarImpBase(home),
lub(home,ubMin,ubMax), glb(home,lbMin,lbMax) {
glb.card(std::max(cardMin, glb.size() ));
lub.card(std::min(cardMax, lub.size() ));
}
forceinline
SetVarImp::SetVarImp(Space& home,
const IntSet& theGlb,int ubMin,int ubMax,
unsigned int cardMin, unsigned int cardMax)
: SetVarImpBase(home),
lub(home,ubMin,ubMax), glb(home,theGlb) {
glb.card(std::max(cardMin, glb.size() ));
lub.card(std::min(cardMax, lub.size() ));
}
forceinline
SetVarImp::SetVarImp(Space& home,
int lbMin,int lbMax,const IntSet& theLub,
unsigned int cardMin, unsigned int cardMax)
: SetVarImpBase(home),
lub(home,theLub), glb(home,lbMin,lbMax) {
glb.card(std::max(cardMin, glb.size() ));
lub.card(std::min(cardMax, lub.size() ));
}
forceinline
SetVarImp::SetVarImp(Space& home,
const IntSet& theGlb,const IntSet& theLub,
unsigned int cardMin, unsigned int cardMax)
: SetVarImpBase(home), lub(home,theLub), glb(home,theGlb) {
glb.card(std::max(cardMin, glb.size() ));
lub.card(std::min(cardMax, lub.size() ));
}
forceinline bool
SetVarImp::assigned(void) const {
return glb.size() == lub.size();
}
forceinline unsigned int
SetVarImp::cardMin(void) const { return glb.card(); }
forceinline unsigned int
SetVarImp::cardMax(void) const { return lub.card(); }
forceinline bool
SetVarImp::knownIn(int i) const { return (glb.in(i)); }
forceinline bool
SetVarImp::knownOut(int i) const { return !(lub.in(i)); }
forceinline int
SetVarImp::lubMin(void) const { return lub.min(); }
forceinline int
SetVarImp::lubMax(void) const { return lub.max(); }
forceinline int
SetVarImp::lubMinN(unsigned int n) const { return lub.minN(n); }
forceinline int
SetVarImp::glbMin(void) const { return glb.min(); }
forceinline int
SetVarImp::glbMax(void) const { return glb.max(); }
forceinline unsigned int
SetVarImp::glbSize() const { return glb.size(); }
forceinline unsigned int
SetVarImp::lubSize() const { return lub.size(); }
/*
* Support for delta information
*
*/
forceinline int
SetVarImp::glbMin(const Delta& d) {
return static_cast<const SetDelta&>(d).glbMin();
}
forceinline int
SetVarImp::glbMax(const Delta& d) {
return static_cast<const SetDelta&>(d).glbMax();
}
forceinline bool
SetVarImp::glbAny(const Delta& d) {
return static_cast<const SetDelta&>(d).glbAny();
}
forceinline int
SetVarImp::lubMin(const Delta& d) {
return static_cast<const SetDelta&>(d).lubMin();
}
forceinline int
SetVarImp::lubMax(const Delta& d) {
return static_cast<const SetDelta&>(d).lubMax();
}
forceinline bool
SetVarImp::lubAny(const Delta& d) {
return static_cast<const SetDelta&>(d).lubAny();
}
forceinline ModEvent
SetVarImp::cardMin(Space& home,unsigned int newMin) {
if (cardMin() >= newMin)
return ME_SET_NONE;
if (newMin > cardMax())
return fail(home);
glb.card(newMin);
return cardMin_full(home);
}
forceinline ModEvent
SetVarImp::cardMax(Space& home,unsigned int newMax) {
if (cardMax() <= newMax)
return ME_SET_NONE;
if (cardMin() > newMax)
return fail(home);
lub.card(newMax);
return cardMax_full(home);
}
forceinline ModEvent
SetVarImp::intersect(Space& home,int i, int j) {
BndSetRanges lb(glb);
Iter::Ranges::Singleton s(i,j);
Iter::Ranges::Diff<BndSetRanges, Iter::Ranges::Singleton> probe(lb, s);
if (probe())
return fail(home);
if (assigned())
return ME_SET_NONE;
int oldMin = lub.min();
int oldMax = lub.max();
if (lub.intersect(home, i, j)) {
SetDelta d;
if (i == oldMin) {
d._lubMin = lub.max()+1;
d._lubMax = oldMax;
} else if (j == oldMax) {
d._lubMin = oldMin;
d._lubMax = lub.min()-1;
}
return processLubChange(home, d);
}
return ME_SET_NONE;
}
forceinline ModEvent
SetVarImp::intersect(Space& home,int i) {
return intersect(home, i, i);
}
template<class I>
inline ModEvent
SetVarImp::intersectI(Space& home, I& iterator) {
if (assigned()) {
BndSetRanges lbi(glb);
Iter::Ranges::Diff<BndSetRanges,I> probe(lbi,iterator);
if (probe())
return fail(home);
return ME_SET_NONE;
}
if (!iterator()) {
if (cardMin() > 0)
return fail(home);
lub.card(0);
SetDelta d(1, 0, lub.min(), lub.max());
lub.excludeAll(home);
return notify(home, ME_SET_VAL, d);
}
int mi=iterator.min();
int ma=iterator.max();
++iterator;
if (iterator())
return intersectI_full(home, mi, ma, iterator);
else
return intersect(home, mi, ma);
}
template<class I>
ModEvent
SetVarImp::intersectI_full(Space& home, int mi, int ma, I& iterator) {
Iter::Ranges::SingletonAppend<I> si(mi,ma,iterator);
if (lub.intersectI(home, si)) {
BndSetRanges ub(lub);
BndSetRanges lb(glb);
if (!Iter::Ranges::subset(lb,ub)) {
glb.become(home, lub);
glb.card(glb.size());
lub.card(glb.size());
return fail(home);
}
ModEvent me = ME_SET_LUB;
if (cardMax() > lub.size()) {
lub.card(lub.size());
if (cardMin() > cardMax()) {
glb.become(home, lub);
glb.card(glb.size());
lub.card(glb.size());
return fail(home);
}
me = ME_SET_CLUB;
}
if (cardMax() == lub.size() && cardMin() == cardMax()) {
glb.become(home, lub);
me = ME_SET_VAL;
}
SetDelta d;
return notify(home, me, d);
}
return ME_SET_NONE;
}
forceinline ModEvent
SetVarImp::include(Space& home, int i, int j) {
if (j<i)
return ME_SET_NONE;
BndSetRanges ub(lub);
Iter::Ranges::Singleton sij(i,j);
if (!Iter::Ranges::subset(sij,ub)) {
return fail(home);
}
SetDelta d;
if (glb.include(home, i, j, d))
return processGlbChange(home, d);
return ME_SET_NONE;
}
forceinline ModEvent
SetVarImp::include(Space& home, int i) {
return include(home, i, i);
}
template<class I> forceinline ModEvent
SetVarImp::includeI(Space& home, I& iterator) {
if (!iterator()) {
return ME_SET_NONE;
}
if (assigned()) {
BndSetRanges lbi(glb);
Iter::Ranges::Diff<I,BndSetRanges>
probe(iterator,lbi);
return probe() ? fail(home) : ME_SET_NONE;
}
int mi=iterator.min();
int ma=iterator.max();
++iterator;
if (iterator())
return includeI_full(home, mi, ma, iterator);
else
return include(home, mi, ma);
}
template<class I>
ModEvent
SetVarImp::includeI_full(Space& home, int mi, int ma, I& iterator) {
Iter::Ranges::SingletonAppend<I> si(mi,ma,iterator);
if (glb.includeI(home, si)) {
BndSetRanges ub(lub);
BndSetRanges lb(glb);
if (!Iter::Ranges::subset(lb,ub)) {
glb.become(home, lub);
glb.card(glb.size());
lub.card(glb.size());
return fail(home);
}
ModEvent me = ME_SET_GLB;
if (cardMin() < glb.size()) {
glb.card(glb.size());
if (cardMin() > cardMax()) {
glb.become(home, lub);
glb.card(glb.size());
lub.card(glb.size());
return fail(home);
}
me = ME_SET_CGLB;
}
if (cardMin() == glb.size() && cardMin() == cardMax()) {
lub.become(home, glb);
me = ME_SET_VAL;
}
SetDelta d;
return notify(home, me, d);
}
return ME_SET_NONE;
}
forceinline ModEvent
SetVarImp::exclude(Space& home, int i, int j) {
if (j<i)
return ME_SET_NONE;
Iter::Ranges::Singleton sij(i,j);
BndSetRanges lb(glb);
Iter::Ranges::Inter<Iter::Ranges::Singleton,BndSetRanges> probe(sij,lb);
if (probe())
return fail(home);
SetDelta d;
if (lub.exclude(home, i, j, d))
return processLubChange(home, d);
return ME_SET_NONE;
}
forceinline ModEvent
SetVarImp::exclude(Space& home, int i) {
return exclude(home, i, i);
}
template<class I>
inline ModEvent
SetVarImp::excludeI(Space& home, I& iterator) {
if (!iterator())
return ME_SET_NONE;
if (assigned()) {
BndSetRanges ubi(lub);
Iter::Ranges::Inter<BndSetRanges,I> probe(ubi,iterator);
return probe() ? fail(home) : ME_SET_NONE;
}
int mi=iterator.min();
int ma=iterator.max();
++iterator;
if (iterator())
return excludeI_full(home, mi, ma, iterator);
else
return exclude(home, mi, ma);
}
template<class I>
ModEvent
SetVarImp::excludeI_full(Space& home, int mi, int ma, I& iterator) {
Iter::Ranges::SingletonAppend<I> si(mi,ma,iterator);
if (lub.excludeI(home, si)) {
BndSetRanges ub(lub);
BndSetRanges lb(glb);
if (!Iter::Ranges::subset(lb,ub)) {
glb.become(home, lub);
glb.card(glb.size());
lub.card(glb.size());
return fail(home);
}
ModEvent me = ME_SET_LUB;
if (cardMax() > lub.size()) {
lub.card(lub.size());
if (cardMin() > cardMax()) {
glb.become(home, lub);
glb.card(glb.size());
lub.card(glb.size());
return fail(home);
}
me = ME_SET_CLUB;
}
if (cardMax() == lub.size() && cardMin() == cardMax()) {
glb.become(home, lub);
me = ME_SET_VAL;
}
SetDelta d;
return notify(home, me, d);
}
return ME_SET_NONE;
}
/*
* Copying a variable
*
*/
forceinline SetVarImp*
SetVarImp::copy(Space& home) {
return copied() ?
static_cast<SetVarImp*>(forward()) :
perform_copy(home);
}
/*
* Iterator specializations
*
*/
/**
* \brief Range iterator for the least upper bound of a set variable implementation
*
* This class provides (by specialization) a range iterator
* for the least upper bounds of set variable implementations.
*
* \ingroup TaskActorSet
*/
template<>
class LubRanges<SetVarImp*> : public BndSetRanges {
public:
/// \name Constructors and initialization
//@{
/// Default constructor
LubRanges(void);
/// Initialize with ranges for variable implementation \a x
LubRanges(const SetVarImp*);
/// Initialize with ranges for variable implementation \a x
void init(const SetVarImp*);
//@}
};
forceinline
LubRanges<SetVarImp*>::LubRanges(void) {}
forceinline
LubRanges<SetVarImp*>::LubRanges(const SetVarImp* x)
: BndSetRanges(x->lub) {}
forceinline void
LubRanges<SetVarImp*>::init(const SetVarImp* x) {
BndSetRanges::init(x->lub);
}
/**
* \brief Range iterator for the greatest lower bound of a set variable implementation
*
* This class provides (by specialization) a range iterator
* for the greatest lower bounds of set variable implementations.
*
* \ingroup TaskActorSet
*/
template<>
class GlbRanges<SetVarImp*> : public BndSetRanges {
public:
/// \name Constructors and initialization
//@{
/// Default constructor
GlbRanges(void);
/// Initialize with ranges for variable implementation \a x
GlbRanges(const SetVarImp* x);
/// Initialize with ranges for variable implementation \a x
void init(const SetVarImp*);
//@}
};
forceinline
GlbRanges<SetVarImp*>::GlbRanges(void) {}
forceinline
GlbRanges<SetVarImp*>::GlbRanges(const SetVarImp* x)
: BndSetRanges(x->glb) {}
forceinline void
GlbRanges<SetVarImp*>::init(const SetVarImp* x) {
BndSetRanges::init(x->glb);
}
}}
// STATISTICS: set-var