git-subtree-dir: software/gecode_base git-subtree-split: bbefcea214fec798a0f5acc442581984555acd21
615 lines
19 KiB
C++
Executable File
615 lines
19 KiB
C++
Executable File
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
/*
|
|
* Main authors:
|
|
* Guido Tack <tack@gecode.org>
|
|
* Christian Schulte <schulte@gecode.org>
|
|
*
|
|
* Contributing authors:
|
|
* Gabor Szokoli <szokoli@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.
|
|
*
|
|
*/
|
|
|
|
#ifndef GECODE_SET_RELOP_COMM_ICC
|
|
#define GECODE_SET_RELOP_COMM_ICC
|
|
|
|
namespace Gecode {
|
|
|
|
template<class View0, class View1>
|
|
forceinline bool
|
|
viewarrayshared(const ViewArray<View0>& va, const View1& y) {
|
|
return shared(va,y);
|
|
}
|
|
|
|
template<>
|
|
forceinline bool
|
|
viewarrayshared<Set::SingletonView,Set::SetView>
|
|
(const ViewArray<Set::SingletonView>&, const Set::SetView&) {
|
|
return false;
|
|
}
|
|
|
|
template<>
|
|
forceinline bool
|
|
viewarrayshared<Set::ComplementView<Set::SingletonView>,Set::SetView>
|
|
(const ViewArray<Set::ComplementView<Set::SingletonView> >&,
|
|
const Set::SetView&) {
|
|
return false;
|
|
}
|
|
|
|
template<>
|
|
forceinline bool
|
|
viewarrayshared<Set::ComplementView<Set::SingletonView>,
|
|
Set::ComplementView<Set::SetView> >
|
|
(const ViewArray<Set::ComplementView<Set::SingletonView> >&,
|
|
const Set::ComplementView<Set::SetView>&) {
|
|
return false;
|
|
}
|
|
|
|
|
|
namespace Set { namespace RelOp {
|
|
|
|
/*
|
|
* Detect sharing between 3 variables
|
|
*
|
|
*/
|
|
template<class View0, class View1, class View2>
|
|
forceinline bool
|
|
shared(View0 v0, View1 v1, View2 v2) {
|
|
return shared(v0,v1) || shared(v0,v2) || shared(v1,v2);
|
|
}
|
|
|
|
template<class View0, class View1, class View2>
|
|
ExecStatus interCard(Space& home,
|
|
bool& retmodified, View0& x0, View1& x1, View2& x2) {
|
|
bool modified = false;
|
|
do {
|
|
retmodified |= modified;
|
|
modified = false;
|
|
|
|
{
|
|
LubRanges<View0> x0ub(x0);
|
|
LubRanges<View1> x1ub(x1);
|
|
Iter::Ranges::Union<LubRanges<View0>, LubRanges<View1> >
|
|
u1(x0ub,x1ub);
|
|
unsigned int s1 = Iter::Ranges::size(u1);
|
|
|
|
if (x0.cardMin() + x1.cardMin() > s1) {
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x2.cardMin(home, x0.cardMin()+x1.cardMin()-s1));
|
|
}
|
|
|
|
// unsigned int res = std::max(x0.cardMin()+
|
|
// (x1.cardMin()<s1 ?
|
|
// 0 : x1.cardMin()-s1),
|
|
// std::max(x0.cardMin(),
|
|
// x1.cardMin()));
|
|
// GECODE_ME_CHECK_MODIFIED(modified, x2.cardMin(home,res));
|
|
}
|
|
|
|
{
|
|
GlbRanges<View0> x0lb(x0);
|
|
GlbRanges<View1> x1lb(x1);
|
|
Iter::Ranges::Union<GlbRanges<View0>, GlbRanges<View1> >
|
|
u1(x0lb,x1lb);
|
|
unsigned int s1 = Iter::Ranges::size(u1);
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x2.cardMax(home,
|
|
x0.cardMax()+x1.cardMax()-s1));
|
|
}
|
|
|
|
if (x2.cardMax() < x1.cardMin())
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x0.cardMax(home,
|
|
Set::Limits::card+x2.cardMax()-x1.cardMin()));
|
|
|
|
if (x2.cardMax() < x0.cardMin())
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x1.cardMax(home,
|
|
Set::Limits::card+x2.cardMax()-x0.cardMin()));
|
|
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x0.cardMin(home,x2.cardMin()));
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x1.cardMin(home,x2.cardMin()));
|
|
} while(modified);
|
|
return ES_FIX;
|
|
}
|
|
template<class View0, class View1, class View2>
|
|
ExecStatus unionCard(Space& home,
|
|
bool& retmodified, View0& x0, View1& x1, View2& x2) {
|
|
bool modified = false;
|
|
do {
|
|
retmodified |= modified;
|
|
modified = false;
|
|
|
|
{
|
|
LubRanges<View0> x0ub(x0);
|
|
LubRanges<View1> x1ub(x1);
|
|
Iter::Ranges::Inter<LubRanges<View0>, LubRanges<View1> > i1(x0ub,x1ub);
|
|
unsigned int s1 = Iter::Ranges::size(i1);
|
|
unsigned int res = std::max(x0.cardMin()+
|
|
(x1.cardMin()<s1 ?
|
|
0 : x1.cardMin()-s1),
|
|
std::max(x0.cardMin(),
|
|
x1.cardMin()));
|
|
GECODE_ME_CHECK_MODIFIED(modified, x2.cardMin(home,res));
|
|
}
|
|
|
|
{
|
|
LubRanges<View0> x0ub(x0);
|
|
LubRanges<View1> x1ub(x1);
|
|
Iter::Ranges::Union<LubRanges<View0>, LubRanges<View1> > u1(x0ub,x1ub);
|
|
unsigned int s1 = Iter::Ranges::size(u1);
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x2.cardMax(home,
|
|
std::min(x0.cardMax()+x1.cardMax(),s1)));
|
|
}
|
|
|
|
if (x2.cardMin() > x1.cardMax())
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x0.cardMin(home,x2.cardMin() - x1.cardMax()));
|
|
|
|
if (x2.cardMin() > x0.cardMax())
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x1.cardMin(home,x2.cardMin() - x0.cardMax()));
|
|
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x0.cardMax(home,x2.cardMax()));
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x1.cardMax(home,x2.cardMax()));
|
|
} while(modified);
|
|
return ES_FIX;
|
|
}
|
|
|
|
template<class View0, class View1>
|
|
ExecStatus
|
|
unionNCard(Space& home, bool& modified, ViewArray<View0>& x,
|
|
View1& y, GLBndSet& unionOfDets) {
|
|
int xsize = x.size();
|
|
// Max(Xi.cardMin) <= y.card <= Sum(Xi.cardMax)
|
|
// Xi.card <=y.cardMax
|
|
unsigned int cardMaxSum=unionOfDets.size();
|
|
bool maxValid = true;
|
|
for (int i=xsize; i--; ) {
|
|
cardMaxSum+=x[i].cardMax();
|
|
if (cardMaxSum < x[i].cardMax()) { maxValid = false; } //overflow
|
|
GECODE_ME_CHECK_MODIFIED(modified, y.cardMin(home,x[i].cardMin()) );
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].cardMax(home,y.cardMax()) );
|
|
}
|
|
if (maxValid) {
|
|
GECODE_ME_CHECK_MODIFIED(modified, y.cardMax(home,cardMaxSum));
|
|
}
|
|
//y.cardMin - Sum(Xj.cardMax) <= Xi.card
|
|
|
|
if (x.size() == 0)
|
|
return ES_NOFIX;
|
|
|
|
Region r;
|
|
//TODO: overflow management is a waste now.
|
|
{
|
|
unsigned int* rightSum = r.alloc<unsigned int>(xsize);
|
|
rightSum[xsize-1]=0;
|
|
|
|
for (int i=x.size()-1;i--;) {
|
|
rightSum[i] = rightSum[i+1] + x[i+1].cardMax();
|
|
if (rightSum[i] < rightSum[i+1]) {
|
|
//overflow, fill the rest of the array.
|
|
for (int j=i; j>0;j--) {
|
|
rightSum[j]=Limits::card;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Size of union of determied vars missing from x sneaked in here:
|
|
unsigned int leftAcc=unionOfDets.size();
|
|
|
|
for (int i=0; i<xsize;i++) {
|
|
unsigned int jsum = leftAcc+rightSum[i];
|
|
//If jsum did not overflow and is less than y.cardMin:
|
|
if (jsum >= leftAcc && jsum < y.cardMin()) {
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].cardMin(home,y.cardMin()-jsum));
|
|
}
|
|
leftAcc += x[i].cardMax();
|
|
if (leftAcc < x[i].cardMax()) {leftAcc = Limits::card;}
|
|
}
|
|
}
|
|
|
|
//y.cardMin - |U(Xj.ub)| <= Xi.card
|
|
|
|
{
|
|
GLBndSet* rightUnion =
|
|
static_cast<GLBndSet*>(r.ralloc(sizeof(GLBndSet)*xsize));
|
|
new (&rightUnion[xsize-1]) GLBndSet(home);
|
|
for (int i=xsize-1;i--;) {
|
|
BndSetRanges prev(rightUnion[i+1]);
|
|
LubRanges<View0> prevX(x[i+1]);
|
|
Iter::Ranges::Union< BndSetRanges,LubRanges<View0> >
|
|
iter(prev,prevX);
|
|
new (&rightUnion[i]) GLBndSet(home);
|
|
rightUnion[i].includeI(home, iter);
|
|
}
|
|
|
|
//union of determied vars missing from x sneaked in here:
|
|
GLBndSet leftAcc;
|
|
leftAcc.update(home,unionOfDets);
|
|
for (int i=0; i<xsize; i++) {
|
|
BndSetRanges left(leftAcc);
|
|
BndSetRanges right(rightUnion[i]);
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> iter(left, right);
|
|
unsigned int unionSize = Iter::Ranges::size(iter);
|
|
if (y.cardMin() > unionSize) {
|
|
GECODE_ME_CHECK_MODIFIED(modified,
|
|
x[i].cardMin(home, y.cardMin() - unionSize) );
|
|
}
|
|
LubRanges<View0> xiub(x[i]);
|
|
leftAcc.includeI(home, xiub);
|
|
}
|
|
|
|
for (int i=xsize; i--;)
|
|
rightUnion[i].dispose(home);
|
|
leftAcc.dispose(home);
|
|
}
|
|
|
|
//no need for this: |y.lb - U(Xj.cardMax)| <= S.card
|
|
|
|
return ES_NOFIX;
|
|
|
|
}
|
|
|
|
/*
|
|
* Xi UB is subset of YUB
|
|
* Subscribes to Y UB
|
|
*/
|
|
template<class View0, class View1>
|
|
ExecStatus
|
|
unionNXiUB(Space& home,
|
|
bool& modified, ViewArray<View0>& x, View1& y,
|
|
GLBndSet &) {
|
|
int xsize = x.size();
|
|
for (int i=xsize; i--; ) {
|
|
LubRanges<View1> yub(y);
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].intersectI(home, yub));
|
|
}
|
|
return ES_FIX;
|
|
}
|
|
|
|
// cardinality rules for PartitionN constraint
|
|
template<class View0, class View1>
|
|
ExecStatus
|
|
partitionNCard(Space& home,
|
|
bool& modified, ViewArray<View0>& x, View1& y,
|
|
GLBndSet& unionOfDets) {
|
|
unsigned int cardMinSum=unionOfDets.size();
|
|
unsigned int cardMaxSum=unionOfDets.size();
|
|
int xsize = x.size();
|
|
for (int i=xsize; i--; ) {
|
|
cardMinSum+=x[i].cardMin();
|
|
if (cardMinSum < x[i].cardMin()) {
|
|
//sum of mins overflows: fail the space.
|
|
GECODE_ME_CHECK(ME_SET_FAILED);
|
|
}
|
|
}
|
|
GECODE_ME_CHECK_MODIFIED(modified, y.cardMin(home,cardMinSum));
|
|
for (int i=xsize; i--; ) {
|
|
cardMaxSum+=x[i].cardMax();
|
|
if (cardMaxSum < x[i].cardMax()) {
|
|
//sum of maxes overflows: no useful information to tell.
|
|
goto overflow;
|
|
}
|
|
}
|
|
GECODE_ME_CHECK_MODIFIED(modified, y.cardMax(home,cardMaxSum));
|
|
|
|
if (x.size() == 0)
|
|
return ES_NOFIX;
|
|
|
|
overflow:
|
|
|
|
//Cardinality of each x[i] limited by cardinality of y minus all x[j]s:
|
|
|
|
{
|
|
Region r;
|
|
unsigned int* rightMinSum = r.alloc<unsigned int>(xsize);
|
|
unsigned int* rightMaxSum = r.alloc<unsigned int>(xsize);
|
|
rightMinSum[xsize-1]=0;
|
|
rightMaxSum[xsize-1]=0;
|
|
|
|
for (int i=x.size()-1;i--;) {
|
|
rightMaxSum[i] = rightMaxSum[i+1] + x[i+1].cardMax();
|
|
if (rightMaxSum[i] < rightMaxSum[i+1]) {
|
|
//overflow, fill the rest of the array.
|
|
for (int j=i; j>0;j--) {
|
|
rightMaxSum[j]=Limits::card;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
for (int i=x.size()-1;i--;) {
|
|
rightMinSum[i] = rightMinSum[i+1] + x[i+1].cardMin();
|
|
if (rightMinSum[i] < rightMinSum[i+1]) {
|
|
//overflow, fail the space
|
|
GECODE_ME_CHECK(ME_SET_FAILED);
|
|
}
|
|
}
|
|
unsigned int leftMinAcc=unionOfDets.size();
|
|
unsigned int leftMaxAcc=unionOfDets.size();
|
|
|
|
for (int i=0; i<xsize;i++) {
|
|
unsigned int maxSum = leftMaxAcc+rightMaxSum[i];
|
|
unsigned int minSum = leftMinAcc+rightMinSum[i];
|
|
//If maxSum did not overflow and is less than y.cardMin:
|
|
if (maxSum >= leftMaxAcc && maxSum < y.cardMin()) {
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].cardMin(home,y.cardMin()-maxSum));
|
|
}
|
|
|
|
//Overflow, fail.
|
|
if (minSum < leftMinAcc || y.cardMax() < minSum) {
|
|
GECODE_ME_CHECK(ME_SET_FAILED);
|
|
}
|
|
else {
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].cardMax(home,y.cardMax()-minSum));
|
|
}
|
|
|
|
leftMaxAcc += x[i].cardMax();
|
|
if (leftMaxAcc < x[i].cardMax())
|
|
leftMaxAcc = Limits::card;
|
|
leftMinAcc += x[i].cardMin();
|
|
if (leftMinAcc < x[i].cardMin())
|
|
GECODE_ME_CHECK(ME_SET_FAILED);
|
|
}
|
|
}
|
|
|
|
return ES_NOFIX;
|
|
}
|
|
|
|
// Xi LB includes YLB minus union Xj UB
|
|
// Xi UB is subset of YUB minus union of Xj LBs
|
|
template<class View0, class View1>
|
|
ExecStatus
|
|
partitionNXi(Space& home,
|
|
bool& modified, ViewArray<View0>& x, View1& y) {
|
|
int xsize = x.size();
|
|
Region r;
|
|
GLBndSet* afterUB =
|
|
static_cast<GLBndSet*>(r.ralloc(sizeof(GLBndSet)*xsize));
|
|
GLBndSet* afterLB =
|
|
static_cast<GLBndSet*>(r.ralloc(sizeof(GLBndSet)*xsize));
|
|
|
|
{
|
|
GLBndSet sofarAfterUB;
|
|
GLBndSet sofarAfterLB;
|
|
for (int i=xsize; i--;) {
|
|
new (&afterUB[i]) GLBndSet(home);
|
|
new (&afterLB[i]) GLBndSet(home);
|
|
afterUB[i].update(home,sofarAfterUB);
|
|
afterLB[i].update(home,sofarAfterLB);
|
|
LubRanges<View0> xiub(x[i]);
|
|
GlbRanges<View0> xilb(x[i]);
|
|
sofarAfterUB.includeI(home,xiub);
|
|
sofarAfterLB.includeI(home,xilb);
|
|
}
|
|
sofarAfterUB.dispose(home);
|
|
sofarAfterLB.dispose(home);
|
|
}
|
|
|
|
{
|
|
GLBndSet sofarBeforeUB;
|
|
GLBndSet sofarBeforeLB;
|
|
for (int i=0; i<xsize; i++) {
|
|
LubRanges<View1> yub(y);
|
|
BndSetRanges slb(sofarBeforeLB);
|
|
BndSetRanges afterlb(afterLB[i]);
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> xjlb(slb, afterlb);
|
|
Iter::Ranges::Diff<LubRanges<View1>,
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> > diff1(yub, xjlb);
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].intersectI(home,diff1));
|
|
|
|
GlbRanges<View1> ylb(y);
|
|
BndSetRanges sub(sofarBeforeUB);
|
|
BndSetRanges afterub(afterUB[i]);
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> xjub(sub, afterub);
|
|
Iter::Ranges::Diff<GlbRanges<View1>,
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> > diff2(ylb, xjub);
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].includeI(home,diff2));
|
|
|
|
LubRanges<View0> xiub(x[i]);
|
|
GlbRanges<View0> xilb(x[i]);
|
|
sofarBeforeUB.includeI(home,xiub);
|
|
sofarBeforeLB.includeI(home,xilb);
|
|
}
|
|
sofarBeforeLB.dispose(home);
|
|
sofarBeforeUB.dispose(home);
|
|
}
|
|
|
|
for (int i=xsize;i--;) {
|
|
afterUB[i].dispose(home);
|
|
afterLB[i].dispose(home);
|
|
}
|
|
|
|
return ES_NOFIX;
|
|
}
|
|
|
|
// Xi UB is subset of YUB minus union of Xj LBs
|
|
template<class View0, class View1>
|
|
ExecStatus
|
|
partitionNXiUB(Space& home,
|
|
bool& modified, ViewArray<View0>& x, View1& y,
|
|
GLBndSet& unionOfDets) {
|
|
int xsize = x.size();
|
|
Region r;
|
|
GLBndSet* afterLB =
|
|
static_cast<GLBndSet*>(r.ralloc(sizeof(GLBndSet)*xsize));
|
|
|
|
{
|
|
GLBndSet sofarAfterLB;
|
|
for (int i=xsize; i--;) {
|
|
new (&afterLB[i]) GLBndSet(home);
|
|
afterLB[i].update(home,sofarAfterLB);
|
|
GlbRanges<View0> xilb(x[i]);
|
|
sofarAfterLB.includeI(home,xilb);
|
|
}
|
|
sofarAfterLB.dispose(home);
|
|
}
|
|
|
|
{
|
|
GLBndSet sofarBeforeLB;
|
|
sofarBeforeLB.update(home,unionOfDets);
|
|
for (int i=0; i<xsize; i++) {
|
|
LubRanges<View1> yub(y);
|
|
BndSetRanges slb(sofarBeforeLB);
|
|
BndSetRanges afterlb(afterLB[i]);
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> xjlb(slb, afterlb);
|
|
Iter::Ranges::Diff<LubRanges<View1>,
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> > diff1(yub, xjlb);
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].intersectI(home,diff1));
|
|
|
|
GlbRanges<View0> xilb(x[i]);
|
|
sofarBeforeLB.includeI(home,xilb);
|
|
}
|
|
sofarBeforeLB.dispose(home);
|
|
}
|
|
for (int i=xsize; i--;)
|
|
afterLB[i].dispose(home);
|
|
return ES_NOFIX;
|
|
}
|
|
|
|
// Xi LB includes YLB minus union Xj UB
|
|
template<class View0, class View1>
|
|
ExecStatus
|
|
partitionNXiLB(Space& home,
|
|
bool& modified, ViewArray<View0>& x, View1& y,
|
|
GLBndSet& unionOfDets) {
|
|
int xsize = x.size();
|
|
Region r;
|
|
GLBndSet* afterUB =
|
|
static_cast<GLBndSet*>(r.ralloc(sizeof(GLBndSet)*xsize));
|
|
|
|
{
|
|
GLBndSet sofarAfterUB;
|
|
for (int i=xsize; i--;) {
|
|
new (&afterUB[i]) GLBndSet(home);
|
|
afterUB[i].update(home,sofarAfterUB);
|
|
LubRanges<View0> xiub(x[i]);
|
|
sofarAfterUB.includeI(home,xiub);
|
|
}
|
|
sofarAfterUB.dispose(home);
|
|
}
|
|
|
|
{
|
|
//The union of previously determined x[j]-s is added to the mix here:
|
|
GLBndSet sofarBeforeUB;
|
|
sofarBeforeUB.update(home,unionOfDets);
|
|
for (int i=0; i<xsize; i++) {
|
|
GlbRanges<View1> ylb(y);
|
|
BndSetRanges sub(sofarBeforeUB);
|
|
BndSetRanges afterub(afterUB[i]);
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> xjub(sub, afterub);
|
|
Iter::Ranges::Diff<GlbRanges<View1>,
|
|
Iter::Ranges::Union<BndSetRanges,
|
|
BndSetRanges> > diff2(ylb, xjub);
|
|
GECODE_ME_CHECK_MODIFIED(modified, x[i].includeI(home,diff2));
|
|
|
|
LubRanges<View0> xiub(x[i]);
|
|
sofarBeforeUB.includeI(home,xiub);
|
|
}
|
|
sofarBeforeUB.dispose(home);
|
|
}
|
|
for (int i=xsize;i--;)
|
|
afterUB[i].dispose(home);
|
|
return ES_NOFIX;
|
|
}
|
|
|
|
// Y LB contains union of X LBs
|
|
template<class View0, class View1>
|
|
ExecStatus
|
|
partitionNYLB(Space& home,
|
|
bool& modified, ViewArray<View0>& x, View1& y,
|
|
GLBndSet& unionOfDets) {
|
|
assert(unionOfDets.isConsistent());
|
|
int xsize = x.size();
|
|
Region reg;
|
|
GlbRanges<View0>* xLBs = reg.alloc<GlbRanges<View0> >(xsize);
|
|
int nonEmptyCounter=0;
|
|
for (int i = xsize; i--; ) {
|
|
GlbRanges<View0> r(x[i]);
|
|
if (r()) {
|
|
xLBs[nonEmptyCounter] = r;
|
|
nonEmptyCounter++;
|
|
}
|
|
}
|
|
if (nonEmptyCounter !=0) {
|
|
Iter::Ranges::NaryUnion xLBUnion(reg,xLBs,nonEmptyCounter);
|
|
BndSetRanges dets(unionOfDets);
|
|
xLBUnion |= dets;
|
|
GECODE_ME_CHECK_MODIFIED(modified, y.includeI(home,xLBUnion));
|
|
}
|
|
return ES_FIX;
|
|
}
|
|
|
|
// Y UB is subset of union of X UBs
|
|
template<class View0, class View1>
|
|
ExecStatus
|
|
partitionNYUB(Space& home,
|
|
bool& modified, ViewArray<View0>& x, View1& y,
|
|
GLBndSet& unionOfDets) {
|
|
int xsize = x.size();
|
|
Region reg;
|
|
LubRanges<View0>* xUBs = reg.alloc<LubRanges<View0> >(xsize);
|
|
int nonEmptyCounter=0;
|
|
for (int i = xsize; i--; ) {
|
|
LubRanges<View0> r(x[i]);
|
|
if (r()) {
|
|
xUBs[nonEmptyCounter] = r;
|
|
nonEmptyCounter++;
|
|
}
|
|
}
|
|
if (nonEmptyCounter != 0) {
|
|
Iter::Ranges::NaryUnion xUBUnion(reg,xUBs,nonEmptyCounter);
|
|
BndSetRanges dets(unionOfDets);
|
|
xUBUnion |= dets;
|
|
GECODE_ME_CHECK_MODIFIED(modified, y.intersectI(home,xUBUnion));
|
|
}
|
|
return ES_FIX;
|
|
}
|
|
|
|
}}}
|
|
|
|
#endif
|
|
|
|
// STATISTICS: set-prop
|