Czy istnieje algorytm „sortowania”, który zwraca losową permutację podczas korzystania z komparatora z monetą?

9

Zainspirowane tym pytaniem, w którym pytający chce wiedzieć, czy czas działania zmienia się, gdy komparator użyty w standardowym algorytmie wyszukiwania zostaje zastąpiony uczciwym rzucie monetą, a także wyraźnym niepowodzeniem Microsoftu w napisaniu jednolitego generatora permutacji, moje pytanie jest zatem :

Czy istnieje algorytm sortowania oparty na porównaniu, który w zależności od naszej implementacji komparatora:

  1. zwracaj elementy w posortowanej kolejności, gdy używasz prawdziwego komparatora (tzn. porównanie robi to, czego oczekujemy od standardowego algorytmu sortowania)
  2. zwraca jednolicie losową permutację pierwiastków, gdy komparator jest zastąpiony przez uczciwą rzut monetą (tzn. zwraca x < y = truez prawdopodobieństwem 1/2, niezależnie od wartości x i y)

Kod algorytmu sortowania musi być taki sam. Tylko kod w „czarnej skrzynce” porównania może ulec zmianie.

Joe
źródło
Zobacz także to pytanie .
Raphael
2
Zobacz także następujące interesujące pytanie: cstheory.stackexchange.com/questions/5321/… .
Yuval Filmus
1
Czy chcesz, aby Twój przypadkowy komparator zachowywał się dobrze? Oto dwa możliwe sposoby. (1) Gdy komparator podejmie decyzję, że , to zawsze , a także . (2) To samo, ale jeśli ponadto komparator zdecyduje, że i , to zatwierdza (i ). W obu przypadkach każde nieograniczone zapytanie jest nadal całkowicie losowe. x<yx<yy>xx<yy<zx<zz>x
Yuval Filmus
@YuvalFilmus Chcę zasadniczo tego, o co jest proszone w łączonym pytaniu, z tym wyjątkiem, że ten sam obwód powinien również posortować, jeśli zastąpimy bramę losową bramką wymiany porównania, która zamawia parę elementów.
Joe
1
Zobacz tutaj ładne wizualizacje.
Raphael

Odpowiedzi:

3

Poniższy algorytm deterministyczny (bez komparatora) działa dla krotki wejściowej :(a1,,an)

  1. Wykonaj tasowanie Fisher-Yates za pomocą komparatora z parą statyczną (powiedz ) jako rzut monetą (próbkowanie przy odrzucaniu-odrzucaniu). Jeśli komparator wyprowadza za pierwszym razem, użyj go odwróconego, aby uniknąć nieskończonej pętli odrzucania w przypadku deterministycznym.a1<a21
  2. (opcjonalne przyspieszenie: Wypróbuj pojedynczą parę razy, gdzie jest długością lub wartością wejściową. Jeśli dowolne dwa wyjścia różnią się, zwróć permutację uzyskaną w (1))nn
  3. Posortuj tablicę za pomocą sortowania scalającego.

Biorąc pod uwagę deterministyczną relację porządku jako komparator, ten algorytm sortuje tablicę w czasie ponieważ losowanie Fisher-Yates działa w przy użyciu maximal nielosowe „losowe bity” (np. wywołania do twojego komparatora) na każdym kroku i sortowanie według scalania ma tę samą asymptotyczną złożoność. Wynik (1) jest w tym przypadku całkowicie bezużyteczny, ale ponieważ następuje po nim prawdziwy rodzaj, nie szkodzi.O(nlogn)O(n)O(logn)

Biorąc pod uwagę prawdziwy rzut monetą, ponieważ komparator (1) permutuje tablicę z jednakowym prawdopodobieństwem dla każdej permutacji, a jeśli naprawdę musisz zrobić (3) (pominąłeś (2) lub (2) nie udało się ustalić losowości), to nie jest szkoda, ponieważ rozkład jego wyniku zależy tylko od kolejności jego wejścia, która jest równomiernie rozłożona między wszystkimi permutacjami z powodu (1), więc wynik całego algorytmu jest również równomiernie rozłożony. Liczba powtórzeń każdego próbkowania akceptacji-odrzucenia jest rozkładem geometrycznym (odrzucenie z prawdopodobieństwem ), a zatem ma wartość oczekiwaną . Każde powtórzenie wykorzystuje maksymalnie bitów, więc analiza czasu wykonywania jest prawie taka sama jak w przypadku deterministycznym, ale otrzymujemy tylko<12<2lognoczekiwany czas działania , z możliwością nieterminacji (kończy się prawie na pewno ).O(nlogn)


Jak wskazał Joe: Jeśli nie podoba ci się test dla pierwszego bitu w (1), zrób (3), a następnie (1) i użyj który zawsze wynosi , ponieważ tablica jest już posortowana w przypadku deterministycznym . Dodatkowo musisz odjąć swoją liczbę losową od górnej granicy zakresu w pętli, ponieważ górna granica liczby losowej daje identyczną permutację. Pamiętaj jednak, że (2) jest wtedy zabronione, ponieważ zawsze musisz wykonać losowanie w przypadku okupu.an<a10


Możesz nawet użyć tych samych wywołań do komparatora dla (1) i (3), ale udowodnienie, że wynik jest równomiernie rozłożony, jest co najmniej o wiele trudniejsze, o ile w ogóle możliwe.


Poniższy algorytm nie ma odrębnych faz do losowego sortowania i sortowania, ale jest asymptotycznie wolniejszy. Jest to w zasadzie sortowanie przez wstawianie z wyszukiwaniem binarnym . Będzie używać do oznaczenia wejściowe i dla określenia rezultatu po -tym etap:a=(a1,,an)bk=(bk,1,,bk,k)k

  1. Ustawb1,1=a1
  2. Jeśli to i inaczej i . W obu przypadkach będzie zawsze wynosić (tj. Fałsz) dla nielosowego komparatora.a2<a1b2=(a2,a1)(c,d):=(2,1)b2=(a1,a2)(c,d):=(1,2)ad<ac0
  3. Aby uzyskać dla najpierw uzyskaj .bkk3bk1
  4. Niech i , tzn. jest najmniejszą potęgą nie mniejszą niż .l=log2kk=2lk2k
  5. Niech . Dla każdego niech i0=0j{1,,l}
    ij={ij1+2ljij1+2lj>k1ad<acij1ij1+2lj>k1¬(ad<ac)ij1+2ljij1+2ljk1bk1,ij1+2lj<akij1ij1+2ljk1¬(bk1,ij1+2lj<ak)
  6. Jeśli powtórz (5.) elseil>kbk=(bk1,1,,bk1,il1,ak,bk1,il,,bk1,k1)
  7. Wyjściebn

Przypadek losowy: 5 + klauzula if z 6 jest w zasadzie próbką akceptacji-odrzucenia. Reszta algorytmu jest naiwnym tasowaniem: przetasuj pierwsze elementy i dodaj ty element do każdej pozycji z jednakowym prawdopodobieństwem. Gdybyśmy użyli normalnego sortowania wstawiania, otrzymalibyśmy zamiast tego rozkład dwumianowy.k-1k

Zauważ, że ten algorytm jest nieefektywny w obu trybach w porównaniu do sortowania i łączenia przez Fisher-Yatesa, ponieważ wstawianie elementu do dowolnej pozycji jest kosztowne, jeśli użycie tablicy i wyszukiwanie binarne wymaga czasu liniowego, jeśli używasz listy. Ale być może modyfikacja sortowania sterty lub sortowania drzewa w podobny sposób może prowadzić do szybszego algorytmu.

Frafl
źródło
@Joe, czy możesz w jednym komentarzu umieścić wszystkie ważne dla posta punkty w bieżącym kształcie i usunąć resztę?
frafl
Miałem nadzieję na algorytm, który nie wykonuje różnych kroków w zależności od używanego komparatora. Czy można uniknąć nieskończonej pętli odrzucania bez sondowania komparatora? Myślę, że można uniknąć odrzucenia, wykonując najpierw krok (3) ...
Joe
Co się stanie, jeśli wykonasz krok sortowania, a następnie przetasujesz, ale zastosujesz sekwencję porównań, które zależą od indeksu , aby w przypadku deterministycznym uzyskać indeks elementu (bez zamiany) i pozostanie on posortowany, ale w przypadkowym przypadku wykonujesz standardowe odtwarzanie losowe z próbkowaniem odrzucania. ja
Joe
Pierwszy komentarz: Zauważ, że nie wyrzucam tego pierwszego fragmentu próbki, to „podwójne zastosowanie”. Myślałem o odwracaniu co 2 bity, ale to nie zapobiegnie niekończącej się pętli. W rzeczywistości potrzebny jest jakiś nieregularny wzór, a nawet może odrzucić o wiele więcej wpisów. Oczywiście mógłbym XOR dwa ostatnie bity zamiast pierwszego i najnowszego, ale to naprawdę nie jest inaczej.
frafl
Drugi komentarz: Kolejność (1) vs. (3) jest ważna tylko wtedy, gdy użyjesz kroku (2), ponieważ w przypadkowym przypadku musisz upewnić się, że losowanie zostanie wykonane z prawdopodobieństwem 1, w przeciwnym razie rozkład jednolity zostanie naruszony. Dlaczego to ma zależeć ? W takim przypadku zawsze odpowie , co jest wszystkim, czego potrzebujemy. jaan<a10
frafl
4

Nie, jest to niemożliwe, chyba że . Prawdopodobieństwo, że algorytm generujący permutację jest generowany za pomocą losowego komparatora, ma charakter dyadyczny, tzn. Ma postać , natomiast prawdopodobieństwo powinno wynosić. Gdy , nie ma sposobu na napisanieW formie .n2)ZA/2)b1/n!n>2)1/n!ZA/2)b

Yuval Filmus
źródło
1
Jest tak jednak tylko wtedy, gdy potrzebujemy deterministycznego ograniczenia w czasie wykonywania, czego nie wymagano w pytaniu. Jeśli wymagamy tylko skończonego czasu działania, nie powinno to stanowić problemu.
frafl
1
Czy znasz jakiś rozsądny algorytm sortowania, który nie kończy się w czasie wielomianowym?
Yuval Filmus
2
Miksujesz przypadek deterministyczny i losowy. Algorytm może kończyć się w deterministycznym czasie wielomianowym, jeśli zostanie wywołany z deterministyczną relacją rzędu i w oczekiwanym czasie wielomianowym, jeśli zostanie wywołany z monetą jako komparatorem.
frafl
@YuvalFilmus dlaczego drzewo decyzyjne musi mieć liści? 2)k
Joe
Jeśli robisz w sumie do porównań, prawdopodobieństwo dowolnego zdarzenia będzie miało postać . Nie chodzi o liczbę liści. Jedynym wyjściem jest, jak sugeruje Frafl, nieograniczona liczba porównań. kZA/2)k
Yuval Filmus