bnd.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/2005 *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{ template<classCard> forceinline Bnd<Card>:: Bnd(Homehome,ViewArray<IntView>&x0,ViewArray<Card>&k0, boolcf,boolnolbc): Propagator(home),x(x0),y(home,x0),k(k0), card_fixed(cf),skip_lbc(nolbc){ y.subscribe(home,*this,PC_INT_BND); k.subscribe(home,*this,PC_INT_BND); } template<classCard> forceinline Bnd<Card>:: Bnd(Space&home,boolshare,Bnd<Card>&p) :Propagator(home,share,p), card_fixed(p.card_fixed),skip_lbc(p.skip_lbc){ x.update(home,share,p.x); y.update(home,share,p.y); k.update(home,share,p.k); } template<classCard> forceinlinesize_t Bnd<Card>::dispose(Space&home){ y.cancel(home,*this,PC_INT_BND); k.cancel(home,*this,PC_INT_BND); (void)Propagator::dispose(home); returnsizeof(*this); } template<classCard> Actor* Bnd<Card>::copy(Space&home,boolshare){ returnnew(home)Bnd<Card>(home,share,*this); } template<classCard> PropCost Bnd<Card>::cost(constSpace&, constModEventDelta&med)const{ intn_k=Card::propagate?k.size():0; if(IntView::me(med)==ME_INT_VAL) returnPropCost::linear(PropCost::LO,y.size()+n_k); else returnPropCost::quadratic(PropCost::LO,x.size()+n_k); } template<classCard> forceinlineExecStatus Bnd<Card>::lbc(Space&home,int&nb, HallInfohall[],Rankrank[],intmu[],intnu[]){ intn=x.size(); /* *LetI(S)denotethenumberofvariableswhosedomainintersects *thesetSandC(S)thenumberofvariableswhosedomainiscontainded *inS.Letfurthermin_cap(S)betheminimalnumberofvariables *thatmustbeassignedtovalues,thatis *min_cap(S)isthesumoveralll[i]foravaluev_ithatisan *elementofS. * *AfailuresetisasetFif *I(F)<min_cap(F) *AnunstablesetisasetUif *I(U)=min_cap(U) *AstablesetisasetSif *C(S)>min_cap(S)andSintersetcsnor *anyfailuresetnoranyunstableset *forallunstableandfailuresets * *failuresetsdeterminethesatisfiabilityoftheLBC *unstablesetshavetobepruned *stablesetdonothavetobepruned * *hall[].ps~storestheunstable *setsthathavetobepruned *hall[].s~storessetsthatmustnotbepruned *hall[].h~containsstableandunstablesets *hall[].d~containsthedifferencebetweenintervalbounds,i.e. *theminimalcapacityoftheinterval *hall[].t~containsthecriticalcapacitypointer,pointingtothe *values */ //LBClowerbounds inti=0; intj=0; intw=0; intz=0; intv=0; //initializationofthetreestructure intrightmost=nb+1;//rightmostaccesiblevalueinbounds intbsize=nb+2; w=rightmost; //test //unusedbutuninitialized hall[0].d=0; hall[0].s=0; hall[0].ps=0; for(i=bsize;--i;){//imustnotbezero intpred=i-1; hall[i].s=pred; hall[i].ps=pred; hall[i].d=lps.sumup(hall[pred].bounds,hall[i].bounds-1); /*Let[hall[i].bounds,hall[i-1].bounds]=:I *Ifthecapacityiszero=>min_cap(I)=0 *=>Icannotbeafailureset *=>Iisanunstableset */ if(hall[i].d==0){ hall[pred].h=w; }else{ hall[w].h=pred; w=pred; } } w=rightmost; for(i=bsize;i--;){//icanbezero hall[i].t=i-1; if(hall[i].d==0){ hall[i].t=w; }else{ hall[w].t=i; w=i; } } /* *Thealgorithmassignstoeachvaluevinbounds *emptybucketscorrespondingtotheminimalcapacityl[i]tobe *filledforv.(thebucketscorrespondtohall[].dcontainingthe *differencebetweentheintervalbounds)Processingit *searchesforthesmallestvaluevindom(x_i)thathasan *emptybucket,i.e.ifallbucketsarefilleditisguaranteed *thatthereareatleastl[i]variablesthatwillbe *instantiatedtov.Sincethebucketsareinitiallyempty, *theyareconsideredasFAILURESETS */ for(i=0;i<n;i++){ //visitintervalsinincreasingmaxorder intx0=rank[mu[i]].min; inty=rank[mu[i]].max; intsucc=x0+1; z=pathmax_t(hall,succ); j=hall[z].t; /* *POTENTIALLYSTABLESET: *z\neqsucc\Leftrigharrowz>succ,i.e. *min(D_{\mu(i)})isguaranteedtooccurmin(K_i)times *\Rightarrow[x0,min(y,z)]ispotentiallystable */ if(z!=succ){ w=pathmax_ps(hall,succ); v=hall[w].ps; pathset_ps(hall,succ,w,w); w=std::min(y,z); pathset_ps(hall,hall[w].ps,v,w); hall[w].ps=v; } /* *STABLESET: *beingstableimpliesbeingpotentiallystable,i.e. *[hall[y].ps,hall[y].bounds-1]isthelargeststablesubsetof *[hall[j].bounds,hall[y].bounds-1]. */ if(hall[z].d<=lps.sumup(hall[y].bounds,hall[z].bounds-1)){ w=pathmax_s(hall,hall[y].ps); pathset_s(hall,hall[y].ps,w,w); //Pathcompression v=hall[w].s; pathset_s(hall,hall[y].s,v,y); hall[y].s=v; }else{ /* *FAILURESET: *Iftheconsideredinterval[x0,y]isneitherPOTENTIALLYSTABLE *norSTABLEtherearestillbucketsthatcanbefilled, *thereforedcanbedecreased.Ifdequalszerotheintervals *minimumcapacityismetandthepathcanbecompressedtothe *nextvaluehavinganemptybucket. *seeDOMINATIONin"ubc" */ if(--hall[z].d==0){ hall[z].t=z+1; z=pathmax_t(hall,hall[z].t); hall[z].t=j; } /* *FINDINGNEWLOWERBOUND: *Ifthelowerboundbelongstoanunstableorastableset, *remindthenewvaluewemightassignedtothelowerbound *incasethevariabledoesn'tbelongtoastableset. */ if(hall[x0].h>x0){ hall[i].newBound=pathmax_h(hall,x0); w=hall[i].newBound; pathset_h(hall,x0,w,w);//pathcompression }else{ //Donotshrinkthevariable:takeoldminasnewmin hall[i].newBound=x0; } /*UNSTABLESET *Ifanunstablesetisdiscovered *thedifferencebetweentheintervalboundsisequaltothe *numberofvariableswhosedomainintersecttheinterval *(seeZEROTESTin"gcc") */ //CLEARLYTHISWASNOTSTABLE==UNSTABLE if(hall[z].d==lps.sumup(hall[y].bounds,hall[z].bounds-1)){ if(hall[y].h>y) /* *yisnottheendofthepotentiallystableset *thusensurethatthepotentiallystablesupersetismarked */ y=hall[y].h; //Equivalenttopathmaxsincethepathisfullycompressed pathset_h(hall,hall[y].h,j-1,y); //markthenewunstableset[j,y] hall[y].h=j-1; } } pathset_t(hall,succ,z,z);//pathcompression } /*IfthereisaFAILURESETlefttheminimumoccurencesofthevalues *arenotguaranteed.InordertosatisfytheLBCthelastvalue *inthestableandunstabledatastructurehall[].hmustpointto *thesentinelatthebeginningofbounds. */ if(hall[nb].h!=0) returnES_FAILED; //Performpathcompressionoverallelementsin //thestableintervaldatastructure.Thisdata //structurewillnolongerbemodifiedandwillbe //accessednor2ntimes.Therefore,wecanafford //alineartimecompression. for(i=bsize;--i;) if(hall[i].s>i) hall[i].s=w; else w=i; /* *UPDATINGLOWERBOUND: *Forallvariablesthatarenotasubsetofastableset, *shrinkthelowerbound,i.e.forallstablesetsSwehave: *x0<S_min<=y<=S_maxorS_min<=x0<=S_max<y *thatis[x0,y]isNOTapropersubsetofanystablesetS */ for(i=n;i--;){ intx0=rank[mu[i]].min; inty=rank[mu[i]].max; //updateonlythosevariablesthatarenotcontainedinastableset if((hall[x0].s<=x0)||(y>hall[x0].s)){ //stillhavetocheckthisout,howskippingworks(considerdominatedindices) intm=lps.skipNonNullElementsRight(hall[hall[i].newBound].bounds); GECODE_ME_CHECK(x[mu[i]].gq(home,m)); } } //LBCnarrowupperbounds w=0; for(i=0;i<=nb;i++){ hall[i].d=lps.sumup(hall[i].bounds,hall[i+1].bounds-1); if(hall[i].d==0){ hall[i].t=w; }else{ hall[w].t=i; w=i; } } hall[w].t=i; w=0; for(i=1;i<=nb;i++) if(hall[i-1].d==0){ hall[i].h=w; }else{ hall[w].h=i; w=i; } hall[w].h=i; for(i=n;i--;){ //visitintervalsindecreasingminorder //i.e.minsortedfromrighttoleft intx0=rank[nu[i]].max; inty=rank[nu[i]].min; intpred=x0-1;//predecessorofx0intheindices z=pathmin_t(hall,pred); j=hall[z].t; /*Ifthevariableisnotinadiscoveredstableset *(seeaboveconditionforSTABLESET) */ if(hall[z].d>lps.sumup(hall[z].bounds,hall[y].bounds-1)){ //FAILURESET if(--hall[z].d==0){ hall[z].t=z-1; z=pathmin_t(hall,hall[z].t); hall[z].t=j; } //FINDINGNEWUPPERBOUND if(hall[x0].h<x0){ w=pathmin_h(hall,hall[x0].h); hall[i].newBound=w; pathset_h(hall,x0,w,w);//pathcompression }else{ hall[i].newBound=x0; } //UNSTABLESET if(hall[z].d==lps.sumup(hall[z].bounds,hall[y].bounds-1)){ if(hall[y].h<y){ y=hall[y].h; } intsuccj=j+1; //marknewunstableset[y,j] pathset_h(hall,hall[y].h,succj,y); hall[y].h=succj; } } pathset_t(hall,pred,z,z); } //UPDATINGUPPERBOUND for(i=n;i--;){ intx0=rank[nu[i]].min; inty=rank[nu[i]].max; if((hall[x0].s<=x0)||(y>hall[x0].s)){ intm=lps.skipNonNullElementsLeft(hall[hall[i].newBound].bounds-1); GECODE_ME_CHECK(x[nu[i]].lq(home,m)); } } returnES_OK; } template<classCard> forceinlineExecStatus Bnd<Card>::ubc(Space&home,int&nb, HallInfohall[],Rankrank[],intmu[],intnu[]){ intrightmost=nb+1;//rightmostaccesiblevalueinbounds intbsize=nb+2;//numberofuniqueboundsincludingsentinels //Narrowlowerbounds(UBC) /* *Initializingtreestructurewiththevaluesfrombounds *andtheintervalcapacitiesofneighbouredvalues *fromlefttoright */ hall[0].h=0; hall[0].t=0; hall[0].d=0; for(inti=bsize;--i;){ hall[i].h=hall[i].t=i-1; hall[i].d=ups.sumup(hall[i-1].bounds,hall[i].bounds-1); } intn=x.size(); for(inti=0;i<n;i++){ //visitintervalsinincreasingmaxorder intx0=rank[mu[i]].min; intsucc=x0+1; inty=rank[mu[i]].max; intz=pathmax_t(hall,succ); intj=hall[z].t; /*DOMINATION: *v^i_jdenotes *unusedvaluesinthecurrentinterval.Ifthedifferenced *betweentocriticalcapacitiesv^i_jandv^i_z *isequaltozero,jdominatesz * *i.e.[hall[l].bounds,hall[nb+1].bounds]isnotleft-maximaland *[hall[j].bounds,hall[l].bounds]isaHallsetiff *[hall[j].bounds,hall[l].bounds]processingavariablex_iusesupavalueintheinterval *[hall[z].bounds,hall[z+1].bounds]accordingtotheintervals *capacity.Therefore,ifd=0 *theconsideredvaluehasalreadybeenusedbyprocessedvariables *m-times,wherem=u[i]forvaluev_i.Sincethisvaluemustnot *bereconsideredthepathcanbecompressed */ if(--hall[z].d==0){ hall[z].t=z+1; z=pathmax_t(hall,hall[z].t); if(z>=bsize) z--; hall[z].t=j; } pathset_t(hall,succ,z,z);//pathcompression /*NEGATIVECAPACITY: *Anegativecapacityresultsinafailure.Sincea *negativecapacitysignalsthatthenumberofvariables *whosedomainiscontainedinthesetSislargerthan *themaximumcapacityofS=>UBCisnotsatisfiable, *i.e.therearemorevariablesthanvaluestoinstantiatethem */ if(hall[z].d<ups.sumup(hall[y].bounds,hall[z].bounds-1)) returnES_FAILED; /*UPDATINGLOWERBOUND: *Ifthelowerboundmin_iliesinsideaHallinterval[a,b] *i.e.a<=min_i<=b<=max_i *min_iissettomin_i:=b+1 */ if(hall[x0].h>x0){ intw=pathmax_h(hall,hall[x0].h); intm=hall[w].bounds; GECODE_ME_CHECK(x[mu[i]].gq(home,m)); pathset_h(hall,x0,w,w);//pathcompression } /*ZEROTEST: *(usingthedifferencebetweencapacitypointers) *zerocapacity=>thedifferencebetweencriticalcapacity *pointersisequaltothemaximumcapacityoftheinterval,i.e. *thenumberofvariableswhosedomainiscontainedinthe *intervalisequaltothesumoverallu[i]foravaluev_ithat *liesintheHall-Intervallwhichcanalsobethoughtofasa *Hall-Set * *ZeroTestLemma:Letkandlbesuccesivecriticalindices. *v^i_k=0=>v^i_k=max_i+1-l+d *<=>v^i_k=y+1-z+d *<=>d=z-1-y *ifthisequationholdstheinterval[j,z-1]isahallintervall */ if(hall[z].d==ups.sumup(hall[y].bounds,hall[z].bounds-1)){ /* *markhallinterval[j,z-1] *hallpointersformapathtotheupperboundoftheinterval */ intpredj=j-1; pathset_h(hall,hall[y].h,predj,y); hall[y].h=predj; } } /*Narrowupperbounds(UBC) *symmetrictothenarrowingofthelowerbounds */ for(inti=0;i<rightmost;i++){ hall[i].h=hall[i].t=i+1; hall[i].d=ups.sumup(hall[i].bounds,hall[i+1].bounds-1); } for(inti=n;i--;){ //visitintervalsindecreasingminorder intx0=rank[nu[i]].max; intpred=x0-1; inty=rank[nu[i]].min; intz=pathmin_t(hall,pred); intj=hall[z].t; //DOMINATION: if(--hall[z].d==0){ hall[z].t=z-1; z=pathmin_t(hall,hall[z].t); hall[z].t=j; } pathset_t(hall,pred,z,z); //NEGATIVECAPACITY: if(hall[z].d<ups.sumup(hall[z].bounds,hall[y].bounds-1)) returnES_FAILED; /*UPDATINGUPPERBOUND: *Iftheupperboundmax_iliesinsideaHallinterval[a,b] *i.e.min_i<=a<=max_i<b *max_iissettomax_i:=a-1 */ if(hall[x0].h<x0){ intw=pathmin_h(hall,hall[x0].h); intm=hall[w].bounds-1; GECODE_ME_CHECK(x[nu[i]].lq(home,m)); pathset_h(hall,x0,w,w); } //ZEROTEST if(hall[z].d==ups.sumup(hall[z].bounds,hall[y].bounds-1)){ //markhallinterval[y,j] pathset_h(hall,hall[y].h,j+1,y); hall[y].h=j+1; } } returnES_OK; } template<classCard> ExecStatus Bnd<Card>::pruneCards(Space&home){ //Removeallvalueswith0maxoccurrence //andremovecorrespondingoccurrencevariablesfromk //Thenumberofzeroes intn_z=0; for(inti=k.size();i--;) if(k[i].max()==0) n_z++; if(n_z>0){ Regionr(home); int*z=r.alloc<int>(n_z); n_z=0; intn_k=0; for(inti=0;i<k.size();i++) if(k[i].max()==0){ z[n_z++]=k[i].card(); }else{ k[n_k++]=k[i]; } k.size(n_k); Support::quicksort(z,n_z); for(inti=x.size();i--;){ Iter::Values::Arrayzi(z,n_z); GECODE_ME_CHECK(x[i].minus_v(home,zi,false)); } lps.reinit();ups.reinit(); } returnES_OK; } template<classCard> ExecStatus Bnd<Card>::propagate(Space&home,constModEventDelta&med){ if(IntView::me(med)==ME_INT_VAL){ GECODE_ES_CHECK(prop_val<Card>(home,*this,y,k)); returnhome.ES_NOFIX_PARTIAL(*this,IntView::med(ME_INT_BND)); } if(Card::propagate) GECODE_ES_CHECK(pruneCards(home)); Regionr(home); int*count=r.alloc<int>(k.size()); for(inti=k.size();i--;) count[i]=0; boolall_assigned=true; intnoa=0; for(inti=x.size();i--;){ if(x[i].assigned()){ noa++; intidx; //reductionisessentialfororderonvaluenodesindom //henceintroducetestforfailedlookup if(!lookupValue(k,x[i].val(),idx)) returnES_FAILED; count[idx]++; }else{ all_assigned=false; //Weonlyneedthecountsintheviewcaseorwhenall //xareassigned if(!Card::propagate) break; } } if(Card::propagate){ //beforepropagationperformsinferencesoncardinalityvariables: if(noa>0) for(inti=k.size();i--;) if(!k[i].assigned()){ GECODE_ME_CHECK(k[i].lq(home,x.size()-(noa-count[i]))); GECODE_ME_CHECK(k[i].gq(home,count[i])); } if(!card_consistent<Card>(x,k)) returnES_FAILED; GECODE_ES_CHECK(prop_card<Card>(home,x,k)); //Cardinalitiesmayhavebeenmodified,sorecompute //countandall_assigned for(inti=k.size();i--;) count[i]=0; all_assigned=true; for(inti=x.size();i--;){ if(x[i].assigned()){ intidx; //reductionisessentialfororderonvaluenodesindom //henceintroducetestforfailedlookup if(!lookupValue(k,x[i].val(),idx)) returnES_FAILED; count[idx]++; }else{ //Wewon'tneedtheremainingcounts,they'reonlyusedwhen //allxareassigned all_assigned=false; break; } } } if(all_assigned){ for(inti=k.size();i--;) GECODE_ME_CHECK(k[i].eq(home,count[i])); returnhome.ES_SUBSUMED(*this); } if(Card::propagate) GECODE_ES_CHECK(pruneCards(home)); intn=x.size(); int*mu=r.alloc<int>(n); int*nu=r.alloc<int>(n); for(inti=n;i--;) nu[i]=mu[i]=i; //Createsortingpermutationmuaccordingtothevariablesupperbounds MaxInc<IntView>max_inc(x); Support::quicksort<int,MaxInc<IntView>>(mu,n,max_inc); //Createsortingpermutationnuaccordingtothevariableslowerbounds MinInc<IntView>min_inc(x); Support::quicksort<int,MinInc<IntView>>(nu,n,min_inc); //Sortthecardinalityboundsbyindex MinIdx<Card>min_idx; Support::quicksort<Card,MinIdx<Card>>(&k[0],k.size(),min_idx); if(!lps.initialized()){ assert(!ups.initialized()); lps.init(home,k,false); ups.init(home,k,true); }elseif(Card::propagate){ //iftherehasbeenachangetothecardinalityvariables //reconstructionofthepartialsumstructureisnecessary if(lps.check_update_min(k)) lps.init(home,k,false); if(ups.check_update_max(k)) ups.init(home,k,true); } //assertthattheminimalvalueofthepartialsumstructurefor //LBCisconsistentwiththesmallestvalueavariablecantake assert(lps.minValue()<=x[nu[0]].min()); //assertthatthemaximalvalueofthepartialsumstructurefor //UBCisconsistentwiththelargestvalueavariablecantake /* *Setuprankandboundsinfo *SincethisimplementationisbasedonthetheoryofHallIntervals *additionaldatastructuresareneededinordertorepresentthese *intervalsandthe"partial-sum"datastructure(cf."gcc/bnd-sup.hpp") * */ HallInfo*hall=r.alloc<HallInfo>(2*n+2); Rank*rank=r.alloc<Rank>(n); intnb=0; //setupboundsandrank intmin=x[nu[0]].min(); intmax=x[mu[0]].max()+1; intlast=lps.firstValue+1;//equivalenttolast=min-2 hall[0].bounds=last; /* *Firstthealgorithmmergesthearraysminsortedandmaxsorted *intoboundsi.e.hall[].boundscontainstheorderedunion *ofthelowerandupperdomainboundsincludingtwosentinels *atthebeginningandattheendoftheset *(theuppervariableboundsinthisunionareincreasedby1) */ { inti=0; intj=0; while(true){ if(i<n&&min<max){ if(min!=last){ last=min; hall[++nb].bounds=last; } rank[nu[i]].min=nb; if(++i<n) min=x[nu[i]].min(); }else{ if(max!=last){ last=max; hall[++nb].bounds=last; } rank[mu[j]].max=nb; if(++j==n) break; max=x[mu[j]].max()+1; } } } intrightmost=nb+1;//rightmostaccesiblevalueinbounds hall[rightmost].bounds=ups.lastValue+1; if(Card::propagate){ skip_lbc=true; for(inti=k.size();i--;) if(k[i].min()!=0){ skip_lbc=false; break; } } if(!card_fixed&&!skip_lbc) GECODE_ES_CHECK((lbc(home,nb,hall,rank,mu,nu))); GECODE_ES_CHECK((ubc(home,nb,hall,rank,mu,nu))); if(Card::propagate) GECODE_ES_CHECK(prop_card<Card>(home,x,k)); for(inti=k.size();i--;) count[i]=0; for(inti=x.size();i--;) if(x[i].assigned()){ intidx; if(!lookupValue(k,x[i].val(),idx)) returnES_FAILED; count[idx]++; }else{ //Wewon'tneedtheremainingcounts,they'reonlyusedwhen //allxareassigned returnES_NOFIX; } for(inti=k.size();i--;) GECODE_ME_CHECK(k[i].eq(home,count[i])); returnhome.ES_SUBSUMED(*this); } template<classCard> ExecStatus Bnd<Card>::post(Homehome, ViewArray<IntView>&x,ViewArray<Card>&k){ boolcardfix=true; for(inti=k.size();i--;) if(!k[i].assigned()){ cardfix=false;break; } boolnolbc=true; for(inti=k.size();i--;) if(k[i].min()!=0){ nolbc=false;break; } GECODE_ES_CHECK(postSideConstraints<Card>(home,x,k)); if(isDistinct<Card>(home,x,k)) returnDistinct::Bnd<IntView>::post(home,x); (void)new(home)Bnd<Card>(home,x,k,cardfix,nolbc); returnES_OK; } }}} //STATISTICS:int-prop