Erlang-蒙特卡洛方法求Pi

来源:互联网 发布:淘宝返现软件哪个好 编辑:程序博客网 时间:2024/05/17 02:50

这里面有两种方法,核数为2的幂见代码1,核数不为2的幂见代码2.
代码1:

-module(exe5_2).-export([start/2]).%Points 是投掷点的个数 Cores是核数,为2的幂start(Points,Cores)    ->spawn(fun()->parent_proces(Points,Cores) end),    io:format("").parent_proces(Points,Cores) ->        PointsPerProcess = Points div Cores,        creat_child_proces(Points,PointsPerProcess,Cores,Cores,[]).%创建子进程creat_child_proces(Points,PointsPerProcess,Cores,N,L)       when N =:=1 ->       Pid = spawn(fun()->process_points(Points,Points-PointsPerProcess*(Cores-1)) end),        Father = self(),      PidR = spawn(fun()->loop_control(Father,0,Cores,2) end),      sendInfo(L++[Pid]++[PidR],1,Cores,2,Cores);creat_child_proces(Points,PointsPerProcess,Cores,N,L)      ->Pid=spawn(fun()->process_points(Points,PointsPerProcess) end),        creat_child_proces(Points,PointsPerProcess,Cores,N-1,L++[Pid]).%计算命中的点 process_points(Points,PointsPerProcess) ->    apply(random, seed, tuple_to_list(now())),    Count = test_points(PointsPerProcess, 0),    io:format("~p 's result is ~p~n",[self(),Count]),    loop_send_get(Points,Count).test_points(0, Count) -> Count;test_points(PointsPerProcess, Count) ->    X = (random:uniform() * 2) - 1,    Y = (random:uniform() * 2) - 1,    I = X*X + Y*Y,    if        I < 1 ->            test_points(PointsPerProcess - 1, Count + 1);        true ->            test_points(PointsPerProcess - 1, Count)    end.%子进程部分和的发送和接收,由主进程sendInfo方法控制loop_send_get(Points,Sum) ->        receive                 {From,Sum1,Father,PidR} ->                        io:format("~p from ~p to ~p result is ~p ~n",[Sum1,From,self(),Sum1+Sum]),                        PidR!{"ok"},                        loop_send_get(Points,Sum+Sum1);                {Pid,Father,PidR} ->                        Pid!{self(),Sum,Father,PidR};                {"getRes"} ->Res=(Sum/Points)*4,                            io:format("Pi:~p~n",[Res])        end.%控制每一轮迭代求和的次数,N为一轮迭代中求和的次数,初始值为0,Divisor为控制变量,初始值为2loop_control(Father,N,Cores,Divisor) ->%io:format("N:~p Divisor:~p~n",[N,Divisor]),        if            Cores =:= N*Divisor ->                                Father!{self(),"over"},                                loop_control(Father,0,Cores,Divisor*2);            true ->                    receive                        {"ok"} ->   loop_control(Father,N+1,Cores,Divisor)                    end        end.sendInfo(PidList,N,Cores,Divisor,Dsum) ->%io:format("Pidlist:~p ~nN:~p Cores:~p Divisor:~p Dsum:~p ~n",[PidList,N,Cores,Divisor,Dsum]),                                        Nt = erlang:trunc(N),            if                Divisor =:= 2*Dsum -> Pid_1=lists:nth(1,PidList),                                      Sum=Pid_1!{"getRes"};                Nt > Cores ->                        receive                            {From,"over"} ->sendInfo(PidList,1,Cores-Divisor/2,Divisor*2,Dsum)                        end;                Nt rem Divisor =:= 1 ->                        sendInfo(PidList,N+Divisor/2,Cores,Divisor,Dsum);                Nt rem Divisor =/= 1 ->                        Pid_send = lists:nth(Nt,PidList),                        Pid_get = lists:nth(erlang:trunc(Nt-Divisor/2),PidList),%io:format("send:~p get:~p~n",[Pid_send,Pid_get]),                        Pid_send!{Pid_get,self(),lists:nth(erlang:trunc(Dsum+1),PidList)},                        sendInfo(PidList,N+Divisor/2,Cores,Divisor,Dsum)                     end.

代码2:

-module(exe5_4).-export([main/2]).%Points投掷点的总数 Core为核数,任意值main(Points,CoreNum) ->                 SumDie=temp(CoreNum,1),                 PointsPerProcess = Points div CoreNum,                 createP(1,CoreNum,SumDie,Points,PointsPerProcess),                 io:format("").temp(Num,SNum) when Num =< SNum -> SNum;temp(Num,SNum) -> temp(Num,SNum*2).createP(N,CoreNum,SumDie,Points,PointsPerProcess) when N =:= CoreNum ->                register(integer_to_atom(N),spawn(fun()->process_points(Points,N,2,CoreNum,SumDie,Points,Points-PointsPerProcess*(CoreNum-1)) end));createP(N,CoreNum,SumDie,Points,PointsPerProcess) ->                register(integer_to_atom(N),spawn(fun()->process_points(Points,N,2,CoreNum,SumDie,Points,PointsPerProcess) end)),               createP(N+1,CoreNum,SumDie,Points,PointsPerProcess).integer_to_atom(Int) -> T=integer_to_binary(Int),                        binary_to_atom(T,utf8).%计算命中的点 process_points(Points,N,Die,CoreNum,SumDie,Points,PointsPerProcess) ->  apply(random, seed, tuple_to_list(now())),  Count = test_points(PointsPerProcess, 0),  io:format("~p 's result is ~p~n",[self(),Count]),  loop(Points,N,Die,SumDie,CoreNum,Count).test_points(0, Count) -> Count;test_points(PointsPerProcess, Count) ->  X = (random:uniform() * 2) - 1,  Y = (random:uniform() * 2) - 1,  I = X*X + Y*Y,  if    I < 1 ->      test_points(PointsPerProcess - 1, Count + 1);    true ->      test_points(PointsPerProcess - 1, Count)  end.%每个core 收发信息loop(Points,Number,Die,SumDie,CoreNum,Count) ->    if        Die =:= SumDie*2 -> Res = (Count/Points)*4,                        io:format("Pi=~p~n",[Res]);      true -> [H|L]=judge(CoreNum,Number,Die),            if                H =:= 1 -> [H2|_]=L,                        {send,To,DieThat}=H2,                       (integer_to_atom(To))!{Number,DieThat,Count};                true -> [H2|_]=L,                    {get,From,DieThat}=H2,                    receive                        {From,DieThat,Count1} -> io:format("~p ~p get info from ~p,the result is ~p~n",[Count1,Number,From,Count+Count1]),                                    loop(Points,Number,Die*2,SumDie,CoreNum,Count1+Count)                    end            end     end.%判断每核的收发judge(SumCore,Number,Die) -> R=lslast(SumCore,Number,Die),   if      R =:= 1 ->         if            Number rem Die =:= 1 -> {DieThat,To}=find(Number,Die),                                    [1,{send,To,DieThat}];            true -> [1,{send,Number-erlang:trunc(Die/2),Die}]         end;      true ->          if            Number rem Die =:= 1 -> [0,{get,Number+erlang:trunc(Die/2),Die}];            true -> [1,{send,Number-erlang:trunc(Die/2),Die}]         end   end.%判断最后一核信息发送给哪里find(Number,Die) -> Current_order=ceil(Number*2/Die),   if      Current_order rem 2 =:= 0 -> {Die,Number-erlang:trunc(Die/2)};      true -> find(Number,Die*2)   end.%计算live的核在本轮迭代中的序号,若为最后一个标记为1.lslast(SumCores,Number,Die) -> Current_order=ceil(Number*2/Die),                                Sum_order=ceil(SumCores*2/Die),                               io:format("~p ~p ~p ~p ~p~n",[SumCores,Number,Die,Current_order,Sum_order]),      if         Current_order =:= Sum_order -> 1;         true -> 0      end.%对小数取上界,比如ceil(15.1)=16ceil(N) -> T=trunc(N),           Temp = N-T,   case Temp =:= 0.000 of      true -> T;      false -> T+1   end.
0 0
原创粉丝点击