dom.hpp /usr/include/gecode/int/gcc.hh Gecode Gecode::Int Gecode::Int::GCC /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *PatrickPekczynski<pekczynski@ps.uni-sb.de> * *Contributingauthors: *ChristianSchulte<schulte@gecode.org> *GuidoTack<tack@gecode.org> * *Copyright: *PatrickPekczynski,2004 *ChristianSchulte,2009 *GuidoTack,2009 * *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{namespaceGCC{ /* *Analogouslyto"gcc/bnd.hpp"wesplitthealgorithm *intwoparts: *1)theUBC(UpperBoundConstraint)statingthatthereare *atmostk[i].max()occurencesofthevaluev_i *2)theLBC(LowerBoundConstraint)statingthatthereare *atleastk[i].min()occurencesofthevaluev_i * *Thealgorithmproceedsin5STEPS: * *STEP1: *Buildthebipartitevalue-graphG=(<X,D>,E), *withX=allvariablenodes(eachvariableformsanode) *D=allvaluenodes(unionoveralldomainsofthevariables) *and(x_i,v)isanedgeinGiffvaluevisinthedomainD_iofx_i * *STEP2:Computeamatchinginthevaluegraph. *STEP3:Computeallevenalternatingpathsfromunmatchednodes *STEP4:Computestronglyconnectedcomponentsinthemergedgraph *STEP5:UpdatetheDomainsaccordingtothecomputededges * */ template<classCard> inline Dom<Card>::Dom(Homehome,ViewArray<IntView>&x0, ViewArray<Card>&k0,boolcf) :Propagator(home),x(x0),y(home,x0), k(k0),vvg(NULL),card_fixed(cf){ //yisusedforboundspropagationsinceprop_bndneedsallvariables //valueswithinthedomainbounds x.subscribe(home,*this,PC_INT_DOM); k.subscribe(home,*this,PC_INT_DOM); } template<classCard> forceinline Dom<Card>::Dom(Space&home,boolshare,Dom<Card>&p) :Propagator(home,share,p),vvg(NULL),card_fixed(p.card_fixed){ x.update(home,share,p.x); y.update(home,share,p.y); k.update(home,share,p.k); } template<classCard> forceinlinesize_t Dom<Card>::dispose(Space&home){ x.cancel(home,*this,PC_INT_DOM); k.cancel(home,*this,PC_INT_DOM); (void)Propagator::dispose(home); returnsizeof(*this); } template<classCard> Actor* Dom<Card>::copy(Space&home,boolshare){ returnnew(home)Dom<Card>(home,share,*this); } template<classCard> PropCost Dom<Card>::cost(constSpace&,constModEventDelta&)const{ returnPropCost::cubic(PropCost::LO,x.size()); } template<classCard> ExecStatus Dom<Card>::propagate(Space&home,constModEventDelta&){ Regionr(home); int*count=r.alloc<int>(k.size()); for(inti=k.size();i--;) count[i]=0; //totalnumberofassignedviews intnoa=0; for(inti=y.size();i--;) if(y[i].assigned()){ noa++; intidx; if(!lookupValue(k,y[i].val(),idx)) returnES_FAILED; count[idx]++; if(Card::propagate&&(k[idx].max()==0)) returnES_FAILED; } if(noa==y.size()){ //Allviewsareassigned for(inti=k.size();i--;){ if((k[i].min()>count[i])||(count[i]>k[i].max())) returnES_FAILED; //thesolutioncontainscioccurencesofvaluek[i].card(); if(Card::propagate) GECODE_ME_CHECK(k[i].eq(home,count[i])); } returnhome.ES_SUBSUMED(*this); } //beforepropagationperformsinferencesoncardinalityvariables: if(Card::propagate){ if(noa>0) for(inti=k.size();i--;) if(!k[i].assigned()){ GECODE_ME_CHECK(k[i].lq(home,y.size()-(noa-count[i]))); GECODE_ME_CHECK(k[i].gq(home,count[i])); } GECODE_ES_CHECK(prop_card<Card>(home,y,k)); if(!card_consistent<Card>(y,k)) returnES_FAILED; } if(x.size()==0){ for(intj=k.size();j--;) if((k[j].min()>k[j].counter())||(k[j].max()<k[j].counter())) returnES_FAILED; returnhome.ES_SUBSUMED(*this); }elseif((x.size()==1)&&(x[0].assigned())){ intidx; if(!lookupValue(k,x[0].val(),idx)) returnES_FAILED; GECODE_ME_CHECK(k[idx].inc()); for(intj=k.size();j--;) if((k[j].min()>k[j].counter())||(k[j].max()<k[j].counter())) returnES_FAILED; returnhome.ES_SUBSUMED(*this); } if(vvg==NULL){ intsmin=0; intsmax=0; for(inti=k.size();i--;) if(k[i].counter()>k[i].max()){ returnES_FAILED; }else{ smax+=(k[i].max()-k[i].counter()); if(k[i].counter()<k[i].min()) smin+=(k[i].min()-k[i].counter()); } if((x.size()<smin)||(smax<x.size())) returnES_FAILED; vvg=new(home)VarValGraph<Card>(home,x,k,smin,smax); GECODE_ES_CHECK(vvg->min_require(home,x,k)); GECODE_ES_CHECK(vvg->templatemaximum_matching<UBC>(home)); if(!card_fixed) GECODE_ES_CHECK(vvg->templatemaximum_matching<LBC>(home)); }else{ GECODE_ES_CHECK(vvg->sync(home,x,k)); } vvg->templatefree_alternating_paths<UBC>(home); vvg->templatestrongly_connected_components<UBC>(home); GECODE_ES_CHECK(vvg->templatenarrow<UBC>(home,x,k)); if(!card_fixed){ if(Card::propagate) GECODE_ES_CHECK(vvg->sync(home,x,k)); vvg->templatefree_alternating_paths<LBC>(home); vvg->templatestrongly_connected_components<LBC>(home); GECODE_ES_CHECK(vvg->templatenarrow<LBC>(home,x,k)); } { boolcard_assigned=true; if(Card::propagate){ GECODE_ES_CHECK(prop_card<Card>(home,y,k)); card_assigned=k.assigned(); } if(card_assigned){ if(x.size()==0){ for(intj=k.size();j--;) if((k[j].min()>k[j].counter())|| (k[j].max()<k[j].counter())) returnES_FAILED; returnhome.ES_SUBSUMED(*this); }elseif((x.size()==1)&&x[0].assigned()){ intidx; if(!lookupValue(k,x[0].val(),idx)) returnES_FAILED; GECODE_ME_CHECK(k[idx].inc()); for(intj=k.size();j--;) if((k[j].min()>k[j].counter())|| (k[j].max()<k[j].counter())) returnES_FAILED; returnhome.ES_SUBSUMED(*this); } } } for(inti=k.size();i--;) count[i]=0; boolall_assigned=true; //totalnumberofassignedviews for(inti=y.size();i--;) if(y[i].assigned()){ intidx; if(!lookupValue(k,y[i].val(),idx)) returnES_FAILED; count[idx]++; if(Card::propagate&&(k[idx].max()==0)) returnES_FAILED; }else{ all_assigned=false; } if(Card::propagate) GECODE_ES_CHECK(prop_card<Card>(home,y,k)); if(all_assigned){ for(inti=k.size();i--;){ if((k[i].min()>count[i])||(count[i]>k[i].max())) returnES_FAILED; //thesolutioncontainscount[i]occurencesofvaluek[i].card(); if(Card::propagate) GECODE_ME_CHECK(k[i].eq(home,count[i])); } returnhome.ES_SUBSUMED(*this); } if(Card::propagate){ intysmax=y.size(); for(inti=k.size();i--;) ysmax-=k[i].max(); intsmax=0; boolcard_ass=true; for(inti=k.size();i--;){ GECODE_ME_CHECK(k[i].gq(home,ysmax+k[i].max())); smax+=k[i].max(); GECODE_ME_CHECK(k[i].lq(home,y.size()+k[i].min())); if(!k[i].assigned()) card_ass=false; } if(card_ass&&(smax!=y.size())) returnES_FAILED; } returnCard::propagate?ES_NOFIX:ES_FIX; } template<classCard> inlineExecStatus Dom<Card>::post(Homehome, ViewArray<IntView>&x,ViewArray<Card>&k){ GECODE_ES_CHECK((postSideConstraints<Card>(home,x,k))); if(isDistinct<Card>(home,x,k)) returnDistinct::Dom<IntView>::post(home,x); boolcardfix=true; for(inti=k.size();i--;) if(!k[i].assigned()){ cardfix=false;break; } (void)new(home)Dom<Card>(home,x,k,cardfix); returnES_OK; } }}} //STATISTICS:int-prop