Завдання полягає в тому, щоб написати найшвидший код, можливий для обчислення Хафніана матриці .
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 секунд. (Піпі повільніше)