Efficiently generating “subtraction chains”

我怕爱的太早我们不能终老 提交于 2019-12-11 12:27:07

问题


I posted another question earlier if you want some context. It appears that I was on the wrong path with that approach.

Addition chains can be used to minimize the number of multiplications needed to exponentiate a number. For example, a7 requires four multiplications. Two to compute a2=a×a and a4=a2×a2, and another two to compute a7=a4×a2×a.

Similarly, I'm trying to generate all of the possible "subtraction chains" for a set of numbers. For example, given the set of numbers {1, 2, 3}, I'm trying to generate the following permutations.

{1, 2, 3}

{1, 2, 3}, {1, 2}
{1, 2, 3}, {1, 2}, {1}
{1, 2, 3}, {1, 2}, {2}
{1, 2, 3}, {1, 2}, {1}, {2}

{1, 2, 3}, {1, 3}
{1, 2, 3}, {1, 3}, {1}
{1, 2, 3}, {1, 3}, {3}
{1, 2, 3}, {1, 3}, {1}, {3}

{1, 2, 3}, {2, 3}
{1, 2, 3}, {2, 3}, {2}
{1, 2, 3}, {2, 3}, {3}
{1, 2, 3}, {2, 3}, {2}, {3}

{1, 2, 3}, {1, 2}, {1, 3}
{1, 2, 3}, {1, 2}, {1, 3}, {1}
{1, 2, 3}, {1, 2}, {1, 3}, {2}
{1, 2, 3}, {1, 2}, {1, 3}, {3}
{1, 2, 3}, {1, 2}, {1, 3}, {1}, {2}
{1, 2, 3}, {1, 2}, {1, 3}, {1}, {3}
{1, 2, 3}, {1, 2}, {1, 3}, {2}, {3}
{1, 2, 3}, {1, 2}, {1, 3}, {1}, {2}, {3}

# and so on...

Where each element in the permutation (besides {1, 2, 3}) can be found by removing a single element from another set in the permutation.

For example, the permutation {1, 2, 3}, {1} is invalid because {1} can not be constructed by removing a single element from {1, 2, 3}.

Is there a known algorithm to find this subset of the power set of a power set? My implementation will be in Python, but the question is language agnostic. Also, I don't actually want the permutations which contain a set with a single element (e.g. {1, 2, 3}, {1, 2}, {1}) because they corresponds to a "dictator" case which is not of interest.


回答1:


An algorithm to generate all those lists as you describe it could work as follows: For each set in the current list, create a copy, remove one element, add it to the list, and call the algorithm recursively. You also have to make sure not to generate duplicates, which could by done by ensuring that the new list is "smaller" (by length or pairwise comparison of the (sorted) elements) than the previous one.

Here's an implementation in Python, as a generator function, without much optimization. This seems to work pretty well now, generating all the subsets without any duplicates.

def generate_sets(sets, min_num=2):
    yield sets
    added = set() # new sets we already generated in this iteration
    for set_ in sets:
        # only if the current set has the right length
        if min_num < len(set_) <= len(sets[-1]) + 1:
            for x in set_:
                # remove each element in turn (frozenset so we can put in into added)
                new = set_.difference({x})
                # prevent same subset being reachable form multiple sets
                frozen = frozenset(new)
                if frozen not in added:
                    added.add(frozen)
                    # recurse only if current element is "smaller" than last
                    if (len(new), sorted(new)) < (len(sets[-1]), sorted(sets[-1])):
                        for result in generate_sets(sets + [new], min_num):
                            yield result

For generate_sets([{1,2,3}], min_num=2) this generates the following lists:

[{1, 2, 3}]
[{1, 2, 3}, {2, 3}]
[{1, 2, 3}, {2, 3}, {1, 3}]
[{1, 2, 3}, {2, 3}, {1, 3}, {1, 2}]
[{1, 2, 3}, {2, 3}, {1, 2}]
[{1, 2, 3}, {1, 3}]
[{1, 2, 3}, {1, 3}, {1, 2}]
[{1, 2, 3}, {1, 2}]

For generate_sets([{1,2,3}], 1), a total of 45 lists of sets are generated.

However, I fail to see the connection to your previous question: Shouldn't {1, 2, 3}, {1, 2}, {1, 2, 3}, {1, 3}, and {1, 2, 3}, {2, 3} all be considered equivalent?



来源:https://stackoverflow.com/questions/36049630/efficiently-generating-subtraction-chains

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