pow.hpp gecode/int/rel.hh climits algorithm /usr/include/gecode/int/arithmetic.hh Gecode::Int::Arithmetic::ValuesMapPow Gecode::Int::Arithmetic::ValuesMapNroot Gecode::Int::Arithmetic::ValuesMapNrootSigned Gecode Gecode::Int Gecode::Int::Arithmetic /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *ChristianSchulte<schulte@gecode.org> * *Copyright: *ChristianSchulte,2012 * *Lastmodified: *$Date:2013-03-1220:08:33+0100(Tue,12Mar2013)$by$Author:schulte$ *$Revision:13510$ * *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<gecode/int/rel.hh> #include<climits> #include<algorithm> namespaceGecode{namespaceInt{namespaceArithmetic{ /* *Positiveboundsconsistentpower * */ template<classVA,classVB,classOps> inlineExecStatus prop_pow_plus_bnd(Space&home,VAx0,VBx1,constOps&ops){ boolmod; do{ mod=false; { ModEventme=x0.lq(home,ops.fnroot(x1.max())); if(me_failed(me))returnES_FAILED; mod|=me_modified(me); } { ModEventme=x0.gq(home,ops.cnroot(x1.min())); if(me_failed(me))returnES_FAILED; mod|=me_modified(me); } { ModEventme=x1.lq(home,ops.pow(x0.max())); if(me_failed(me))returnES_FAILED; mod|=me_modified(me); } { ModEventme=x1.gq(home,ops.pow(x0.min())); if(me_failed(me))returnES_FAILED; mod|=me_modified(me); } }while(mod); returnES_OK; } template<classVA,classVB,classOps> forceinline PowPlusBnd<VA,VB,Ops>::PowPlusBnd(Homehome,VAx0,VBx1,constOps&o) :MixBinaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND>(home,x0,x1), ops(o){} template<classVA,classVB,classOps> forceinlineExecStatus PowPlusBnd<VA,VB,Ops>::post(Homehome,VAx0,VBx1,Opsops){ GECODE_ME_CHECK(x0.gq(home,0)); GECODE_ME_CHECK(x1.gq(home,0)); GECODE_ES_CHECK(prop_pow_plus_bnd(home,x0,x1,ops)); if(!x0.assigned()){ assert(!x1.assigned()); (void)new(home)PowPlusBnd<VA,VB,Ops>(home,x0,x1,ops); } returnES_OK; } template<classVA,classVB,classOps> forceinline PowPlusBnd<VA,VB,Ops>::PowPlusBnd(Space&home,boolshare, PowPlusBnd<VA,VB,Ops>&p) :MixBinaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND>(home,share,p), ops(p.ops){} template<classVA,classVB,classOps> Actor* PowPlusBnd<VA,VB,Ops>::copy(Space&home,boolshare){ returnnew(home)PowPlusBnd<VA,VB,Ops>(home,share,*this); } template<classVA,classVB,classOps> ExecStatus PowPlusBnd<VA,VB,Ops>::propagate(Space&home,constModEventDelta&){ GECODE_ES_CHECK(prop_pow_plus_bnd(home,x0,x1,ops)); returnx0.assigned()?home.ES_SUBSUMED(*this):ES_FIX; } /* *Boundsconsistentpower * */ template<classOps> inlineExecStatus prop_pow_bnd(Space&home,IntViewx0,IntViewx1,constOps&ops){ assert((x0.min()<0)&&(0<x0.max())); if(ops.even()){ assert(x1.min()>=0); intu=ops.fnroot(x1.max()); GECODE_ME_CHECK(x0.lq(home,u)); GECODE_ME_CHECK(x0.gq(home,-u)); GECODE_ME_CHECK(x1.lq(home,std::max(ops.pow(x0.max()), ops.pow(-x0.min())))); }else{ assert((x1.min()<0)&&(0<x1.max())); GECODE_ME_CHECK(x0.lq(home,ops.fnroot(x1.max()))); GECODE_ME_CHECK(x0.gq(home,-ops.fnroot(-x1.min()))); GECODE_ME_CHECK(x1.lq(home,ops.pow(x0.max()))); GECODE_ME_CHECK(x1.gq(home,ops.pow(x0.min()))); } returnES_OK; } template<classOps> forceinline PowBnd<Ops>::PowBnd(Homehome,IntViewx0,IntViewx1,constOps&o) :BinaryPropagator<IntView,PC_INT_BND>(home,x0,x1), ops(o){} template<classOps> inlineExecStatus PowBnd<Ops>::post(Homehome,IntViewx0,IntViewx1,Opsops){ if(static_cast<unsignedint>(ops.exp())>=sizeof(int)*CHAR_BIT){ //Theintegerlimitsallowonly-1,0,1forx0 GECODE_ME_CHECK(x0.lq(home,1)); GECODE_ME_CHECK(x0.gq(home,-1)); //Justrewritetovaluesthatcanbehandeledwithoutoverflow ops.exp(ops.even()?2:1); } if(ops.exp()==0){ GECODE_ME_CHECK(x1.eq(home,1)); returnES_OK; }elseif(ops.exp()==1){ returnRel::EqBnd<IntView,IntView>::post(home,x0,x1); } if(same(x0,x1)){ assert(ops.exp()!=0); GECODE_ME_CHECK(x0.lq(home,1)); GECODE_ME_CHECK(x0.gq(home,ops.even()?0:-1)); returnES_OK; } //Limitsvaluessuchthatnooverflowcanoccur assert(Limits::max==-Limits::min); { intl=ops.fnroot(Limits::max); GECODE_ME_CHECK(x0.lq(home,l)); GECODE_ME_CHECK(x0.gq(home,-l)); } if((x0.min()>=0)||((x1.min()>=0)&&!ops.even())) returnPowPlusBnd<IntView,IntView,Ops>::post(home,x0,x1,ops); if(ops.even()&&(x0.max()<=0)) returnPowPlusBnd<MinusView,IntView,Ops> ::post(home,MinusView(x0),x1,ops); if(!ops.even()&&((x0.max()<=0)||(x1.max()<=0))) returnPowPlusBnd<MinusView,MinusView,Ops> ::post(home,MinusView(x0),MinusView(x1),ops); if(ops.even()) GECODE_ME_CHECK(x1.gq(home,0)); assert((x0.min()<0)&&(x0.max()>0)); if(ops.even()){ GECODE_ME_CHECK(x1.lq(home,std::max(ops.pow(x0.min()), ops.pow(x0.max())))); }else{ GECODE_ME_CHECK(x1.lq(home,ops.pow(x0.max()))); GECODE_ME_CHECK(x1.gq(home,ops.pow(x0.min()))); } (void)new(home)PowBnd<Ops>(home,x0,x1,ops); returnES_OK; } template<classOps> forceinline PowBnd<Ops>::PowBnd(Space&home,boolshare,PowBnd<Ops>&p) :BinaryPropagator<IntView,PC_INT_BND>(home,share,p), ops(p.ops){} template<classOps> Actor* PowBnd<Ops>::copy(Space&home,boolshare){ returnnew(home)PowBnd<Ops>(home,share,*this); } template<classOps> ExecStatus PowBnd<Ops>::propagate(Space&home,constModEventDelta&){ if((x0.min()>=0)||((x1.min()>=0)&&!ops.even())) GECODE_REWRITE(*this,(PowPlusBnd<IntView,IntView,Ops> ::post(home(*this),x0,x1,ops))); if(ops.even()&&(x0.max()<=0)) GECODE_REWRITE(*this,(PowPlusBnd<MinusView,IntView,Ops> ::post(home(*this),MinusView(x0),x1,ops))); if(!ops.even()&&((x0.max()<=0)||(x1.max()<=0))) GECODE_REWRITE(*this,(PowPlusBnd<MinusView,MinusView,Ops> ::post(home(*this),MinusView(x0), MinusView(x1),ops))); GECODE_ES_CHECK(prop_pow_bnd<Ops>(home,x0,x1,ops)); if(x0.assigned()&&x1.assigned()) return(ops.pow(x0.val())==x1.val())? home.ES_SUBSUMED(*this):ES_FAILED; returnES_NOFIX; } /* *Valuemappingsforpowerandnroot * */ template<classOps> classValuesMapPow{ protected: Opsops; public: forceinlineValuesMapPow(constOps&o):ops(o){} forceinlineintval(intx)const{ returnops.pow(x); } }; template<classOps> classValuesMapNroot{ protected: Opsops; public: forceinlineValuesMapNroot(constOps&o):ops(o){} forceinlineintval(intx)const{ returnops.fnroot(x); } }; template<classOps> classValuesMapNrootSigned{ protected: Opsops; public: forceinlineValuesMapNrootSigned(constOps&o):ops(o){} forceinlineintval(intx)const{ if(x<0) return-ops.fnroot(-x); else returnops.fnroot(x); } }; /* *Positivedomainconsistentpower * */ template<classVA,classVB,classOps> forceinline PowPlusDom<VA,VB,Ops>::PowPlusDom(Homehome,VAx0,VBx1,constOps&o) :MixBinaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM>(home,x0,x1), ops(o){} template<classVA,classVB,classOps> forceinlineExecStatus PowPlusDom<VA,VB,Ops>::post(Homehome,VAx0,VBx1,Opsops){ GECODE_ME_CHECK(x0.gq(home,0)); GECODE_ME_CHECK(x1.gq(home,0)); GECODE_ES_CHECK(prop_pow_plus_bnd(home,x0,x1,ops)); if(!x0.assigned()){ assert(!x1.assigned()); (void)new(home)PowPlusDom<VA,VB,Ops>(home,x0,x1,ops); } returnES_OK; } template<classVA,classVB,classOps> forceinline PowPlusDom<VA,VB,Ops>::PowPlusDom(Space&home,boolshare, PowPlusDom<VA,VB,Ops>&p) :MixBinaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM>(home,share,p), ops(p.ops){} template<classVA,classVB,classOps> Actor* PowPlusDom<VA,VB,Ops>::copy(Space&home,boolshare){ returnnew(home)PowPlusDom<VA,VB,Ops>(home,share,*this); } template<classVA,classVB,classOps> PropCost PowPlusDom<VA,VB,Ops>::cost(constSpace&,constModEventDelta&med)const{ if(VA::me(med)==ME_INT_VAL) returnPropCost::unary(PropCost::LO); elseif(VA::me(med)==ME_INT_DOM) returnPropCost::binary(PropCost::HI); else returnPropCost::binary(PropCost::LO); } template<classVA,classVB,classOps> ExecStatus PowPlusDom<VA,VB,Ops>::propagate(Space&home,constModEventDelta&med){ if(VA::me(med)!=ME_INT_DOM){ GECODE_ES_CHECK(prop_pow_plus_bnd(home,x0,x1,ops)); returnx0.assigned()? home.ES_SUBSUMED(*this) :home.ES_NOFIX_PARTIAL(*this,VA::med(ME_INT_DOM)); } { ViewValues<VA>v0(x0); ValuesMapPow<Ops>vmp(ops); Iter::Values::Map<ViewValues<VA>,ValuesMapPow<Ops>>s0(v0,vmp); GECODE_ME_CHECK(x1.inter_v(home,s0,false)); } { ViewValues<VB>v1(x1); ValuesMapNroot<Ops>vmn(ops); Iter::Values::Map<ViewValues<VB>,ValuesMapNroot<Ops>>s1(v1,vmn); GECODE_ME_CHECK(x0.inter_v(home,s1,false)); } returnx0.assigned()?home.ES_SUBSUMED(*this):ES_FIX; } /* *Domainconsistentpower * */ template<classOps> forceinline PowDom<Ops>::PowDom(Homehome,IntViewx0,IntViewx1,constOps&o) :BinaryPropagator<IntView,PC_INT_DOM>(home,x0,x1),ops(o){} template<classOps> inlineExecStatus PowDom<Ops>::post(Homehome,IntViewx0,IntViewx1,Opsops){ if(static_cast<unsignedint>(ops.exp())>=sizeof(int)*CHAR_BIT){ //Theintegerlimitsallowonly-1,0,1forx0 GECODE_ME_CHECK(x0.lq(home,1)); GECODE_ME_CHECK(x0.gq(home,-1)); //Justrewritetovaluesthatcanbehandeledwithoutoverflow ops.exp(ops.even()?2:1); } if(ops.exp()==0){ GECODE_ME_CHECK(x1.eq(home,1)); returnES_OK; }elseif(ops.exp()==1){ returnRel::EqDom<IntView,IntView>::post(home,x0,x1); } if(same(x0,x1)){ assert(ops.exp()!=0); GECODE_ME_CHECK(x0.lq(home,1)); GECODE_ME_CHECK(x0.gq(home,ops.even()?0:-1)); returnES_OK; } //Limitsvaluessuchthatnooverflowcanoccur assert(Limits::max==-Limits::min); { intl=ops.fnroot(Limits::max); GECODE_ME_CHECK(x0.lq(home,l)); GECODE_ME_CHECK(x0.gq(home,-l)); } if((x0.min()>=0)||((x1.min()>=0)&&!ops.even())) returnPowPlusDom<IntView,IntView,Ops>::post(home,x0,x1,ops); if(ops.even()&&(x0.max()<=0)) returnPowPlusDom<MinusView,IntView,Ops> ::post(home,MinusView(x0),x1,ops); if(!ops.even()&&((x0.max()<=0)||(x1.max()<=0))) returnPowPlusDom<MinusView,MinusView,Ops> ::post(home,MinusView(x0),MinusView(x1),ops); if(ops.even()) GECODE_ME_CHECK(x1.gq(home,0)); assert((x0.min()<0)&&(x0.max()>0)); if(ops.even()){ GECODE_ME_CHECK(x1.lq(home,std::max(ops.pow(x0.min()), ops.pow(x0.max())))); }else{ GECODE_ME_CHECK(x1.lq(home,ops.pow(x0.max()))); GECODE_ME_CHECK(x1.gq(home,ops.pow(x0.min()))); } (void)new(home)PowDom<Ops>(home,x0,x1,ops); returnES_OK; } template<classOps> forceinline PowDom<Ops>::PowDom(Space&home,boolshare,PowDom<Ops>&p) :BinaryPropagator<IntView,PC_INT_DOM>(home,share,p), ops(p.ops){} template<classOps> Actor* PowDom<Ops>::copy(Space&home,boolshare){ returnnew(home)PowDom<Ops>(home,share,*this); } template<classOps> PropCost PowDom<Ops>::cost(constSpace&,constModEventDelta&med)const{ if(IntView::me(med)==ME_INT_VAL) returnPropCost::unary(PropCost::LO); elseif(IntView::me(med)==ME_INT_DOM) returnPropCost::binary(PropCost::HI); else returnPropCost::binary(PropCost::LO); } template<classOps> ExecStatus PowDom<Ops>::propagate(Space&home,constModEventDelta&med){ if((x0.min()>=0)||((x1.min()>=0)&&!ops.even())) GECODE_REWRITE(*this,(PowPlusDom<IntView,IntView,Ops> ::post(home(*this),x0,x1,ops))); if(ops.even()&&(x0.max()<=0)) GECODE_REWRITE(*this,(PowPlusDom<MinusView,IntView,Ops> ::post(home(*this),MinusView(x0),x1,ops))); if(!ops.even()&&((x0.max()<=0)||(x1.max()<=0))) GECODE_REWRITE(*this,(PowPlusDom<MinusView,MinusView,Ops> ::post(home(*this),MinusView(x0), MinusView(x1),ops))); if(IntView::me(med)!=ME_INT_DOM){ GECODE_ES_CHECK(prop_pow_bnd<Ops>(home,x0,x1,ops)); if(x0.assigned()&&x1.assigned()) return(ops.pow(x0.val())==x1.val())? home.ES_SUBSUMED(*this):ES_FAILED; returnhome.ES_NOFIX_PARTIAL(*this,IntView::med(ME_INT_DOM)); } Regionr(home); if(ops.even()){ ViewValues<IntView>i(x0),j(x0); usingnamespaceIter::Values; Positive<ViewValues<IntView>>pos(i); Negative<ViewValues<IntView>>neg(j); Minusm(r,neg); ValuesMapPow<Ops>vmp(ops); Map<Positive<ViewValues<IntView>>,ValuesMapPow<Ops>,true>sp(pos,vmp); Map<Minus,ValuesMapPow<Ops>,true>sm(m,vmp); Union<Map<Positive<ViewValues<IntView>>,ValuesMapPow<Ops>,true>, Map<Minus,ValuesMapPow<Ops>,true>>u(sp,sm); GECODE_ME_CHECK(x1.inter_v(home,u,false)); }else{ ViewValues<IntView>v0(x0); ValuesMapPow<Ops>vmp(ops); Iter::Values::Map<ViewValues<IntView>,ValuesMapPow<Ops>>s0(v0,vmp); GECODE_ME_CHECK(x1.inter_v(home,s0,false)); } if(ops.even()){ ViewValues<IntView>i(x1),j(x1); usingnamespaceIter::Values; ValuesMapNroot<Ops>vmn(ops); Map<ViewValues<IntView>,ValuesMapNroot<Ops>,true>si(i,vmn),sj(j,vmn); Minusmi(r,si); Union<Minus, Map<ViewValues<IntView>,ValuesMapNroot<Ops>,true>>u(mi,sj); GECODE_ME_CHECK(x0.inter_v(home,u,false)); }else{ ViewValues<IntView>v1(x1); ValuesMapNrootSigned<Ops>vmn(ops); Iter::Values::Map<ViewValues<IntView>,ValuesMapNrootSigned<Ops>> s1(v1,vmn); GECODE_ME_CHECK(x0.inter_v(home,s1,false)); } returnx0.assigned()?home.ES_SUBSUMED(*this):ES_FIX; } }}} //STATISTICS:int-prop