Перестановка матриці на місці


27

Я хочу змінити щільну квадратну матрицю переходу на місці, змінивши порядок кількох її рядків і стовпців, використовуючи бібліотеку numpy python. Математично це відповідає попередньому множенню матриці на перестановкову матрицю P і післяпомноження на P ^ -1 = P ^ T, але це не є обчислювально обґрунтованим рішенням.

Зараз я обмінюю рядки та стовпці вручну, але я б очікував, що numpy матиме гарну функцію f (M, v), де M має n рядків та стовпців, а v має n записів, так що f (M, v) оновлення М відповідно до індексу перестановки проти. Можливо, мені просто не вдається шукати Інтернет.

Щось подібне може бути можливим при "розширеному індексуванні" numpy, але я розумію, що таке рішення не було б на місці. Також для деяких простих ситуацій може бути достатньо окремо відстежити перестановку індексу, але це не зручно в моєму випадку.

Додано:
Іноді, коли люди говорять про перестановки, вони мають на увазі лише вибірку випадкових перестановок, наприклад, як частину процедури отримання р-значень у статистиці. Або вони означають підрахунок або перерахування всіх можливих перестановок. Я не кажу про ці речі.

Додано:
Матриця є досить маленькою, щоб вміститися в робочу пам’ять, але досить велика, що я не хочу копіювати її бездумно. Насправді я хотів би використовувати матриці якомога більші, але я не хочу мати справу з незручністю неможливості їх утримувати в оперативній пам'яті, і я виконую операції O (N ^ 3) LAPACK на матриці, яка також обмежте практичний розмір матриці. Наразі я копіюю матриці цієї великої кількості без потреби, але сподіваюся, що цього можна легко уникнути для перестановки.


3
Було б добре, якби ви могли оновити питання, щоб вказати розмір матриць. "Гігантський" не означає одне й те саме для всіх людей.
Білл Барт

2
Ви праві, що розширена (або так звана фантазія) індексація створює копію. Але якщо ви погоджуєтеся жити з цим фактом, то ваш код - це просто M[v]перестановка рядків.
Даніель Велков

@daniel: І було б M [v,:] [:, v] зробити всю перестановку? Це був би найкращий спосіб отримати перестановку за допомогою фантазійної індексації? І чи використовував би він 3x матричну пам'ять, включаючи розмір вихідної матриці, рядка + стовпчик перестановленої матриці та тимчасовий рядок перестановленої матриці?
немає

Це правильно, ви мали б свою оригінальну матрицю та 2 примірники. До речі, для чого вам потрібно переставляти одночасно і рядки, і стовпці?
Даніель Велков

4
Що ти будеш робити з перестановленою матрицею? Можливо, буде краще просто переставити вектор при застосуванні оператора.
Джед Браун

Відповіді:


9

Згідно з документами, у нумері немає методу перестановки на місці, такого як ndarray.sort .

Отже, ваші варіанти (якщо припустити, що Mце матриця та вектор перестановки)N×Np

  1. реалізація власного алгоритму в C як модуля розширення (але на місці алгоритми важкі, принаймні для мене!)
  2. накладних витратN

    for i in range(N):
        M[:,i] = M[p,i]
    for i in range(N):
        M[i,:] = M[i,p]
  3. пам'яті накладніN2

    M[:,:] = M[p,:]
    M[:,:] = M[:,p]

Сподіваємось, що ці неоптимальні хаки корисні.


@none - це злом 2. що ви називаєте "вручну міняти рядки та стовпці"?
Стефано М

1
Я б поєднав варіанти 1 і 2: записати код C, який використовує буфер порядку N для запису кожного перестановленого стовпця, а потім записує його назад, звідки він прийшов; потім зробіть те ж саме для рядків. Як пише @Stefano, для цього потрібна лише додаткова пам'ять, яку ви вже витрачаєте для зберігання перестановки p в першу чергу. O(N)p
Ерік П.

@ErikP. для впровадження C додаткова пам'ять є розумною, і впевненість, що ваше записування на розсип записується на темп та копіювати назад, є здоровим. Цікавим питанням є те, чи існують більш ефективні алгоритми, що мають O ( N ) додаткову пам'ять. Думаю, відповідь важко, оскільки ми повинні враховувати архітектуру процесора, схеми доступу до пам’яті, хіти кешу, ... Це сказав, що я буду дотримуватися ваших порад і піти на простий і простий в реалізації алгоритм. O(N)O(N)
Стефано М

2
Це дійсно хороший канідат для функції цитона. Має бути не більше 10 рядків. . . хочете, щоб я дав йому тріщину?
meawoppl

Лол. Я почав це Cython, потім знайшов правильну відповідь у функції, якою я весь час користуюся. До. Дивіться мою опубліковану відповідь.
meawoppl

6

Попередження: Наведений нижче приклад працює належним чином, але за допомогою повного набору параметрів, запропонованих у кінцевому підсумку, виявляється помилка або, принаймні, «недокументована функція» у функції numpy.take (). Деталі див. У коментарях нижче. Повідомлення про помилку подано .

Це можна зробити на місці за допомогою функції take () numpy , але для цього потрібно трохи стрибнути з обручем.

Ось приклад виконання випадкової перестановки рядків матриці ідентичності:

import numpy as np
i = np.identity(10)
rr = range(10)
np.random.shuffle(rr)
np.take(i, rr, axis=0)
array([[ 0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.]])

Щоб зробити це на місці, все, що вам потрібно зробити, - це вказати параметр "out", який буде таким же, як вхідний масив І вам потрібно встановити mode = "clip" або mode = "wrap". Якщо ви не встановите режим, він створить копію для відновлення стану масиву за винятком Python (див. Тут) .

На завершення нотатка здається, що це метод масиву, тому замість

np.take(i, rr, axis=0)

ви могли б зателефонувати

i.take(rr, axis=0)

якщо це більше на ваш смак. Таким чином, загалом дзвінок повинен виглядати приблизно так:

#Inplace Rearrange
arr = makeMyBixMatrix()
pVec0, pVec1 = calcMyPermutationVectors()
arr.take(pVec0, axis=0, out=arr, mode="clip")
arr.take(pVec1, axis=1, out=arr, mode="clip")

Для перестановки і рядків, і стовпців я думаю, що вам або доведеться запустити його двічі, або витягнути якісь потворні шенагігани з numpy.unravel_index, що болить мені в голові задуматися.


Як сказано, на місці алгоритми важкі. Ваше рішення не працює з numpy 1.6.2. та 1.7.1 (копії рядків / стовпців). Не встигли перевірити, чи вирішує цю проблему 1.8.x
Стефано М

Хммм. Чи можете ви розмістити тестовий код десь? В голові я відчуваю, ніби потрібно здійснити своєрідну операцію над показниками, що відбувається спочатку перед вищипуванням. Я більше буду досліджувати цього прем'єр-міністра.
meawoppl

1
Коли я запускаю цей код я отримую 1.6.2, test take, not overwriting: True, test not-in-place take: True, test in-place take: False, rr [3, 7, 8, 1, 4, 5, 9, 0, 2, 6], arr [30 70 80 70 40 50 90 30 80 90], ref [30 70 80 10 40 50 90 0 20 60]. Так, np.takeпринаймні, для numpy 1.6.2 не знає, як робити перестановку на місці і переплутує речі.
Стефано М

Єуч. Добре продемонстровано. Це, ймовірно, кваліфікується як помилка IMHO. Принаймні, документи повинні сказати, що вхід і вихід не можуть бути однаковим масивом, ймовірно, перевірте, щоб побачити, і виняток, якщо він є.
meawoppl

Погоджено про помилку: можливо, ви повинні додати до свого повідомлення примітку, щоб попередити читачів, що ваше рішення може призвести до неправильних результатів.
Стефано М

2

Якщо у вас розріджена матриця зберігається у COOформаті, може бути корисним наступне

    A.row = perm[A.row];
    A.col = perm[A.col];

ACOOpermnumpy.arraymm


але яка пам’ять накладні для зберігання повної щільної матриці як розрідженої C00матриці?
Федеріко Полоні

intfloatfloatn2numpy.ndarray

1

У мене недостатньо репутації для коментарів, але я думаю, що наступне питання ТА може бути корисним: /programming/4370745/view-onto-a-numpy-array

Основні моменти , які ви можете використовувати основні нарізки і створять уявлення про до масиву без копіювання, але якщо ви робите передові нарізки / індексацію , то це буде створювати копію.


ОП просить перестановку, а це неможливо при базовому нарізанні.
Стефано М

Ви, звичайно, правильні. Я подумав, що ОП буде корисно зрозуміти, що відбувається з нарізкою (якщо вони не знають), оскільки їх турбує, коли будуть копії. Якщо він використовував щось із вашої відповіді, я думаю, що це було б добре знати, оскільки ви використовуєте їх всередині петель.
відбувся

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.