我想在Erlang中做一些像这样的数字:
你有一个包含以下值的数组:
[2,3,4]
在每次迭代中,您计算
0.1 * [n-1] + 0.7 *[n] + 0.2 * [n+1]
这成为new [n]
。
If n == 0 then [n-1] = 0. If [n] == length of array then [n] = 0.
所以我试了一个例子:
[2,3,4]
计算:
0.1 * 0 + 0.7 * 2 + 0.2 * 3 = 2
0.1 * 2 + 0.7 * 3 + 0.2 * 4 = 3.1
0.1 * 3 + 0.7 * 4 + 0.2 * 0 = 3.1
所以[2,3,4]
在一次迭代后变为[2, 3.1, 3.1]
。
我知道如何用像C这样的非功能性语言来写这个。 但我很难想象,如何在Erlang中完成。 我找到了一些关于如何将文件读入列表的教程。所以这 不是问题。
如何生成不同的Erlang进程,每个进程都有一个列表元素? 如何通过与“邻居”进行交流来进行计算,以便邻居知道他们的邻居在哪里,而不指定每个? 如何将数据收集到列表中?
最终,是否有可能在Erlang中解决这个问题?
感谢您的帮助。
答案 0 :(得分:3)
回答原始问题:
-module(simulation).
-export([start/0]).
f([N0, N1, N2]) ->
M0 = 0.7 * N0 + 0.2 * N1,
M1 = 0.1 * N0 + 0.7 * N1 + 0.2 * N2,
M2 = 0.1 * N1 + 0.7 * N2,
[M0, M1, M2].
iterate(List, Iterations) ->
iterate(1, List, Iterations).
iterate(_Iteration, List, 0) ->
List;
iterate(Iteration, List = [N0, N1, N2], MoreIterations) ->
io:format("~.5f ~.5f ~.5f~n", [N0, N1, N2]),
NextList = f(List),
iterate(Iteration + 1, NextList, MoreIterations-1).
start() ->
iterate([2.0, 3.0, 4.0], 10),
ok.
任意列表长度的广义答案:
-module(simulation2).
-export([start/0]).
f(Prev, Current, Next) ->
0.1 * Prev + 0.7 * Current + 0.2 * Next.
transform(List) ->
transform(0.0, List, 0.0).
transform(_First, [], _Last) ->
[];
transform(First, [X], Last) ->
Y = f(First, X, Last),
[Y];
transform(First, [X1, X2 | More], Last) ->
Y1 = f(First, X1, X2),
[Y1 | transform(X1, [X2 | More], Last)].
iterate(List, Iterations) ->
iterate(1, List, Iterations).
iterate(_Iteration, List, 0) ->
List;
iterate(Iteration, List, MoreIterations) ->
io:format("~p~n", [List]),
NextList = transform(List),
iterate(Iteration + 1, NextList, MoreIterations-1).
start() ->
iterate([1.0, 2.0, 3.0, 4.0, 5.0], 10),
ok.
答案 1 :(得分:1)
迭代模式很棒。但是,如果列表中的元素多于三个并且每个成员都需要他的邻居,那么你会怎么做?这个例子会更有活力。 功能编程是一种不同的思维方式。但我认为 - 作为一个新手 - 它具有与C相同的潜力。 当我想写的时候,我该怎么办:
start() ->
iterate([2.0, 3.0, 4.0, 5.0, ...], 10),
ok.
感谢你的所有提示。他们真的很有帮助。 我正在做这个模拟只是为了好玩:)。我在C中进行了这样的模拟。我只是想知道它是否能在Erlang中动态运行。
答案 2 :(得分:0)
这绝对是可能的(但如果你想做的是纯粹的数值计算,你可能想重新考虑,除非你正在进行智力练习 - 或者你可以看看使用像http://discoproject.org/这样的框架)。
但是,你似乎还没有完全掌握在Erlang中使用进程编程的基本技术,所以我建议你从这开始。 (例如,获取Joe Armstrong的书并使用这些例子。)一旦你进入它 - 这不需要很长时间 - 你应该不会有很多麻烦找出构建这样一个程序的一些不同方法。
答案 3 :(得分:0)
我会尝试标准功能模式来处理列表
iter([], Acc) ->
lists:reverse(Acc);
iter([H|Tail], Acc) ->
iter(Tail, [do_something_with(H)|Acc]).
并将其扩展为在其模式中使用三个值,以处理公式处理为新值的三个值:
...
iter([H1,H2,H3|Tail], Acc) ->
iter([H2,H3|Tail], [do_something_with(H1,H2,H3)|Acc]);
...
当然,这需要一些额外的函数子句来正确处理列表的开头和结尾。
答案 4 :(得分:0)
我尝试了一些东西,但失败了。下面的代码应该为每个列表元素生成一个进程,但不知怎的,如果我给它一个4个元素的列表,它将不会停止创建进程,然后崩溃。错误 - 我认为 - 发生的部分标有%BUG。 模拟:模拟/ 2开始一切,即模拟:模拟([1,2,3,4],7),其中7是迭代次数。编号为0的元素是单独创建的,因为它永远不会更改它的值。进程应该获得前一个和下一个邻居的PID,以便它们可以交换它们的值。我尝试使用debuger im()调试它。但它崩溃了。我看到创建了太多进程。不知怎的,我现在没有发现错误。也许你注意到一些完全错误的东西?
-module(simulation).
-compile(export_all).
%-export().
f(Prev, Current, Next) ->
0.1 * Prev + 0.7 * Current + 0.2 * Next.
simulate([], _Iteration) -> [];
simulate([X], 0) -> [X];
simulate([X], Iteration) -> simulate([f(0.0, X, 0.0)], Iteration - 1);
simulate(Liste, 0) -> Liste;
simulate(Liste, Iteration) ->
PidStarter = self(),
{Number, ProcList} = startProcesses(Liste, Iteration, PidStarter), %BUG
Connector = spawn(fun() -> simProcessStarter(0.0, PidStarter, Iteration, 0) end), %untested
[H1, H2 | _] = ProcList,
H1 ! {startinformation, Connector, H2}, %untested
ReversedProcList = lists:reverse(ProcList),
[L1, L2 | _] = ReversedProcList,
L1 ! {startinformation, L2, Connector},%untested
fold(ProcList),%untested
evaluate(Number, []).%untested
fold([]) -> ready;
fold([_X1]) -> ready;
fold([_X1, _X2]) -> ready;
fold([X1, X2, X3 | Tail]) ->
X2 ! {statusinformation, X1, X3},
fold([X2, X3 | Tail]).
evaluate(0, List) ->
List;
evaluate(N, List) ->
receive
{N, Current} ->
Result = [Current | List]
end,
evaluate(N-1, Result).
% returns {number of processes, list of processes started}
startProcesses(Liste, Iteration, PidStarter) -> startProcesses(Liste, 0, Iteration, [], PidStarter).
startProcesses([], N, _Iteration, List, _PidStarter) -> {N, lists:reverse(List)};
startProcesses([H | T], N, Iteration, List, PidStarter) ->
startProcesses([T], N + 1, Iteration, [spawn(fun() -> simProcessStarter(H, PidStarter, Iteration, N + 1) end) | List], PidStarter).
simProcessStarter(Current, PidStarter, Iteration, Number) ->
receive
{startinformation, PidPrev, PidNext} ->
Result = simProcess(Current, PidPrev, self(), PidNext, Iteration, Number)
end,
PidStarter ! Result.
simProcess(Current, _PidPrev, _PidCurrent, _PidNext, 0, Number) ->
{Number, Current};
simProcess(Current, PidPrev, PidCurrent, PidNext, Iteration, Number) ->
PidNext ! {prev, PidCurrent, Current, Iteration},
receive
{prev, PidPrev, Prev, Iteration} -> Prev
end,
PidPrev ! {next, PidCurrent, Current, Iteration},
receive
{next, PidNext, Next, Iteration} -> Next
end,
New = f(Prev, Current, Next),
simProcess(New, PidPrev, PidCurrent, PidNext, Iteration-1, Number).