dom.hpp /usr/include/gecode/int/channel.hh Gecode::Int::Channel::DomInfo Gecode Gecode::Int Gecode::Int::Channel /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *ChristianSchulte<schulte@gecode.org> * *Contributingauthors: *MikaelLagerkvist<lagerkvist@gecode.org> * *Copyright: *ChristianSchulte,2006 *MikaelLagerkvist,2006 * *Lastmodified: *$Date:2012-09-0717:31:22+0200(Fri,07Sep2012)$by$Author:schulte$ *$Revision:13068$ * *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{namespaceChannel{ template<classView,classOffset> classDomInfo{ public: Viewview; unsignedintsize; intmin; intmax; voidinit(Viewx,intn); voidupdate(Space&home,boolshare,DomInfo<View,Offset>&vcb); booldoval(void)const; booldodom(void)const; voidassigned(void); voidremoved(inti); voiddone(Offset&o); }; template<classView,classOffset> forceinlinevoid DomInfo<View,Offset>::init(Viewx,intn){ view=x; size=static_cast<unsignedint>(n); min=0; max=n-1; } template<classView,classOffset> forceinlinevoid DomInfo<View,Offset>::update(Space&home,boolshare, DomInfo<View,Offset>&di){ view.update(home,share,di.view); size=di.size; min=di.min; max=di.max; } template<classView,classOffset> forceinlinebool DomInfo<View,Offset>::doval(void)const{ return(size!=1)&&view.assigned(); } template<classView,classOffset> forceinlinebool DomInfo<View,Offset>::dodom(void)const{ returnsize!=view.size(); } template<classView,classOffset> forceinlinevoid DomInfo<View,Offset>::assigned(void){ size=1; } template<classView,classOffset> forceinlinevoid DomInfo<View,Offset>::removed(inti){ size--; if(i==min) min++; elseif(i==max) max--; } template<classView,classOffset> forceinlinevoid DomInfo<View,Offset>::done(Offset&o){ size=view.size(); min=o(view).min(); max=o(view).max(); } //Propagatedomaininformationfromxtoy template<classView,classOffset> ExecStatus prop_dom(Space&home,intn,DomInfo<View,Offset>*x,Offset&ox, DomInfo<View,Offset>*y,Offset&oy,ProcessStack&ya){ for(inti=n;i--;) //Onlyviewswithnotyetpropagatedmissingvalues if(x[i].dodom()){ //Iteratethevaluesinthecomplementofx[i] ViewRanges<typename Offset::ViewType> xir(ox(x[i].view)); Iter::Ranges::ComplVal<ViewRanges<typename Offset::ViewType>> xirc(x[i].min,x[i].max,xir); Iter::Ranges::ToValues<Iter::Ranges::ComplVal< ViewRanges<typename Offset::ViewType>>>jv(xirc); while(jv()){ //jisnotinthedomainofx[i],sopruneifromy[j] intj=jv.val(); ModEventme=oy(y[j].view).nq(home,i); if(me_failed(me)) returnES_FAILED; if(me_modified(me)){ if(me==ME_INT_VAL){ //Recordthaty[j]hasbeenassignedandmustbepropagated ya.push(j); }else{ //Obviousasx[i]isdifferentfromj y[j].removed(i); } } ++jv; } //Updatewhichvalueshavebeenpropagatedandwhatarethenewbounds x[i].done(ox); } returnES_OK; } /* *Theactualpropagator * */ template<classView,classOffset,boolshared> forceinline Dom<View,Offset,shared>::Dom(Homehome,intn,DomInfo<View,Offset>*xy, Offset&ox,Offset&oy) :Base<DomInfo<View,Offset>,Offset,PC_INT_DOM>(home,n,xy,ox,oy){} template<classView,classOffset,boolshared> forceinline Dom<View,Offset,shared>::Dom(Space&home,boolshare, Dom<View,Offset,shared>&p) :Base<DomInfo<View,Offset>,Offset,PC_INT_DOM>(home,share,p){} template<classView,classOffset,boolshared> Actor* Dom<View,Offset,shared>::copy(Space&home,boolshare){ returnnew(home)Dom<View,Offset,shared>(home,share,*this); } template<classView,classOffset,boolshared> PropCost Dom<View,Offset,shared>::cost(constSpace&, constModEventDelta&med)const{ if(View::me(med)==ME_INT_VAL) returnPropCost::quadratic(PropCost::LO,2*n); else returnPropCost::quadratic(PropCost::HI,2*n); } template<classView,classOffset,boolshared> ExecStatus Dom<View,Offset,shared>::propagate(Space&home,constModEventDelta&med){ Regionr(home); ProcessStackxa(r,n); ProcessStackya(r,n); DomInfo<View,Offset>*x=xy; DomInfo<View,Offset>*y=xy+n; if(View::me(med)==ME_INT_VAL){ //Scanxandyforassignedbutnotyetpropagatedviews for(inti=n;i--;){ if(x[i].doval())xa.push(i); if(y[i].doval())ya.push(i); } if(shared){ do{ //Propagateassignedviewsforx GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset>> (home,n,x,ox,y,oy,n_na,xa,ya))); //Propagateassignedviewsfory GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset>> (home,n,y,oy,x,ox,n_na,ya,xa))); assert(ya.empty()); }while(!xa.empty()||!ya.empty()); returnhome.ES_NOFIX_PARTIAL(*this,View::med(ME_INT_DOM)); }else{ do{ //Propagateassignedviewsforx GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset>> (home,n,x,ox,y,oy,n_na,xa,ya))); //Propagateassignedviewsfory GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset>> (home,n,y,oy,x,ox,n_na,ya,xa))); assert(ya.empty()); }while(!xa.empty()); returnhome.ES_FIX_PARTIAL(*this,View::med(ME_INT_DOM)); } } //Processchangedviewsfory //Thispropagatesfromytoxandpossiblyrecordsxsthat //gotassigned GECODE_ES_CHECK(prop_dom(home,n,y,oy,x,ox,xa)); //Processassignedviewsforx GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset>> (home,n,x,ox,y,oy,n_na,xa,ya))); //Performdomainconsistentpropagationfordistinctonthexviews if(dc.available()){ GECODE_ES_CHECK(dc.sync(home)); }else{ ViewArray<View>xv(r,n); for(inti=n;i--;) xv[i]=x[i].view; GECODE_ES_CHECK(dc.init(home,xv)); } boolassigned; GECODE_ES_CHECK(dc.propagate(home,assigned)); if(assigned){ //Thishasassignedsomemoreviewsinxwhichgoesunnoticed //(thatis,notrecordedinxa).Thismustbecheckedandpropagated //totheyviews,howeverthedistinctnessonxisalready //propagated. for(inti=n;i--;) if(x[i].doval()){ intj=ox(x[i].view).val(); //Assigntheyvariabletoi(ortestifalreadyassigned!) ModEventme=oy(y[j].view).eq(home,i); if(me_failed(me)) returnES_FAILED; if(me_modified(me)){ //Recordthaty[j]hasbeenassignedandmustbepropagated assert(me==ME_INT_VAL); //OtherwisethemodificationeventwouldnotbeME_INT_VAL ya.push(j); } x[i].assigned();n_na--; } } //Processchangedviewsforx //Thispropagatesfromxtoyandpossiblyrecordsysthat //gotassigned GECODE_ES_CHECK(prop_dom(home,n,x,ox,y,oy,ya)); //Processassignedviewagain(somemighthavebeenfoundabove) while(!xa.empty()||!ya.empty()){ //Processassignedviewsforx GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset>> (home,n,x,ox,y,oy,n_na,xa,ya))); //Processassignedviewsfory GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset>> (home,n,y,oy,x,ox,n_na,ya,xa))); }; if(shared){ for(inti=2*n;i--;) if(!xy[i].view.assigned()) returnES_NOFIX; returnhome.ES_SUBSUMED(*this); }else{ return(n_na==0)?home.ES_SUBSUMED(*this):ES_FIX; } } template<classView,classOffset,boolshared> ExecStatus Dom<View,Offset,shared>::post(Homehome,intn,DomInfo<View,Offset>*xy, Offset&ox,Offset&oy){ assert(n>0); if(n==1){ GECODE_ME_CHECK(ox(xy[0].view).eq(home,0)); GECODE_ME_CHECK(oy(xy[1].view).eq(home,0)); returnES_OK; } for(inti=n;i--;){ GECODE_ME_CHECK(ox(xy[i].view).gq(home,0)); GECODE_ME_CHECK(ox(xy[i].view).le(home,n)); GECODE_ME_CHECK(oy(xy[i+n].view).gq(home,0)); GECODE_ME_CHECK(oy(xy[i+n].view).le(home,n)); } (void)new(home)Dom<View,Offset,shared>(home,n,xy,ox,oy); returnES_OK; } }}} //STATISTICS:int-prop