123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352openCommon2openCommon(*****************************************************************************)(* coded for LFS *)(* todo: could take an incr/decr func in param, to make it generic
* opti: remember the min/max (optimisation to have intersect biggest x -> x)
* opti: avoid all those rev, and avoid the intervise
* (but yes the algo are then more complex :)
* opti: balanced set intervalle
*)(*****************************************************************************)typeseti=eltlist(* last elements is in first pos, ordered reverse *)andelt=Exactofint|Intervofint*int(* invariant= ordered list, no incoherent interv (one elem or zero elem),
* merged (intervalle are separated) *)letinvariantxs=letrecauxminxs=xs|>List.fold_left(funmine->matchewith|Exacti->ifi<=minthenpr2(spf"i = %d, min = %d"imin);(* todo: should be even stronger, shoud be i > min+1 *)assert(i>min);i|Interv(i,j)->assert(i>min);assert(j>i);j)mininignore(auxmin_int(List.revxs));()letstring_of_setixs="["^join","(xs|>List.rev|>List.map(function|(Exacti)->string_of_inti|(Interv(i,j))->Printf.sprintf"%d - %d"ij))^"]"(*****************************************************************************)letempty=[]letpacknewij=function|[]->[Interv(newi,j)]|(Exactz)::xs->(Interv(newi,j))::(ifnewi=|=zthenxselse(Exactz)::xs)|(Interv(i',j'))::xs->ifnewi=|=j'then(Interv(i',j))::xs(* merge *)else(Interv(newi,j))::(Interv(i',j'))::xs(* the only possible merges are when x = i-1, otherwise, the job is done before *)letrec(add2:int->seti->seti)=funx->function|[]->[Exactx]|(Exacti)::xswhenx>i+1->(Exactx)::(Exacti)::xs|(Interv(i,j)::xs)whenx>j+1->(Exactx)::(Interv(i,j))::xs|(Interv(i,j)::xs)whenx=|=j+1->(Interv(i,x))::xs|(Exacti)::xswhenx=|=i+1->(Interv(i,x))::xs|(Exacti)::xswheni=|=x->(Exacti)::xs|(Interv(i,j)::xs)whenx<=j&&x>=i->(Interv(i,j))::xs|other->(* let _ = log "Cache miss" in *)let_=Common2.count2()in(matchotherwith|(Exacti)::xswhenx=|=i-1->packxixs|(Exacti)::xswhenx<i-1->(Exacti)::addxxs|(Interv(i,j)::xs)whenx=|=i-1->packxjxs|(Interv(i,j)::xs)whenx<i-1->(Interv(i,j))::addxxs|_->raiseImpossible)andaddxy=let_=Common2.count5()inadd2xyletrectolist2=function|[]->[]|(Exacti)::xs->i::tolist2xs|(Interv(i,j))::xs->Common2.enumij@tolist2xsletrectolistxs=List.rev(tolist2xs)letrecfromlist=functionxs->List.fold_left(funae->addea)emptyxsletintervise=function|Exactx->Interv(x,x)|y->yletexactize=function|Interv(i,j)wheni=|=j->Exacti|y->yletexactize2xy=ifx=|=ythenExactxelseInterv(x,y)letrec(remove:int->seti->seti)=funxxs->matchxswith|[]->[](* pb, not in *)|(Exactz)::zs->(matchx<=>zwith|Equal->zs|Sup->xs(* pb, not in *)|Inf->(Exactz)::removexzs)|(Interv(i,j)::zs)->ifx>jthenxs(* pb not in *)elseifx>=i&&x<=jthen(let_=assert(j>i)in(* otherwise can lead to construct seti such as [7,6] when removing 6 from [6,6] *)match()with|_whenx=|=i->[exactize2(i+1)j]|_whenx=|=j->[exactize2i(j-1)]|_->[exactize2(x+1)j;exactize2i(x-1)])@zselse(Interv(i,j))::removexzs(* let _ = Example (remove 635 [Interv (3, 635)] = [Interv (3, 634)]) *)(* let _ = Example (remove 2 [Interv (6, 7); Interv(1,4)] = [Interv (6,7); Interv (3,4); Exact 1]) *)(* let _ = Example (remove 6 [Interv (6, 7); Interv(1,4)] = [Exact 7; Interv (1,4)]) *)(* let _ = Example (remove 1 [Interv (6, 7); Interv(1,2)] = [Interv (6,7); Exact 2]) *)(* let _ = Example (remove 3 [Interv (1, 7)] = [Interv (4,7); Interv (1,2)]) *)let_=assert_equal(remove3[Interv(1,7)])[Interv(4,7);Interv(1,2)]let_=assert_equal(remove4[Interv(3,4)])[Exact(3);](* let _ = example (try (ignore(remove 6 [Interv (6, 6)] = []); false) with _ -> true) *)letrecmeme=function|[]->false|(Exactx)::xs->(matche<=>xwith|Equal->true|Sup->false|Inf->memexs)|(Interv(i,j)::xs)->ife>jthenfalseelseife>=i&&e<=jthentrueelsememexsletiterfxs=xs|>List.iter(function|Exacti->fi|Interv(i,j)->fork=itojdofkdone)letis_emptyxs=xs=*=[]letchoose=function|[]->failwith"not supposed to be called with empty set"|(Exacti)::xs->i|(Interv(i,j))::xs->iletelementsxs=tolistxsletreccardinal=function|[]->0|(Exact_)::xs->1+cardinalxs|(Interv(i,j)::xs)->(j-i)+1+cardinalxs(*****************************************************************************)(* TODO: could return corresponding osetb ? *)letrecinterxsys=letrecaux=funxsys->match(xs,ys)with|(_,[])->[]|([],_)->[]|(x::xs,y::ys)->(match(x,y)with|(Interv(i1,j1),Interv(i2,j2))->(matchi1<=>i2with|Equal->(matchj1<=>j2with|Equal->(Interv(i1,j1))::auxxsys(* [ ] *)(* [ ] *)|Inf->(Interv(i1,j1))::auxxs((Interv(j1+1,j2))::ys)(* [ ] [ TODO? could have [ so cant englobe right now, but would be better *)(* [ ] *)|Sup->(Interv(i1,j2))::aux((Interv(j2+1,j1))::xs)ys(* [ ] *)(* [ ] [ same *))|Inf->ifj1<i2thenauxxs(y::ys)(* need order ? *)(* [ ] *)(* [ ] *)else(matchj1<=>j2with|Equal->(Interv(i2,j1))::auxxsys(* [ ] *)(* [ ] *)|Inf->(Interv(i2,j1))::auxxs((Interv(j1+1,j2))::ys)(* [ ] [ same *)(* [ ] *)|Sup->(Interv(i2,j2))::aux((Interv(j2+1,j1))::xs)ys(* [ ] *)(* [ ] [ same *))|Sup->aux(y::ys)(x::xs)(* can cos commutative *))|_->raiseImpossible(* intervise *))in(* TODO avoid the rev rev, but aux good ? need order ? *)List.rev_mapexactize(aux(List.rev_mapintervisexs)(List.rev_mapinterviseys))letunionxsys=letrecaux=funxsys->match(xs,ys)with|(vs,[])->vs|([],vs)->vs|(x::xs,y::ys)->(match(x,y)with|(Interv(i1,j1),Interv(i2,j2))->(matchi1<=>i2with|Equal->(matchj1<=>j2with|Equal->(Interv(i1,j1))::auxxsys(* [ ] *)(* [ ] *)|Inf->(Interv(i1,j1))::auxxs((Interv(j1+1,j2))::ys)(* [ ] [ TODO? could have [ so cant englobe right now, but would be better *)(* [ ] *)|Sup->(Interv(i1,j2))::aux((Interv(j2+1,j1))::xs)ys(* [ ] *)(* [ ] [ same *))|Inf->ifj1<i2thenInterv(i1,j1)::auxxs(y::ys)(* [ ] *)(* [ ] *)else(matchj1<=>j2with|Equal->(Interv(i1,j1))::auxxsys(* [ ] *)(* [ ] *)|Inf->(Interv(i1,j1))::auxxs((Interv(j1+1,j2))::ys)(* [ ] [ same *)(* [ ] *)|Sup->(Interv(i1,j2))::aux((Interv(j2+1,j1))::xs)ys(* [ ] *)(* [ ] [ same *))|Sup->aux(y::ys)(x::xs)(* can cos commutative *))|_->raiseImpossible(* intervise *))in(* union_set (tolist xs) (tolist ys) +> fromlist *)List.rev_mapexactize(aux(List.rev_mapintervisexs)(List.rev_mapinterviseys))(* bug/feature: discovered by vlad rusu, my invariant for intervalle is
* not very strong, should return (Interv (1,4)) *)(* let _ = Example (union [Interv (1, 4)] [Interv (1, 3)] = ([Exact 4; Interv (1,3)])) *)letdiffxsys=letrecaux=funxsys->match(xs,ys)with|(vs,[])->vs|([],vs)->[]|(x::xs,y::ys)->(match(x,y)with|(Interv(i1,j1),Interv(i2,j2))->(matchi1<=>i2with|Equal->(matchj1<=>j2with|Equal->auxxsys(* [ ] *)(* [ ] *)|Inf->auxxs((Interv(j1+1,j2))::ys)(* [ ] *)(* [ ] *)|Sup->aux((Interv(j2+1,j1))::xs)ys(* [ ] *)(* [ ] *))|Inf->ifj1<i2thenInterv(i1,j1)::auxxs(y::ys)(* [ ] *)(* [ ] *)else(matchj1<=>j2with|Equal->(Interv(i1,i2-1))::auxxsys(* -1 cos exlude [ *)(* [ ] *)(* [ ] *)|Inf->(Interv(i1,i2-1))::auxxs((Interv(j1+1,j2))::ys)(* [ ] *)(* [ ] *)|Sup->(Interv(i1,i2-1))::aux((Interv(j2+1,j1))::xs)ys(* [ ] *)(* [ ] *))|Sup->ifj2<i1thenaux(x::xs)ys(* [ ] *)(* [ ] *)else(matchj1<=>j2with|Equal->auxxsys(* [ ] *)(* [ ] *)|Inf->auxxs((Interv(j1+1,j2))::ys)(* [ ] *)(* [ ] *)|Sup->aux((Interv(j2+1,j1))::xs)ys(* [ ] *)(* [ ] *)))|_->raiseImpossible(* intervise *))in(* minus_set (tolist xs) (tolist ys) +> fromlist *)List.rev_mapexactize(aux(List.rev_mapintervisexs)(List.rev_mapinterviseys))(* let _ = Example (diff [Interv (3,7)] [Interv (4,5)] = [Interv (6, 7); Exact 3]) *)(*****************************************************************************)letrecdebug=function|[]->""|(Exacti)::xs->(Printf.sprintf"Exact:%d;"i)^(debugxs)|(Interv(i,j)::xs)->(Printf.sprintf"Interv:(%d,%d);"ij)^debugxs(*****************************************************************************)(* if operation return wrong result, then may later have to patch them *)letpatch1xs=List.mapexactizexsletpatch2xs=xs|>List.map(fune->matchewith|Interv(i,j)wheni>j&&i=|=j+1->let_=pr2(spf"i = %d, j = %d"ij)inExacti|e->e)letpatch3xs=letrecauxminxs=xs|>List.fold_left(fun(min,acc)e->matchewith|Exacti->ifi=|=minthen(min,acc)else(i,(Exacti)::acc)|Interv(i,j)->(j,(Interv(i,j)::acc)))(min,[])inauxmin_int(List.revxs)|>snd