Erlang Concurrent Montecarlo Pi估计

时间:2018-04-03 09:27:41

标签: concurrency erlang spawn montecarlo pi

对于作业,我需要使用蒙特卡罗方法估计Erlang中的pi,但是需要指定数量的actor和迭代。我有一个工作版本(改编自https://programmingpraxis.com/2009/10/09/calculating-pi/),它不使用并发,因此接受一个参数,N =迭代次数(点)。我试图通过创建另一个带有两个参数的montecarlo()函数来添加它,N =迭代次数和X = actor的数量。我无法弄清楚如何使用(伪)循环来生成每个actor。

之前的版本返回pi估计,但在我弄清楚产卵之后,我假设我必须对每个actor的返回值进行平均以进行最终的pi估计。

这就是我所拥有的:

-module(pi).
-export([montecarlo/1, montecarlo/2]).

montecarlo(N, X)->
    NumIterPerActor = N div X,
    %io:fwrite("Number of actors = ~w~n",[X]),
    %io:fwrite("Number of iterations per actor = ~w~n",[NumIterPerActor]),
    lists:seq(1, X),
    spawn(pi, montecarlo, [NumIterPerActor]).

montecarlo(N)->
    montecarlo(N,0,0).

montecarlo(0,InCircle,NumPoints)->
    PiEst = 4*InCircle / NumPoints,
    io:fwrite("Pi = ~w~n", [PiEst]);

montecarlo(N,InCircle,NumPoints)->
    Xcoord = rand:uniform(),
    Ycoord = rand:uniform(),
    montecarlo(N-1,if Xcoord*Xcoord + Ycoord*Ycoord < 1 -> InCircle + 1; true -> InCircle end,NumPoints + 1).

从研究问题开始,我已经看过使用map(),但据我所知,你在map()中创建了一个新函数,而不是使用已经实现的函数。

编辑:

我没有在截止日期前收到任何建议(我等了这么久的错误),所以我向同学寻求帮助,想出了一个递归的解决方案:

-module(pi).
-export([montecarlo/1, montecarlo/2, assign/3, compute/2, addPi/3]).

montecarlo(N, X)->
    NumIterPerActor = N div X,  %number of iterations for each actor
    io:fwrite("Number of actors = ~w~n",[X]),
    io:fwrite("Number of iterations per actor = ~w~n",[NumIterPerActor]),
    %Actors = lists:seq(1, X),   %generate desired number of actors
    %Pi1 = spawn(pi, montecarlo, [NumIterPerActor]),
    %Pi2 = spawn(pi, montecarlo, [NumIterPerActor]).
    ReceiverID = spawn(pi, addPi, [0, X, X]),
    assign(ReceiverID, X, NumIterPerActor).

assign(ReceiverID, 1, Iter)->
    spawn(pi, compute, [Iter, ReceiverID]);

assign(ReceiverID, X, Iter)->
    spawn(pi, compute, [Iter, ReceiverID]),
    assign(ReceiverID, X-1, Iter).

compute(Iter, ReceiverID)->
    Est = montecarlo(Iter),
    ReceiverID ! {Est}.

addPi(Pies, X, 0)->
    FinalPi = Pies/X,
    io:fwrite("Pi = ~w~n", [FinalPi]);

addPi(Pies, X, Rem)->
    receive
        {Estimate} ->
            addPi(Pies+Estimate, X, Rem-1)  
    end.

montecarlo(N)->
    montecarlo(N,0,0).

montecarlo(0,InCircle,NumPoints)->
    4*InCircle / NumPoints;
    %io:fwrite("Pi = ~w~n", [PiEst]);

montecarlo(N,InCircle,NumPoints)->
    Xcoord = rand:uniform(),
    Ycoord = rand:uniform(),
    montecarlo(N-1,if Xcoord*Xcoord + Ycoord*Ycoord < 1 -> InCircle + 1; true -> InCircle end,NumPoints + 1).

1 个答案:

答案 0 :(得分:1)

<input type='button' value="Approve" id="Approve" class="btn<%=details._id%>"/> <input type='button' value="Disapprove" id="Disapprove" class="btn<%=details._id%>"/> </form> <script> $(document).ready(function(){ $('.btn').on('click',function(){ var id=this.className.slice(4); $.ajax({ type:'GET', url:'/principal/leave/approval/'+id, data:{approval:this.id}, success:function(data){ alert('success'); } }); }); }); </script> 似乎非常适合你需要迭代地处理副作用,例如产生一个过程。

您可以lists:foreach/2 map/2进入NumIterPerActor列表并使用IterList迭代生成流程。

foreach/2

要回答你的上一个问题,请注意在montecarlo(N, X) -> NumIterPerActor = N div X, IterList = lists:map(fun(_) -> NumIterPerActor end, lists:seq(1, X)), lists:foreach(fun(IPA) -> spawn(?MODULE, montecarlo, [IPA]) end, IterList). map/2内你可以在lambda函数中包装任何函数调用并将相关参数传递给它。