Beal의 $ 1,000,000를 가져갑니다


17

Beal 's Conjecture 는 당신이 그것을 증명 / 증거하면 백만 달러의 상을받습니다.

이 경우한다고 A ^ x + B ^ y = C ^ zA, B, C, X, Y, Z는 X, Y, Z> 2 다음 A, B와 양의 정수이며, 여기서 C 공통 소인수있다.

문제는이를 반증하기 위해 반대의 예를 찾는 프로그램을 작성하는 것입니다!

규칙

  • Beal 's Conjecture의 반대 사례를 검색하는 프로그램 작성
  • 철저한 검색을 수행하거나 (예 :이 형식에 맞는 모든 가능한 숫자 조합) 일부 최적화를 사용할 수 있습니다 (예 : A 및 B는 대칭).
  • 임의 정밀도 정수를 사용해야합니다.

노트

  • 이 작품은 인기 콘테스트입니다.
  • 속도는 필요하지 않지만 더 재미있게 만듭니다. 최적화!
  • 또한 가장 짧은 코드를 보는 데 관심이 있습니다. 당신은 나에게서 +1을 얻을 것입니다!
  • 내가 접근 할 수있는 슈퍼 컴퓨터에서 우승 프로그램을 운영 할 것입니다!
  • 이 추측은 사실로 간주되지만 시도 할 수 없다는 것을 의미하지는 않습니다!
  • Google의 Peter Norvig도이 문제를 시도했습니다. 그의 페이지 를 지침으로 사용할 수 있습니다 . 그는 예제로 사용할 수있는 짧은 파이썬 프로그램을 가지고 있습니다.
  • 구글에서 일하는 다른 사람이 Norvig의 접근 방식을 크게 개선했으며, 그의 페이지 (소스 코드 포함)는 여기 에서 찾을 수 있습니다 .
  • 2 년 전의 이것과 관련된 나의 SO 질문도 도움이 될 수 있습니다 . 지정된 범위의 모든 A ^ x 찾기 .

1
슈퍼 컴퓨터? 이제 멋지다. 현금을 나눌 가능성이 있습니까?
ɐɔıʇǝɥʇuʎs

@Synthetica이 추측은 이미 매우 큰 숫자로 이미 테스트되었으므로 이것은 대부분 재미를위한 것입니다. 그러나 물론 우리는 현금을 나눌 수 있습니다 :)
Austin Henley

2
"이것은 영원히 계속되거나 유한 한 상한을 허용해야한다. ... 어떤 대안이 아닌가?
undergroundmonorail

@undergroundmonorail 소수의 사용자 만 작업합니다.
Austin Henley

2
작은 숫자는 유한 상한입니다.
undergroundmonorail

답변:


4

나는 병적으로 게으르고 (말장난 의도) 있지만, 왜 ... 규칙을 이행하지 않는 것 같습니다.

하스켈, 204

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"

그러면 counterexample 속성을 충족하는 모든 조합 1 이 인쇄 됩니다. 나는 6 을 대각선으로 만들기 위해 control-monad-omega 패키지 를 사용했습니다 ... 라이브러리 속임수로 간주 될 수 있습니다. 그러나 누군가가 나중에이 모든 것들이 언어에 내장 된 APL 답변을 게시 할 때 (또는 그렇지 않습니까?), 나는 그것에 대해 너무 많이주지 않습니다 ...

물론이 프로그램은 실제로 속도가 느리기 때문에 (순진한 피로 및 데이터 구조로서의 링크 된 목록) 실제로는 반대의 예를 산출 할 수는 없지만 Haskell 자체는 실제로 적절한 성능을 달성 할 수 있습니다.


(1) 이 한 줄에 목록 형식의 튜플, 즉를 출력하기 때문에, 당신은 당신의 터미널의 전원이 버퍼링 전환해야하거나 결과에 올 때 당신은 볼 수 없습니다. 또는, 당신은 대체 할 수 printmapM_ print각 결과 후 줄 바꿈을 얻을 수 있도록, 라인 버퍼 터미널 플러싱.

프로그램을 테스트하려면로 변경 each[3..]하면 each[2..]코 프라임이 아닌 피타고라스 튜플을 모두 얻을 수 있습니다.


2

C #, 루프 없음

좋아, 나는 그 두 개의 링크를 훑어 보았지만 솔직히 말하면 약간 지루했다. 나는 해시 테이블과 그 밖의 것들로 지옥을 최적화하는 데 관심이 없다. 왜해야합니까? 당신은 망할 슈퍼 컴퓨터를 가지고 있습니다!

지옥, 나는 루프로 귀찮게하고 싶지 않습니다! 이 솔루션은 루프없는 규칙을 따릅니다 .

내가 쓰려고하는 코드는 좋은 코드가 아니거나 실생활에서 쓰려는 코드가 아닙니다 (예상 고용주가이 코드를 읽을 경우). 이 코드는 간결성과 내러티브 작업 능력을 강조하며 적절한 관습, 의식 및 고리 등을 강조하지 않습니다.

내가 말하고있는 것을 보여주기 위해, 우리는 방정식의 피연산자를 저장하기 위해 퍼블릭 필드를 가진 충격적인 클래스로 시작할 것입니다.

class BealOperands
{
    public BigInteger A, B, C, x, y, z;
}

가장 어려운 과제부터 시작하겠습니다. 이러한 피연산자의 모든 조합을 순회하는 방법을 찾아야합니다. 모든 순열을 확인하는 것보다 더 효율적으로 수행 할 수있는 방법이 있지만, 그것들을 알아낼 수는 없습니다. 왜 내가해야합니까? 망할 슈퍼 컴퓨터가 있습니다!

여기 내가 생각해 낸 알고리즘이 있습니다. 엄청나게 비효율적이며 동일한 피연산자를 반복해서 반복하지만 누가 신경 쓰나요? 슈퍼 컴퓨터!

  • 6 개의 피연산자를 밑이 2 인 숫자로 취급하고 모든 조합을 통해 순열하십시오.
  • 6 개의 피연산자를 밑 수가 3 인 숫자로 취급하고 모든 조합을 통과하십시오.
  • 6 개의 피연산자를 기본 4 자리 숫자로 취급하고 모든 조합을 통해 순열하십시오.
  • (...)

루프 없이이 모든 작업을 수행하는 방법은 무엇입니까? 쉬운! 그냥 구현 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() { }
}

이제 우리는 사업을 시작했습니다! 우리가해야 할 일은 인스턴스를 열거하고 BealOperandGeneratorBeal 's Conjecture의 반례를 찾는 것입니다.

우리의 다음 큰 문제는 BigInteger의 힘 을 높이기위한 기본 제공 방법이없는 것 BigInteger입니다. 있다 BigInteger.Pow(BigInteger value, int exponent), 그리고 BigInteger.ModPow(BigInteger value, BigInteger exponent, BigInteger modulus),하지만 방법은 인상하지 않으려면 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;
    }
}

이제 우리는 확장 메서드있어 PowA의 호출 할 수 있습니다, BigInteger그리고 소요 BigInteger지수없이 계수.

좋아, 물러서 자 특정 BealOperands이 Beal의 추측에 대한 반례 인지 어떻게 알 수 있습니까? 두 가지 사실이 필요합니다.

  • 페이지 상단에서 해당 수식에 연결하면 피연산자는 실제 방정식을 형성해야합니다.
  • A, B 및 C는 공통 소인수를 가져서는 안됩니다 (예 : GCD가 1).

우리는 첫 번째 상태를 확인하기 위해 필요한 것을 얻었습니다. 그리고 두 번째 조건은 소리보다 확인하기가 훨씬 쉽습니다. 루프없이 구현하려고하는 모든 악몽을 편리하게 회피 할 수 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!");
        }
    }
}

2

C ^ Z <= 1.0E27의 반례는 없습니다.

2019 년 2 월 기준으로“X”및 / 또는“Y”지수가> = 5 여야한다는 가정하에 C ^ Z <= 1.0E29를 확인하고 있습니다.

이 프로그램의 현재 버전 ( "X"및 / 또는 "Y"> = 5)은 C ^ Z <= 1.0E15에 대한 모든 솔루션을 찾기 위해 AMD 2920X에서 1 초 미만입니다. (그러나 모든 gcd (A, B, C)는> = 2입니다)

http://www.durangobill.com/BealsConjecture.html의 세부 사항

현재 코드 ( "C"및 OpenMP 사용)를 이러한 제한을 초과하여 수정할 수 있지만 실행하려면 128GB 이상의 RAM이 필요합니다. (수백 개의 CPU가 도움이 될 것입니다. 수천 개의 CPU가 더 나을 것입니다.) (이와 같은 것에 자유롭게 액세스 할 수 있다면 저에게 연락하십시오.)

내 이메일 주소는 내 홈페이지 ( http://www.durangobill.com) 에 있습니다 .


1
일부 코드로 이것을 해결할 수 있다면 올바른 답변 일 수 있습니다. 그렇지 않으면 질문에 대한 의견으로 가장 적합 할 것입니다. 그러나 당신이 한 일이 인상적입니다.
OUurous

많은 대학에는 고성능 클러스터가 있습니다. 하나에 연락하면 액세스 권한을 부여 할 수 있습니다. 유휴 상태 인 클러스터가 너무 많습니다.
Austin Henley

1

Beal 검색 프로그램의 두 번째 변형이 완료되었습니다. 결과는 다음과 같습니다.

<1026엑스+와이=(엑스,와이)> =4

(엑스,와이)> =5<1028엑스+와이=(엑스,와이)> =5

세부 사항 : http://www.durangobill.com/BealsConjecture.html

다음 두 가지 질문은 다음과 같습니다. 1) 슈퍼 컴퓨터가 검색을 확장 할 수 있습니까? 2) 슈퍼 컴퓨터가 검색을 확장 할 수 있다면 실용적입니까?

1) 위 검색 중 하나를 1.0E30으로 확장하려면 코어가 300GB를 공유 할 수 없으면 코어 당 300GB의 RAM이 필요합니다. 1.0E30을 초과하여 지수 전력이 추가로 증가 할 때마다 필요한 RAM의 양이 2.2 배 이상 증가합니다.

2) 1.0E30 이상으로 지수가 증가 할 때마다 필요한 처리 능력은 결합 된 CPU 시간에 약 3.8을 곱합니다. 1.0E29에 대한 검색은 12 개의 코어를 사용하여 2 주가 걸렸습니다. 슈퍼 컴퓨터 시간은 일반적으로 "자유"가 아니며, 반례가있을 가능성이 거의 없습니다.

durangobill.com/BealE29code.txt의 코드 효율성에 대한 지침으로 12 개의 코어 각각은 내부 루프에 대해 초당 평균 2 억 2 천만 개의 루프 반복을 수행했습니다. (평균은 2 주 실행입니다.) (내가 가진 것보다 RAM 메모리가 증가하면이 평균 속도가 2 배까지 증가합니다.)

오스틴이 슈퍼 컴퓨터에 액세스 할 수 있기 때문에 1)과 2)에 대답하도록하겠습니다. (원격으로 1)과 2)가 "go"인 경우 대형 슈퍼 컴퓨터 클러스터에 대한 다중 스레드 명령어에 익숙하지 않은 경고에 "C"코드를 제공 할 수 있습니다.


질문 하나에 답을 세 개로 나누지 않고 한 가지만 사용할 수 있습니까? 이전 답변을 편집 할 수 있다는 것을 알고 있습니까?
조 왕

반례 문을 찾아서 인쇄하지 말아 주셔서 감사합니다. 또한 이것도 코드 골프가 아닙니다 ...
Axman6

0

그것을 맞추기 위해 이것을 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”)입니다. 주석이 게시 된 줄 길이에 맞기를 바랍니다. 그렇지 않은 경우 주석을 복사하여 줄 길이가 더 긴 일부 문서에 붙여 넣으십시오.


주석 상자에는 600자를 사용할 수 있으며 코드에는 3,000+가 필요합니다. (모든 제안?) (여기에 코드를 게시 할 수없는 경우 웹 페이지에 코드를 게시 할 수 있습니다.)
Bill Butler

"main" "C"코드를 여기에 넣습니다. durangobill.com/BealE29code.txt 다른 내용이 없으면“C”의 다중 스레드 처리를위한“방법”의 예입니다.
Bill Butler

1
사이트에 오신 것을 환영합니다. 주석 상자는 600 자로 제한되지만 답변은 아닙니다. 답변에 코드를 쉽게 맞출 수 있어야합니다. 주석을 다듬지 않으려면. 또한 코드 블록을 사용하도록 답변을 다시 포맷했습니다. 이것은 내가했던 것처럼 4 개의 공백으로 수행 할 수 있습니다. 코드를 답변으로 옮길 때 코드 블록에 넣어야합니다. 그렇지 않으면 완전히 읽을 수 없습니다.
Post Rock Garf Hunter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.