对称2n
按2n
矩阵的Hafnian A
定义为:
这里S 2n表示整数从1
to 的所有置换的集合2n
,即[1, 2n]
。
Wikipedia链接还提供了一个可能引起您兴趣的不同外观公式(如果您在网络上进一步浏览,甚至可以使用更快的方法)。相同的Wiki页面讨论了邻接矩阵,但是您的代码也应适用于其他矩阵。您可以假设所有值都是整数,但不能假设它们都是正数。
还有一种更快的算法, 但似乎很难理解。而Christian Sievers是第一个实施它的人(在Haskell中)。
在这个问题上,矩阵都是正方形的,并且对称且偶数维。
参考实现(请注意,这是使用最慢的方法)。
这是Xcoder先生提供的一些示例python代码。
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
by 2n
矩阵,并输出其Hafnian。
因为我将需要测试您的代码,所以如果您能提供一种简单的方法将矩阵作为代码的输入,这将很有帮助,例如通过读取标准输入。我将使用元素随机选择矩阵来测试代码从{-1,0,1}中选择。这样测试的目的是为了减少Hafnian值很大的机会。
理想情况下,您的代码将能够完全按照我在本问题中的示例中的格式直接从标准输入中读取矩阵。这就是[[1,-1],[-1,-1]]
例如输入。如果您想使用其他输入格式,请询问,我将尽力适应。
得分和联系
我将在大小增加的随机矩阵上测试您的代码,并在您的代码第一次在我的计算机上花费超过1分钟时停止。所有提交的评分矩阵将保持一致,以确保公平。
如果两个人获得相同的分数,那么胜者就是那个值最快的人n
。如果它们彼此相距1秒以内,则它是第一个发布的。
语言和图书馆
您可以使用任何喜欢的可用语言和库,但不能使用预先存在的函数来计算Hafnian。在可行的情况下,能够运行您的代码将是一个很好的选择,因此,请尽可能提供有关如何在Linux中运行/编译代码的完整说明。
我的机器计时将在我的64位机器上运行。这是带有8GB RAM,AMD FX-8350八核处理器和Radeon HD 4250的标准ubuntu安装。这也意味着我需要能够运行您的代码。
要求更多语言的答案
最好用您喜欢的超快速编程语言获得答案。首先,fortran,nim和rust怎么样?
排行榜
- 使用C ++达到52英里。30秒。
- 50通过NGN使用Ç。50秒
- 46由Christian Sievers使用Haskell撰写。40秒
- 使用Python 2 + pypy达到40英里。41秒。
- 34,通过使用NGN 的Python 3 + pypy。29秒。
- 28由Dennis使用Python 3编写。35秒 (Pypy慢一些)