graph.hpp /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. * */ namespaceGecode{namespaceInt{namespaceNValues{ forceinline Graph::Graph(void) :n_matched(0){} forceinlineint Graph::size(void)const{ returnn_matched; } forceinlinevoid Graph::init(Space&home,constValSet&vs,constViewArray<IntView>&x){ usingnamespaceViewValGraph; n_view=x.size()+vs.size(); view=home.alloc<ViewNode<IntView>*>(n_view); //Createnodescorrespondingtothevaluesetvs { inti=x.size(); ValSet::Rangesvsr(vs); ValNode<IntView>**v=&val; for(Iter::Ranges::ToValues<ValSet::Ranges>n(vsr);n();++n){ //Createviewnode view[i]=new(home)ViewNode<IntView>(); //Createandlinkvaluenode ValNode<IntView>*nv=new(home)ValNode<IntView>(n.val()); *v=nv;v=nv->next_val_ref(); //Createandlinksingleedge Edge<IntView>**e=view[i]->val_edges_ref(); *e=new(home)Edge<IntView>(nv,view[i],NULL); //Matchedge (*e)->revert(view[i]);nv->matching(*e); i++; } *v=NULL; n_val=vs.size(); n_matched=vs.size(); assert(i-x.size()==vs.size()); } //Initializerealviewnodes for(inti=x.size();i--;){ view[i]=new(home)ViewNode<IntView>(x[i]); ViewValGraph::Graph<IntView>::init(home,view[i]); } //Matchtherealviewnodes,ifpossible Regionr(home); ViewNodeStackm(r,n_view); for(inti=x.size();i--;) if(match(m,view[i])) n_matched++; } forceinlinevoid Graph::sync(Space&home){ usingnamespaceViewValGraph; Regionr(home); //Whethertorematch boolrematch=false; //Synchronizenodes for(inti=n_view;i--;){ ViewNode<IntView>*x=view[i]; //Skipfakedviewnodes,theycorrespondtovaluesinthevalueset if(!x->fake()){ if(x->changed()){ ViewRanges<IntView>r(x->view()); Edge<IntView>*m=x->matched()?x->edge_fst():NULL; Edge<IntView>**p=x->val_edges_ref(); Edge<IntView>*e=*p; do{ while(e->val(x)->val()<r.min()){ //Skipedge e->unlink();e->mark(); e=e->next_edge(); } *p=e; assert(r.min()==e->val(x)->val()); //Thisedgesmustbekept for(unsignedintj=r.width();j--;){ e->free(); p=e->next_edge_ref(); e=e->next_edge(); } ++r; }while(r()); *p=NULL; while(e!=NULL){ e->unlink();e->mark(); e=e->next_edge(); } if((m!=NULL)&&m->marked()){ //Matchinghasbeendeleted! m->val(x)->matching(NULL); rematch=true; n_matched--; } }else{ //Justfreeedges for(Edge<IntView>*e=x->val_edges();e!=NULL;e=e->next_edge()) e->free(); } } } if(rematch){ ViewNodeStackm(r,n_view); for(inti=n_view;i--;) if(!view[i]->matched()&&match(m,view[i])) n_matched++; } } forceinlinebool Graph::mark(Space&home){ usingnamespaceViewValGraph; Regionr(home); intn_view_visited=0; { //Marksalledgesasusedthatareonsimplepathsinthegraph //thatstartfromafreevaluenodebydepth-first-search Support::StaticStack<ValNode<IntView>*,Region>visit(r,n_val); //Insertallfreevaluenodes count++; { ValNode<IntView>**v=&val; while(*v!=NULL) //Isthenodefree? if(!(*v)->matching()){ //Eliminateemptyvaluenodes if((*v)->empty()){ *v=(*v)->next_val(); n_val--; }else{ (*v)->min=count; visit.push(*v); v=(*v)->next_val_ref(); } }else{ v=(*v)->next_val_ref(); } } //Invariant:onlyvaluenodesareonthestack! while(!visit.empty()){ ValNode<IntView>*n=visit.pop(); for(Edge<IntView>*e=n->edge_fst();e!=n->edge_lst(); e=e->next()){ //Istheviewnodeismatched:thepathmustbealternating! ViewNode<IntView>*x=e->view(n); if(x->matched()){ //Marktheedgeasused e->use(); if(x->min<count){ n_view_visited++; x->min=count; assert(x->edge_fst()->next()==x->edge_lst()); ValNode<IntView>*m=x->edge_fst()->val(x); x->edge_fst()->use(); if(m->min<count){ m->min=count; visit.push(m); } } } } } } if(n_view_visited<n_view){ //Markalledgesasusedstartingfromafreeviewnodeon //analternatingpathbydepth-firstsearch. Support::StaticStack<ViewNode<IntView>*,Region>visit(r,n_view); //Insertallfreeviewnodes count++; for(inti=n_view;i--;) if(!view[i]->matched()){ view[i]->min=count; visit.push(view[i]); } //Invariant:onlyviewnodesareonthestack! while(!visit.empty()){ n_view_visited++; ViewNode<IntView>*x=visit.pop(); for(Edge<IntView>*e=x->val_edges();e!=NULL;e=e->next_edge()) //Consideronlyfreeedges if(e!=x->edge_fst()){ ValNode<IntView>*n=e->val(x); //Isthereamatchededgefromthevaluenodetoaviewnode? if(n->matching()!=NULL){ e->use(); n->matching()->use(); ViewNode<IntView>*y=n->matching()->view(n); if(y->min<count){ y->min=count; visit.push(y); } } } } } if(n_view_visited<n_view){ scc(home); returntrue; }else{ returnfalse; } } forceinlineExecStatus Graph::prune(Space&home){ usingnamespaceViewValGraph; //Tellconstraintsandalsoeliminatenodesandedges for(inti=n_view;i--;){ ViewNode<IntView>*x=view[i]; if(!x->fake()){ if(x->matched()&&!x->edge_fst()->used(x)){ GECODE_ME_CHECK(x->view().eq(home,x->edge_fst()->val(x)->val())); x->edge_fst()->val(x)->matching(NULL); for(Edge<IntView>*e=x->val_edges();e!=NULL;e=e->next_edge()) e->unlink(); view[i]=view[--n_view]; }else{ IterPruneVal<IntView>pv(x); GECODE_ME_CHECK(x->view().minus_v(home,pv,false)); } } } returnES_OK; } }}} //STATISTICS:int-prop