dom-sup.hpp /usr/include/gecode/int/gcc.hh Gecode::Int::GCC::Node Gecode::Int::GCC::VarNode Gecode::Int::GCC::ValNode Gecode::Int::GCC::Edge Gecode::Int::GCC::VarValGraph 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,2005 *ChristianSchulte,2009 *GuidoTack,2009 * *Lastmodified: *$Date:2013-03-1220:10:44+0100(Tue,12Mar2013)$by$Author:schulte$ *$Revision:13511$ * *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{ enumBC{UBC=1,LBC=0}; classEdge; classNode{ protected: Edge*e; Edge*fst; Edge*lst; Edge*ie; intidx; enumNodeFlag{ NF_NONE=0, NF_VAL=1<<0, NF_M_LBC=1<<1, NF_M_UBC=1<<2 }; unsignedcharnf; public: intnoe; Node(void); Node(NodeFlagnf,inti); booltype(void)const; Edge**adj(void); Edge*first(void)const; Edge*last(void)const; Edge*inedge(void)const; intindex(void)const; boolremoved(void)const; voidfirst(Edge*p); voidlast(Edge*p); voidinedge(Edge*p); voidindex(inti); staticvoid*operatornew(size_ts,Space&home); staticvoidoperatordelete(void*,Space&){}; staticvoidoperatordelete(void*){}; }; classVarNode:publicNode{ protected: Edge*ubm; Edge*lbm; public: VarNode(void); VarNode(inti); Edge*get_match(BCbc)const; boolmatched(BCbc)const; voidset_match(BCbc,Edge*m); voidmatch(BCbc); voidunmatch(BCbc); }; classValNode:publicNode{ protected: int_klb; int_kub; int_kidx; int_kcount; intnoc; intlb; intublow; intub; public: intval; ValNode(void); ValNode(intmin,intmax,intvalue,intkidx,intkshift,intcount); intmaxlow(void)const; voidcard_conflict(intc); intcard_conflict(void)const; voidred_conflict(void); voidinc(void); intkcount(void)const; intincid_match(BCbc)const; intkindex(void)const; boolmatched(BCbc)const; boolsink(void)const; boolsource(void)const; intkmin(void)const; intkmax(void)const; intkbound(BCbc)const; voidmaxlow(inti); voidkcount(int); voidkindex(int); voiddec(BCbc); voidinc(BCbc); intcap(BCbc)const; voidcap(BCbc,intc); voidmatch(BCbc); voidunmatch(BCbc); voidreset(void); voidkmin(intmin); voidkmax(intmax); }; classEdge{ private: VarNode*x; ValNode*v; Edge*next_edge; Edge*prev_edge; Edge*next_vedge; Edge*prev_vedge; enumEdgeFlag{ EF_NONE=0, EF_MRKLB=1<<0, EF_MRKUB=1<<1, EF_LM=1<<2, EF_UM=1<<3, EF_DEL=1<<4 }; unsignedcharef; public: Edge(void){} Edge(VarNode*x,ValNode*v); boolused(BCbc)const; boolmatched(BCbc)const; booldeleted(void)const; Edge*next(boolt)const; Edge*next(void)const; Edge*prev(void)const; Edge*vnext(void)const; Edge*vprev(void)const; VarNode*getVar(void)const; ValNode*getVal(void)const; Node*getMate(boolt)const; voiduse(BCbc); voidfree(BCbc); voidreset(BCbc); voidmatch(BCbc); voidunmatch(BCbc); voidunmatch(BCbc,boolt); voidunlink(void); voiddel_edge(void); voidinsert_edge(void); Edge**next_ref(void); Edge**prev_ref(void); Edge**vnext_ref(void); Edge**vprev_ref(void); staticvoid*operatornew(size_ts,Space&home); staticvoidoperatordelete(void*,Space&){}; staticvoidoperatordelete(void*){}; }; template<classCard> classVarValGraph{ private: typedefSupport::StaticStack<Node*,Region>NodeStack; typedefSupport::BitSet<Region>BitSet; VarNode**vars; ValNode**vals; intn_var; intn_val; intn_node; intsum_min; intsum_max; public: VarValGraph(Space&home, ViewArray<IntView>&x,ViewArray<Card>&k, intsmin,intsmax); ExecStatusmin_require(Space&home, ViewArray<IntView>&x,ViewArray<Card>&k); ExecStatussync(Space&home, ViewArray<IntView>&x,ViewArray<Card>&k); template<BC> ExecStatusnarrow(Space&home, ViewArray<IntView>&x,ViewArray<Card>&k); template<BC> ExecStatusmaximum_matching(Space&home); template<BC> voidfree_alternating_paths(Space&home); template<BC> voidstrongly_connected_components(Space&home); template<BC> boolaugmenting_path(Space&home,Node*); protected: template<BC> voiddfs(Node*,BitSet&,BitSet&,int[], NodeStack&,NodeStack&,int&); public: void*operatornew(size_tt,Space&home); voidoperatordelete(void*,Space&){} }; /* *Nodes * */ forceinline Node::Node(void){} forceinline Node::Node(NodeFlagnf0,inti) :e(NULL),fst(NULL),lst(NULL),ie(NULL),idx(i), nf(static_cast<unsignedchar>(nf0)),noe(0){} forceinlineEdge** Node::adj(void){ return&e; } forceinlineEdge* Node::first(void)const{ returnfst; } forceinlineEdge* Node::last(void)const{ returnlst; } forceinlinevoid Node::first(Edge*p){ fst=p; } forceinlinevoid Node::last(Edge*p){ lst=p; } forceinlinebool Node::type(void)const{ return(nf&NF_VAL)!=0; } forceinlineEdge* Node::inedge(void)const{ returnie; } forceinlinevoid Node::inedge(Edge*p){ ie=p; } forceinlinebool Node::removed(void)const{ returnnoe==0; } forceinlinevoid Node::index(inti){ idx=i; } forceinlineint Node::index(void)const{ returnidx; } forceinlinevoid* Node::operatornew(size_ts,Space&home){ returnhome.ralloc(s); } /* *Variablenodes * */ forceinline VarNode::VarNode(void){} forceinline VarNode::VarNode(intx): Node(NF_NONE,x),ubm(NULL),lbm(NULL){} forceinlinebool VarNode::matched(BCbc)const{ if(bc==UBC) return(nf&NF_M_UBC)!=0; else return(nf&NF_M_LBC)!=0; } forceinlinevoid VarNode::match(BCbc){ if(bc==UBC) nf|=NF_M_UBC; else nf|=NF_M_LBC; } forceinlinevoid VarNode::set_match(BCbc,Edge*p){ if(bc==UBC) ubm=p; else lbm=p; } forceinlinevoid VarNode::unmatch(BCbc){ if(bc==UBC){ nf&=~NF_M_UBC;ubm=NULL; }else{ nf&=~NF_M_LBC;lbm=NULL; } } forceinlineEdge* VarNode::get_match(BCbc)const{ if(bc==UBC) returnubm; else returnlbm; } /* *Valuenodes * */ forceinline ValNode::ValNode(void){} forceinline ValNode::ValNode(intmin,intmax,intvalue, intkidx,intkshift,intcount): Node(NF_VAL,kshift),_klb(min),_kub(max),_kidx(kidx),_kcount(count), noc(0), lb(min),ublow(max),ub(max), val(value){} forceinlinevoid ValNode::maxlow(inti){ assert(i>=lb); ublow=i; } forceinlineint ValNode::maxlow(void)const{ if(_klb==_kub){ assert(ublow==lb); } returnublow; } forceinlinevoid ValNode::card_conflict(intc){ noc=c; } forceinlinevoid ValNode::red_conflict(void){ noc--; assert(noc>=0); } forceinlineint ValNode::card_conflict(void)const{ returnnoc; } forceinlineint ValNode::cap(BCbc)const{ if(bc==UBC) returnub; else returnlb; } forceinlinebool ValNode::matched(BCbc)const{ returncap(bc)==0; } forceinlinevoid ValNode::reset(void){ lb=_klb; ublow=_kub; ub=_kub; noe=0; } forceinlineint ValNode::kbound(BCbc)const{ if(bc==UBC){ return_kub; }else{ return_klb; } } forceinlineint ValNode::kmax(void)const{ return_kub; } forceinlineint ValNode::kmin(void)const{ return_klb; } forceinlinevoid ValNode::kmin(intklb){ _klb=klb; } forceinlinevoid ValNode::kmax(intkub){ _kub=kub; } forceinlinevoid ValNode::dec(BCbc){ if(bc==UBC){ ub--; }else{ lb--;ublow--; } } forceinlinevoid ValNode::inc(BCbc){ if(bc==UBC){ ub++; }else{ lb++;ublow++; } } forceinlinevoid ValNode::match(BCbc){ dec(bc); } forceinlinevoid ValNode::unmatch(BCbc){ inc(bc); } forceinlinevoid ValNode::cap(BCbc,intc){ if(bc==UBC) ub=c; else lb=c; } forceinlinevoid ValNode::inc(void){ _kcount++; } forceinlineint ValNode::kcount(void)const{ return_kcount; } forceinlinevoid ValNode::kcount(intc){ _kcount=c; } forceinlinevoid ValNode::kindex(inti){ _kidx=i; } forceinlineint ValNode::kindex(void)const{ return_kidx; } forceinlineint ValNode::incid_match(BCbc)const{ if(bc==LBC) return_kub-ublow+_kcount; else return_kub-ub+_kcount; } forceinlinebool ValNode::sink(void)const{ //thereareonlyincomingedges //incaseoftheUBC-matching return_kub-ub==noe; } forceinlinebool ValNode::source(void)const{ //thereareonlyincomingedges //incaseoftheUBC-matching return_klb-lb==noe; } /* *Edges * */ forceinlinevoid Edge::unlink(void){ //unlinkfromvariableside Edge*p=prev_edge; Edge*n=next_edge; if(p!=NULL) *p->next_ref()=n; if(n!=NULL) *n->prev_ref()=p; if(this==x->first()){ Edge**ref=x->adj(); *ref=n; x->first(n); } if(this==x->last()) x->last(p); //unlinkfromvalueside Edge*pv=prev_vedge; Edge*nv=next_vedge; if(pv!=NULL) *pv->vnext_ref()=nv; if(nv!=NULL) *nv->vprev_ref()=pv; if(this==v->first()){ Edge**ref=v->adj(); *ref=nv; v->first(nv); } if(this==v->last()) v->last(pv); } forceinline Edge::Edge(VarNode*var,ValNode*val): x(var),v(val), next_edge(NULL),prev_edge(NULL), next_vedge(NULL),prev_vedge(NULL),ef(EF_NONE){} forceinlinevoid Edge::use(BCbc){ if(bc==UBC) ef|=EF_MRKUB; else ef|=EF_MRKLB; } forceinlinevoid Edge::free(BCbc){ if(bc==UBC) ef&=~EF_MRKUB; else ef&=~EF_MRKLB; } forceinlinebool Edge::used(BCbc)const{ if(bc==UBC) return(ef&EF_MRKUB)!=0; else return(ef&EF_MRKLB)!=0; } forceinlineEdge* Edge::next(void)const{ returnnext_edge; } forceinlineEdge* Edge::next(boolt)const{ if(t){ returnnext_vedge; }else{ returnnext_edge; } } forceinlineEdge* Edge::vnext(void)const{ returnnext_vedge; } forceinlineEdge** Edge::vnext_ref(void){ return&next_vedge; } forceinlineEdge* Edge::prev(void)const{ returnprev_edge; } forceinlineEdge** Edge::prev_ref(void){ return&prev_edge; } forceinlineEdge* Edge::vprev(void)const{ returnprev_vedge; } forceinlineEdge** Edge::vprev_ref(void){ return&prev_vedge; } forceinlineEdge** Edge::next_ref(void){ return&next_edge; } forceinlineVarNode* Edge::getVar(void)const{ assert(x!=NULL); returnx; } forceinlineValNode* Edge::getVal(void)const{ assert(v!=NULL); returnv; } forceinlineNode* Edge::getMate(booltype)const{ if(type) returnx; else returnv; } forceinlinevoid Edge::unmatch(BCbc){ if(bc==UBC) ef&=~EF_UM; else ef&=~EF_LM; x->unmatch(bc);v->unmatch(bc); } forceinlinevoid Edge::unmatch(BCbc,boolnode){ if(bc==UBC) ef&=~EF_UM; else ef&=~EF_LM; if(node) v->unmatch(bc); else x->unmatch(bc); } forceinlinevoid Edge::reset(BCbc){ free(bc);unmatch(bc); } forceinlinevoid Edge::match(BCbc){ if(bc==UBC) ef|=EF_UM; else ef|=EF_LM; x->match(bc); x->set_match(bc,this); v->match(bc); } forceinlinebool Edge::matched(BCbc)const{ if(bc==UBC) return(ef&EF_UM)!=0; else return(ef&EF_LM)!=0; } forceinlinevoid Edge::del_edge(void){ ef|=EF_DEL; } forceinlinevoid Edge::insert_edge(void){ ef&=~EF_DEL; } forceinlinebool Edge::deleted(void)const{ return(ef&EF_DEL)!=0; } forceinlinevoid* Edge::operatornew(size_ts,Space&home){ returnhome.ralloc(s); } /* *Variablevaluegraph * */ template<classCard> VarValGraph<Card>::VarValGraph(Space&home, ViewArray<IntView>&x,ViewArray<Card>&k, intsmin,intsmax) :n_var(x.size()), n_val(k.size()), n_node(n_var+n_val), sum_min(smin), sum_max(smax){ unsignedintnoe=0; for(inti=x.size();i--;) noe+=x[i].size(); vars=home.alloc<VarNode*>(n_var); vals=home.alloc<ValNode*>(n_val); for(inti=n_val;i--;){ intkmi=k[i].min(); intkma=k[i].max(); intkc=k[i].counter(); if(kc!=kma){ if(kmi>=kc){ kmi-=kc; assert(kmi>=0); }else{ kmi=0; } kma-=kc; assert(kma>0); vals[i]=new(home) ValNode(kmi,kma,k[i].card(),i,i+n_var,kc); }else{ vals[i]=new(home) ValNode(0,0,k[i].card(),i,i+n_var,kc); } } for(inti=n_var;i--;){ vars[i]=new(home)VarNode(i); //getthespacefortheedgesofthevarnode Edge**xadjacent=vars[i]->adj(); intj=0; for(ViewValues<IntView>xi(x[i]);xi();++xi){ //getthecorrectindexforthevalue while(vals[j]->val<xi.val()) j++; *xadjacent=new(home)Edge(vars[i],vals[j]); vars[i]->noe++; if(vars[i]->first()==NULL) vars[i]->first(*xadjacent); Edge*oldprev=vars[i]->last(); vars[i]->last(*xadjacent); *vars[i]->last()->prev_ref()=oldprev; if(vals[j]->first()==NULL){ vals[j]->first(*xadjacent); vals[j]->last(*xadjacent); }else{ Edge*old=vals[j]->first(); vals[j]->first(*xadjacent); *vals[j]->first()->vnext_ref()=old; *old->vprev_ref()=vals[j]->first(); } vals[j]->noe++; xadjacent=(*xadjacent)->next_ref(); } *xadjacent=NULL; } } template<classCard> inlineExecStatus VarValGraph<Card>::min_require(Space&home, ViewArray<IntView>&x, ViewArray<Card>&k){ for(inti=n_val;i--;){ ValNode*vln=vals[i]; if(vln->noe>0){ if(k[i].min()==vln->noe){ //allvariablenodesreachablefromvlnshouldbeequaltovln->val for(Edge*e=vln->first();e!=NULL;e=e->vnext()){ VarNode*vrn=e->getVar(); for(Edge*f=vrn->first();f!=NULL;f=f->next()) if(f!=e){ ValNode*w=f->getVal(); w->noe--; vrn->noe--; f->del_edge(); f->unlink(); } assert(vrn->noe==1); intvi=vrn->index(); GECODE_ME_CHECK(x[vi].eq(home,vln->val)); vars[vi]=vars[--n_var]; vars[vi]->index(vi); x.move_lst(vi); n_node--; vln->noe--; } intvidx=vln->kindex(); if(Card::propagate) GECODE_ME_CHECK(k[vidx].eq(home,k[vidx].min())); k[vidx].counter(k[vidx].min()); vln->cap(UBC,0); vln->cap(LBC,0); vln->maxlow(0); if(sum_min>=k[vidx].min()) sum_min-=k[vidx].min(); if(sum_max>=k[vidx].max()) sum_max-=k[vidx].max(); } }else{ vals[i]->cap(UBC,0); vals[i]->cap(LBC,0); vals[i]->maxlow(0); vals[i]->kmax(0); vals[i]->kmin(0); } if(Card::propagate&&(k[i].counter()==0)) GECODE_ME_CHECK(k[i].lq(home,vals[i]->noe)); } for(inti=n_val;i--;) vals[i]->index(n_var+i); returnES_OK; } template<classCard> inlineExecStatus VarValGraph<Card>::sync(Space&home, ViewArray<IntView>&x,ViewArray<Card>&k){ Regionr(home); //Anodecanbepushedtwice(oncewhencheckingcardinalityandlateragain) NodeStackre(r,2*n_node); //synchronizecardinalityvariables if(Card::propagate){ for(inti=n_val;i--;){ ValNode*v=vals[i]; intinc_ubc=v->incid_match(UBC); intinc_lbc=v->incid_match(LBC); if(v->noe==0){ inc_ubc=0; inc_lbc=0; } intrm=v->kmax()-k[i].max(); //thecardinalityboundshavebeenmodified if((k[i].max()<v->kmax())||(k[i].min()>v->kmin())){ if((k[i].max()!=k[i].counter())||(k[i].max()==0)){ //updatethebounds v->kmax(k[i].max()); v->kmin(k[i].min()); //everythingisfine if(inc_ubc<=k[i].max()){ //adjustcapacities v->cap(UBC,k[i].max()-inc_ubc); v->maxlow(k[i].max()-inc_lbc); if(v->kmin()==v->kmax()) v->cap(LBC,k[i].max()-inc_lbc); }else{ //setcaptomaxandresolveconflictsonviewside //settofullcapacityforlaterrescheduling if(v->cap(UBC)) v->cap(UBC,k[i].max()); v->maxlow(k[i].max()-(inc_lbc)); if(v->kmin()==v->kmax()) v->cap(LBC,k[i].max()-(inc_lbc)); v->card_conflict(rm); } } } if(inc_lbc<k[i].min()&&v->noe>0){ v->cap(LBC,k[i].min()-inc_lbc); re.push(v); } } for(inti=n_var;i--;){ Edge*mub=vars[i]->get_match(UBC); if(mub!=NULL){ ValNode*vu=mub->getVal(); if((vars[i]->noe!=1)&&vu->card_conflict()){ vu->red_conflict(); mub->unmatch(UBC,vars[i]->type()); re.push(vars[i]); } } } } //goonwithsynchronization assert(x.size()==n_var); for(inti=n_var;i--;){ VarNode*vrn=vars[i]; if(static_cast<int>(x[i].size())!=vrn->noe){ //ifthevariableisalreadyassigned if(x[i].assigned()){ intv=x[i].val(); Edge*mub=vrn->get_match(UBC); if((mub!=NULL)&&(v!=mub->getVal()->val)){ mub->unmatch(UBC); re.push(vars[i]); } Edge*mlb=vrn->get_match(LBC); if(mlb!=NULL){ ValNode*vln=mlb->getVal(); if(v!=vln->val){ mlb->unmatch(LBC); if(vln->incid_match(LBC)<vln->kmin()) re.push(vln); } } for(Edge*e=vrn->first();e!=NULL;e=e->next()){ ValNode*vln=e->getVal(); if(vln->val!=v){ vrn->noe--; e->getVal()->noe--; e->del_edge(); e->unlink(); } } }else{ //deletetheedge ViewValues<IntView>xiter(x[i]); Edge*mub=vrn->get_match(UBC); Edge*mlb=vrn->get_match(LBC); Edge**p=vrn->adj(); Edge*e=*p; do{ //searchtheedgethathastobedeleted while(e!=NULL&&(e->getVal()->val<xiter.val())){ //Skipedge e->getVal()->noe--; vrn->noe--; e->del_edge(); e->unlink(); e=e->next(); *p=e; } assert(xiter.val()==e->getVal()->val); //Thisedgemustbekept e->free(UBC); e->free(LBC); ++xiter; p=e->next_ref(); e=e->next(); }while(xiter()); *p=NULL; while(e){ e->getVar()->noe--; e->getVal()->noe--; e->del_edge(); e->unlink(); e=e->next(); } if((mub!=NULL)&&mub->deleted()){ mub->unmatch(UBC); re.push(vars[i]); } //lowerboundmatchingcanbezero if((mlb!=NULL)&&mlb->deleted()){ ValNode*vln=mlb->getVal(); mlb->unmatch(LBC); if(vln->incid_match(LBC)<vln->kmin()) re.push(vln); } } } vars[i]->index(i); } for(inti=n_val;i--;){ if((k[i].min()>vals[i]->noe)&&(k[i].counter()==0)) returnES_FAILED; vals[i]->index(n_var+i); } //startrepair while(!re.empty()){ Node*n=re.pop(); if(!n->removed()){ if(!n->type()){ VarNode*vrn=static_cast<VarNode*>(n); if(!vrn->matched(UBC)&&!augmenting_path<UBC>(home,vrn)) returnES_FAILED; }else{ ValNode*vln=static_cast<ValNode*>(n); while(!vln->matched(LBC)) if(!augmenting_path<LBC>(home,vln)) returnES_FAILED; } } } returnES_OK; } template<classCard>template<BCbc> inlineExecStatus VarValGraph<Card>::narrow(Space&home, ViewArray<IntView>&x,ViewArray<Card>&k){ for(inti=n_var;i--;) if(vars[i]->noe==1){ ValNode*v=vars[i]->first()->getVal(); vars[i]->first()->free(bc); GECODE_ME_CHECK(x[i].eq(home,v->val)); v->inc(); } for(inti=n_val;i--;){ ValNode*v=vals[i]; if(Card::propagate&&(k[i].counter()==0)) GECODE_ME_CHECK(k[i].lq(home,v->noe)); if(v->noe>0){ if(Card::propagate) GECODE_ME_CHECK(k[i].lq(home,v->noe)); //Ifthemaximumnumberofoccurencesofavalueisreached //itcannotbeconsumedbyanotherview if(v->kcount()==v->kmax()){ intvidx=v->kindex(); k[i].counter(v->kcount()); if(Card::propagate) GECODE_ME_CHECK(k[i].eq(home,k[i].counter())); booldelall=v->card_conflict()&&(v->noe>v->kmax()); for(Edge*e=v->last();e!=NULL;e=e->vprev()){ VarNode*vrn=e->getVar(); if(vrn->noe==1){ vrn->noe--; v->noe--; intvi=vrn->index(); x.move_lst(vi); vars[vi]=vars[--n_var]; vars[vi]->index(vi); n_node--; e->del_edge(); e->unlink(); }elseif(delall){ GECODE_ME_CHECK(x[vrn->index()].nq(home,v->val)); vrn->noe--; v->noe--; e->del_edge(); e->unlink(); } } v->cap(UBC,0); v->cap(LBC,0); v->maxlow(0); if(sum_min>=k[vidx].min()) sum_min-=k[vidx].min(); if(sum_max>=k[vidx].max()) sum_max-=k[vidx].max(); }elseif(v->kcount()>0){ v->kcount(0); } } } for(inti=n_var;i--;) vars[i]->index(i); for(inti=n_val;i--;){ if(vals[i]->noe==0){ vals[i]->cap(UBC,0); vals[i]->cap(LBC,0); vals[i]->maxlow(0); } vals[i]->index(n_var+i); } for(inti=n_var;i--;){ if(vars[i]->noe>1){ for(Edge*e=vars[i]->first();e!=NULL;e=e->next()){ if(!e->matched(bc)&&!e->used(bc)){ GECODE_ME_CHECK(x[i].nq(home,e->getVal()->val)); }else{ e->free(bc); } } } } returnES_OK; } template<classCard>template<BCbc> forceinlinebool VarValGraph<Card>::augmenting_path(Space&home,Node*v){ Regionr(home); NodeStackns(r,n_node); BitSetvisited(r,static_cast<unsignedint>(n_node)); Edge**start=r.alloc<Edge*>(n_node); //keeptrackofthenodesthathavealreadybeenvisited Node*sn=v; //markthestartpartition boolsp=sn->type(); //nodesinsponlyfollowfreeedges //nodesinV-sponlyfollowmatchededges for(inti=n_node;i--;) if(i>=n_var){ vals[i-n_var]->inedge(NULL); start[i]=vals[i-n_var]->first(); }else{ vars[i]->inedge(NULL); start[i]=vars[i]->first(); } v->inedge(NULL); ns.push(v); visited.set(static_cast<unsignedint>(v->index())); while(!ns.empty()){ Node*v=ns.top(); Edge*e=NULL; if(v->type()==sp){ e=start[v->index()]; while((e!=NULL)&&e->matched(bc)) e=e->next(v->type()); }else{ e=start[v->index()]; while((e!=NULL)&&!e->matched(bc)) e=e->next(v->type()); start[v->index()]=e; } if(e!=NULL){ start[v->index()]=e->next(v->type()); Node*w=e->getMate(v->type()); if(!visited.get(static_cast<unsignedint>(w->index()))){ //unexploredpath boolm=w->type()? static_cast<ValNode*>(w)->matched(bc): static_cast<VarNode*>(w)->matched(bc); if(!m&&w->type()!=sp){ if(v->inedge()!=NULL){ //augmentingpathoflengthl>1 e->match(bc); break; }else{ //augmentingpathoflengthl=1 e->match(bc); ns.pop(); returntrue; } }else{ w->inedge(e); visited.set(static_cast<unsignedint>(w->index())); //findmatchingedgemincidentwithw ns.push(w); } } }else{ //triedalloutgoingedgeswithoutfindinganaugmentingpath ns.pop(); } } boolpathfound=!ns.empty(); while(!ns.empty()){ Node*t=ns.pop(); if(t!=sn){ Edge*in=t->inedge(); if(t->type()!=sp){ in->match(bc); }elseif(!sp){ in->unmatch(bc,!sp); }else{ in->unmatch(bc); } } } returnpathfound; } template<classCard>template<BCbc> inlineExecStatus VarValGraph<Card>::maximum_matching(Space&home){ intcard_match=0; //findanintialmatchinginO(n*d) //greedyalgorithm for(inti=n_val;i--;) for(Edge*e=vals[i]->first();e!=NULL;e=e->vnext()) if(!e->getVar()->matched(bc)&&!vals[i]->matched(bc)){ e->match(bc);card_match++; } Regionr(home); switch(bc){ caseLBC: if(card_match<sum_min){ Support::StaticStack<ValNode*,Region>free(r,n_val); //findfailednodes for(inti=n_val;i--;) if(!vals[i]->matched(LBC)) free.push(vals[i]); while(!free.empty()){ ValNode*v=free.pop(); while(!v->matched(LBC)) if(augmenting_path<LBC>(home,v)) card_match++; else break; } return(card_match>=sum_min)?ES_OK:ES_FAILED; }else{ returnES_OK; } break; caseUBC: if(card_match<n_var){ Support::StaticStack<VarNode*,Region>free(r,n_var); //findfailednodes for(inti=n_var;i--;) if(!vars[i]->matched(UBC)) free.push(vars[i]); while(!free.empty()){ VarNode*v=free.pop(); if(!v->matched(UBC)&&augmenting_path<UBC>(home,v)) card_match++; } return(card_match>=n_var)?ES_OK:ES_FAILED; }else{ returnES_OK; } break; default:GECODE_NEVER; } GECODE_NEVER; returnES_FAILED; } template<classCard>template<BCbc> forceinlinevoid VarValGraph<Card>::free_alternating_paths(Space&home){ Regionr(home); NodeStackns(r,n_node); BitSetvisited(r,static_cast<unsignedint>(n_node)); switch(bc){ caseLBC: //afteramaximummatchingonthevaluenodestherestillcanbe //freevaluenodes,hencewehavetoconsiderALLnodeswhether //theyarethestartingpointofanevenalternatingpathinG for(inti=n_var;i--;) if(!vars[i]->matched(LBC)){ ns.push(vars[i]); visited.set(static_cast<unsignedint>(vars[i]->index())); } for(inti=n_val;i--;) if(!vals[i]->matched(LBC)){ ns.push(vals[i]); visited.set(static_cast<unsignedint>(vals[i]->index())); } break; caseUBC: //clearly,afteramaximummatchingonthexvariables //correspondingtoasetcoveronxthereareNOfreevarnodes for(inti=n_val;i--;) if(!vals[i]->matched(UBC)){ ns.push(vals[i]); visited.set(static_cast<unsignedint>(vals[i]->index())); } break; default:GECODE_NEVER; } while(!ns.empty()){ Node*node=ns.pop(); if(node->type()){ //ValNode ValNode*vln=static_cast<ValNode*>(node); for(Edge*cur=vln->first();cur!=NULL;cur=cur->vnext()){ VarNode*mate=cur->getVar(); switch(bc){ caseLBC: if(cur->matched(LBC)){ //marktheedge cur->use(LBC); if(!visited.get(static_cast<unsignedint>(mate->index()))){ ns.push(mate); visited.set(static_cast<unsignedint>(mate->index())); } } break; caseUBC: if(!cur->matched(UBC)){ //marktheedge cur->use(UBC); if(!visited.get(static_cast<unsignedint>(mate->index()))){ ns.push(mate); visited.set(static_cast<unsignedint>(mate->index())); } } break; default:GECODE_NEVER; } } }else{ //VarNode VarNode*vrn=static_cast<VarNode*>(node); switch(bc){ caseLBC: //afterLBC-matchingwecanfolloweveryunmatchededge for(Edge*cur=vrn->first();cur!=NULL;cur=cur->next()){ ValNode*mate=cur->getVal(); if(!cur->matched(LBC)){ cur->use(LBC); if(!visited.get(static_cast<unsignedint>(mate->index()))){ ns.push(mate); visited.set(static_cast<unsignedint>(mate->index())); } } } break; caseUBC: //afterUBC-matchingwecanonlyfollowamatchededge { Edge*cur=vrn->get_match(UBC); if(cur!=NULL){ cur->use(UBC); ValNode*mate=cur->getVal(); if(!visited.get(static_cast<unsignedint>(mate->index()))){ ns.push(mate); visited.set(static_cast<unsignedint>(mate->index())); } } } break; default:GECODE_NEVER; } } } } template<classCard>template<BCbc> void VarValGraph<Card>::dfs(Node*v, BitSet&inscc,BitSet&in_unfinished,intdfsnum[], NodeStack&roots,NodeStack&unfinished, int&count){ count++; intv_index=v->index(); dfsnum[v_index]=count; inscc.set(static_cast<unsignedint>(v_index)); in_unfinished.set(static_cast<unsignedint>(v_index)); unfinished.push(v); roots.push(v); for(Edge*e=v->first();e!=NULL;e=e->next(v->type())){ boolm; switch(bc){ caseLBC: m=v->type()?e->matched(LBC):!e->matched(LBC); break; caseUBC: m=v->type()?!e->matched(UBC):e->matched(UBC); break; default:GECODE_NEVER; } if(m){ Node*w=e->getMate(v->type()); intw_index=w->index(); assert(w_index<n_node); if(!inscc.get(static_cast<unsignedint>(w_index))){ //wisanuncompletedscc w->inedge(e); dfs<bc>(w,inscc,in_unfinished,dfsnum, roots,unfinished,count); }elseif(in_unfinished.get(static_cast<unsignedint>(w_index))){ //evenalternatingcyclefoundmarktheedgeclosingthecycle, //completingthescc e->use(bc); //ifwbelongstoansccwedetectedearlier //mergecomponents assert(roots.top()->index()<n_node); while(dfsnum[roots.top()->index()]>dfsnum[w_index]){ roots.pop(); } } } } if(v==roots.top()){ while(v!=unfinished.top()){ //wbelongstothesccwithrootv Node*w=unfinished.top(); w->inedge()->use(bc); in_unfinished.clear(static_cast<unsignedint>(w->index())); unfinished.pop(); } assert(v==unfinished.top()); in_unfinished.clear(static_cast<unsignedint>(v_index)); roots.pop(); unfinished.pop(); } } template<classCard>template<BCbc> forceinlinevoid VarValGraph<Card>::strongly_connected_components(Space&home){ Regionr(home); BitSetinscc(r,static_cast<unsignedint>(n_node)); BitSetin_unfinished(r,static_cast<unsignedint>(n_node)); int*dfsnum=r.alloc<int>(n_node); for(inti=n_node;i--;) dfsnum[i]=0; intcount=0; NodeStackroots(r,n_node); NodeStackunfinished(r,n_node); for(inti=n_var;i--;) dfs<bc>(vars[i],inscc,in_unfinished,dfsnum, roots,unfinished,count); } template<classCard> forceinlinevoid* VarValGraph<Card>::operatornew(size_tt,Space&home){ returnhome.ralloc(t); } }}} //STATISTICS:int-prop