Thách thức là viết mã nhanh nhất có thể để tính toán Hafnian của ma trận .
Các Hafnian của một đối xứng 2n
-by- 2n
ma trận A
được định nghĩa là:
Ở đây S 2n đại diện cho tập hợp tất cả các hoán vị của các số nguyên từ 1
đến 2n
, đó là[1, 2n]
.
Liên kết wikipedia cũng cung cấp một công thức tìm kiếm khác có thể được quan tâm (và thậm chí các phương thức nhanh hơn tồn tại nếu bạn tìm kiếm thêm trên web). Cùng một trang wiki nói về ma trận kề, nhưng mã của bạn cũng sẽ hoạt động cho các ma trận khác. Bạn có thể giả sử tất cả các giá trị sẽ là số nguyên nhưng không phải tất cả chúng đều dương.
Ngoài ra còn có một thuật toán nhanh hơn nhưng có vẻ khó hiểu. và Christian Sievers là người đầu tiên thực hiện nó (trong Haskell).
Trong câu hỏi này, ma trận đều vuông và đối xứng với kích thước chẵn.
Tham chiếu thực hiện (lưu ý điều này là sử dụng phương pháp chậm nhất có thể).
Dưới đây là một số ví dụ mã python từ ông 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
Nhiệm vụ
Bạn nên viết mã, được đưa ra 2n
bởi một 2n
ma trận, xuất ra Hafnian của nó.
Vì tôi sẽ cần kiểm tra mã của bạn, sẽ rất hữu ích nếu bạn có thể đưa ra một cách đơn giản để tôi đưa ra một ma trận làm đầu vào cho mã của bạn, ví dụ bằng cách đọc từ tiêu chuẩn trong. Tôi sẽ kiểm tra mã của bạn trong các ma trận được chọn ngẫu nhiên với các yếu tố được chọn từ {-1, 0, 1}. Mục đích của việc thử nghiệm như thế này là để giảm khả năng Hafnian sẽ có giá trị rất lớn.
Lý tưởng nhất là mã của bạn sẽ có thể đọc chính xác như tôi có chúng trong các ví dụ trong câu hỏi này ngay từ tiêu chuẩn. Đó là [[1,-1],[-1,-1]]
ví dụ đầu vào sẽ như thế nào . Nếu bạn muốn sử dụng định dạng đầu vào khác, vui lòng hỏi và tôi sẽ cố gắng hết sức để đáp ứng.
Điểm và quan hệ
Tôi sẽ kiểm tra mã của bạn trên các ma trận ngẫu nhiên có kích thước tăng dần và dừng lần đầu tiên mã của bạn mất hơn 1 phút trên máy tính của tôi. Các ma trận cho điểm sẽ phù hợp với tất cả các bài nộp để đảm bảo sự công bằng.
Nếu hai người có cùng số điểm thì người chiến thắng là người nhanh nhất với giá trị đó n
. Nếu những cái đó trong vòng 1 giây với nhau thì đó là cái được đăng đầu tiên.
Ngôn ngữ và thư viện
Bạn có thể sử dụng bất kỳ ngôn ngữ và thư viện có sẵn nào bạn thích nhưng không có chức năng có sẵn để tính toán Hafnian. Nếu khả thi, sẽ rất tốt để có thể chạy mã của bạn, vì vậy vui lòng bao gồm một lời giải thích đầy đủ về cách chạy / biên dịch mã của bạn trong Linux nếu có thể.
Máy của tôi Thời gian sẽ được chạy trên máy 64 bit của tôi. Đây là bản cài đặt Ubuntu tiêu chuẩn với RAM 8GB, Bộ xử lý tám lõi AMD FX-8350 và Radeon HD 4250. Điều này cũng có nghĩa là tôi cần có thể chạy mã của bạn.
Gọi để trả lời bằng nhiều ngôn ngữ
Sẽ thật tuyệt khi nhận được câu trả lời bằng ngôn ngữ lập trình siêu nhanh yêu thích của bạn. Để bắt đầu mọi thứ, làm thế nào về fortran , nim và rỉ sét ?
Bảng xếp hạng
- 52 và đấm bằng C ++ . 30 giây.
- 50 bởi NGN sử dụng C . 50 giây.
- 46 bởi Christian Sievers sử dụng Haskell . 40 giây.
- 40 và đấm bằng Python 2 + PyPy . 41 giây.
- 34 bởi ngn sử dụng Python 3 + pypy . 29 giây.
- 28 bởi Dennis bằng Python 3 . 35 giây. (Pypy chậm hơn)