专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > Erlang

Erlang-蒙特卡洛步骤求Pi

发布时间:2011-06-29 17:48:34 文章来源:www.iduyao.cn 采编人员:星星草
Erlang-蒙特卡洛方法求Pi
-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为控制变量,初始值为2
loop_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.
友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: