比尔的猜想如果您证明/反驳则一百万美元的奖金。
它指出,如果A,B,C,x,y和z是x,y,z> 2的正整数,则A,B和C具有共同的质因数。
挑战在于编写一个程序来搜索反例以证明这一点!
规则
- 编写程序,搜索比尔猜想的反例
- 您可以执行穷举搜索(即,所有适合此格式的数字的可能组合)或使用一些优化方法(例如,A和B是对称的)。
- 您必须使用任意精度的整数。
比尔的猜想如果您证明/反驳则一百万美元的奖金。
它指出,如果A,B,C,x,y和z是x,y,z> 2的正整数,则A,B和C具有共同的质因数。
挑战在于编写一个程序来搜索反例以证明这一点!
Answers:
我可怜的懒惰(双关语意),但是为什么不……似乎符合规则。
import Control.Monad
import Control.Monad.Omega
main=print.filter(\[(a,x),(b,y),(c,z)]
->and$(a^x+b^y==c^z):zipWith(((>1).).gcd)[a,b,c][b,c,a])
.runOmega$mapM(\_->liftM2(,)(each[1..])$each[3..])"123"
这将打印1个满足counterexample属性的所有组合。我使用了control-monad-omega软件包为diagonalisingℕ 6 ...可能被认为是库作弊。但是看到有人以后会在APL答案中发布所有这些内容已内置在语言中的信息(不是吗?),我对此不做过多介绍...
当然,该程序太慢了(天真的用尽,并且链表作为数据结构),以至于无法真正产生反例,但是Haskell本身实际上可以实现不错的性能。
1因为它以列表格式(即一行)打印元组,所以您需要关闭终端的缓冲,否则将看不到结果何时出现。或者,您也可以替换print
为mapM_ print
以便在每个结果之后都换行,刷新行缓冲的终端。
要测试该程序,请更改each[3..]
为each[2..]
,然后您将得到所有非互质毕达哥拉斯元组作为结果。
好的,我浏览了其中的一些链接,但是老实说它们有点无聊。我对用哈希表和诸如此类的东西来优化地狱不感兴趣。我为什么要这样?您有一个该死的超级计算机!
地狱,我什至不想打扰循环!此解决方案将遵循无循环规则。
请注意,我将要编写的代码不是很好的代码,也不是我在现实生活中编写的那种代码(以防任何潜在的雇主偶然读到此代码)。该代码强调简洁和在叙述中工作的能力,并且不强调适当的约定,仪式和循环等。
为了演示我在说什么,我们将从一个带有公共字段的令人震惊的类开始,以存储该方程的操作数:
class BealOperands
{
public BigInteger A, B, C, x, y, z;
}
好的,我们将从最困难的挑战开始。我们需要找出一种方法来对这些操作数的每种组合进行置换。毫无疑问,有比检查每个排列更有效的方法,但是我不介意弄清楚它们。我为什么要呢?我们有一个该死的超级计算机!
这是我想出的算法。它效率极低,并且一次又一次地遍历相同的操作数,但是谁在乎呢?超级计算机!
如何做到所有这些没有循环?简单!只需实现IEnumerable
和相关联IEnumerator
即可抽出排列。稍后,我们将使用LINQ进行查询。
class BealOperandGenerator : IEnumerable<BealOperands>
{
// Implementation of IEnumerable<> and IEnumerable -- basically boilerplate to get to BealOperandGeneratorEnumerator.
public IEnumerator<BealOperands> GetEnumerator() { return new BealOperandGeneratorEnumerator(); }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
class BealOperandGeneratorEnumerator : IEnumerator<BealOperands>
{
public BealOperandGeneratorEnumerator() { Reset(); }
private BealOperands operands;
private BigInteger @base;
public void Reset()
{
// A is set to 0, which is "before" its minimum value, because IEnumerators are supposed to
// point to their first element *after* the first call to MoveNext().
// All other operands are set to their minimum values.
operands = new BealOperands { A = 0, B = 1, C = 1, x = 3, y = 3, z = 3 };
@base = 2;
}
public BealOperands Current
{
get
{
// We need to return a copy, since we'll be manipulating our internal one.
return new BealOperands {
A = operands.A, B = operands.B, C = operands.C,
x = operands.x, y = operands.y, z = operands.z };
}
}
public bool MoveNext()
{
// Increment the lowest "digit" and "carry" as necessary.
operands.A++;
if (operands.A - 1 >= @base)
{
operands.A = 1; operands.B++;
if (operands.B - 1 >= @base)
{
operands.B = 1; operands.C++;
if (operands.C - 1 >= @base)
{
operands.C = 1; operands.x++;
if (operands.x - 3 >= @base)
{
operands.x = 3; operands.y++;
if (operands.y - 3 >= @base)
{
operands.y = 3; operands.z++;
if (operands.z - 3 >= @base)
{
operands.z = 3; @base++;
}
}
}
}
}
}
// There will always be more elements in this sequence.
return true;
}
// More boilerplate
object System.Collections.IEnumerator.Current { get { return Current; } }
public void Dispose() { }
}
现在我们开始营业!我们所需要做的就是枚举BealOperandGenerator
Beal猜想的一个实例并找到一个反例。
我们的下一个大问题是,似乎没有一种将a提升为a BigInteger
的幂的内置方法BigInteger
。有BigInteger.Pow(BigInteger value, int exponent)
和BigInteger.ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
,但没有方法将a提升BigInteger
为另一BigInteger
模无穷大的幂。
问题的根基啊!看来是要用我们的IEnumerable
/ IEnumerator
锤子解决!
class BigIntegerPowerEnumerable : IEnumerable<Tuple<BigInteger, BigInteger>>
{
public BigIntegerPowerEnumerable(BigInteger @base, BigInteger exponent) { this.@base = @base; this.exponent = exponent; }
BigInteger @base, exponent;
public IEnumerator<Tuple<BigInteger, BigInteger>> GetEnumerator() { return new BigIntegerPowerEnumerator(@base, exponent); }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
class BigIntegerPowerEnumerator : IEnumerator<Tuple<BigInteger, BigInteger>>
{
public BigIntegerPowerEnumerator(BigInteger @base, BigInteger exponent)
{
originalBase = @base;
originalExponent = exponent;
Reset();
}
BigInteger originalBase, currentBase, originalExponent, currentExponent;
bool finished;
public void Reset()
{
// IEnumerable.Reset() is a silly method. You're required to implement it when you implement IEnumerable,
// but it isn't used by foreach or LINQ or anything. If you want to re-enumerate the enumerable, just get
// a brand new enumerator.
// In this case it gets in the way. The only reason I'm storing the original values is so I can implement
// this useless method properly. I supposed I could just throw a NotImplementedException or something,
// but it's done now.
currentBase = originalBase;
currentExponent = originalExponent;
finished = false;
}
public bool MoveNext()
{
if (finished) return false;
if (currentExponent <= Int32.MaxValue)
{
currentBase = BigInteger.Pow(currentBase, (Int32)currentExponent);
currentExponent = 1;
finished = true;
}
else
{
currentBase = BigInteger.Pow(currentBase, Int32.MaxValue);
currentExponent -= Int32.MaxValue;
}
return true;
}
public Tuple<BigInteger, BigInteger> Current
{
get { return new Tuple<BigInteger, BigInteger>(currentBase, currentExponent); }
}
object System.Collections.IEnumerator.Current { get { return Current; } }
public void Dispose() { }
}
static class BigIntegerPowExtension
{
public static BigInteger Pow(this BigInteger @base, BigInteger exponent)
{
return new BigIntegerPowerEnumerable(@base, exponent).Last().Item1;
}
}
现在我们有了一个扩展方法Pow
,可以在上调用它BigInteger
,并采用BigInteger
指数且没有模数。
好,让我们退后一步。我们怎么知道一个特定的BealOperands
某件事是否是Beal猜想的反例?好吧,有两件事必须是正确的:
我们已经具备了检查第一个条件所需的条件。事实证明,第二种情况比听起来容易得多。BigInteger
提供一个可爱的GreatestCommonDivisor
方法,它使我们可以方便地回避试图实现无循环的整个噩梦。
因此,我们准备编写一种方法来检查a BealOperands
是否是反例。开始...
static class BealOperandsExtensions
{
public static bool IsBealsConjectureCounterExample(this BealOperands o)
{
// If the equation isn't even true, we don't have a counter example unfortunately
if (o.A.Pow(o.x) + o.B.Pow(o.y) != o.C.Pow(o.z))
{
return false;
}
// We have a counterexample if A, B and C are coprime
return BigInteger.GreatestCommonDivisor(o.A, o.B) == 1 &&
BigInteger.GreatestCommonDivisor(o.A, o.C) == 1 &&
BigInteger.GreatestCommonDivisor(o.B, o.C) == 1;
}
}
最后,我们可以使用这种相当巧妙的Main
方法将所有内容整合在一起:
static class Program
{
static void Main()
{
var bealOperandGenerator = new BealOperandGenerator();
if (bealOperandGenerator.Any(o => o.IsBealsConjectureCounterExample()))
{
Console.WriteLine("IN YOUR FACE, BEAL!");
}
}
}
没有C ^ Z <= 1.0E27的反例。
自2019年2月起,我将根据“ X”和/或“ Y”指数必须大于等于5的假设签出C ^ Z <= 1.0E29。
该程序的当前版本(“ X”和/或“ Y”> = 5)在AMD 2920X上花费不到1秒的时间才能找到C ^ Z <= 1.0E15的所有解决方案。(但是所有的gcd(A,B,C)> = 2)
有关详细信息,请访问http://www.durangobill.com/BealsConjecture.html
我可以修改当前代码(使用“ C”和OpenMP)以超出这些限制,但是要运行它需要128GB以上的RAM。(数百个CPU也会有所帮助。成千上万个CPU甚至会更好。)(如果您可以免费使用这样的东西,请与我联系。)
我的电子邮件地址在我的主页上,网址为http://www.durangobill.com
Beal搜索程序的第二个版本已完成。结果是:
1)没有反例。所有通用解决方案的完整列表 至少有一个指数 可以在以下位置看到:http : //www.durangobill.com/BealXgt3e27.txt
2)如果您假设至少有指数 一定是 ,没有反例 。所有通用解决方案的完整列表 至少有一个指数 且C ^ Z <1.0E29可以在以下网址查看:http ://www.durangobill.com/BealXgt4e29.txt
有关详细信息,请访问:http : //www.durangobill.com/BealsConjecture.html
接下来的两个问题是:1)超级计算机可以扩展搜索范围吗?2)如果超级计算机可以扩展搜索范围,是否可行?
1)要将以上任一搜索扩展到1.0E30,除非内核可以共享300GB,否则每个内核将需要300GB RAM。对于超过1.0E30的指数幂,每增加一次增量,所需的RAM量将增加至少2.2倍。
2)指数进一步增加到1.0E30或超过1.0E30,所需的处理能力将使总CPU时间乘以约3.8。使用12个核心,搜索到1.0E29花费了2周的时间。超级计算机时间通常不是“空闲”的,几乎没有任何反例的前景。
作为durangobill.com/BealE29code.txt上代码效率的指南,12个内核中的每个内核平均每秒对内部循环进行2.2亿次循环迭代。(平均是2周的运行时间。)(RAM内存的增加超过我的能力,则平均速度将提高2倍。)
我将让奥斯汀回答1)和2),因为他可以使用超级计算机,但我没有。(如果偶然)1)和2)都是“执行”,则可以向“ C”代码提供我不熟悉大型超级计算机集群的多线程指令的警告。)
不得不在2条评论中添加它以使其适合。
主要数组分配如下:
SortHeads = calloc(PRIME1+1, 8);
X2YmodPrime1 = calloc(ARRAYSIZE+1, 4);
X2YmodPrime2 = calloc(ARRAYSIZE+1, 4);
Base = calloc(ARRAYSIZE+1, 4);
Power = malloc(ARRAYSIZE+1);
(这些阵列需要128GB的RAM)
与:
#define PRIME1 2147483647LLU
#define PRIME2 2147483629LLU
#define ARRAYSIZE 4700000000LL
“基本”实际上需要33位(cbrt(1.0E29)
)-多余的位填充在“电源”中(仅需要7位)。
数组的操作类似于哈希表。但是,由于它们是按PRIME1排序的,并且仅用作查找表,因此不需要链接列表即可访问它们。因此,结果是非常快速的线性时间查找,以查看试验A ^ X + B ^ Y =任何C ^ Z。
因此,最内部循环中的语句仅深两个循环。
“ Pragma”语句控制所使用的多处理核心的数量(在本例中为12)-全部都可以访问阵列的单个副本。
这是“主”代码(在“ C”中)(希望注释适合所发布的行长。如果不行,请将其复制出来,然后将代码粘贴到行长更长的某些文档中。)