Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file mcop.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189(******************************************************************************)(* *)(* Menhir *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under *)(* the terms of the GNU General Public License version 2, as described in *)(* the file LICENSE. *)(* *)(******************************************************************************)typeproblem=intarraytype'asolution=|Matrixof'a|Productof'asolution*'asolutionletrecmap_solutionf=function|Matrixx->Matrix(fx)|Product(t,u)->lett'=map_solutionftinletu'=map_solutionfuinProduct(t',u')exceptionEmpty(** Try to handle trivial cases before falling back to smart algorithms. *)lettrivial_cases=function|[||]|[|_|]->raiseEmpty(* One or two matrices, one solution *)|[|_;_|]->Some(Matrix0)|[|_;_;_|]->Some(Product(Matrix0,Matrix1))|[|a;b;c;d|]->(* Three matrices, two possible solutions.
One test is sufficient. *)letcost_AB_C=a*b*c+a*c*dinletcost_A_BC=a*b*d+b*c*dinifcost_AB_C<cost_A_BCthenSome(Product(Product(Matrix0,Matrix1),Matrix2))elseSome(Product(Matrix0,Product(Matrix1,Matrix2)))|_->None(* Left-leaning tree *)letleft_solutionarr=letlen=Array.lengtharriniflen<=1thenraiseEmpty;letsolution=ref(Matrix0)infori=1tolen-1dosolution:=Product(!solution,Matrixi)done;!solution(* Right-leaning tree *)letright_solutionarr=letlen=Array.lengtharriniflen<=1thenraiseEmpty;letsolution=ref(Matrix(len-1))infori=len-2downto0dosolution:=Product(Matrixi,!solution)done;!solution(* Francis Chin O(n) approximation *)(** Returns the index of the biggest float in the array *)letargmax(a:floatarray):int=leti=ref0inletm=refa.(0)inforj=1toArray.lengtha-1doletm'=a.(j)inifm'>!mthenbegini:=j;m:=m';enddone;!i(** Returns the permutation vector corresponding to problem [k] *)letapprox_vector(k:problem)=(* k.(0..n) *)letn=Array.lengthk-1in(* v.(0..n-2) *)letv=Array.make(n-1)0in(* r.(0..n) *)letr=Array.map(funk_i->1.0/.floatk_i)kin(* 0 <= m <= n, r_m = r.(m) *)letm=argmaxrinletr_m=r.(m)inletc=ref1inletj=ref0inlets=Array.make(n+1)0in(*Printf.printf "n=%d\n" n;*)fori=1ton-1doincrj;s.(!j)<-i;while!j>0&&r.(s.(!j))+.r_m<r.(s.(!j-1))+.r.(i+1)do(*Printf.printf "j=%d s(j)=%d\n" !j s.(!j);*)v.(s.(!j)-1)<-!c;incrc;decrj;done;done;letb=ref(n-1)inincrj;(*Printf.printf "j=%d " !j;*)(*Printf.printf "s(j)=%d\n" s.(!j);*)s.(!j)<-n;letk=ref0inletstop=reffalseinwhilenot!stopdoifr.(s.(!k))<r.(s.(!j))thenbeginifr.(s.(!j))+.r_m<r.(s.(!j-1))+.r.(s.(!k))thenbegindecrj;v.(s.(!j)-1)<-!b;decrb;endelseifr.(s.(!k))+.r_m<r.(s.(!k+1))+.r.(s.(!j))thenbeginincrk;(*Printf.printf "k=%d " !k;*)(*Printf.printf "s(k)=%d " s.(!k);*)(*Printf.printf "b=%d\n" !b;*)ifs.(!k)<nthenv.(s.(!k)-1)<-!b;decrb;endelsestop:=trueendelsestop:=truedone;fori=m-1downtos.(!k)+1doifv.(i-1)=0thenbeginv.(i-1)<-!c;incrcenddone;fori=m+1tos.(!j)-1doifv.(i-1)=0thenbeginv.(i-1)<-!c;incrcenddone;ifm>0&&m<n&&v.(m-1)=0thenv.(m-1)<-!c;v(* Parse the permutation vector produced by the approximation using
a variant of shunting-yard algorithm *)letapprox_parse_vectororder=letrecpop(n:int)x=function|(n',x')::xswhenn'<=n->popn(Product(x',x))xs|other->(n,x)::otherinletpush(i,stack)v=(i+1,popv(Matrixi)stack)inletclose(i,stack)=snd(List.hd(popmax_int(Matrixi)stack))inletfinal_stack=Array.fold_leftpush(0,[])orderinclosefinal_stackletapprox_solutiondims=matchtrivial_casesdimswith|Somesolution->solution|None->approx_parse_vector(approx_vectordims)(* Optimal solution, O(n^3) using dynamic programming *)(** Returns the solution matrix for problem [dims] *)letdynamic_matrix(dims:problem)=letn=Array.lengthdims-1inletm=Array.make_matrixnn0inlets=Array.make_matrixnn0inforlen=1ton-1dofori=0ton-len-1doletj=i+leninm.(i).(j)<-max_int;fork=itoj-1doletcost=m.(i).(k)+m.(k+1).(j)+dims.(i)*dims.(k+1)*dims.(j+1)inifcost<m.(i).(j)thenbeginm.(i).(j)<-cost;s.(i).(j)<-k;enddonedonedone;sletdynamic_parse_matrixs=letrecloopij=ifi<>jthen(leti_s=loopis.(i).(j)inlets_j=loop(s.(i).(j)+1)jinProduct(i_s,s_j))elseMatrixiinloop0(Array.lengths-1)letdynamic_solutiondims=matchtrivial_casesdimswith|Somesolution->solution|None->dynamic_parse_matrix(dynamic_matrixdims)