Завдання полягає в тому, щоб написати найшвидший код, можливий для обчислення Хафніана матриці .
Hafnian симетричною 2n
матриці з розмірністю 2n
матриці A
визначаються наступним чином:
Тут S 2n являє собою сукупність усіх перестановок цілих чисел від 1
до 2n
, тобто [1, 2n]
.
Посилання на вікіпедію також дає іншу формулу, яка може представляти інтерес (і ще швидші методи існують, якщо ви заглянете далі в Інтернет). Ця ж сторінка вікі розповідає про матриці суміжності, але ваш код повинен працювати і для інших матриць. Ви можете припустити, що всі значення будуть цілими числами, але не те, що вони всі позитивні.
Існує також більш швидкий алгоритм, але він, здається, важко зрозуміти. а Крістіан Сіверс першим здійснив це (у Хаскеллі).
У цьому питанні матриці всі квадратні та симетричні з рівними розмірами.
Реалізація довідки (зверніть увагу, що це використовується найповільніший можливий метод).
Ось приклад коду python від містера Xcoder.
from itertools import permutations
from math import factorial
def hafnian(matrix):
my_sum = 0
n = len(matrix) // 2
for sigma in permutations(range(n*2)):
prod = 1
for j in range(n):
prod *= matrix[sigma[2*j]][sigma[2*j+1]]
my_sum += prod
return my_sum / (factorial(n) * 2 ** n)
print(hafnian([[-1, 1, 1, -1, 0, 0, 1, -1], [1, 0, 1, 0, -1, 0, -1, -1], [1, 1, -1, 1, -1, -1, 0, -1], [-1, 0, 1, -1, -1, 1, -1, 0], [0, -1, -1, -1, -1, 0, 0, -1], [0, 0, -1, 1, 0, 0, 1, 1], [1, -1, 0, -1, 0, 1, 1, 0], [-1, -1, -1, 0, -1, 1, 0, 1]]))
4
M = [[1, 1, 0, 0, 0, 0, 0, 1, 0, 0], [1, 1, -1, 0, -1, 1, 1, 1, 0, -1], [0, -1, -1, -1, 0, -1, -1, 0, -1, 1], [0, 0, -1, 1, -1, 1, -1, 0, 1, -1], [0, -1, 0, -1, -1, -1, -1, 1, -1, 1], [0, 1, -1, 1, -1, 1, -1, -1, 1, -1], [0, 1, -1, -1, -1, -1, 1, 0, 0, 0], [1, 1, 0, 0, 1, -1, 0, 1, 1, -1], [0, 0, -1, 1, -1, 1, 0, 1, 1, 1], [0, -1, 1, -1, 1, -1, 0, -1, 1, 1]]
print(hafnian(M))
-13
M = [[-1, 0, -1, -1, 0, -1, 0, 1, -1, 0, 0, 0], [0, 0, 0, 0, 0, -1, 0, 1, -1, -1, -1, -1], [-1, 0, 0, 1, 0, 0, 0, 1, -1, 1, -1, 0], [-1, 0, 1, -1, 1, -1, -1, -1, 0, -1, -1, -1], [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 0], [-1, -1, 0, -1, 0, 0, 1, 1, 1, 1, 1, 0], [0, 0, 0, -1, 0, 1, 1, -1, -1, 0, 1, 0], [1, 1, 1, -1, 0, 1, -1, 1, -1, -1, -1, -1], [-1, -1, -1, 0, 0, 1, -1, -1, -1, 1, -1, 0], [0, -1, 1, -1, 1, 1, 0, -1, 1, -1, 1, 1], [0, -1, -1, -1, -1, 1, 1, -1, -1, 1, 0, -1], [0, -1, 0, -1, 0, 0, 0, -1, 0, 1, -1, 1]]
print(hafnian(M))
13
M = [[-1, 1, 0, 1, 0, -1, 0, 0, -1, 1, -1, 1, 0, -1], [1, -1, 1, -1, 1, 1, -1, 0, -1, 1, 1, 0, 0, -1], [0, 1, 1, 1, -1, 1, -1, -1, 0, 0, -1, 0, -1, -1], [1, -1, 1, -1, 1, 0, 1, 1, -1, -1, 0, 0, 1, 1], [0, 1, -1, 1, 0, 1, 0, 1, -1, -1, 1, 1, 0, -1], [-1, 1, 1, 0, 1, 1, -1, 0, 1, -1, -1, -1, 1, -1], [0, -1, -1, 1, 0, -1, -1, -1, 0, 1, -1, 0, 1, -1], [0, 0, -1, 1, 1, 0, -1, 0, 0, -1, 0, 0, 0, 1], [-1, -1, 0, -1, -1, 1, 0, 0, 1, 1, 0, 1, -1, 0], [1, 1, 0, -1, -1, -1, 1, -1, 1, 1, 1, 0, 1, 0], [-1, 1, -1, 0, 1, -1, -1, 0, 0, 1, -1, 0, -1, 0], [1, 0, 0, 0, 1, -1, 0, 0, 1, 0, 0, 1, 1, 1], [0, 0, -1, 1, 0, 1, 1, 0, -1, 1, -1, 1, 1, -1], [-1, -1, -1, 1, -1, -1, -1, 1, 0, 0, 0, 1, -1, -1]]
print(hafnian(M))
83
Завдання
Ви повинні написати код , який, дається з 2n
допомогою 2n
матриці, виводить її Hafnian.
Оскільки мені знадобиться перевірити ваш код, було б корисно, якби ви могли дати простий спосіб мені надати матрицю як вхід до вашого коду, наприклад, читаючи зі стандарту дюйма. Я перевірю ваш код у випадково вибраних матрицях з елементами вибрано з {-1, 0, 1}. Мета такого тестування - зменшити ймовірність того, що Гафній буде дуже великою цінністю.
В ідеалі ваш код зможе читати в матрицях саме так, як я їх маю у прикладах у цьому питанні прямо від стандартних дюймів. Це буде вхідний вигляд, [[1,-1],[-1,-1]]
наприклад. Якщо ви хочете використовувати інший формат введення, будь ласка, запитайте, і я зроблю все можливе, щоб розмістити його.
Оцінки та зв’язки
Я перевіряю ваш код на випадкових матрицях збільшення розміру і зупиняюсь, коли ваш код займе більше ніж 1 хвилину на моєму комп’ютері. Матриці оцінювання будуть послідовними для всіх робіт, щоб забезпечити справедливість.
Якщо двоє людей отримують однаковий бал, тоді виграє той, хто найшвидший за цю величину n
. Якщо вони знаходяться в межах 1 секунди один від одного, то це перша, розміщена першою.
Мови та бібліотеки
Ви можете використовувати будь-яку доступну мову та бібліотеки, які вам подобаються, але жодної попередньої функції для обчислення Хафніана. Там, де це можливо, було б добре запустити свій код, тому, будь-ласка, включіть повне пояснення, як запустити / скомпілювати свій код в Linux, якщо це можливо. "
Моя машина Часи синхронізуються на моєму 64-бітному апараті. Це стандартна установка ubuntu з 8 ГБ оперативної пам’яті, AMD FX-8350 восьмиядерний процесор та Radeon HD 4250. Це також означає, що мені потрібно мати можливість запускати ваш код.
Зателефонуйте на відповіді іншими мовами
Було б чудово отримати відповіді на вашій улюбленій мові програмування супер швидкої. Для того, щоб почати речі, як про FORtran , ЧПМ і іржі ?
Таблиця лідерів
- 52 миль за допомогою C ++ . 30 секунд.
- 50 з використанням СПП C . 50 секунд.
- 46 Крістіан Сіверс за допомогою Haskell . 40 секунд.
- 40 миль за допомогою Python 2 + pypy . 41 секунда.
- 34 на ngn, використовуючи Python 3 + pypy . 29 секунд.
- 28 Деніс за допомогою Python 3 . 35 секунд. (Піпі повільніше)