Quel algorithme peut calculer l'ensemble de puissance d'un ensemble donné?

je voudrais générer efficacement une liste unique de combinaisons de nombres basée sur une liste de départ de nombres.

exemple de début list = [1,2,3,4,5] mais l'algorithme doit travailler pour [1,2,3...n]

result = 

[1],[2],[3],[4],[5]
[1,2],[1,3],[1,4],[1,5]
[1,2,3],[1,2,4],[1,2,5]
[1,3,4],[1,3,5],[1,4,5]
[2,3],[2,4],[2,5]
[2,3,4],[2,3,5]
[3,4],[3,5]
[3,4,5]
[4,5]

Remarque. Je ne veux pas de combinaisons en double, bien que je puisse vivre avec, par exemple dans l'exemple ci-dessus je n'ai pas vraiment besoin de la combinaison [1,3,2] parce qu'elle présente déjà comme [1,2,3]

22
demandé sur Abhi 2010-05-06 10:58:41

7 réponses

Il y a un nom pour ce que vous demandez. Il est appelé le puissance.

recherche sur Google pour "la puissance de l'algorithme" m'a conduit à cette solution récursive.

Algorithme De Ruby

def powerset!(set)
   return [set] if set.empty?

   p = set.pop
   subset = powerset!(set)  
   subset | subset.map { |x| x | [p] }
end

L'Intuition Du Jeu De Puissance

Si S = (a, b, c) alors groupe motopropulseur(S) est l'ensemble de tous les sous-ensembles groupe motopropulseur(S) = {(), (a), (b), (c), (a,b), (a,c), (b,c), (a,b,c)}

Le premier "truc" est de essayez d' définir de façon récursive.

quel serait un État d'arrêt?

S = () a ce que groupe motopropulseur (s)?

Comment get?

Réduire fixé par un élément

Envisager de prendre un élément dans l'exemple ci-dessus, de prendre {c}

S = (a,b) then groupe motopropulseur (S) = {(), (a), (b), (A,b)}

Qu'est-ce que manquant?

groupe motopropulseur(S) = {(c), (A,c), (b,c), (A,b,c)}

hmmm

Avis des similitudes? Regardez à nouveau...

groupe motopropulseur(S) = {(), (a), (b), (c), (a,b), (a,c), (b,c), (a,b,c)}

enlever tout élément

groupe motopropulseur(S) = {(), (a), (b), (c), (a,b), (a,c), (b,c), (a,b,c)}

groupe motopropulseur(S - {C}) = {(), (a), (b), (A, b)} uni avec

{c} U groupe motopropulseur(S - {C}) = {(c), (A, c), (b, c), (a,b, c)}

groupe motopropulseur (S)=groupe motopropulseur (S - {e i}) U ({e i} U groupe motopropulseur (S - {e i}))

où e i est un élément de S (un singleton)

Pseudo-algorithme

  1. L'ensemble est-il vide? Fait (notez que l'ensemble de puissance de {} est {{}})
  2. sinon, enlever un élément
    • récursivement appel de méthode sur le reste de la set
    • retourner l'ensemble composé de l'Union des
      1. l'ensemble des parties de l'ensemble sans l'élément (à partir de l'appel récursif)
      2. ce même ensemble (c'est à dire, 2.1), mais avec chaque élément qui y est fusionné avec l'élément initialement sorti
18
répondu hobodave 2017-08-11 14:13:02

count 02^n - 1 et imprimez les nombres selon la représentation binaire de votre compte. 1 signifie que vous imprimez et un 0 signifie que vous ne le faites pas. Exemple:

set is {1, 2, 3, 4, 5}
count from 0 to 31:
count = 00000 => print {}
count = 00001 => print {1} (or 5, the order in which you do it really shouldn't matter)
count = 00010 => print {2}
        00011 => print {1, 2}
        00100 => print {3}
        00101 => print {1, 3}
        00110 => print {2, 3}
        00111 => print {1, 2, 3}
        ...
        11111 => print {1, 2, 3, 4, 5}
61
répondu IVlad 2010-05-06 08:06:27
def power(a)
 (0..a.size).map {|x| a.combination(x).to_a}.flatten(1)
end
5
répondu AfDev 2017-05-24 14:30:59

identique à la réponse de hobodave, mais itérative et plus rapide (en rubis). Il fonctionne également avec les deux Array et Set.

def Powerset(set)
    ret = set.class[set.class[]]
    set.each do |s|
        deepcopy = ret.map { |x| set.class.new(x) }
        deepcopy.map { |r| r << s }
        ret = ret + deepcopy
    end
    return ret
end

dans mes tests, la méthode D'IVlad ne fonctionne pas si bien à Ruby.

0
répondu Kache 2012-11-07 11:57:03

à Partir d'un commentaire par OP (révisé):

l'exemple est une forme simplifiée de ce que je fais réellement. Les nombres sont des objets qui ont une propriété "Qty", je veux faire la somme des quantités pour chaque combinaison possible puis choisir la combinaison qui utilise le plus d'objets où la somme des quantités N est à l'intérieur de certaines autres limites, e.g.x < N < y.

Ce que vous avez est un problème d'optimisation. Ce que vous avez supposé est que la bonne façon d'aborder ce problème d'optimisation est de le décomposer en une énumération problème (qui est ce que vous avez demandé), puis une filtration problème (qui sans doute vous savez comment le faire).

ce que vous ne réalisez pas encore est que ce genre de solution ne fonctionne que (a) pour l'analyse théorique, ou (b) Pour de très petites valeurs de n. L'énumération que vous demandez est exponentielle dans

par conséquent, trouvez comment poser votre problème d'optimisation en tant que tel, écrivez une nouvelle question, et éditez celle-ci pour y pointer.

0
répondu eh9 2012-11-07 13:10:40

Récursive et itérative des solutions pour calculer la puissance en régime. Pas entièrement testé cependant

(define (power_set set)
      (cond 
        ((empty? set) (list '()))
        (else
         (let ((part_res (power_set (cdr set))))
           (append (map (lambda (s) (cons (car set) s)) part_res) part_res)))))

(define (power_set_iter set)
  (let loop ((res '(())) (s set))
    (if (empty? s)
        res
        (loop (append (map (lambda (i) (cons (car s) i)) res) res) (cdr s)))))
0
répondu cobie 2013-07-26 16:01:05

Ci-après est une solution récursive, qui est similaire à déjà posté. Quelques assertions fournissent comme genre de tests unitaires. Je n'ai pas réussi à utiliser le type "set" Python pour représenter set of sets. Python a dit que " set objects are unhashable "en essayant des expressions comme" S. add (set ())".

Voir aussi les solutions dans de nombreux langages de programmation à http://rosettacode.org/wiki/Power_set

def generatePowerSet(s, niceSorting = True):
    """Generate power set of a given set.

    The given set, as well as, return set of sets, are implemented
    as lists.

    "niceSorting" optionnaly sorts the powerset by increasing subset size.
    """
    import copy

    def setCmp(a,b):
        """Compare two sets (implemented as lists) for nice sorting"""
        if len(a) < len(b):
            return -1
        elif len(a) > len(b):
            return 1
        else:
            if len(a) == 0:
                return 0
            else:
                if a < b:
                    return -1
                elif a > b:
                    return 1
                else:
                    return 0

    # Initialize the power set "ps" of set "s" as an empty set                    
    ps = list()

    if len(s) == 0:
        ps.append(list())
    else:

        # Generate "psx": the power set of "sx", 
        # which is "s" without a chosen element "x"
        sx = copy.copy(s)
        x = sx.pop()
        psx = generatePowerSet(sx, False)        

        # Include "psx" to "ps"      
        ps.extend(psx)

        # Include to "ps" any set, which contains "x"
        # Such included sets are obtained by adding "x" to any subset of "sx"
        for y in psx:
            yx = copy.copy(y)
            yx.append(x)
            ps.append(yx)

    if niceSorting:
        ps.sort(cmp=setCmp)      

    return ps

assert generatePowerSet([]) == [[]]

assert generatePowerSet(['a']) == [[], ['a']]

assert generatePowerSet(['a', 'b']) == [[], ['a'], ['b'], ['a', 'b']]

assert generatePowerSet(['a', 'b','c']) == [[], 
                                            ['a'], ['b'], ['c'], 
                                            ['a', 'b'], ['a', 'c'], ['b', 'c'],
                                            ['a', 'b', 'c'] ]

assert generatePowerSet(['a', 'b','c'], False) == [ [], 
                                                    ['a'], 
                                                    ['b'], 
                                                    ['a', 'b'], 
                                                    ['c'], 
                                                    ['a', 'c'], 
                                                    ['b', 'c'], 
                                                    ['a', 'b', 'c'] ]

print generatePowerSet(range(4), True)
0
répondu leframibra 2014-01-26 17:51:13