Алгоритм кучи с перестановкой подписи - PullRequest
0 голосов
/ 05 февраля 2019

Я делаю код, который может генерировать всю перестановку списка элементов и сигнатуру перестановки на основе исходного списка.

Как правило, число перестановок задается числами Стирлинга:первый вид как композиция из k = n - C-циклов, которые разбивают n элементов.

       [n]           [n - 1]   [n - 1]
       [ ] = (n - 1) [     ] + [     ]
       [k]           [  k  ]   [k - 1]

Количество способов разбить n элементов на k циклов состоит в разбиении n - 1 не максимального элементав k циклов и разделить максимальный элемент одним из n - 1 образом или поместить максимальный элемент в свой собственный цикл и разделить n - 1 не максимальный элемент на k - 1 циклов.Тогда знак будет задан как (-1) ^ NC, где N - количество индексов, а C - количество циклов, образованных при перемещении элемента из его исходного положения.

Я кодировал варианталгоритма кучи, который может генерировать сигнатуру каждой перестановки.

    def permute(a, l, r): 
        if l==r:          
            print'Permutation--:',a
        else: 
            for i in xrange(l,r+1): 
                if i!=l:
                    a[0]=(-1)*int(a[0])#Sign for permutation
                a[l], a[i] = a[i], a[l] 
                permute(a, l+1, r)             
                a[l], a[i] = a[i], a[l]                         
                if i!=l:#Sign for permutation
                    a[0]=(-1)*int(a[0])




    test = "1hgfe"
    n = len(test) 
    a = list(test) 
    permute(a, 1, n-1)

В процедуре перестановки в список a вводится первый член списка, a [0] - знак, который в этом случае равен +1, и для каждой перестановки пение списка умножается на -1.Пока я думаю, что код работает, это результат теста.

          ['1', 'h', 'g', 'f', 'e']  (h->h) (g->g) (f->f) (e->e)       (-1)^(4-4) or identity =+1  
          [-1, 'h', 'g', 'e', 'f']   (h->h) (g->g) (f->e)              (-1)^(4-3)=-1
          [-1, 'h', 'f', 'g', 'e']   (h->h) (g->f) (e->e)              (-1)^(4-3)=-1
          [1, 'h', 'f', 'e', 'g']    (h->h) (g->f->e)                  (-1)^(4-2)=+1
          [-1, 'h', 'e', 'f', 'g']   (h->h) (g->e) (f->f)              (-1)^(4-3)=-1
          [1, 'h', 'e', 'g', 'f']    (h->h) (g->e->f)                  (-1)^(4-2)=+1
          [-1, 'g', 'h', 'f', 'e']   (h->g) (f->f) (e->e)              (-1)^(4-3)=-1
          [1, 'g', 'h', 'e', 'f']    (h->g) (f->e)                     (-1)^(4-2)=+1
          [1, 'g', 'f', 'h', 'e']    (h->g->f) (e->e)                  (-1)^(4-2)=+1
          [-1, 'g', 'f', 'e', 'h']   (h->g->f->e)                      (-1)^(4-1)=-1
          [1, 'g', 'e', 'f', 'h']    (h->g->e) (f->f)                  (-1)^(4-2)=+1
          [-1, 'g', 'e', 'h', 'f']   (h->g->e->f)                      (-1)^(4-1)=-1
          [-1, 'f', 'g', 'h', 'e']   (h->f) (g->g)(e->e)               (-1)^(4-3)=-1
          [1, 'f', 'g', 'e', 'h']    (h->f->e) (g->g)                  (-1)^(4-2)=+1
          [1, 'f', 'h', 'g', 'e']    (h->f->g) (e->e)                  (-1)^(4-2)=+1
          [-1, 'f', 'h', 'e', 'g']   (h->f->e->g)                      (-1)^(4-1)=-1
          [1, 'f', 'e', 'h', 'g']    (h->f) (g->e)                     (-1)^(4-2)=+1
          [-1, 'f', 'e', 'g', 'h']   (h->f->g->e)                      (-1)^(4-1)=-1
          [-1, 'e', 'g', 'f', 'h']   (h->e) (g->g) (f->f)              (-1)^(4-3)=-1
          [1, 'e', 'g', 'h', 'f']    (h->e->f) (g->g)                  (-1)^(4-2)=+1
          [1, 'e', 'f', 'g', 'h']    (h->e) (g->f)                     (-1)^(4-2)=+1
          [-1, 'e', 'f', 'h', 'g']   (h->e->g->f)                      (-1)^(4-1)=-1
          [1, 'e', 'h', 'f', 'g']    (h->e->g) (f->f)                  (-1)^(4-2)=+1
          [-1, 'e', 'h', 'g', 'f']   (h->e->f->g)                      (-1)^(4-1)=-1  

Мои вопросы: Как вы думаете, мой код будет применим к любому размеру списка, то есть [1, A, B, C ......, Z_n]?Есть ли более эффективный способ генерировать перестановки и их знаки?

1 Ответ

0 голосов
/ 08 февраля 2019

Да, ваш метод правильный.Вместо того, чтобы доказать это непосредственно, вы должны доказать, что

(1) выполнение permute(a, l, r) возвращает каждую перестановку от l -го до r -го букв a ровно один раз и завершаются с a, равным тому, что было в начале выполнения.

Это просто доказать путем наведения на r - l.Без «выходов с a равными» части заявки это было бы сложно.

Что касается правильных знаков, то это просто инвариант цикла: каждый раз, когда вы меняете две разные записи, выумножьте знак на -1, и это единственный раз, когда вы меняете знак.Так что да, 0-я запись является знаком перестановки в каждый момент вашего процесса.

TAoCP Кнута (Том 4A) имеет раздел 7.2.1.2, посвященный алгоритмам, генерирующим все перестановки.Некоторые из них также могут быть легко изменены, чтобы генерировать свои знаки.Мне интересно, если ваш среди них.

...