Diberikan satu set
{0, 1, 2, 3}
Bagaimana saya bisa menghasilkan subset:
[set(),
{0},
{1},
{2},
{3},
{0, 1},
{0, 2},
{0, 3},
{1, 2},
{1, 3},
{2, 3},
{0, 1, 2},
{0, 1, 3},
{0, 2, 3},
{1, 2, 3},
{0, 1, 2, 3}]
Jawaban:
itertools
Halaman Python memiliki powerset
resep persis untuk ini:
from itertools import chain, combinations
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Keluaran:
>>> list(powerset("abcd"))
[(), ('a',), ('b',), ('c',), ('d',), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd'), ('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'd'), ('b', 'c', 'd'), ('a', 'b', 'c', 'd')]
Jika Anda tidak suka tupel kosong di awal, Anda bisa mengubah range
pernyataan range(1, len(s)+1)
untuk menghindari kombinasi panjang 0.
s = list(iterable)
dibutuhkan?
__len__
diimplementasikan; mencoba powerset((n for n in range(3)))
tanpa membungkus daftar.
powerset(range(3))
akan bekerja dengan baik bahkan tanpas = list(iterable)
.
Berikut ini lebih banyak kode untuk set kekuatan. Ini ditulis dari awal:
>>> def powerset(s):
... x = len(s)
... for i in range(1 << x):
... print [s[j] for j in range(x) if (i & (1 << j))]
...
>>> powerset([4,5,6])
[]
[4]
[5]
[4, 5]
[6]
[4, 6]
[5, 6]
[4, 5, 6]
Komentar Mark Rushakoff dapat diterapkan di sini: "Jika Anda tidak menyukai tupel kosong itu di awal, aktif." Anda dapat mengubah pernyataan rentang ke range (1, len (s) +1) untuk menghindari kombinasi panjang 0 ", kecuali dalam kasus saya Anda berubah for i in range(1 << x)
menjadi for i in range(1, 1 << x)
.
Kembali ke tahun-tahun ini kemudian, saya sekarang akan menulisnya seperti ini:
def powerset(s):
x = len(s)
masks = [1 << i for i in range(x)]
for i in range(1 << x):
yield [ss for mask, ss in zip(masks, s) if i & mask]
Dan kemudian kode tes akan terlihat seperti ini, katakanlah:
print(list(powerset([4, 5, 6])))
Menggunakan yield
berarti Anda tidak perlu menghitung semua hasil dalam satu bagian memori. Melakukan prakalkulasi mask di luar loop utama dianggap sebagai pengoptimalan yang bermanfaat.
Jika Anda mencari jawaban cepat, saya baru saja mencari "python power set" di google dan menemukan ini: Python Power Set Generator
Berikut adalah copy-paste dari kode di halaman itu:
def powerset(seq):
"""
Returns all the subsets of this set. This is a generator.
"""
if len(seq) <= 1:
yield seq
yield []
else:
for item in powerset(seq[1:]):
yield [seq[0]]+item
yield item
Ini bisa digunakan seperti ini:
l = [1, 2, 3, 4]
r = [x for x in powerset(l)]
Sekarang r adalah daftar semua elemen yang Anda inginkan, dan dapat disortir dan dicetak:
r.sort()
print r
[[], [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 4], [1, 3], [1, 3, 4], [1, 4], [2], [2, 3], [2, 3, 4], [2, 4], [3], [3, 4], [4]]
[[][]]
, untuk memperbaikinya hanya memisahkan kasus untuk pemeriksaan panjangif len(seq) == 0: yield [] elif len(seq) == 1: yield seq yield []
Ada penyempurnaan PowerSet:
def powerset(seq):
"""
Returns all the subsets of this set. This is a generator.
"""
if len(seq) <= 0:
yield []
else:
for item in powerset(seq[1:]):
yield [seq[0]]+item
yield item
Saya tahu saya sebelumnya telah menambahkan jawaban, tetapi saya sangat menyukai implementasi baru saya. Saya mengambil satu set sebagai input, tapi sebenarnya bisa jadi iterable, dan saya mengembalikan satu set yang merupakan set daya dari input. Saya suka pendekatan ini karena lebih selaras dengan definisi matematis dari himpunan daya ( himpunan semua himpunan bagian ).
def power_set(A):
"""A is an iterable (list, tuple, set, str, etc)
returns a set which is the power set of A."""
length = len(A)
l = [a for a in A]
ps = set()
for i in range(2 ** length):
selector = f'{i:0{length}b}'
subset = {l[j] for j, bit in enumerate(selector) if bit == '1'}
ps.add(frozenset(subset))
return ps
Jika Anda menginginkan output yang Anda posting di jawaban Anda, gunakan ini:
>>> [set(s) for s in power_set({1, 2, 3, 4})]
[{3, 4},
{2},
{1, 4},
{2, 3, 4},
{2, 3},
{1, 2, 4},
{1, 2},
{1, 2, 3},
{3},
{2, 4},
{1},
{1, 2, 3, 4},
set(),
{1, 3},
{1, 3, 4},
{4}]
Diketahui bahwa jumlah elemen dari himpunan adalah 2 ** len(A)
, sehingga dapat dengan jelas dilihat dalam for
loop.
Saya perlu mengubah masukan (idealnya satu set) menjadi daftar karena menurut satu set adalah struktur data dari elemen tak berurutan yang unik, dan urutannya akan sangat penting untuk menghasilkan himpunan bagian.
selector
adalah kunci dalam algoritma ini. Catat yang selector
memiliki panjang yang sama dengan set input, dan untuk memungkinkannya menggunakan f-string dengan padding. Pada dasarnya, ini memungkinkan saya untuk memilih elemen yang akan ditambahkan ke setiap subset selama setiap iterasi. Misalkan set input memiliki 3 elemen {0, 1, 2}
, jadi selektor akan mengambil nilai antara 0 dan 7 (inklusif), yang dalam biner adalah:
000 # 0
001 # 1
010 # 2
011 # 3
100 # 4
101 # 5
110 # 6
111 # 7
Jadi, setiap bit dapat berfungsi sebagai indikator apakah elemen dari set asli harus ditambahkan atau tidak. Lihatlah bilangan biner, dan anggap saja setiap bilangan sebagai elemen dari himpunan super yang 1
berarti bahwa elemen pada indeks j
harus ditambahkan, dan 0
berarti elemen ini tidak boleh ditambahkan.
Saya menggunakan pemahaman set untuk menghasilkan subset pada setiap iterasi, dan saya mengubah subset ini menjadi a frozenset
sehingga saya dapat menambahkannya ke ps
(power set). Jika tidak, saya tidak akan bisa menambahkannya karena satu set di Python hanya terdiri dari objek yang tidak bisa diubah.
Anda dapat menyederhanakan kode menggunakan beberapa pemahaman python, sehingga Anda dapat membuangnya untuk loop. Anda juga dapat menggunakan zip
untuk menghindari penggunaan j
indeks dan kode akan berakhir sebagai berikut:
def power_set(A):
length = len(A)
return {
frozenset({e for e, b in zip(A, f'{i:{length}b}') if b == '1'})
for i in range(2 ** length)
}
Itu dia. Yang saya suka dari algoritma ini adalah yang lebih jelas dan lebih intuitif daripada yang lain karena terlihat cukup ajaib untuk diandalkan itertools
meskipun berfungsi seperti yang diharapkan.
Saya menemukan algoritme berikut sangat jelas dan sederhana:
def get_powerset(some_list):
"""Returns all subsets of size 0 - len(some_list) for some_list"""
if len(some_list) == 0:
return [[]]
subsets = []
first_element = some_list[0]
remaining_list = some_list[1:]
# Strategy: get all the subsets of remaining_list. For each
# of those subsets, a full subset list will contain both
# the original subset as well as a version of the subset
# that contains first_element
for partial_subset in get_powerset(remaining_list):
subsets.append(partial_subset)
subsets.append(partial_subset[:] + [first_element])
return subsets
Cara lain untuk menghasilkan set kekuatan adalah dengan menghasilkan semua bilangan biner yang memiliki n
bit. Sebagai kekuatan mengatur jumlah angka dengan n
digit 2 ^ n
. Prinsip dari algoritma ini adalah bahwa suatu elemen bisa ada atau tidak dalam suatu subset karena digit biner bisa satu atau nol tapi tidak keduanya.
def power_set(items):
N = len(items)
# enumerate the 2 ** N possible combinations
for i in range(2 ** N):
combo = []
for j in range(N):
# test bit jth of integer i
if (i >> j) % 2 == 1:
combo.append(items[j])
yield combo
Saya menemukan kedua algoritme tersebut ketika saya menggunakan MITx: 6.00.2x Pengantar Pemikiran Komputasi dan Ilmu Data, dan saya menganggap ini adalah salah satu algoritme termudah untuk dipahami yang pernah saya lihat.
def get_power_set(s):
power_set=[[]]
for elem in s:
# iterate over the sub sets so far
for sub_set in power_set:
# add a new subset consisting of the subset at hand added elem
power_set=power_set+[list(sub_set)+[elem]]
return power_set
Sebagai contoh:
get_power_set([1,2,3])
menghasilkan
[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
power_set
) dalam perulangan yang diaturnya adalah praktik yang sangat dipertanyakan. Misalnya, Anda menulis ini bukan kode variabel-memodifikasi diusulkan: power_set += [list(sub_set)+[elem]]
. Kemudian loop tidak berhenti.
Saya hanya ingin memberikan solusi yang paling mudah dipahami, versi anti kode-golf.
from itertools import combinations
l = ["x", "y", "z", ]
def powerset(items):
combo = []
for r in range(len(items) + 1):
#use a list to coerce a actual list from the combinations generator
combo.append(list(combinations(items,r)))
return combo
l_powerset = powerset(l)
for i, item in enumerate(l_powerset):
print "All sets of length ", i
print item
Hasil
Semua set panjang 0
[()]
Semua set panjang 1
[('x',), ('y',), ('z',)]
Semua set panjang 2
[('x', 'y'), ('x', 'z'), ('y', 'z')]
Semua set panjang 3
[('x', 'y', 'z')]
Untuk lebih lanjut, lihat dokumen itertools , juga entri wikipedia tentang set daya
Ini dapat dilakukan secara alami dengan itertools.product
:
import itertools
def powerset(l):
for sl in itertools.product(*[[[], [i]] for i in l]):
yield {j for i in sl for j in i}
Hanya penyegaran set daya cepat!
Himpunan daya dari sebuah himpunan X, hanyalah himpunan dari semua himpunan bagian dari X termasuk himpunan kosong
Contoh himpunan X = (a, b, c)
Set Daya = {{a, b, c}, {a, b}, {a, c}, {b, c}, {a}, {b}, {c}, {}}
Berikut cara lain untuk menemukan set daya:
def power_set(input):
# returns a list of all subsets of the list a
if (len(input) == 0):
return [[]]
else:
main_subset = [ ]
for small_subset in power_set(input[1:]):
main_subset += [small_subset]
main_subset += [[input[0]] + small_subset]
return main_subset
print(power_set([0,1,2,3]))
kredit penuh untuk sumber
Cara sederhana adalah dengan memanfaatkan representasi internal bilangan bulat di bawah aritmatika komplemen 2.
Representasi biner bilangan bulat adalah sebagai {000, 001, 010, 011, 100, 101, 110, 111} untuk bilangan mulai dari 0 hingga 7. Untuk nilai penghitung bilangan bulat, mempertimbangkan 1 sebagai penyertaan elemen yang sesuai dalam kumpulan dan '0' sebagai pengecualian kita dapat menghasilkan subset berdasarkan urutan penghitungan. Nomor harus dihasilkan dari 0
ke pow(2,n) -1
mana n adalah panjang array jumlah yaitu bit dalam representasi biner.
Fungsi Generator Subset sederhana berdasarkan itu dapat ditulis seperti di bawah ini. Itu pada dasarnya bergantung
def subsets(array):
if not array:
return
else:
length = len(array)
for max_int in range(0x1 << length):
subset = []
for i in range(length):
if max_int & (0x1 << i):
subset.append(array[i])
yield subset
dan kemudian bisa digunakan sebagai
def get_subsets(array):
powerset = []
for i in subsets(array):
powerser.append(i)
return powerset
Menguji
Menambahkan mengikuti di file lokal
if __name__ == '__main__':
sample = ['b', 'd', 'f']
for i in range(len(sample)):
print "Subsets for " , sample[i:], " are ", get_subsets(sample[i:])
memberikan hasil sebagai berikut
Subsets for ['b', 'd', 'f'] are [[], ['b'], ['d'], ['b', 'd'], ['f'], ['b', 'f'], ['d', 'f'], ['b', 'd', 'f']]
Subsets for ['d', 'f'] are [[], ['d'], ['f'], ['d', 'f']]
Subsets for ['f'] are [[], ['f']]
Hampir semua jawaban ini menggunakan list
daripada set
, yang terasa seperti sedikit curang bagi saya. Jadi, karena penasaran saya mencoba membuat versi sederhana set
dan merangkum untuk orang-orang "baru mengenal Python" lainnya.
Saya menemukan ada beberapa keanehan dalam menangani implementasi set Python . Kejutan utama bagi saya adalah menangani set kosong. Ini berbeda dengan implementasi Ruby Set , di mana saya dapat dengan mudah melakukan Set[Set[]]
dan mendapatkan yang Set
berisi kosong Set
, jadi saya merasa awalnya agak membingungkan.
Untuk meninjau, saat melakukan powerset
dengan set
s, saya menemui dua masalah:
set()
mengambil iterable, jadi set(set())
akan dikembalikan set()
karena set kosong iterable kosong (ya saya kira :))set({set()})
dan set.add(set)
tidak akan berfungsi karena set()
tidak dapat di-hashUntuk mengatasi kedua masalah tersebut, saya memanfaatkan frozenset()
, yang berarti saya tidak cukup mendapatkan apa yang saya inginkan (tipe secara harfiah set
), tetapi menggunakan set
antarmuka keseluruhan .
def powerset(original_set):
# below gives us a set with one empty set in it
ps = set({frozenset()})
for member in original_set:
subset = set()
for m in ps:
# to be added into subset, needs to be
# frozenset.union(set) so it's hashable
subset.add(m.union(set([member]))
ps = ps.union(subset)
return ps
Di bawah ini kami mendapatkan 2² (16) frozenset
dengan benar sebagai keluaran:
In [1]: powerset(set([1,2,3,4]))
Out[2]:
{frozenset(),
frozenset({3, 4}),
frozenset({2}),
frozenset({1, 4}),
frozenset({3}),
frozenset({2, 3}),
frozenset({2, 3, 4}),
frozenset({1, 2}),
frozenset({2, 4}),
frozenset({1}),
frozenset({1, 2, 4}),
frozenset({1, 3}),
frozenset({1, 2, 3}),
frozenset({4}),
frozenset({1, 3, 4}),
frozenset({1, 2, 3, 4})}
Karena tidak ada cara untuk memiliki set
dari set
dalam Python, jika Anda ingin mengubah ini frozenset
s menjadi set
s, Anda harus memetakan mereka kembali ke dalam list
( list(map(set, powerset(set([1,2,3,4]))))
) atau memodifikasi atas.
Mungkin pertanyaannya semakin lama, tapi saya harap kode saya akan membantu seseorang.
def powSet(set):
if len(set) == 0:
return [[]]
return addtoAll(set[0],powSet(set[1:])) + powSet(set[1:])
def addtoAll(e, set):
for c in set:
c.append(e)
return set
Gunakan fungsi powerset()
dari paket more_itertools
.
Menghasilkan semua subset yang mungkin dari iterable
>>> list(powerset([1, 2, 3]))
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
Jika Anda ingin set, gunakan:
list(map(set, powerset(iterable)))
Mendapatkan semua subset dengan rekursi. Satu kalimat gila
from typing import List
def subsets(xs: list) -> List[list]:
return subsets(xs[1:]) + [x + [xs[0]] for x in subsets(xs[1:])] if xs else [[]]
Berdasarkan solusi Haskell
subsets :: [a] -> [[a]]
subsets [] = [[]]
subsets (x:xs) = map (x:) (subsets xs) ++ subsets xs
NameError: name 'List' is not defined
List
import
def findsubsets(s, n):
return list(itertools.combinations(s, n))
def allsubsets(s) :
a = []
for x in range(1,len(s)+1):
a.append(map(set,findsubsets(s,x)))
return a
Anda bisa melakukannya seperti ini:
def powerset(x):
m=[]
if not x:
m.append(x)
else:
A = x[0]
B = x[1:]
for z in powerset(B):
m.append(z)
r = [A] + z
m.append(r)
return m
print(powerset([1, 2, 3, 4]))
Keluaran:
[[], [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]]
Saya tahu ini sudah terlambat
Ada banyak solusi lain tapi tetap ...
def power_set(lst):
pw_set = [[]]
for i in range(0,len(lst)):
for j in range(0,len(pw_set)):
ele = pw_set[j].copy()
ele = ele + [lst[i]]
pw_set = pw_set + [ele]
return pw_set
Ini liar karena tidak ada dari jawaban ini yang benar-benar memberikan kembalinya set Python yang sebenarnya. Berikut adalah implementasi yang berantakan yang akan memberikan kekuatan yang sebenarnya adalah Python set
.
test_set = set(['yo', 'whatup', 'money'])
def powerset( base_set ):
""" modified from pydoc's itertools recipe shown above"""
from itertools import chain, combinations
base_list = list( base_set )
combo_list = [ combinations(base_list, r) for r in range(len(base_set)+1) ]
powerset = set([])
for ll in combo_list:
list_of_frozensets = list( map( frozenset, map( list, ll ) ) )
set_of_frozensets = set( list_of_frozensets )
powerset = powerset.union( set_of_frozensets )
return powerset
print powerset( test_set )
# >>> set([ frozenset(['money','whatup']), frozenset(['money','whatup','yo']),
# frozenset(['whatup']), frozenset(['whatup','yo']), frozenset(['yo']),
# frozenset(['money','yo']), frozenset(['money']), frozenset([]) ])
Saya ingin melihat implementasi yang lebih baik.
[*map(set, chain.from_iterable(combinations(s, r) for r in range(len(s)+1)))]
; fungsi arg dari map
bisa frozenset
jika Anda mau.
Berikut adalah penerapan cepat saya yang memanfaatkan kombinasi tetapi hanya menggunakan bawaan.
def powerSet(array):
length = str(len(array))
formatter = '{:0' + length + 'b}'
combinations = []
for i in xrange(2**int(length)):
combinations.append(formatter.format(i))
sets = set()
currentSet = []
for combo in combinations:
for i,val in enumerate(combo):
if val=='1':
currentSet.append(array[i])
sets.add(tuple(sorted(currentSet)))
currentSet = []
return sets
Semua subset dalam rentang n sebagai set:
n = int(input())
l = [i for i in range (1, n + 1)]
for number in range(2 ** n) :
binary = bin(number)[: 1 : -1]
subset = [l[i] for i in range(len(binary)) if binary[i] == "1"]
print(set(sorted(subset)) if number > 0 else "{}")
import math
def printPowerSet(set,set_size):
pow_set_size =int(math.pow(2, set_size))
for counter in range(pow_set_size):
for j in range(set_size):
if((counter & (1 << j)) > 0):
print(set[j], end = "")
print("")
set = ['a', 'b', 'c']
printPowerSet(set,3)
Variasi pertanyaan tersebut, merupakan latihan yang saya lihat pada buku "Discovering Computer Science: Interdisciplinary Problems, Principles, and Python Programming. Edisi 2015". Dalam latihan 10.2.11 itu, masukannya hanyalah bilangan bulat, dan keluarannya harus set daya. Ini solusi rekursif saya (tidak menggunakan yang lain selain python3 dasar)
def powerSetR(n):
assert n >= 0
if n == 0:
return [[]]
else:
input_set = list(range(1, n+1)) # [1,2,...n]
main_subset = [ ]
for small_subset in powerSetR(n-1):
main_subset += [small_subset]
main_subset += [ [input_set[-1]] + small_subset]
return main_subset
superset = powerSetR(4)
print(superset)
print("Number of sublists:", len(superset))
Dan hasilnya adalah
[[], [4], [3], [4, 3], [2], [4, 2], [3, 2], [4, 3, 2], [1], [4, 1 ], [3, 1], [4, 3, 1], [2, 1], [4, 2, 1], [3, 2, 1], [4, 3, 2, 1]] Jumlah sublists: 16
Saya belum menemukan more_itertools.powerset
fungsinya dan akan merekomendasikan untuk menggunakannya. Saya juga merekomendasikan untuk tidak menggunakan pengurutan default dari output dari itertools.combinations
, seringkali Anda ingin meminimalkan jarak antara posisi dan mengurutkan subset item dengan jarak yang lebih pendek di antara mereka di atas / sebelum item dengan jarak yang lebih besar di antara mereka.
The itertools
resep Halaman menunjukkan menggunakanchain.from_iterable
r
sini cocok dengan notasi standar untuk bagian bawah koefisien binomial , yang s
biasanya disebut n
dalam teks matematika dan pada kalkulator ("n Pilih r")def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Contoh lain di sini memberikan kumpulan pangkat [1,2,3,4]
sedemikian rupa sehingga 2-tupel terdaftar dalam urutan "leksikografik" (ketika kita mencetak angka sebagai bilangan bulat). Jika saya menulis jarak antara angka di sampingnya (yaitu perbedaannya), ini menunjukkan poin saya:
12 ⇒ 1
13 ⇒ 2
14 ⇒ 3
23 ⇒ 1
24 ⇒ 2
34 ⇒ 1
Urutan yang benar untuk subset haruslah urutan yang 'menghabiskan' jarak minimal terlebih dahulu, seperti:
12 ⇒ 1
23 ⇒ 1
34 ⇒ 1
13 ⇒ 2
24 ⇒ 2
14 ⇒ 3
Menggunakan angka di sini membuat urutan ini terlihat 'salah', tetapi perhatikan misalnya huruf-hurufnya ["a","b","c","d"]
, lebih jelas mengapa ini mungkin berguna untuk mendapatkan set pangkat dalam urutan ini:
ab ⇒ 1
bc ⇒ 1
cd ⇒ 1
ac ⇒ 2
bd ⇒ 2
ad ⇒ 3
Efek ini lebih terasa dengan lebih banyak item, dan untuk tujuan saya, ini membuat perbedaan antara kemampuan untuk menggambarkan kisaran indeks powerset secara bermakna.
(Ada banyak yang tertulis kode Gray dll. Untuk urutan keluaran dari algoritma dalam kombinatorika, saya tidak melihatnya sebagai masalah sampingan).
Saya sebenarnya baru saja menulis program yang cukup terlibat yang menggunakan kode partisi bilangan bulat cepat ini untuk mengeluarkan nilai dalam urutan yang benar, tetapi kemudian saya menemukan more_itertools.powerset
dan untuk sebagian besar penggunaan mungkin baik-baik saja untuk hanya menggunakan fungsi itu seperti:
from more_itertools import powerset
from numpy import ediff1d
def ps_sorter(tup):
l = len(tup)
d = ediff1d(tup).tolist()
return l, d
ps = powerset([1,2,3,4])
ps = sorted(ps, key=ps_sorter)
for x in ps:
print(x)
⇣
()
(1,)
(2,)
(3,)
(4,)
(1, 2)
(2, 3)
(3, 4)
(1, 3)
(2, 4)
(1, 4)
(1, 2, 3)
(2, 3, 4)
(1, 2, 4)
(1, 3, 4)
(1, 2, 3, 4)
Aku menulis beberapa kode lebih terlibat yang akan mencetak Powerset yang baik (lihat repo untuk cukup mencetak fungsi saya tidak termasuk di sini: print_partitions
, print_partitions_by_length
, dan pprint_tuple
).
pset_partitions.py
Ini semua cukup sederhana, tetapi mungkin masih berguna jika Anda menginginkan beberapa kode yang memungkinkan Anda langsung mengakses berbagai level set kekuatan:
from itertools import permutations as permute
from numpy import cumsum
# http://jeromekelleher.net/generating-integer-partitions.html
# via
# /programming/10035752/elegant-python-code-for-integer-partitioning#comment25080713_10036764
def asc_int_partitions(n):
a = [0 for i in range(n + 1)]
k = 1
y = n - 1
while k != 0:
x = a[k - 1] + 1
k -= 1
while 2 * x <= y:
a[k] = x
y -= x
k += 1
l = k + 1
while x <= y:
a[k] = x
a[l] = y
yield tuple(a[:k + 2])
x += 1
y -= 1
a[k] = x + y
y = x + y - 1
yield tuple(a[:k + 1])
# https://stackoverflow.com/a/6285330/2668831
def uniquely_permute(iterable, enforce_sort=False, r=None):
previous = tuple()
if enforce_sort: # potential waste of effort (default: False)
iterable = sorted(iterable)
for p in permute(iterable, r):
if p > previous:
previous = p
yield p
def sum_min(p):
return sum(p), min(p)
def partitions_by_length(max_n, sorting=True, permuting=False):
partition_dict = {0: ()}
for n in range(1,max_n+1):
partition_dict.setdefault(n, [])
partitions = list(asc_int_partitions(n))
for p in partitions:
if permuting:
perms = uniquely_permute(p)
for perm in perms:
partition_dict.get(len(p)).append(perm)
else:
partition_dict.get(len(p)).append(p)
if not sorting:
return partition_dict
for k in partition_dict:
partition_dict.update({k: sorted(partition_dict.get(k), key=sum_min)})
return partition_dict
def print_partitions_by_length(max_n, sorting=True, permuting=True):
partition_dict = partitions_by_length(max_n, sorting=sorting, permuting=permuting)
for k in partition_dict:
if k == 0:
print(tuple(partition_dict.get(k)), end="")
for p in partition_dict.get(k):
print(pprint_tuple(p), end=" ")
print()
return
def generate_powerset(items, subset_handler=tuple, verbose=False):
"""
Generate the powerset of an iterable `items`.
Handling of the elements of the iterable is by whichever function is passed as
`subset_handler`, which must be able to handle the `None` value for the
empty set. The function `string_handler` will join the elements of the subset
with the empty string (useful when `items` is an iterable of `str` variables).
"""
ps = {0: [subset_handler()]}
n = len(items)
p_dict = partitions_by_length(n-1, sorting=True, permuting=True)
for p_len, parts in p_dict.items():
ps.setdefault(p_len, [])
if p_len == 0:
# singletons
for offset in range(n):
subset = subset_handler([items[offset]])
if verbose:
if offset > 0:
print(end=" ")
if offset == n - 1:
print(subset, end="\n")
else:
print(subset, end=",")
ps.get(p_len).append(subset)
for pcount, partition in enumerate(parts):
distance = sum(partition)
indices = (cumsum(partition)).tolist()
for offset in range(n - distance):
subset = subset_handler([items[offset]] + [items[offset:][i] for i in indices])
if verbose:
if offset > 0:
print(end=" ")
if offset == n - distance - 1:
print(subset, end="\n")
else:
print(subset, end=",")
ps.get(p_len).append(subset)
if verbose and p_len < n-1:
print()
return ps
Sebagai contoh, saya menulis program demo CLI yang mengambil string sebagai argumen baris perintah:
python string_powerset.py abcdef
⇣
a, b, c, d, e, f
ab, bc, cd, de, ef
ac, bd, ce, df
ad, be, cf
ae, bf
af
abc, bcd, cde, def
abd, bce, cdf
acd, bde, cef
abe, bcf
ade, bef
ace, bdf
abf
aef
acf
adf
abcd, bcde, cdef
abce, bcdf
abde, bcef
acde, bdef
abcf
abef
adef
abdf
acdf
acef
abcde, bcdef
abcdf
abcef
abdef
acdef
abcdef
Jika Anda menginginkan panjang subset tertentu, Anda dapat melakukannya seperti ini:
from itertools import combinations
someSet = {0, 1, 2, 3}
([x for i in range(len(someSet)+1) for x in combinations(someSet,i)])
Secara lebih umum untuk subset panjang arbiter, Anda dapat memodifikasi arugment rentang. Outputnya adalah
[(), (0,), (1,), (2,), (3,), (0, 1), (0, 2), (0, 3), (1, 2), (1 , 3), (2, 3), (0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3), (0, 1, 2, 3 )]
Ini dia solusi saya, ini mirip (secara konseptual) dengan solusi lmiguelvargasf.
Izinkan saya mengatakan bahwa - [item matematika] menurut definisi PowerSet memang berisi set kosong - [selera pribadi] dan juga bahwa saya tidak suka menggunakan frozenset.
Jadi inputnya adalah daftar dan outputnya adalah daftar daftar. Fungsi bisa ditutup lebih awal, tapi saya suka elemen set pangkat diurutkan secara leksikografis , yang pada dasarnya berarti baik.
def power_set(L):
"""
L is a list.
The function returns the power set, but as a list of lists.
"""
cardinality=len(L)
n=2 ** cardinality
powerset = []
for i in range(n):
a=bin(i)[2:]
subset=[]
for j in range(len(a)):
if a[-j-1]=='1':
subset.append(L[j])
powerset.append(subset)
#the function could stop here closing with
#return powerset
powerset_orderred=[]
for k in range(cardinality+1):
for w in powerset:
if len(w)==k:
powerset_orderred.append(w)
return powerset_orderred
def powerset(some_set):
res = [(a,b) for a in some_set for b in some_set]
return res