首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Erlang并发Montecarlo Pi估计

Erlang并发Montecarlo Pi估计
EN

Stack Overflow用户
提问于 2018-04-03 09:27:40
回答 1查看 153关注 0票数 1

对于赋值,我需要使用Montecarlo方法估计Erlang中的pi值,但要使用指定数量的参与者和迭代。我有一个工作版本(改编自https://programmingpraxis.com/2009/10/09/calculating-pi/),它不使用并发性,因此使用一个参数,N=迭代次数(点数)。我试图通过创建另一个montecarlo()函数来添加它,该函数包含两个参数,迭代的N=#和参与者的X=#。我很难弄清楚如何使用(伪)循环来生成每个演员。

上一个版本返回pi估计,但是在我计算出产卵量之后,我假设我必须对每个参与者的返回值进行平均值,以进行最后的pi估计。

以下是我所拥有的:

代码语言:javascript
复制
-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()内部创建一个新函数,而不是使用已经实现的函数。

编辑:

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

代码语言:javascript
复制
-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).
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-05 18:20:47

当您需要迭代地执行一些附带副作用的操作时,lists:foreach/2似乎是一个很好的选择,比如生成一个过程。

您可以将map/2 NumIterPerActor放入IterList列表中,并使用foreach/2迭代地在其上生成进程。

代码语言:javascript
复制
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/2foreach/2中,您可以在lambda函数中包装任何函数调用,并将相关参数传递给它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49626598

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档