int-base.hpp gecode/int/distinct.hh /usr/include/gecode/int/nvalues.hh Gecode Gecode::Int Gecode::Int::NValues /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *ChristianSchulte<schulte@gecode.org> * *Copyright: *ChristianSchulte,2011 * *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. * */ #include<gecode/int/distinct.hh> namespaceGecode{namespaceInt{namespaceNValues{ template<classVY> forceinline IntBase<VY>::IntBase(Homehome,ValSet&vs0,ViewArray<IntView>&x,VYy) :MixNaryOnePropagator<IntView,PC_INT_DOM,VY,PC_INT_BND>(home,x,y), vs(vs0){} template<classVY> forceinline IntBase<VY>::IntBase(Space&home,boolshare,IntBase<VY>&p) :MixNaryOnePropagator<IntView,PC_INT_DOM,VY,PC_INT_BND>(home,share,p){ vs.update(home,share,p.vs); } template<classVY> forceinlinesize_t IntBase<VY>::dispose(Space&home){ vs.dispose(home); (void)MixNaryOnePropagator<IntView,PC_INT_DOM,VY,PC_INT_BND> ::dispose(home); returnsizeof(*this); } template<classVY> PropCost IntBase<VY>::cost(constSpace&,constModEventDelta&)const{ returnPropCost::quadratic(PropCost::HI,x.size()); } template<classVY> void IntBase<VY>::add(Space&home){ intn=x.size(); for(inti=n;i--;) if(x[i].assigned()){ vs.add(home,x[i].val()); x[i]=x[--n]; } x.size(n); } template<classVY> void IntBase<VY>::disjoint(Space&home,Region&r,int*&dis,int&n_dis){ //Computepositionsofdisjointviews intn=x.size(); dis=r.alloc<int>(n);n_dis=0; inti=0; while(i<n) switch(vs.compare(x[i])){ caseIter::Ranges::CS_SUBSET: //Allvaluesarealreadycontainedinvs,eliminatex[i] x[i].cancel(home,*this,PC_INT_DOM); x[i]=x[--n]; break; caseIter::Ranges::CS_DISJOINT: dis[n_dis++]=i++; break; caseIter::Ranges::CS_NONE: i++; break; default: GECODE_NEVER; } x.size(n); } template<classVY> void IntBase<VY>::eliminate(Space&home){ intn=x.size(); for(inti=n;i--;) if(vs.subset(x[i])){ //Allvaluesarealreadycontainedinvs,eliminatex[i] x[i].cancel(home,*this,PC_INT_DOM); x[i]=x[--n]; } x.size(n); } template<classVY> int IntBase<VY>::size(Space&home)const{ Regionr(home); assert(x.size()>0); ValSet::Rangesvsr(vs); ViewRanges<IntView>xr(x[x.size()-1]); Iter::Ranges::NaryUnionu(r,vsr,xr); for(inti=x.size()-1;i--;){ ViewRanges<IntView>xir(x[i]); u|=xir; } unsignedints=Iter::Ranges::size(u); //Toavoidoverflow if(static_cast<unsignedint>(x.size()+vs.size())<s) returnx.size()+vs.size(); else returnstatic_cast<int>(s); } template<classVY> ExecStatus IntBase<VY>::all_in_valset(Space&home){ for(inti=x.size();i--;){ ValSet::Rangesvsr(vs); GECODE_ME_CHECK(x[i].inter_r(home,vsr,false)); } returnhome.ES_SUBSUMED(*this); } template<classVY> ExecStatus IntBase<VY>::prune_lower(Space&home,int*dis,intn_dis){ assert(n_dis>0); //Atleastonemorevaluewillbeneeded GECODE_ME_CHECK(y.gq(home,vs.size()+1)); Regionr(home); //Onlyoneadditionalvalueisallowed if(y.max()==vs.size()+1){ //Computepossiblevalues ViewRanges<IntView>*r_dis=r.alloc<ViewRanges<IntView>>(n_dis); for(inti=n_dis;i--;) r_dis[i]=ViewRanges<IntView>(x[dis[i]]); Iter::Ranges::NaryInteriv(r,r_dis,n_dis); //Isthereacommonvalueatall? if(!iv()) returnES_FAILED; ValSet::Rangesvsr(vs); Iter::Ranges::NaryUnionpv(r,iv,vsr); //Enforcecommonvalues for(inti=x.size();i--;){ pv.reset(); GECODE_ME_CHECK(x[i].inter_r(home,pv,false)); } returnES_OK; } //Computeindependentsetforlowerbound //ovlisabit-matrixdefiningwhethertwoviewsoverlap SymBitMatrixovl(r,x.size()); //deg[i]isthedegreeofx[i] int*deg=r.alloc<int>(x.size()); //ovl_i[i]isanarrayofindicesjsuchthatx[j]overlapswithx[i] int**ovl_i=r.alloc<int*>(x.size()); //n_ovl_i[i]defineshowmanyintegersarestoredforovl_i[i] int*n_ovl_i=r.alloc<int>(x.size()); { #ifndefNDEBUG //Initializealltonullpointerssothatthingscrash;-) for(inti=x.size();i--;) ovl_i[i]=NULL; #endif //Foreachitherecanbeatmostn_dis-1entriesinovl_i[i] int*m=r.alloc<int>(n_dis*(n_dis-1)); for(inti=n_dis;i--;){ deg[dis[i]]=0; ovl_i[dis[i]]=m;m+=n_dis-1; } } //Initializeoverlapmatrixbyanalyzingtheviewranges { //Computehowmanyeventsareneeded //Oneeventfortheendmarker intn_re=1; //Twoeventsforeachrange for(inti=n_dis;i--;) for(ViewRanges<IntView>rx(x[dis[i]]);rx();++rx) n_re+=2; //Allocateandinitializeevents RangeEvent*re=r.alloc<RangeEvent>(n_re); intj=0; for(inti=n_dis;i--;) for(ViewRanges<IntView>rx(x[dis[i]]);rx();++rx){ //Eventwhenarangestarts re[j].ret=RET_FST;re[j].val=rx.min();re[j].view=dis[i];j++; //Eventwhenarangeends re[j].ret=RET_LST;re[j].val=rx.max();re[j].view=dis[i];j++; } //Makethisthelastevent re[j].ret=RET_END;re[j].val=Int::Limits::infinity; assert(j+1==n_re); //Sortandprocessevents Support::quicksort(re,n_re); //Currentviewswitharangebeingactive Support::BitSet<Region>cur(r,static_cast<unsignedint>(x.size())); //Processallevents for(inti=0;true;i++) switch(re[i].ret){ caseRET_FST: //Processalloverlappingviews for(Iter::Values::BitSet<Support::BitSet<Region>>j(cur); j();++j){ intdi=re[i].view,dj=j.val(); if(!ovl.get(di,dj)){ ovl.set(di,dj); ovl_i[di][deg[di]++]=dj; ovl_i[dj][deg[dj]++]=di; } } cur.set(static_cast<unsignedint>(re[i].view)); break; caseRET_LST: cur.clear(static_cast<unsignedint>(re[i].view)); break; caseRET_END: gotodone; default: GECODE_NEVER; } done: r.free<RangeEvent>(re,n_re); } //Whiledegchanges,n_ovl_iremainsunchangedandisneeded,socopyit for(inti=n_dis;i--;){ assert(deg[dis[i]]<n_dis); n_ovl_i[dis[i]]=deg[dis[i]]; } //Viewsintheindependentset int*ind=r.alloc<int>(n_dis); intn_ind=0; while(n_dis>0){ inti_min=n_dis-1; intd_min=deg[dis[i_min]]; unsignedints_min=x[dis[i_min]].size(); //Findviewwithsmallest(degree,size) for(inti=n_dis-1;i--;) if((d_min>deg[dis[i]])|| ((d_min==deg[dis[i]])&&(s_min>x[dis[i]].size()))){ i_min=i; d_min=deg[dis[i]]; s_min=x[dis[i]].size(); } //i_minreferstoviewwithsmallest(degree,size) ind[n_ind++]=dis[i_min];dis[i_min]=dis[--n_dis]; //Filteroutnondisjointviews for(inti=n_dis;i--;) if(ovl.get(dis[i],ind[n_ind-1])){ //Updatedegreeinformation for(intj=n_ovl_i[dis[i]];j--;) deg[ovl_i[dis[i]][j]]--; //Eliminateview dis[i]=dis[--n_dis]; } } //Enforcelowerbound GECODE_ME_CHECK(y.gq(home,vs.size()+n_ind)); //Prune,ifpossible if(vs.size()+n_ind==y.max()){ //Onlyvaluesfromtheindepentsetacanbetaken ViewRanges<IntView>*r_ind=r.alloc<ViewRanges<IntView>>(n_ind); for(inti=n_ind;i--;) r_ind[i]=ViewRanges<IntView>(x[ind[i]]); Iter::Ranges::NaryUnionv_ind(r,r_ind,n_ind); ValSet::Rangesvsr(vs); v_ind|=vsr; for(inti=x.size();i--;){ v_ind.reset(); GECODE_ME_CHECK(x[i].inter_r(home,v_ind,false)); } } returnES_OK; } template<classVY> forceinlineExecStatus IntBase<VY>::prune_upper(Space&home,Graph&g){ if(!g.initialized()){ g.init(home,vs,x); }else{ g.purge(); g.sync(home); } GECODE_ME_CHECK(y.lq(home,g.size())); if(y.min()==g.size()){ //Allvaluesmustbetakenon if(vs.size()+x.size()==g.size()){ //Thisisinfactadistinct,simplifyandrewrite for(inti=x.size();i--;){ ValSet::Rangesvsr(vs); GECODE_ME_CHECK(x[i].minus_r(home,vsr,false)); } GECODE_REWRITE(*this,Distinct::Dom<IntView>::post(home,x)); } if(g.mark(home)) GECODE_ES_CHECK(g.prune(home)); } returnES_OK; } }}} //STATISTICS:int-prop