incremental.hpp /usr/include/gecode/int/extensional.hh Gecode Gecode::Int Gecode::Int::Extensional /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *MikaelLagerkvist<lagerkvist@gecode.org> * *Contributingauthors: *ChristianSchulte<schulte@gecode.org> * *Copyright: *MikaelLagerkvist,2007 *ChristianSchulte,2008 * *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{namespaceExtensional{ /* *Supportadvisor * */ template<classView> forceinline Incremental<View>::SupportAdvisor:: SupportAdvisor(Space&home,Propagator&p,Council<SupportAdvisor>&c, inti0) :Advisor(home,p,c),i(i0){} template<classView> forceinline Incremental<View>::SupportAdvisor:: SupportAdvisor(Space&home,boolshare,SupportAdvisor&a) :Advisor(home,share,a),i(a.i){} template<classView> forceinlinevoid Incremental<View>::SupportAdvisor:: dispose(Space&home,Council<SupportAdvisor>&c){ Advisor::dispose(home,c); } /* *Supportentries * */ template<classView> forceinline Incremental<View>::SupportEntry::SupportEntry(Tuplet0) :t(t0){} template<classView> forceinline Incremental<View>::SupportEntry::SupportEntry(Tuplet0,SupportEntry*n) :FreeList(n),t(t0){} template<classView> forceinlinetypenameIncremental<View>::SupportEntry* Incremental<View>::SupportEntry::next(void)const{ returnstatic_cast<SupportEntry*>(FreeList::next()); } template<classView> forceinlinetypenameIncremental<View>::SupportEntry** Incremental<View>::SupportEntry::nextRef(void){ returnreinterpret_cast<SupportEntry**>(FreeList::nextRef()); } template<classView> forceinlinevoid Incremental<View>::SupportEntry::operatordelete(void*){} template<classView> forceinlinevoid Incremental<View>::SupportEntry::operatordelete(void*,Space&){ GECODE_NEVER; } template<classView> forceinlinevoid* Incremental<View>::SupportEntry::operatornew(size_t,Space&home){ returnhome.fl_alloc<sizeof(SupportEntry)>(); } template<classView> forceinlinevoid Incremental<View>::SupportEntry::dispose(Space&home){ home.fl_dispose<sizeof(SupportEntry)>(this,this); } template<classView> forceinlinevoid Incremental<View>::SupportEntry::dispose(Space&home,SupportEntry*l){ home.fl_dispose<sizeof(SupportEntry)>(this,l); } /* *Workentries * */ template<classView> forceinline Incremental<View>::WorkEntry::WorkEntry(inti0,intn0,WorkEntry*n) :FreeList(n),i(i0),n(n0){} template<classView> forceinlinetypenameIncremental<View>::WorkEntry* Incremental<View>::WorkEntry::next(void)const{ returnstatic_cast<WorkEntry*>(FreeList::next()); } template<classView> forceinlinevoid Incremental<View>::WorkEntry::next(WorkEntry*n){ returnFreeList::next(n); } template<classView> forceinlinevoid Incremental<View>::WorkEntry::operatordelete(void*){} template<classView> forceinlinevoid Incremental<View>::WorkEntry::operatordelete(void*,Space&){ GECODE_NEVER; } template<classView> forceinlinevoid* Incremental<View>::WorkEntry::operatornew(size_t,Space&home){ returnhome.fl_alloc<sizeof(WorkEntry)>(); } template<classView> forceinlinevoid Incremental<View>::WorkEntry::dispose(Space&home){ home.fl_dispose<sizeof(WorkEntry)>(this,this); } /* *Workstack * */ template<classView> forceinline Incremental<View>::Work::Work(void) :we(NULL){} template<classView> forceinlinebool Incremental<View>::Work::empty(void)const{ returnwe==NULL; } template<classView> forceinlinevoid Incremental<View>::Work::push(Space&home,inti,intn){ we=new(home)WorkEntry(i,n,we); } template<classView> forceinlinevoid Incremental<View>::Work::pop(Space&home,int&i,int&n){ WorkEntry*d=we; we=we->next(); i=d->i;n=d->n; d->dispose(home); } /* *Supportmanagement * */ template<classView> forceinlinetypenameIncremental<View>::SupportEntry* Incremental<View>::support(inti,intn){ returnsupport_data[(i*(ts()->domsize))+(n-ts()->min)]; } template<classView> forceinlinevoid Incremental<View>::init_support(Space&home){ assert(support_data==NULL); intliterals=static_cast<int>(ts()->domsize*x.size()); support_data=home.alloc<SupportEntry*>(literals); for(inti=literals;i--;) support_data[i]=NULL; } template<classView> forceinlinevoid Incremental<View>::add_support(Space&home,Tuplel){ for(inti=x.size();i--;){ intpos=(i*static_cast<int>(ts()->domsize))+(l[i]-ts()->min); support_data[pos]=new(home)SupportEntry(l,support_data[pos]); } } template<classView> forceinlinevoid Incremental<View>::find_support(Space&home,Domaindom,inti,intn){ if(support(i,n)==NULL){ //Findsupportforvaluevv.val()inviewi Tuplel=Base<View,false>::find_support(dom,i,n-ts()->min); if(l==NULL){ //Nopossiblesupportsleft w_remove.push(home,i,n); }else{ //Markvaluesinsupportassupported add_support(home,l); } } } template<classView> forceinlinevoid Incremental<View>::remove_support(Space&home,Tuplel,inti,intn){ (void)n; for(intj=x.size();j--;){ intv=l[j]; intov=v-ts()->min; intpos=(j*(static_cast<int>(ts()->domsize)))+ov; assert(support_data[pos]!=NULL); SupportEntry**a=&(support_data[pos]); while((*a)->t!=l){ assert((*a)->next()!=NULL); a=(*a)->nextRef(); } SupportEntry*old=*a; *a=(*a)->next(); old->dispose(home); if((i!=j)&&(support_data[pos]==NULL)) w_support.push(home,j,v); } } /* *Thepropagatorproper * */ template<classView> forceinline Incremental<View>::Incremental(Homehome,ViewArray<View>&x, constTupleSet&t) :Base<View,false>(home,x,t),support_data(NULL), unassigned(x.size()),ac(home){ init_support(home); //Postadvisors for(inti=x.size();i--;) if(x[i].assigned()){ --unassigned; }else{ x[i].subscribe(home,*new(home)SupportAdvisor(home,*this,ac,i)); } Regionr(home); //Addinitialsupports BitSet*dom=r.alloc<BitSet>(x.size()); init_dom(home,dom); for(inti=x.size();i--;) for(ViewValues<View>vv(x[i]);vv();++vv) find_support(home,dom,i,vv.val()); //Worktobedoneorsubsumption if(!w_support.empty()||!w_remove.empty()||(unassigned==0)) View::schedule(home,*this, (unassigned!=x.size())?ME_INT_VAL:ME_INT_DOM); } template<classView> forceinlineExecStatus Incremental<View>::post(Homehome,ViewArray<View>&x,constTupleSet&t){ //Allvariablesinthecorrectdomain for(inti=x.size();i--;){ GECODE_ME_CHECK(x[i].gq(home,t.min())); GECODE_ME_CHECK(x[i].lq(home,t.max())); } (void)new(home)Incremental<View>(home,x,t); returnES_OK; } template<classView> forceinline Incremental<View>::Incremental(Space&home,boolshare,Incremental<View>&p) :Base<View,false>(home,share,p),support_data(NULL), unassigned(p.unassigned){ ac.update(home,share,p.ac); init_support(home); for(inti=static_cast<int>(ts()->domsize*x.size());i--;){ SupportEntry**n=&(support_data[i]); SupportEntry*o=p.support_data[i]; while(o!=NULL){ //Allocatenewsupportentry SupportEntry*s= new(home)SupportEntry(ts()->data+(o->t-p.ts()->data)); //Linkinsupportentry (*n)=s;n=s->nextRef(); //movetonextone o=o->next(); } *n=NULL; } } template<classView> PropCost Incremental<View>::cost(constSpace&,constModEventDelta&med)const{ if(View::me(med)==ME_INT_VAL) returnPropCost::quadratic(PropCost::HI,x.size()); else returnPropCost::cubic(PropCost::HI,x.size()); } template<classView> Actor* Incremental<View>::copy(Space&home,boolshare){ returnnew(home)Incremental<View>(home,share,*this); } template<classView> forceinlinesize_t Incremental<View>::dispose(Space&home){ if(!home.failed()){ intliterals=static_cast<int>(ts()->domsize*x.size()); for(inti=literals;i--;) if(support_data[i]){ SupportEntry*lastse=support_data[i]; while(lastse->next()!=NULL) lastse=lastse->next(); support_data[i]->dispose(home,lastse); } home.rfree(support_data,sizeof(SupportEntry*)*literals); } ac.dispose(home); (void)Base<View,false>::dispose(home); returnsizeof(*this); } template<classView> ExecStatus Incremental<View>::propagate(Space&home,constModEventDelta&){ assert(!w_support.empty()||!w_remove.empty()||unassigned==0); //Setupdatastructures //Bit-setsforamortizedO(1)accesstodomains Regionr(home); //Addinitialsupports BitSet*dom=r.alloc<BitSet>(x.size()); init_dom(home,dom); //Workloop while(!w_support.empty()||!w_remove.empty()){ while(!w_remove.empty()){ inti,n; w_remove.pop(home,i,n); //Workisstillrelevant if(dom[i].get(static_cast<unsignedint>(n-ts()->min))){ GECODE_ME_CHECK(x[i].nq(home,n)); dom[i].clear(static_cast<unsignedint>(n-ts()->min)); } } while(!w_support.empty()){ inti,n; w_support.pop(home,i,n); //Workisstillrelevant if(dom[i].get(static_cast<unsignedint>(n-ts()->min))) find_support(home,dom,i,n); } } if(unassigned!=0) returnES_FIX; returnhome.ES_SUBSUMED(*this); } template<classView> ExecStatus Incremental<View>::advise(Space&home,Advisor&_a,constDelta&d){ SupportAdvisor&a=static_cast<SupportAdvisor&>(_a); ModEventme=View::modevent(d); boolscheduled=!w_support.empty()||!w_remove.empty(); if(x[a.i].any(d)){ ViewValues<View>vv(x[a.i]); for(intn=ts()->min;n<=ts()->max;n++){ if(vv()&&(n==vv.val())){ ++vv; continue; } while(SupportEntry*s=support(a.i,n)) remove_support(home,s->t,a.i,n); } }else{ for(intn=x[a.i].min(d);n<=x[a.i].max(d);n++) while(SupportEntry*s=support(a.i,n)) remove_support(home,s->t,a.i,n); } if(me==ME_INT_VAL){ --unassigned; //nothingtodooralreadyscheduled //propagatorisnotsubsumedsinceunassigned!=0 if(((w_support.empty()&&w_remove.empty())||scheduled)&& (unassigned!=0)) returnhome.ES_FIX_DISPOSE(ac,a); else returnhome.ES_NOFIX_DISPOSE(ac,a); }elseif((w_support.empty()&&w_remove.empty())||scheduled){ //nothingtodooralreadyscheduled returnES_FIX; } returnES_NOFIX; } }}} //STATISTICS:int-prop