2010-08-12 31 views
13

Tôi gặp phải vấn đề này khi thực hiện một số chương trình nhiệt tình. Vấn đề có thể được diễn tả như sau:Có một thuật toán để tạo ra tất cả các hoán vị tròn duy nhất của một multiset?

Đối với một MultiSet A, chúng ta hãy P (A) biểu thị tập hợp của tất cả các hoán vị có thể có của A. P (A) được một cách tự nhiên chia thành tập con rời nhau mà là tương đương các lớp học, với mối quan hệ tương đương là "có thể liên quan theo ca tròn". Liệt kê tất cả các lớp học tương đương bằng cách tạo ra chính xác một thành viên từ mỗi người trong số họ.

Ví dụ: hãy xem xét đa số {0, 1, 1, 2}. Các hoán vị "0112" và "1201" là hoán vị duy nhất, nhưng sau này có thể được tìm thấy bằng cách dịch chuyển vòng tròn cũ và ngược lại. Thuật toán mong muốn không được tạo ra cả hai. Tất nhiên một cách tiếp cận brute-force là có thể: chỉ cần tạo hoán vị - bất kể sao chép hình tròn - sử dụng bất kỳ thuật toán hoán vị đa điểm nào và loại bỏ trùng lặp được tìm thấy bằng cách so sánh với kết quả trước đó. Tuy nhiên, điều này có xu hướng không hiệu quả trong thực tế. Thuật toán mong muốn nên yêu cầu tối thiểu, nếu không phải là zero bookkeeping.

Mọi thông tin chi tiết về vấn đề này được đánh giá cao.

Trả lời

8
+0

Cảm ơn liên kết và tham chiếu đến giấy của Sawada. Tôi sẽ dành chút thời gian để nghiên cứu, nó và đăng lại nếu tôi có thêm câu hỏi. –

+0

Tôi sẽ đánh dấu điều này là giải pháp :) Tôi cũng phát hiện ra một bài báo cho một thuật toán liên quan chặt chẽ, cụ thể là tạo ra tất cả các dây chuyền có độ dài nhất định từ bảng chữ cái. Liên kết tới bài báo: http://dx.doi.org/10.1006/jagm.2000.1108 –

1

nó dễ dàng hơn để đi cho đáy này:

nếu chỉ chứa 1 phần tử, P (A) cũng chứa một hoán vị. thật dễ dàng để xem các tác phẩm tương tự nếu A chỉ chứa 2 phần tử.

Bây giờ, giả sử bạn đã có tất cả P ​​(A) cho A có phần tử n và bạn thêm một phần tử. nó có thể đi vào bất kỳ điểm nào trong bất kỳ hoán vị nào trong P (A).

Tôi nghĩ ý tưởng này dịch khá trực tiếp thành thuật toán đệ quy trong ngôn ngữ bạn chọn và hy vọng lời giải thích của tôi đủ rõ ràng.

EDIT: Tôi biết tôi loại bỏ qua một thực tế rằng A có thể chứa các thành phần trùng lặp, nhưng vẫn suy nghĩ về điều đó một phần :)

cũng giống như một mặc dù - nếu bạn sắp xếp A trước khi bắt đầu các thuật toán hoán vị, tôi nghĩ điều này có thể loại bỏ các bản sao. (Vẫn còn suy nghĩ về điều đó quá)

0

Đối với một sự hiểu biết trực quan của vấn đề tôi nghĩ chúng ta có thể sử dụng phép ẩn dụ này. Hình dung một đồng hồ trên tường nhưng thay vì có 12 vị trí trên mặt nó có n trong đó n là số phần tử trong bộ của bạn.

Sau đó, mỗi lớp tương đương chỉ là nhiệm vụ của phần tử A đến vị trí trên mặt đồng hồ.

Sau khi gán một hoán vị khác từ cùng một lớp tương đương có thể được tạo ra bằng cách xoay đồng hồ trên tường.

Để tạo một hoán vị không liên quan khác của A, bạn cần phải có phần tử bỏ qua ít nhất một phần tử khác.Bây giờ các thuật toán như tôi thấy nó sẽ là bắt đầu với một nhiệm vụ ví dụ nói rằng chúng tôi có bốn yếu tố trong A = {a, b, c, d} và chúng tôi đã gán chúng cho 12, 3, 6 và 9. vị trí tương ứng cho hình ảnh rõ ràng. Sau đó, hoạt động đầu tiên của chúng tôi là hoán đổi a và b. sau đó a và c, sau đó a và d, sau đó chúng ta sẽ đi đến b và hoán đổi nó với phần tử ở vị trí 3 mà bây giờ là c.

Làm điều này cho đến khi chúng tôi đạt đến d sẽ tạo ra một đại diện từ tất cả các lớp tương đương.

này không chăm sóc bản sao nhưng nó phải là xa hiệu quả hơn tạo ra tất cả các hoán vị của A.

+0

Cảm ơn bạn đã trả lời. Trên thực tế đây là những gì tôi đã suy nghĩ ngắn gọn trước khi tôi đăng câu hỏi ở đây. Đối với một số lý do tôi quên nó và đi với điều ngu ngốc "tạo ra tất cả hoán vị": p Như bạn đã nói, nó chỉ hoạt động khi tập A là một bộ "đơn giản" mà không nhân đôi thành viên, nhưng vẫn là một điểm khởi đầu tốt để hiểu vấn đề. –

0

Ý nghĩ mà lò xo để tâm trí của tôi là cho bất kỳ bộ đó có ít nhất một yếu tố mà chỉ có xuất hiện một lần sau đó bạn có thể đặt phần tử đó ở vị trí đầu tiên trong danh sách của bạn cho tất cả các câu trả lời và sau đó tạo tất cả các hoán vị của các số còn lại. Đây là một giải pháp khá tầm thường vì thực tế nguyên tố đầu tiên của bạn là duy nhất đảm bảo rằng không có sự tương đương bằng cách dịch chuyển các phần tử. Rõ ràng sau đó tất cả các giải pháp bạn tạo ra phải là duy nhất.

Vấn đề rõ ràng là nếu bạn không có yếu tố nào là đĩa đơn thì điều này sẽ bị hỏng hoàn toàn. Lý do chính mà tôi đặt này là bởi vì có một số giải pháp khác đối phó với không có bản sao và tôi nghĩ rằng điều này là hiệu quả hơn họ (giải quyết nhiều trường hợp) như vậy là xứng đáng đề cập đến. Nó cũng khá đơn giản về sự hiểu biết cách nó hoạt động và thực hiện nó. Tôi chỉ hy vọng lý luận của tôi là âm thanh. ;-)

Sửa cho suy nghĩ thêm:

Nó xảy ra với tôi rằng nguyên tắc này có thể được mở rộng đến các tình huống mà bạn có bản sao đến một mức độ nhất định.

Nếu bạn lấy một phần tử (mà chúng ta giả sử bây giờ được lặp lại), bạn có thể chỉ xem hoán vị của nó và cái nào sẽ cho phép lặp lại chu kỳ, như trước khi giả sử rằng bạn có thể "khóa" một phần mà không mất tính tổng quát . ví dụ như nếu bạn có tổng cộng 6 yếu tố và A xuất hiện hai lần trong bộ này thì bạn có thể có:

AAXXXX, AXAXXX, AXXAXX, AXXXAX, AXXXXA

cuối cùng trong số này là giống như là người đầu tiên (trong vòng thay đổi theo chu kỳ) vì vậy có thể bỏ qua, ditto thứ hai và thứ tư. Thứ ba (AXXAXX) có thể được đạp xe ba để có được trở lại chính nó vì vậy có tiềm năng cho chu kỳ. Hai cái đầu tiên không bao giờ có thể phát sinh chu kỳ cho dù bạn có chu kỳ bao nhiêu lần cho nên bạn phân phối các phần tử còn lại mà bạn chỉ cần đảm bảo rằng chúng là các bản phân phối duy nhất và bạn được đảm bảo để có được duy nhất bởi kết quả chu kỳ.

Đối với mẫu thứ ba có thể chu kỳ (AXXAXX), bạn sẽ cần xem xét phần tử B và lặp lại quy trình cho phần tử đó. Thời gian này không may bạn sẽ không thể sử dụng lừa khóa giá trị đầu tiên để tiết kiệm thời gian.

Tôi không chắc chắn 100% làm thế nào bạn sẽ đi về làm cho điều này thành một chương trình làm việc đầy đủ nhưng một số khó khăn của nó về cách tránh phải bạo lực.

0

Tôi đề nghị đây là một giải pháp thực hiện trong python

import itertools as it 

L = ['a','b','c','d'] 
B = it.combinations(L,2) 
swaplist = [e for e in B] 
print 'List of elements to permute:' 
print swaplist 
print 
unique_necklaces = [] 
unique_necklaces.append(L) 
for pair in swaplist: 
    necklace = list(L) 
    e1 = pair[0] 
    e2 = pair[1] 
    indexe1 = L.index(e1) 
    indexe2 = L.index(e2) 
    #swap 
    necklace[indexe1],necklace[indexe2] = necklace[indexe2], necklace[indexe1] 
    unique_necklaces.append(necklace) 

for n in unique_necklaces: 
    # Commented code display the rotation of the elements in each necklace 
    print 'Necklaces' 
    print n#, [n[-r:]+n[:-r]for r in (1,2,3)] 

Ý tưởng là để xây dựng dây chuyền khác nhau bằng cách hoán vị của hai yếu tố này.Để biết danh sách bốn yếu tố a, b, c, d sản lượng của bản ngã:

['a', 'b', 'c', 'd'] 
['b', 'a', 'c', 'd'] 
['c', 'b', 'a', 'd'] 
['d', 'b', 'c', 'a'] 
['a', 'c', 'b', 'd'] 
['a', 'd', 'c', 'b'] 
['a', 'b', 'd', 'c'] 
Các vấn đề liên quan