bool-scale.hpp /usr/include/gecode/int/linear.hh Gecode Gecode::Int Gecode::Int::Linear /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *ChristianSchulte<schulte@gecode.org> * *Copyright: *ChristianSchulte,2006 * *Lastmodified: *$Date:2010-03-0317:32:21+0100(Wed,03Mar2010)$by$Author:schulte$ *$Revision:10364$ * *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. * */ namespaceGecode{namespaceInt{namespaceLinear{ /* *ArrayofscaleBooleanviews * */ forceinline ScaleBoolArray::ScaleBoolArray(void){} forceinline ScaleBoolArray::ScaleBoolArray(Space&home,intn){ if(n>0){ _fst=home.alloc<ScaleBool>(n); _lst=_fst+n; }else{ _fst=_lst=NULL; } } forceinlinevoid ScaleBoolArray::subscribe(Space&home,Propagator&p){ for(ScaleBool*f=_fst;f<_lst;f++) f->x.subscribe(home,p,PC_BOOL_VAL); } forceinlinevoid ScaleBoolArray::cancel(Space&home,Propagator&p){ for(ScaleBool*f=_fst;f<_lst;f++) f->x.cancel(home,p,PC_BOOL_VAL); } forceinlinevoid ScaleBoolArray::update(Space&home,boolshare,ScaleBoolArray&sba){ intn=static_cast<int>(sba._lst-sba._fst); if(n>0){ _fst=home.alloc<ScaleBool>(n); _lst=_fst+n; for(inti=n;i--;){ _fst[i].a=sba._fst[i].a; _fst[i].x.update(home,share,sba._fst[i].x); } }else{ _fst=_lst=NULL; } } forceinlineScaleBool* ScaleBoolArray::fst(void)const{ return_fst; } forceinlineScaleBool* ScaleBoolArray::lst(void)const{ return_lst; } forceinlinevoid ScaleBoolArray::fst(ScaleBool*f){ _fst=f; } forceinlinevoid ScaleBoolArray::lst(ScaleBool*l){ _lst=l; } forceinlinebool ScaleBoolArray::empty(void)const{ return_fst==_lst; } forceinlineint ScaleBoolArray::size(void)const{ returnstatic_cast<int>(_lst-_fst); } forceinlinebool ScaleBoolArray::ScaleDec::operator()(constScaleBool&x, constScaleBool&y){ returnx.a>y.a; } inlinevoid ScaleBoolArray::sort(void){ ScaleDecscale_dec; Support::quicksort<ScaleBool,ScaleDec>(fst(),size(),scale_dec); } /* *EmptyarrayofscaleBooleanviews * */ forceinline EmptyScaleBoolArray::EmptyScaleBoolArray(void){} forceinline EmptyScaleBoolArray::EmptyScaleBoolArray(Space&,int){} forceinlinevoid EmptyScaleBoolArray::subscribe(Space&,Propagator&){} forceinlinevoid EmptyScaleBoolArray::cancel(Space&,Propagator&){} forceinlinevoid EmptyScaleBoolArray::update(Space&,bool,EmptyScaleBoolArray&){} forceinlineScaleBool* EmptyScaleBoolArray::fst(void)const{returnNULL;} forceinlineScaleBool* EmptyScaleBoolArray::lst(void)const{returnNULL;} forceinlinevoid EmptyScaleBoolArray::fst(ScaleBool*){} forceinlinevoid EmptyScaleBoolArray::lst(ScaleBool*){} forceinlinebool EmptyScaleBoolArray::empty(void)const{returntrue;} forceinlineint EmptyScaleBoolArray::size(void)const{return0;} forceinlinevoid EmptyScaleBoolArray::sort(void){} /* *Base-classforBooleanconstraintswithcoefficients * */ template<classSBAP,classSBAN,classVX,PropCondpcx> forceinline LinBoolScale<SBAP,SBAN,VX,pcx>::LinBoolScale(Homehome, SBAP&p0,SBAN&n0, VXx0,intc0) :Propagator(home),p(p0),n(n0),x(x0),c(c0){ x.subscribe(home,*this,pcx); p.subscribe(home,*this); n.subscribe(home,*this); } template<classSBAP,classSBAN,classVX,PropCondpcx> PropCost LinBoolScale<SBAP,SBAN,VX,pcx>::cost(constSpace&, constModEventDelta&)const{ returnPropCost::linear(PropCost::LO,p.size()+n.size()); } template<classSBAP,classSBAN,classVX,PropCondpcx> forceinlinesize_t LinBoolScale<SBAP,SBAN,VX,pcx>::dispose(Space&home){ x.cancel(home,*this,pcx); p.cancel(home,*this); n.cancel(home,*this); (void)Propagator::dispose(home); returnsizeof(*this); } template<classSBAP,classSBAN,classVX,PropCondpcx> forceinline LinBoolScale<SBAP,SBAN,VX,pcx>::LinBoolScale(Space&home,boolshare, Propagator&pr, SBAP&p0,SBAN&n0, VXx0,intc0) :Propagator(home,share,pr),c(c0){ x.update(home,share,x0); p.update(home,share,p0); n.update(home,share,n0); } /* *Booleanequalitywithcoefficients * */ template<classSBAP,classSBAN,classVX> forceinline EqBoolScale<SBAP,SBAN,VX>::EqBoolScale(Homehome, SBAP&p,SBAN&n, VXx,intc) :LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,p,n,x,c){} template<classSBAP,classSBAN,classVX> forceinline EqBoolScale<SBAP,SBAN,VX>::EqBoolScale(Space&home,boolshare, Propagator&pr, SBAP&p,SBAN&n, VXx,intc) :LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,share,pr,p,n,x,c){} template<classSBAP,classSBAN,classVX> Actor* EqBoolScale<SBAP,SBAN,VX>::copy(Space&home,boolshare){ if(p.empty()){ EmptyScaleBoolArrayep; if(x.assigned()){ ZeroIntViewz; returnnew(home)EqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView> (home,share,*this,ep,n,z,c+x.val()); }else{ returnnew(home)EqBoolScale<EmptyScaleBoolArray,SBAN,VX> (home,share,*this,ep,n,x,c); } }elseif(n.empty()){ EmptyScaleBoolArrayen; if(x.assigned()){ ZeroIntViewz; returnnew(home)EqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView> (home,share,*this,p,en,z,c+x.val()); }else{ returnnew(home)EqBoolScale<SBAP,EmptyScaleBoolArray,VX> (home,share,*this,p,en,x,c); } }else{ returnnew(home)EqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c); } } template<classSBAP,classSBAN,classVX> ExecStatus EqBoolScale<SBAP,SBAN,VX>::propagate(Space&home,constModEventDelta&med){ intsl_p=0;//Lowerbound,computedpositive intsu_n=0;//Upperbound,computednegative if(BoolView::me(med)==ME_BOOL_VAL){ //Eliminateassignedpositiveviewswhilekeepingorder { //Skipnotassignedviews ScaleBool*f=p.fst(); ScaleBool*l=p.lst(); while((f<l)&&f->x.none()){ su_n+=f->a;f++; } //Copyunassignedviewstot ScaleBool*t=f; while(f<l){ if(f->x.one()){ c-=f->a; }elseif(f->x.none()){ su_n+=f->a;*t=*f;t++; } f++; } p.lst(t); } //Eliminateassignednegativeviewswhilekeepingorder { //Skipnotassignedviews ScaleBool*f=n.fst(); ScaleBool*l=n.lst(); while((f<l)&&f->x.none()){ sl_p+=f->a;f++; } //Copyunassignedviewstot ScaleBool*t=f; while(f<l){ if(f->x.one()){ c+=f->a; }elseif(f->x.none()){ sl_p+=f->a;*t=*f;t++; } f++; } n.lst(t); } }else{ for(ScaleBool*f=p.fst();f<p.lst();f++) su_n+=f->a; for(ScaleBool*f=n.fst();f<n.lst();f++) sl_p+=f->a; } if(p.empty()&&n.empty()){ GECODE_ME_CHECK(x.eq(home,-c)); returnhome.ES_SUBSUMED(*this); } sl_p+=x.max()+c; su_n-=x.min()+c; constintMOD_SL=1<<0; constintMOD_SU=1<<1; intmod=MOD_SL|MOD_SU; do{ if((mod&MOD_SL)!=0){ mod-=MOD_SL; //PropagatelowerboundforpositiveBooleanviews { ScaleBool*f=p.fst(); for(ScaleBool*l=p.lst();(f<l)&&(f->a>sl_p);f++){ GECODE_ME_CHECK(f->x.zero_none(home)); su_n-=f->a; } if(f>p.fst()){ p.fst(f);mod|=MOD_SU; } } //PropagatelowerboundfornegativeBooleanviews { ScaleBool*f=n.fst(); for(ScaleBool*l=n.lst();(f<l)&&(f->a>sl_p);f++){ GECODE_ME_CHECK(f->x.one_none(home));c+=f->a; su_n-=f->a; } if(f>n.fst()){ n.fst(f);mod|=MOD_SU; } } //Propagatelowerboundforintegerview { constintx_min=x.min(); ModEventme=x.gq(home,x.max()-sl_p); if(me_failed(me)) returnES_FAILED; if(me_modified(me)){ su_n-=x.min()-x_min; mod|=MOD_SU; } } } if((mod&MOD_SU)!=0){ mod-=MOD_SU; //PropagateupperboundforpositiveBooleanviews { ScaleBool*f=p.fst(); for(ScaleBool*l=p.lst();(f<l)&&(f->a>su_n);f++){ GECODE_ME_CHECK(f->x.one_none(home));c-=f->a; sl_p-=f->a; } if(f>p.fst()){ p.fst(f);mod|=MOD_SL;; } } //PropagateupperboundfornegativeBooleanviews { ScaleBool*f=n.fst(); for(ScaleBool*l=n.lst();(f<l)&&(f->a>su_n);f++){ GECODE_ME_CHECK(f->x.zero_none(home)); sl_p-=f->a; } if(f>n.fst()){ n.fst(f);mod|=MOD_SL;; } } //Propagateupperboundforintegerview { constintx_max=x.max(); ModEventme=x.lq(home,x.min()+su_n); if(me_failed(me)) returnES_FAILED; if(me_modified(me)){ sl_p+=x.max()-x_max; mod|=MOD_SL;; } } } }while(mod!=0); return(sl_p==-su_n)?home.ES_SUBSUMED(*this):ES_FIX; } template<classSBAP,classSBAN,classVX> ExecStatus EqBoolScale<SBAP,SBAN,VX>::post(Homehome, SBAP&p,SBAN&n,VXx,intc){ p.sort();n.sort(); if(p.empty()){ EmptyScaleBoolArrayep; (void)new(home)EqBoolScale<EmptyScaleBoolArray,SBAN,VX> (home,ep,n,x,c); }elseif(n.empty()){ EmptyScaleBoolArrayen; (void)new(home)EqBoolScale<SBAP,EmptyScaleBoolArray,VX> (home,p,en,x,c); }else{ (void)new(home)EqBoolScale<SBAP,SBAN,VX> (home,p,n,x,c); } returnES_OK; } /* *Booleaninequalitywithcoefficients * */ template<classSBAP,classSBAN,classVX> forceinline LqBoolScale<SBAP,SBAN,VX>::LqBoolScale(Homehome, SBAP&p,SBAN&n, VXx,intc) :LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,p,n,x,c){} template<classSBAP,classSBAN,classVX> forceinline LqBoolScale<SBAP,SBAN,VX>::LqBoolScale(Space&home,boolshare, Propagator&pr, SBAP&p,SBAN&n, VXx,intc) :LinBoolScale<SBAP,SBAN,VX,PC_INT_BND>(home,share,pr,p,n,x,c){} template<classSBAP,classSBAN,classVX> Actor* LqBoolScale<SBAP,SBAN,VX>::copy(Space&home,boolshare){ if(p.empty()){ EmptyScaleBoolArrayep; if(x.assigned()){ ZeroIntViewz; returnnew(home)LqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView> (home,share,*this,ep,n,z,c+x.val()); }else{ returnnew(home)LqBoolScale<EmptyScaleBoolArray,SBAN,VX> (home,share,*this,ep,n,x,c); } }elseif(n.empty()){ EmptyScaleBoolArrayen; if(x.assigned()){ ZeroIntViewz; returnnew(home)LqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView> (home,share,*this,p,en,z,c+x.val()); }else{ returnnew(home)LqBoolScale<SBAP,EmptyScaleBoolArray,VX> (home,share,*this,p,en,x,c); } }else{ returnnew(home)LqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c); } } template<classSBAP,classSBAN,classVX> ExecStatus LqBoolScale<SBAP,SBAN,VX>::propagate(Space&home,constModEventDelta&med){ intsl=0; if(BoolView::me(med)==ME_BOOL_VAL){ //Eliminateassignedpositiveviewswhilekeepingorder { //Skipnotassignedviews ScaleBool*f=p.fst(); ScaleBool*l=p.lst(); while((f<l)&&f->x.none()) f++; //Copyunassignedviewstot ScaleBool*t=f; while(f<l){ if(f->x.one()){ c-=f->a; }elseif(f->x.none()){ *t=*f;t++; } f++; } p.lst(t); } //Eliminateassignednegativeviewswhilekeepingorder { //Skipnotassignedviews ScaleBool*f=n.fst(); ScaleBool*l=n.lst(); while((f<l)&&f->x.none()){ sl+=f->a;f++; } //Copyunassignedviewstot ScaleBool*t=f; while(f<l){ if(f->x.one()){ c+=f->a; }elseif(f->x.none()){ sl+=f->a;*t=*f;t++; } f++; } n.lst(t); } }else{ for(ScaleBool*f=n.fst();f<n.lst();f++) sl+=f->a; } sl+=x.max()+c; //PropagateupperboundforpositiveBooleanviews { ScaleBool*f=p.fst(); for(ScaleBool*l=p.lst();(f<l)&&(f->a>sl);f++) GECODE_ME_CHECK(f->x.zero_none(home)); p.fst(f); } //PropagatelowerboundfornegativeBooleanviews { ScaleBool*f=n.fst(); for(ScaleBool*l=n.lst();(f<l)&&(f->a>sl);f++){ c+=f->a; GECODE_ME_CHECK(f->x.one_none(home)); } n.fst(f); } ExecStatuses=ES_FIX; //Propagatelowerboundforintegerview { constintslx=x.max()-sl; ModEventme=x.gq(home,slx); if(me_failed(me)) returnES_FAILED; if(me_modified(me)&&(slx!=x.min())) es=ES_NOFIX; } if(p.empty()&&n.empty()) returnhome.ES_SUBSUMED(*this); returnes; } template<classSBAP,classSBAN,classVX> ExecStatus LqBoolScale<SBAP,SBAN,VX>::post(Homehome, SBAP&p,SBAN&n,VXx,intc){ p.sort();n.sort(); if(p.empty()){ EmptyScaleBoolArrayep; (void)new(home)LqBoolScale<EmptyScaleBoolArray,SBAN,VX> (home,ep,n,x,c); }elseif(n.empty()){ EmptyScaleBoolArrayen; (void)new(home)LqBoolScale<SBAP,EmptyScaleBoolArray,VX> (home,p,en,x,c); }else{ (void)new(home)LqBoolScale<SBAP,SBAN,VX> (home,p,n,x,c); } returnES_OK; } /* *Booleandisequalitywithcoefficients * */ template<classSBAP,classSBAN,classVX> forceinline NqBoolScale<SBAP,SBAN,VX>::NqBoolScale(Homehome, SBAP&p,SBAN&n, VXx,intc) :LinBoolScale<SBAP,SBAN,VX,PC_INT_VAL>(home,p,n,x,c){} template<classSBAP,classSBAN,classVX> forceinline NqBoolScale<SBAP,SBAN,VX>::NqBoolScale(Space&home,boolshare, Propagator&pr, SBAP&p,SBAN&n, VXx,intc) :LinBoolScale<SBAP,SBAN,VX,PC_INT_VAL>(home,share,pr,p,n,x,c){} template<classSBAP,classSBAN,classVX> Actor* NqBoolScale<SBAP,SBAN,VX>::copy(Space&home,boolshare){ if(p.empty()){ EmptyScaleBoolArrayep; if(x.assigned()){ ZeroIntViewz; returnnew(home)NqBoolScale<EmptyScaleBoolArray,SBAN,ZeroIntView> (home,share,*this,ep,n,z,c+x.val()); }else{ returnnew(home)NqBoolScale<EmptyScaleBoolArray,SBAN,VX> (home,share,*this,ep,n,x,c); } }elseif(n.empty()){ EmptyScaleBoolArrayen; if(x.assigned()){ ZeroIntViewz; returnnew(home)NqBoolScale<SBAP,EmptyScaleBoolArray,ZeroIntView> (home,share,*this,p,en,z,c+x.val()); }else{ returnnew(home)NqBoolScale<SBAP,EmptyScaleBoolArray,VX> (home,share,*this,p,en,x,c); } }else{ returnnew(home)NqBoolScale<SBAP,SBAN,VX>(home,share,*this,p,n,x,c); } } template<classSBAP,classSBAN,classVX> ExecStatus NqBoolScale<SBAP,SBAN,VX>::propagate(Space&home,constModEventDelta&med){ if(BoolView::me(med)==ME_BOOL_VAL){ //Eliminateassignedpositiveviews { ScaleBool*f=p.fst(); ScaleBool*t=f; ScaleBool*l=p.lst(); while(f<l){ if(f->x.one()){ c-=f->a;*f=*(t++); }elseif(f->x.zero()){ *f=*(t++); } f++; } p.fst(t); } //Eliminateassignednegativeviews { ScaleBool*f=n.fst(); ScaleBool*t=f; ScaleBool*l=n.lst(); while(f<l){ if(f->x.one()){ c+=f->a;*f=*(t++); }elseif(f->x.zero()){ *f=*(t++); } f++; } n.fst(t); } } if(p.empty()&&n.empty()){ GECODE_ME_CHECK(x.nq(home,-c)); returnhome.ES_SUBSUMED(*this); } if(x.assigned()){ intr=x.val()+c; if(p.empty()&&(n.size()==1)){ if(r==-n.fst()->a){ GECODE_ME_CHECK(n.fst()->x.zero_none(home)); }elseif(r==0){ GECODE_ME_CHECK(n.fst()->x.one_none(home)); } returnhome.ES_SUBSUMED(*this); } if((p.size()==1)&&n.empty()){ if(r==p.fst()->a){ GECODE_ME_CHECK(p.fst()->x.zero_none(home)); }elseif(r==0){ GECODE_ME_CHECK(p.fst()->x.one_none(home)); } returnhome.ES_SUBSUMED(*this); } } returnES_FIX; } template<classSBAP,classSBAN,classVX> ExecStatus NqBoolScale<SBAP,SBAN,VX>::post(Homehome, SBAP&p,SBAN&n,VXx,intc){ if(p.empty()){ EmptyScaleBoolArrayep; (void)new(home)NqBoolScale<EmptyScaleBoolArray,SBAN,VX> (home,ep,n,x,c); }elseif(n.empty()){ EmptyScaleBoolArrayen; (void)new(home)NqBoolScale<SBAP,EmptyScaleBoolArray,VX> (home,p,en,x,c); }else{ (void)new(home)NqBoolScale<SBAP,SBAN,VX> (home,p,n,x,c); } returnES_OK; } }}} //STATISTICS:int-prop