bool-int.hpp algorithm gecode/int/bool.hh /usr/include/gecode/int/linear.hh Gecode::Int::Linear::BoolNegTraits< BoolView > Gecode::Int::Linear::BoolNegTraits< NegBoolView > Gecode Gecode::Int Gecode::Int::Linear /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *ChristianSchulte<schulte@gecode.org> *TiasGuns<tias.guns@cs.kuleuven.be> * *Copyright: *ChristianSchulte,2006 *TiasGuns,2009 * *Lastmodified: *$Date:2012-10-1816:02:42+0200(Thu,18Oct2012)$by$Author:schulte$ *$Revision:13154$ * *ThisfileispartofGecode,thegenericconstraint *developmentenvironment: *http://www.gecode.org * *Permissionisherebygranted,freeofcharge,toanypersonobtaining *acopyofthissoftwareandassociateddocumentationfiles(the *"Software"),todealintheSoftwarewithoutrestriction,including *withoutlimitationtherightstouse,copy,modify,merge,publish, *distribute,sublicense,and/orsellcopiesoftheSoftware,andto *permitpersonstowhomtheSoftwareisfurnishedtodoso,subjectto *thefollowingconditions: * *Theabovecopyrightnoticeandthispermissionnoticeshallbe *includedinallcopiesorsubstantialportionsoftheSoftware. * *THESOFTWAREISPROVIDED"ASIS",WITHOUTWARRANTYOFANYKIND, *EXPRESSORIMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOF *MERCHANTABILITY,FITNESSFORAPARTICULARPURPOSEAND *NONINFRINGEMENT.INNOEVENTSHALLTHEAUTHORSORCOPYRIGHTHOLDERSBE *LIABLEFORANYCLAIM,DAMAGESOROTHERLIABILITY,WHETHERINANACTION *OFCONTRACT,TORTOROTHERWISE,ARISINGFROM,OUTOFORINCONNECTION *WITHTHESOFTWAREORTHEUSEOROTHERDEALINGSINTHESOFTWARE. * */ #include<algorithm> #include<gecode/int/bool.hh> namespaceGecode{namespaceInt{namespaceLinear{ /* *BaseclassforintegerBooleansumusingdependencies * */ template<classVX> forceinline LinBoolInt<VX>::LinBoolInt(Homehome,ViewArray<VX>&x0, intn_s,intc0) :Propagator(home),co(home),x(x0),n_as(n_s),n_hs(n_s),c(c0){ Advisor*a=new(home)Advisor(home,*this,co); for(inti=n_as;i--;) x[i].subscribe(home,*a); } template<classVX> forceinlinevoid LinBoolInt<VX>::normalize(void){ if(n_as!=n_hs){ //Removeviewsforwhichnomoresubscriptionsexist intn_x=x.size(); for(inti=n_hs;i--;) if(!x[i].none()){ x[i]=x[--n_hs];x[n_hs]=x[--n_x]; } x.size(n_x); } assert(n_as==n_hs); //Removeassignedyetunsubscribedviews { intn_x=x.size(); for(inti=n_x-1;i>=n_hs;i--) if(x[i].one()){ c--;x[i]=x[--n_x]; }elseif(x[i].zero()){ x[i]=x[--n_x]; } x.size(n_x); } } template<classVX> forceinline LinBoolInt<VX>::LinBoolInt(Space&home,boolshare,LinBoolInt<VX>&p) :Propagator(home,share,p),n_as(p.n_as),n_hs(n_as){ p.normalize(); c=p.c; co.update(home,share,p.co); x.update(home,share,p.x); } template<classVX> PropCost LinBoolInt<VX>::cost(constSpace&,constModEventDelta&)const{ returnPropCost::unary(PropCost::HI); } template<classVX> forceinlinesize_t LinBoolInt<VX>::dispose(Space&home){ Advisors<Advisor>as(co); for(inti=n_hs;i--;) x[i].cancel(home,as.advisor()); co.dispose(home); (void)Propagator::dispose(home); returnsizeof(*this); } /* *Greaterorequalpropagator(integerrhs) * */ template<classVX> forceinline GqBoolInt<VX>::GqBoolInt(Homehome,ViewArray<VX>&x,intc) :LinBoolInt<VX>(home,x,c+1,c){} template<classVX> forceinline GqBoolInt<VX>::GqBoolInt(Space&home,boolshare,GqBoolInt<VX>&p) :LinBoolInt<VX>(home,share,p){} template<classVX> Actor* GqBoolInt<VX>::copy(Space&home,boolshare){ returnnew(home)GqBoolInt<VX>(home,share,*this); } template<classVX> ExecStatus GqBoolInt<VX>::advise(Space&home,Advisor&a,constDelta&d){ //Checkwhetherpropagatorisrunning if(n_as==0) returnES_FIX; if(VX::one(d)){ c--;gotocheck; } if(c+1<n_as) gotocheck; //Findanewsubscription for(inti=x.size()-1;i>=n_hs;i--) if(x[i].none()){ std::swap(x[i],x[n_hs]); x[n_hs++].subscribe(home,a); x.size(i+1); returnES_FIX; }elseif(x[i].one()){ c--; if(c+1<n_as){ x.size(i); assert(n_hs<=x.size()); gotocheck; } } //Noviewleftforsubscription x.size(n_hs); check: //Donotupdatesubscription n_as--; intn=x.size()-n_hs+n_as; if(n<c) returnES_FAILED; if((c<=0)||(c==n)) returnES_NOFIX; else returnES_FIX; } template<classVX> ExecStatus GqBoolInt<VX>::propagate(Space&home,constModEventDelta&){ if(c>0){ assert((n_as==c)&&(x.size()==n_hs)); //Signalthatpropagatorisrunning n_as=0; //Allviewsmustbeonetosatisfyinequality for(inti=n_hs;i--;) if(x[i].none()) GECODE_ME_CHECK(x[i].one_none(home)); } returnhome.ES_SUBSUMED(*this); } template<classVX> ExecStatus GqBoolInt<VX>::post(Homehome,ViewArray<VX>&x,intc){ //Eliminateassignedviews intn_x=x.size(); for(inti=n_x;i--;) if(x[i].zero()){ x[i]=x[--n_x]; }elseif(x[i].one()){ x[i]=x[--n_x];c--; } x.size(n_x); //RHStoolarge if(n_x<c) returnES_FAILED; //Whateverthex[i]takeforvalues,theinequalityissubsumed if(c<=0) returnES_OK; //UseBooleandisjunctionforthisspecialcase if(c==1) returnBool::NaryOrTrue<VX>::post(home,x); //Allviewsmustbeonetosatisfyinequality if(c==n_x){ for(inti=n_x;i--;) GECODE_ME_CHECK(x[i].one_none(home)); returnES_OK; } //Thisistheneededinvariantasc+1subscriptionsmustbecreated assert(n_x>c); (void)new(home)GqBoolInt<VX>(home,x,c); returnES_OK; } /* *Equalpropagator(integerrhs) * */ template<classVX> forceinline EqBoolInt<VX>::EqBoolInt(Homehome,ViewArray<VX>&x,intc) :LinBoolInt<VX>(home,x,std::max(c,x.size()-c)+1,c){} template<classVX> forceinline EqBoolInt<VX>::EqBoolInt(Space&home,boolshare,EqBoolInt<VX>&p) :LinBoolInt<VX>(home,share,p){} template<classVX> Actor* EqBoolInt<VX>::copy(Space&home,boolshare){ returnnew(home)EqBoolInt<VX>(home,share,*this); } template<classVX> ExecStatus EqBoolInt<VX>::advise(Space&home,Advisor&a,constDelta&d){ //Checkwhetherpropagatorisrunning if(n_as==0) returnES_FIX; if(VX::one(d)) c--; if((c+1<n_as)&&(x.size()-n_hs<c)) gotocheck; //Findanewsubscription for(inti=x.size()-1;i>=n_hs;i--) if(x[i].none()){ std::swap(x[i],x[n_hs]); x[n_hs++].subscribe(home,a); x.size(i+1); returnES_FIX; }elseif(x[i].one()){ c--; } //Noviewleftforsubscription x.size(n_hs); check: //Donotupdatesubscription n_as--; intn=x.size()-n_hs+n_as; if((c<0)||(c>n)) returnES_FAILED; if((c==0)||(c==n)) returnES_NOFIX; else returnES_FIX; } template<classVX> ExecStatus EqBoolInt<VX>::propagate(Space&home,constModEventDelta&){ assert(x.size()==n_hs); //Signalthatpropagatorisrunning n_as=0; if(c==0){ //Allviewsmustbezerotosatisfyequality for(inti=n_hs;i--;) if(x[i].none()) GECODE_ME_CHECK(x[i].zero_none(home)); }else{ //Allviewsmustbeonetosatisfyequality for(inti=n_hs;i--;) if(x[i].none()) GECODE_ME_CHECK(x[i].one_none(home)); } returnhome.ES_SUBSUMED(*this); } template<classVX> ExecStatus EqBoolInt<VX>::post(Homehome,ViewArray<VX>&x,intc){ //Eliminateassignedviews intn_x=x.size(); for(inti=n_x;i--;) if(x[i].zero()){ x[i]=x[--n_x]; }elseif(x[i].one()){ x[i]=x[--n_x];c--; } x.size(n_x); //RHStoosmallortoolarge if((c<0)||(c>n_x)) returnES_FAILED; //Allviewsmustbezerotosatisfyequality if(c==0){ for(inti=n_x;i--;) GECODE_ME_CHECK(x[i].zero_none(home)); returnES_OK; } //Allviewsmustbeonetosatisfyequality if(c==n_x){ for(inti=n_x;i--;) GECODE_ME_CHECK(x[i].one_none(home)); returnES_OK; } (void)new(home)EqBoolInt<VX>(home,x,c); returnES_OK; } /* *IntegerdisequaltoBooleansum * */ template<classVX> forceinline NqBoolInt<VX>::NqBoolInt(Homehome,ViewArray<VX>&b,intc0) :BinaryPropagator<VX,PC_INT_VAL>(home, b[b.size()-2], b[b.size()-1]),x(b),c(c0){ assert(x.size()>=2); x.size(x.size()-2); } template<classVX> forceinlinesize_t NqBoolInt<VX>::dispose(Space&home){ (void)BinaryPropagator<VX,PC_INT_VAL>::dispose(home); returnsizeof(*this); } template<classVX> forceinline NqBoolInt<VX>::NqBoolInt(Space&home,boolshare,NqBoolInt<VX>&p) :BinaryPropagator<VX,PC_INT_VAL>(home,share,p),x(home,p.x.size()){ //Eliminateallzerosandonesinoriginalandupdate intn=p.x.size(); intp_c=p.c; for(inti=n;i--;) if(p.x[i].zero()){ n--;p.x[i]=p.x[n];x[i]=x[n]; }elseif(p.x[i].one()){ n--;p_c--;p.x[i]=p.x[n];x[i]=x[n]; }else{ x[i].update(home,share,p.x[i]); } c=p_c;p.c=p_c; x.size(n);p.x.size(n); } template<classVX> forceinlineExecStatus NqBoolInt<VX>::post(Homehome,ViewArray<VX>&x,intc){ intn=x.size(); for(inti=n;i--;) if(x[i].one()){ x[i]=x[--n];c--; }elseif(x[i].zero()){ x[i]=x[--n]; } x.size(n); if((n<c)||(c<0)) returnES_OK; if(n==0) return(c==0)?ES_FAILED:ES_OK; if(n==1){ if(c==1){ GECODE_ME_CHECK(x[0].zero_none(home)); }else{ GECODE_ME_CHECK(x[0].one_none(home)); } returnES_OK; } (void)new(home)NqBoolInt(home,x,c); returnES_OK; } template<classVX> Actor* NqBoolInt<VX>::copy(Space&home,boolshare){ returnnew(home)NqBoolInt<VX>(home,share,*this); } template<classVX> PropCost NqBoolInt<VX>::cost(constSpace&,constModEventDelta&)const{ returnPropCost::linear(PropCost::LO,x.size()); } template<classVX> forceinlinebool NqBoolInt<VX>::resubscribe(Space&home,VX&y){ if(y.one()) c--; intn=x.size(); for(inti=n;i--;) if(x[i].one()){ c--;x[i]=x[--n]; }elseif(x[i].zero()){ x[i]=x[--n]; }else{ //Newunassignedviewfound assert(!x[i].zero()&&!x[i].one()); //Movetoyandsubscribe y=x[i];x[i]=x[--n]; x.size(n); y.subscribe(home,*this,PC_INT_VAL,false); returntrue; } //Allviewshavebeenassigned! x.size(0); returnfalse; } template<classVX> ExecStatus NqBoolInt<VX>::propagate(Space&home,constModEventDelta&){ bools0=true; if(x0.zero()||x0.one()) s0=resubscribe(home,x0); bools1=true; if(x1.zero()||x1.one()) s1=resubscribe(home,x1); intn=x.size()+s0+s1; if((n<c)||(c<0)) returnhome.ES_SUBSUMED(*this); if(n==0) return(c==0)?ES_FAILED:home.ES_SUBSUMED(*this); if(n==1){ if(s0){ if(c==1){ GECODE_ME_CHECK(x0.zero_none(home)); }else{ GECODE_ME_CHECK(x0.one_none(home)); } }else{ assert(s1); if(c==1){ GECODE_ME_CHECK(x1.zero_none(home)); }else{ GECODE_ME_CHECK(x1.one_none(home)); } } returnhome.ES_SUBSUMED(*this); } returnES_FIX; } /* *BaseclassforreifiedintegerBooleansum * */ template<classVX,classVB> forceinline ReLinBoolInt<VX,VB>::ReLinBoolInt(Homehome,ViewArray<VX>&x0, intc0,VBb0) :Propagator(home),co(home),x(x0),n_s(x.size()),c(c0),b(b0){ x.subscribe(home,*new(home)Advisor(home,*this,co)); b.subscribe(home,*this,PC_BOOL_VAL); } template<classVX,classVB> forceinlinevoid ReLinBoolInt<VX,VB>::normalize(void){ if(n_s!=x.size()){ intn_x=x.size(); for(inti=n_x;i--;) if(!x[i].none()) x[i]=x[--n_x]; x.size(n_x); assert(x.size()==n_s); } } template<classVX,classVB> forceinline ReLinBoolInt<VX,VB>::ReLinBoolInt(Space&home,boolshare, ReLinBoolInt<VX,VB>&p) :Propagator(home,share,p),n_s(p.n_s),c(p.c){ p.normalize(); co.update(home,share,p.co); x.update(home,share,p.x); b.update(home,share,p.b); } template<classVX,classVB> forceinlinesize_t ReLinBoolInt<VX,VB>::dispose(Space&home){ Advisors<Advisor>as(co); x.cancel(home,as.advisor()); co.dispose(home); b.cancel(home,*this,PC_BOOL_VAL); (void)Propagator::dispose(home); returnsizeof(*this); } template<classVX,classVB> PropCost ReLinBoolInt<VX,VB>::cost(constSpace&,constModEventDelta&)const{ returnPropCost::unary(PropCost::HI); } template<> classBoolNegTraits<BoolView>{ public: typedefNegBoolViewNegView; staticNegBoolViewneg(BoolViewx){ NegBoolViewy(x);returny; } }; template<> classBoolNegTraits<NegBoolView>{ public: typedefBoolViewNegView; staticBoolViewneg(NegBoolViewx){ returnx.base(); } }; /* *Reifiedgreaterorequalpropagator(integerrhs) * */ template<classVX,classVB,ReifyModerm> forceinline ReGqBoolInt<VX,VB,rm>::ReGqBoolInt(Homehome,ViewArray<VX>&x,intc,VBb) :ReLinBoolInt<VX,VB>(home,x,c,b){} template<classVX,classVB,ReifyModerm> forceinline ReGqBoolInt<VX,VB,rm>::ReGqBoolInt(Space&home,boolshare, ReGqBoolInt<VX,VB,rm>&p) :ReLinBoolInt<VX,VB>(home,share,p){} template<classVX,classVB,ReifyModerm> Actor* ReGqBoolInt<VX,VB,rm>::copy(Space&home,boolshare){ returnnew(home)ReGqBoolInt<VX,VB,rm>(home,share,*this); } template<classVX,classVB,ReifyModerm> ExecStatus ReGqBoolInt<VX,VB,rm>::advise(Space&,Advisor&,constDelta&d){ if(VX::one(d)) c--; n_s--; if((n_s<c)||(c<=0)) returnES_NOFIX; else returnES_FIX; } template<classVX,classVB,ReifyModerm> ExecStatus ReGqBoolInt<VX,VB,rm>::propagate(Space&home,constModEventDelta&){ if(b.none()){ if(c<=0){ if(rm!=RM_IMP) GECODE_ME_CHECK(b.one_none(home)); }else{ if(rm!=RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); } }else{ normalize(); if(b.one()){ if(rm!=RM_PMI) GECODE_REWRITE(*this,(GqBoolInt<VX>::post(home(*this),x,c))); }else{ if(rm!=RM_IMP){ ViewArray<typename BoolNegTraits<VX>::NegView>nx(home,x.size()); for(inti=x.size();i--;) nx[i]=BoolNegTraits<VX>::neg(x[i]); GECODE_REWRITE(*this,GqBoolInt<typenameBoolNegTraits<VX>::NegView> ::post(home(*this),nx,x.size()-c+1)); } } } returnhome.ES_SUBSUMED(*this); } template<classVX,classVB,ReifyModerm> ExecStatus ReGqBoolInt<VX,VB,rm>::post(Homehome,ViewArray<VX>&x,intc,VBb){ assert(!b.assigned());//checkedbeforeposting //Eliminateassignedviews intn_x=x.size(); for(inti=n_x;i--;) if(x[i].zero()){ x[i]=x[--n_x]; }elseif(x[i].one()){ x[i]=x[--n_x];c--; } x.size(n_x); if(n_x<c){ //RHStoolarge if(rm!=RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); }elseif(c<=0){ //Whateverthex[i]takeforvalues,theinequalityissubsumed if(rm!=RM_IMP) GECODE_ME_CHECK(b.one_none(home)); }elseif((c==1)&&(rm==RM_EQV)){ //EquivalenttoBooleandisjunction returnBool::NaryOr<VX,VB>::post(home,x,b); }elseif((c==n_x)&&(rm==RM_EQV)){ //EquivalenttoBooleanconjunction,transformtoBooleandisjunction ViewArray<typename BoolNegTraits<VX>::NegView>nx(home,n_x); for(inti=n_x;i--;) nx[i]=BoolNegTraits<VX>::neg(x[i]); returnBool::NaryOr <typenameBoolNegTraits<VX>::NegView, typenameBoolNegTraits<VB>::NegView> ::post(home,nx,BoolNegTraits<VB>::neg(b)); }else{ (void)new(home)ReGqBoolInt<VX,VB,rm>(home,x,c,b); } returnES_OK; } /* *Reifiedequalpropagator(integerrhs) * */ template<classVX,classVB,ReifyModerm> forceinline ReEqBoolInt<VX,VB,rm>::ReEqBoolInt(Homehome,ViewArray<VX>&x,intc,VBb) :ReLinBoolInt<VX,VB>(home,x,c,b){} template<classVX,classVB,ReifyModerm> forceinline ReEqBoolInt<VX,VB,rm>::ReEqBoolInt(Space&home,boolshare, ReEqBoolInt<VX,VB,rm>&p) :ReLinBoolInt<VX,VB>(home,share,p){} template<classVX,classVB,ReifyModerm> Actor* ReEqBoolInt<VX,VB,rm>::copy(Space&home,boolshare){ returnnew(home)ReEqBoolInt<VX,VB,rm>(home,share,*this); } template<classVX,classVB,ReifyModerm> ExecStatus ReEqBoolInt<VX,VB,rm>::advise(Space&,Advisor&,constDelta&d){ if(VX::one(d)) c--; n_s--; if((c<0)||(c>n_s)||(n_s==0)) returnES_NOFIX; else returnES_FIX; } template<classVX,classVB,ReifyModerm> ExecStatus ReEqBoolInt<VX,VB,rm>::propagate(Space&home,constModEventDelta&){ if(b.none()){ if((c==0)&&(n_s==0)){ if(rm!=RM_IMP) GECODE_ME_CHECK(b.one_none(home)); }else{ if(rm!=RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); } }else{ normalize(); if(b.one()){ if(rm!=RM_PMI) GECODE_REWRITE(*this,(EqBoolInt<VX>::post(home(*this),x,c))); }else{ if(rm!=RM_IMP) GECODE_REWRITE(*this,(NqBoolInt<VX>::post(home(*this),x,c))); } } returnhome.ES_SUBSUMED(*this); } template<classVX,classVB,ReifyModerm> ExecStatus ReEqBoolInt<VX,VB,rm>::post(Homehome,ViewArray<VX>&x,intc,VBb){ assert(!b.assigned());//checkedbeforeposting //Eliminateassignedviews intn_x=x.size(); for(inti=n_x;i--;) if(x[i].zero()){ x[i]=x[--n_x]; }elseif(x[i].one()){ x[i]=x[--n_x];c--; } x.size(n_x); if((n_x<c)||(c<0)){ //RHStoolarge if(rm!=RM_PMI) GECODE_ME_CHECK(b.zero_none(home)); }elseif((c==0)&&(n_x==0)){ //allvariablesset,andc==0:equality if(rm!=RM_IMP) GECODE_ME_CHECK(b.one_none(home)); }elseif((c==0)&&(rm==RM_EQV)){ //EquivalenttoBooleandisjunction returnBool::NaryOr<VX,typename BoolNegTraits<VB>::NegView> ::post(home,x,BoolNegTraits<VB>::neg(b)); }elseif((c==n_x)&&(rm==RM_EQV)){ //EquivalenttoBooleanconjunction,transformtoBooleandisjunction ViewArray<typename BoolNegTraits<VX>::NegView>nx(home,n_x); for(inti=n_x;i--;) nx[i]=BoolNegTraits<VX>::neg(x[i]); returnBool::NaryOr <typenameBoolNegTraits<VX>::NegView, typenameBoolNegTraits<VB>::NegView> ::post(home,nx,BoolNegTraits<VB>::neg(b)); }else{ (void)new(home)ReEqBoolInt<VX,VB,rm>(home,x,c,b); } returnES_OK; } }}} //STATISTICS:int-prop