Давайте візьмемо $ 1000 000 Біла


17

Концепція Біла має приз в мільйон доларів, якщо ви докажете / спростуєте це.

У ньому йдеться про те, що якщо A ^ x + B ^ y = C ^ zA, B, C, x, y, z є додатними цілими числами з x, y, z> 2, то A, B і C мають спільний простий множник.

Завдання полягає в тому, щоб написати програму, яка шукає приклад зустрічного, щоб спростувати це!

Правила

  • Напишіть програму, яка шукає зустрічний приклад Концепції Біла
  • Ви можете виконати вичерпний пошук (тобто всі можливі комбінації чисел, що відповідають цій формі) або використовувати деякі оптимізації (наприклад, A і B є симетричними).
  • Ви повинні використовувати цілі числа довільної точності.

Примітки

  • Це конкурс популярності, будьте креативними!
  • Швидкість не потрібна, але робить її цікавішою. Оптимізуйте!
  • Мені також цікаво побачити найкоротший код. Ви отримаєте +1 від мене!
  • Я запускаю програму-виграш на суперкомп'ютері, до якого я маю доступ!
  • Ця думка вважається правдивою, але це не означає, що ми не можемо спробувати!
  • Пітер Норвіг із Google також спробував цю проблему. Ви можете використовувати його сторінку в якості керівництва. У нього є коротка програма Python, яку ви можете використовувати як приклад.
  • Хтось інший хлопець (який також працює в Google) значно покращився під час підходу Норвіга, його сторінку (з вихідним кодом) можна знайти тут .
  • Моє запитання, пов'язане з цим, про те, що минуло два роки тому, також може бути корисним: Завершіть всі A ^ x у заданому діапазоні .

1
Суперкомп'ютер? Тепер це круто. Будь-який шанс розділити готівку?
ɐɔıʇǝɥʇuʎs

@Synthetica Ця гіпотеза вже випробувана з дуже, дуже, дуже великими цифрами, тому це здебільшого для розваги. Але звичайно ми можемо розділити готівку :)
Остін Генлі

2
"Це повинно або продовжуватися назавжди, або допускати обмежену верхню межу (незалежно від того, наскільки велика вона є)." ... на відміну від альтернатив?
підземниймонорельс

@undergroundmonorail Працює лише для невеликої кількості.
Остін Генлі

2
Малі числа - це кінцева верхня межа.
підземниймонорельс

Відповіді:


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"

Це друкує 1 всі комбінації, які відповідають властивості контрприкладу. Я використав пакет "контрольна монада-омега" для діагоналізації ℕ 6 ... може вважатися підробкою бібліотеки. Але бачачи, як хтось пізніше опублікує відповідь APL, де всі ці речі вбудовані в мову (чи не так?), Я не дуже багато про це ...

Звичайно, програма занадто повільна (наївне виснаження та пов'язані списки як структура даних), щоб очікувати, що вона фактично дасть контрприклад, але сам Haskell може реально досягти гідних показників.


1 Так як він друкує кортежі у вигляді списку, тобто в одному рядку, вам потрібно переключити термінал буферними вимкнений або ви не будете бачити , коли результат приходить. Як альтернативи, ви можете замінити printз mapM_ printтак що ви отримаєте символ нового рядка після кожного результату, промивання термінального буфера.

Щоб протестувати програму, перейдіть each[3..]на each[2..], тоді ви просто отримаєте в результаті всі піфагорійські кортежі, що не є одночасно.


2

C #, без петель

Добре, я пропустив пару цих посилань, але якщо чесно вони були трохи нудні. Мені не цікаво оптимізувати хеш-сюди за допомогою хеш-таблиць і чогось іншого. Навіщо мені це потрібно? У тебе проклятий суперкомп'ютер!

Чорт, я навіть не хочу морочитися з петлями! Це рішення буде дотримуватися правила без циклу .

Зверніть увагу, що код, який я збираюся написати, це не гарний код або тип коду, який я б написав у реальному житті (на випадок, якщо будь-які потенційні роботодавці прочитають це). Цей код підкреслює стислість та вміння працювати в оповіданні та демефазує належні умовності та ритуали, петлі тощо.

Щоб продемонструвати те, про що я говорю, ми почнемо з шокуючого класу з публічними полями для зберігання операндів рівняння:

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

Гаразд, ми почнемо з того, що, мабуть, найскладніше. Нам потрібно знайти спосіб перестановки через кожну комбінацію цих операндів. Безсумнівно, є способи зробити це більш ефективно, ніж перевірка кожної перестановки, але я не можу заважати з'ясовувати їх. І навіщо мені це робити? У нас проклятий суперкомп'ютер!

Ось алгоритм, який я придумав. Це неймовірно неефективно, і перетворює одні і ті ж операнди знову і знову, але кого це хвилює? Суперкомп'ютер!

  • Поставтеся до шести операндів як до базового числа 2 та перестановці через кожну комбінацію.
  • Поставтеся до шести операндів як до базового числа 3 та перестановці через кожну комбінацію.
  • Поставтеся до шести операндів як до базового числа 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() { }
}

Зараз ми в бізнесі! Все, що нам потрібно зробити, - це перерахувати екземпляр BealOperandGeneratorі знайти контрприклад з Концепції Біла.

Наступна наша велика проблема полягає в тому, що, здається, не існує вбудованого способу підняти 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, який можна викликати на a BigIntegerі приймає aBigInteger показник, а не модуль.

Добре, давайте відступимо. Як ми можемо визначити, чи є конкретний BealOperandsконтрприклад задуму Біла? Дві речі повинні бути правдивими:

  • Операнди, підключаючись до цієї формули вгорі сторінки, повинні утворювати справжнє рівняння.
  • A, B і C НЕ повинні мати загального основного фактора (тобто їх GCD дорівнює 1).

У нас є те, що нам потрібно для перевірки першої умови. І виявляється, другу умову перевірити набагато простіше, ніж це звучить. BigIntegerнадає чудовий GreatestCommonDivisorметод, який дозволяє нам зручно проходити весь кошмар намагання здійснити це без циклів.

Тож ми готові написати метод, щоб перевірити, чи 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 року я перевіряю C ^ Z <= 1.0E29 з припущенням, що або показник "X" та / або "Y" повинен бути> = 5.

Поточна версія цієї програми ("X" та / або "Y"> = 5) потребує менше 1 секунди на AMD 2920X, щоб знайти всі рішення на C ^ Z <= 1.0E15. (Але всі gcd (A, B, C)> = 2)

Деталі на http://www.durangobill.com/BealsConjecture.html

Я можу змінити поточний код (Використовує "C" і OpenMP) поза межами цих меж, але для його запуску буде потрібно більше 128 Гб оперативної пам'яті. (Сотні процесорів також допоможуть. Тисячі процесорів будуть ще кращі.) (Якщо у вас є вільний доступ до чогось подібного, будь ласка, зв'яжіться зі мною.)

Моя адреса електронної пошти знаходиться на моїй домашній сторінці за адресою http://www.durangobill.com


1
Якщо ви можете розібрати це з допомогою якогось коду, це може бути правильною відповіддю, інакше це, мабуть, найкраще підходить як коментар до питання. Однак будь-яка робота, яку ви зробили над цим, вражає.
Οurous

Багато університетів мають високопродуктивні кластери. Якщо ви зв’язалися з одним, вони, можливо, зможуть надати вам доступ. Я бачив занадто багато кластерів просто без роботи!
Остін Генлі

1

2-я версія пошукової програми Біла закінчилася. Результати:

СZ<1026АХ+БY=СZ(Х,Y)> =4

(Х,Y)> =5СZ<1028АХ+БY=СZ(Х,Y)> =5

Деталі на сайті: http://www.durangobill.com/BealsConjecture.html

Наступні два питання: 1) Чи може суперкомп'ютер розширити пошук? 2) Якби суперкомп'ютер міг би розширити пошук, це було б практично?

1) Для розширення будь-якого з перерахованих вище пошукових запитів до 1.0E30 потрібно 300 Гб оперативної пам’яті на одне ядро, якщо ядра не можуть розділяти 300 ГБ. За кожне додаткове додаткове збільшення експоненціальної потужності за межі 1,0 Е30 кількість необхідної оперативної пам’яті збільшується вдвічі в 2,2 раза.

2) Обсяг процесорної потужності, необхідний для кожного подальшого збільшення коефіцієнта до 1,0E30 і перевищує комбінований час процесора приблизно на 3,8. Пошук в 1.0E29 зайняв 2 тижні, використовуючи 12 ядер. Час суперкомп'ютерів, як правило, не є "безкоштовним", і є дуже мала перспектива існування контрприкладів.

Як керівництво щодо ефективності коду на сайті durangobill.com/BealE29code.txt, кожне з 12 ядер в середньому для внутрішньої петлі становило 220 мільйонів ітерацій циклу в секунду. (Середня величина за 2-тижневий пробіг.) (Збільшення оперативної пам’яті, ніж у мене, збільшило б цю середню швидкість до коефіцієнта 2.)

Я дозволю Остіну відповісти 1) і 2), оскільки він має доступ до суперкомп'ютера, а я - ні. (Якщо за будь-якого віддаленого шансу, що і 1) і 2) є "йти", я можу надати "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);

(Для цих масивів вам знадобиться 128 Гб оперативної пам’яті)

з:

#define PRIME1 2147483647LLU
#define PRIME2 2147483629LLU
#define ARRAYSIZE 4700000000LL

"Базі" насправді потрібно 33 біта ( cbrt(1.0E29)) - додатковий біт заповнений "Power" (для цього потрібно всього 7 біт.)

Масиви працюють аналогічно хеш-таблиці. Однак, оскільки вони сортуються за PRIME1 і використовуються лише як таблиці пошуку, вам не потрібні пов'язані списки для доступу до них. Таким чином, результат є дуже швидким лінійним пошуком часу, щоб дізнатися, чи є випробувальна A ^ X + B ^ Y = яка C ^ Z.

Таким чином, висловлювання у внутрішній петлі мають лише дві петлі.

Висловлювання "Pragma" контролюють кількість використовуваних мультипроцесорних ядер (в даному випадку 12) - усі можуть отримати доступ до єдиної копії масивів.

Ось "основний" код (у "С") (Сподіваюся, коментарі відповідають розміру розміщення рядка. Якщо ні, скопіюйте їх та вставте код у якийсь документ, який має більшу довжину рядка.)


Поле для коментарів дозволить мені використовувати лише 600 символів, і мені потрібно 3 000+ для коду. (Будь-які пропозиції?) (Я можу розмістити код на своїй веб-сторінці, якщо я не можу розмістити його тут.)
Білл Батлер

Я ставлю сюди "головний" "С" код. durangobill.com/BealE29code.txt Якщо нічого іншого, це приклад "як це зробити" для обробки декількох потоків у "C".
Білл Батлер

1
Ласкаво просимо на сайт. Хоча поля коментарів обмежені 600 символами, ваша відповідь - ні. Ви повинні мати можливість легко вписати свій код у свою відповідь. Якщо ви не намагаєтеся обрізати коментарі. Також я переформатував вашу відповідь, щоб використовувати кодові блоки. Це можна зробити за допомогою 4 пробілів, як і я. Під час переміщення коду до своєї відповіді слід ввести його в блок коду, інакше він буде зовсім нечитабельним.
Post Rock Garf Hunter
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.