Parallel power set generation in Erlang?

痴心易碎 提交于 2019-12-08 02:15:44

问题


There is a lot of example implementations of generating a powerset of a set in Java, Python and others, but I still can not understand how the actual algorithm works.

What are the steps taken by an algorithm to generate a power set P(S) of a set S?

(For example, the power set of {1,2,3,4} is {{}, {1}, {2}, {1,2}, {3}, {1,3}, {2,3}, {1,2,3}, {4}, {1,4}, {2,4}, {1,2,4}, {3,4}, {1,3,4}, {2,3,4}, {1,2,3,4}}.)

UPD: I have found this explanation, but still I don't get it. I am trying to understand the algorithm of generating a power set, because I would like to write a parallel implementation of it - the following sequential Erlang implementation has an enormous stack and can not count more than 30-elements set on a machine with 8 GB RAM:

powerset(Lst) ->
    N = length(Lst),
    Max = trunc(math:pow(2,N)),
    [[lists:nth(Pos+1,Lst) || Pos <- lists:seq(0,N-1), I band (1 bsl Pos) =/= 0] || I <- lists:seq(0,Max-1)].

UPD2:

This snippet returns all subsets of a set [a,b,c], except [a,b,c]:

generate_all_subsets([],Full_list,Result) ->
    Result;
generate_all_subsets([Element|Rest_of_list],Full_list,Result) ->
    Filtered_list = [X || X <- Full_list, X =/= Element],
    ?DBG("*Current accumulated result: ~w ~n", [Result]),
    Result2 = generate_subsets(Element,Filtered_list,[],[]),
    ?DBG("Generated new result: ~w ~n", [Result2]),
    New_result = lists:append(Result,Result2),
    ?DBG("Got new accumulated result: ~w ~n", [New_result]),
    generate_all_subsets(Rest_of_list,Full_list,New_result).



generate_subsets(Main_element,[],Accumulated_list,Result) ->
    Result;
generate_subsets(Main_element,[Element|Rest_of_set],Accumulated_list,Result) ->
    ?DBG("*Generating a subset for ~w ~n", [Main_element]),
    New_accumulated_list = lists:flatten([Element|Accumulated_list]),
    New_result = [New_accumulated_list|Result],
    ?DBG("Added ~w to the result: ~w ~n", [New_accumulated_list,New_result]),
    generate_subsets(Main_element,Rest_of_set,New_accumulated_list,New_result).

I am not sure if this snippet is correct.


回答1:


Here is pretty simple version which performs far better than version from rosettacode:

generate([]) -> [[]];
generate([H|T]) -> PT = generate(T),
  [ [H|X] || X <- PT ] ++ PT.

if you want even better performance you can try this:

generate([]) -> [[]];
generate([H|T]) -> PT = generate(T),
  generate(H, PT, PT).

generate(_, [], Acc) -> Acc;
generate(X, [H|T], Acc) -> generate(X, T, [[X|H]|Acc]).

But anyway I doubt if you will be able construct powerset of 30 elements set. According mine calculation it could consume more than 16GB. There can be some reusing of lists tails in mine second version but it would not help enough. I think you can even fail to bigger issue if you will implement it as parallel algorithm because there will be message copying.



来源:https://stackoverflow.com/questions/7967527/parallel-power-set-generation-in-erlang

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!