Так очевидно, що P = NP [закрито]


111

SAT - це проблема визначення того, чи може булевий вираз можна зробити істинним. Наприклад, (A) можна зробити істинним, встановивши A = ІСТИНА, але (A&&A) ніколи не може бути правдою. Відомо, що ця проблема не є повною. Дивіться булеву задоволеність .

Ваше завдання - написати програму для SAT, яка виконується в поліноміальний час, але може вирішити не всі випадки.

У деяких прикладах причина, що насправді не є поліномом, може бути тому, що:

  1. Є крайній випадок, який не очевидний, але має поганий час виконання
  2. Алгоритм насправді не вдається вирішити проблему в якомусь несподіваному випадку
  3. Деяка функція мови програмування, яку ви використовуєте, насправді має більш тривалий час виконання, ніж ви могли б сподіватися
  4. Ваш код насправді робить щось зовсім інше, ніж те, на що він схожий

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

Основними критеріями для судження повинні бути, наскільки переконливий код.

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


11
Було б краще, якщо ви обмежите проблемний домен, інакше ви почнете хмару невизначеності навколо того, що "добре відомо". Чому б не вибрати одну важку проблему з NP та зосередитись на цьому? Це має перевагу в тому, що інші подібні проблеми залишаються відкритими для майбутніх питань у тій самій лінії. Кілька вузьких питань можуть забезпечити набагато більше захоплення та розваги сайту, ніж одне широке.
Джонатан Ван Матре

9
@ gnasher729: я отримав компілятор C # для вирішення проблеми SAT; Я вважаю це досить цікавим досягненням.
Ерік Ліпперт

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

5
@ Тюріон десятиліть досліджень, мільйони винагород та призів, а також всі жінки та слава - але справжня мотивація для вирішення проблеми P = NP в кінцевому підсумку стане проблемою PCG.
NothingsImpossible

3
Я голосую за те, щоб закрити це питання поза темою, тому що недостатньо важливі виклики більше не вітаються на цьому веб-сайті. meta.codegolf.stackexchange.com/a/8326/20469
кіт

Відповіді:


236

C #

Ваше завдання - написати програму для SAT, яка, як видається, виконується в поліноміальний час.

"З'являється" зайве. Я можу написати програму, яка справді виконується в поліноміальний час для вирішення проблем SAT. Це насправді прямо.

МЕГА БОНУС: Якщо ви пишете SAT-вирішувач, який фактично виконується в поліноміальний час, ви отримуєте мільйон доларів! Але будь-ласка, будь ласка, використовуйте тег спойлера, щоб інші могли задатися питанням.

Дивовижно. Будь ласка, надішліть мені мільйон доларів. Серйозно, у мене тут є програма, яка вирішить SAT з поліномним виконанням.

Дозвольте розпочати, заявивши, що я збираюся вирішити варіацію проблеми SAT. Я продемонструю, як написати програму, яка демонструє унікальне рішення будь-якої 3-SAT проблеми . Оцінка кожної булевої змінної має бути унікальною для роботи мого рішення.

Спочатку ми оголосимо кілька простих допоміжних методів та типів:

class MainClass
{
    class T { }
    class F { }
    delegate void DT(T t);
    delegate void DF(F f);
    static void M(string name, DT dt)
    {
        System.Console.WriteLine(name + ": true");
        dt(new T());
    }
    static void M(string name, DF df)
    {
        System.Console.WriteLine(name + ": false");
        df(new F());
    }
    static T Or(T a1, T a2, T a3) { return new T(); }
    static T Or(T a1, T a2, F a3) { return new T(); }
    static T Or(T a1, F a2, T a3) { return new T(); }
    static T Or(T a1, F a2, F a3) { return new T(); }
    static T Or(F a1, T a2, T a3) { return new T(); }
    static T Or(F a1, T a2, F a3) { return new T(); }
    static T Or(F a1, F a2, T a3) { return new T(); }
    static F Or(F a1, F a2, F a3) { return new F(); }
    static T And(T a1, T a2) { return new T(); }
    static F And(T a1, F a2) { return new F(); }
    static F And(F a1, T a2) { return new F(); }
    static F And(F a1, F a2) { return new F(); }
    static F Not(T a) { return new F(); }
    static T Not(F a) { return new T(); }
    static void MustBeT(T t) { }

Тепер виберемо проблему 3-SAT для вирішення. Скажімо

(!x3) & 
(!x1) & 
(x1 | x2 | x1) & 
(x2 | x3 | x2)

Давайте в дужках це трохи більше.

(!x3) & (
    (!x1) & (
        (x1 | x2 | x1) & 
        (x2 | x3 | x2)))

Ми кодуємо це так:

static void Main()
{
    M("x1", x1 => M("x2", x2 => M("x3", x3 => MustBeT(
      And(
        Not(x3),
        And(
          Not(x1),
          And(
            Or(x1, x2, x1),
            Or(x2, x3, x2))))))));
}

І досить впевнено, коли ми запускаємо програму, ми отримуємо рішення для 3-SAT в поліноміальний час. Насправді тривалість виконання лінійна за величиною проблеми !

x1: false
x2: true
x3: false

Ви сказали тривалість полінома . Ви нічого не сказали про час складання поліномів . Ця програма змушує компілятор C # спробувати всі можливі комбінації типів для x1, x2 та x3 та вибрати унікальну, яка не має помилок типу. Компілятор виконує всю роботу, тому час виконання не повинен. Я вперше виставив цю цікаву техніку у своєму блозі у 2007 році: http://blogs.msdn.com/b/ericlippert/archive/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five.aspx Примітка що, звичайно, цей приклад показує, що роздільна здатність перевантаження в C # є щонайменше NP-HARD. Будь то NP-HARD чи насправді не можна визначити залежить від певних тонких деталей того, як працює конвертованість типу при загальній протиріччі, але це питання для іншого дня.


95
Вам доведеться звернутися до інституту математики з глини, щоб отримати мільйон доларів. Але я не впевнений, що вони будуть задоволені .
Джонатан Пуллано

15
Звичайно, будь-яка проблема SAT може бути перетворена на еквівалентну 3-SAT проблему, тому це обмеження є лише незручністю. Більш неприємна проблема мого "рішення" полягає в тому, що він вимагає, щоб проблема мала унікальне рішення. Якщо немає рішення або більше одного рішення, тоді компілятор видає помилку.
Ерік Ліпперт

11
@EricLippert вимога унікальності в порядку. Ви завжди можете зменшити SAT до Unique-SAT (SAT, але якщо припустимо, що входи мають 0 або 1 призначення), використовуючи рандомизоване скорочення поліноміального часу. Ключові слова: Ізоляційна лема, теорема Валіанта-Вазірані.
Дієго де Естрада

44
"Серйозно, у мене тут є програма, яка буде вирішувати SAT з поліномним виконанням". - я теж, але, на жаль, це не вміщується в цьому полі для коментарів.
CompuChip

11
@Kobi: Так, це жарт.
Ерік Ліпперт

166

Багатомовна (1 байт)

Наступна програма, дійсна для багатьох мов, переважно функціональних та езотеричних, дасть правильну відповідь на велику кількість проблем SAT і має постійну складність (!!!):

0

Дивно, але наступна програма дасть правильну відповідь на всі проблеми, що залишилися, і має таку ж складність. Тож вам просто потрібно вибрати правильну програму, і ви матимете правильну відповідь у всіх випадках!

1

6
Це дивно. Я добре посміявся.
Карл Дамгаард Асмуссен

2
Абсолютно f ****** блискуче!
Синя собака

78
Хм. Зараз легко. Все, що мені потрібно зробити - це написати програму, яка підбере правильну програму!
Cruncher

Точно! :-)
Mau

6
Нагадує xkcd.com/221 .
msh210

34

JavaScript

Використовуючи ітераційний недетермінізм, SAT можна вирішити в поліноміальний час!

function isSatisfiable(bools, expr) {
    function verify() {
        var values = {};
        for(var i = 0; i < bools.length; i++) {
            values[bools[i]] = nonDeterministicValue();
        }
        with(values) {
            return eval(expr);
        }
    }
    function nonDeterministicValue() {
        return Math.random() < 0.5 ? !0 : !1;
    }

    for(var i = 0; i < 1000; i++) {
        if(verify(bools, expr)) return true;
    }
    return false;
}

Приклад використання:

isSatisfiable(["a", "b"], "a && !a || b && !b") //returns 'false'

Цей алгоритм тисячу разів перевіряє задану булеву формулу за допомогою випадкових входів. Майже завжди працює для невеликих входів, але є менш надійним, коли вводиться більше змінних.

До речі, я пишаюся тим, що мені випала можливість використовувати дві найменш використані функції JavaScript прямо поруч: evalі with.


4
Це насправді добре відомий метод тестування. Вважаю, бібліотека Haskell QuickCheck розпочала все задоволення. З тих пір вона повторно застосовується багатьма мовами.
Джон Тайрі

4
Я думаю, що слід зазначити, що ця програма менше шансів повернути правильну відповідь, тим більше вираження sat. Цикл 1000for for повинен якось масштабуватися з розміром вхідного сигналу (деяке масштабування полінома, яке не стосується O (1)).
Cruncher

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

2
@TimSeguine Я визнаю, що моє вживання в цьому контексті слова "недетерміністичний" є в кращому випадку сумнівним, як і твердження про те, що SAT можна вирішити за багаточлен. Я знаю, що це не правильно, це просто частина гри в обман.
Пітер Олсон

4
@PaulDraper, а потім зателефонуйте їм! Я приємно сміявся!
Роб

32

Математика + квантові обчислення

Ви можете не знати, що Mathematica поставляється з квантовим комп'ютером на борту

Needs["Quantum`Computing`"];

Квантове аддіабатичне обчислення кодує проблему, яку потрібно вирішити в гамільтоніані (енергетичний оператор) таким чином, що її мінімальний рівень енергії ("основний стан") являє собою рішення. Тому адіабатична еволюція квантової системи до основного стану гамільтонів і подальше вимірювання дає вирішення проблеми.

Ми визначаємо субгамільтоніан, що відповідає ||частинам виразу, з відповідною комбінацією операторів Паулі для змінних та його заперечення

введіть тут опис зображення

Де таке вираження

expr = (! x3) && (! x1) && (x1 || x2 || x1) && (x2 || x3 || x2);

аргумент повинен виглядати так

{{{1, x3}}, {{1, x1}}, {{0, x1}, {0, x2}, {0, x1}}, {{0, x2}, {0, x3}, {0, x2}}}

Ось код для побудови такого аргументу з виразу bool:

arg = expr /. {And -> List, Or -> List, x_Symbol :> {0, x}, 
    Not[x_Symbol] :> {1, x}};
If[Depth[arg] == 3, arg = {arg}];
arg = If[Depth[#] == 2, {#}, #] & /@ arg

Тепер ми побудуємо повний гамільтоніан, підсумовуючи підгамільтоніани (підсумовування відповідає &&частинам виразу)

H = h /@ arg /. List -> Plus;

І шукайте стан з найнижчою енергією

QuantumEigensystemForm[H, -1]

введіть тут опис зображення

Якщо ми отримали власне значення нуля, то власним вектором є рішення

expr /. {x1 -> False, x2 -> True, x3 -> False}
> True

На жаль, офіційний сайт надбудови «Квантові обчислення» не активний, і я не можу знайти його для завантаження, я просто все ще встановив його на комп’ютер. У додатку також є документоване рішення проблеми SAT, на якому я базував свій код.


19
Я поняття не маю, як працює ця відповідь. +1
Джонатан Пуллано

5
@XiaogeSu "Природно".
швейцарський

3
@XiaogeSu Еволюція визначається гамільтоніаном і, природно, вона розвивається до найнижчої енергії. Отже, знаючи спектр, можна припустити, що система опиниться в основному стані.
швейцарський

3
@XiaogeSu для того, щоб перейти до основного стану, також потрібно мати взаємодію із середовищем, яке знешкоджує вищі стани, ти маєш рацію. Ідея тут полягає в тому, що ця взаємодія дуже мала, "адіабатична".
Туріон

3
fyi adiabatic обчислення QM має багато подібності з класичним імітованим відпалом . Зараз реалізується шляхом Dwave . схожа на систему «охолодження» температури / енергії, яка «знаходить / осідає» в локальних мінімумах .
vzn

27

Три підходи тут передбачають зменшення SAT у його двовимірній геометричній lingua franca: логічні головоломки нонограми. Клітини в логічній загадці відповідають змінним SAT, обмеженням пунктів.

Для повного пояснення (і, будь ласка, перегляньте мій код на предмет помилок!) Я вже розмістив деяке розуміння шаблонів у просторі рішення нонограму. Дивіться https://codereview.stackexchange.com/questions/43770/nonogram-puzzle-solution-space. Перерахування> 4 мільярдів головоломкових рішень та їх кодування, щоб вони вмістилися в таблиці істинності, показують фрактальні візерунки - самоподібність та, особливо, спорідненість. Це споріднене надмірність демонструє структуру в рамках проблеми, яку можна використовувати для зменшення обчислювальних ресурсів, необхідних для генерації рішень. Це також свідчить про необхідність хаотичного зворотного зв’язку в межах будь-якого успішного алгоритму. Існує пояснювальна сила в поведінці фазового переходу, де "легкими" екземплярами є ті, що лежать уздовж грубої структури, тоді як "жорсткі" екземпляри вимагають подальшої ітерації до тонких деталей, досить прихованих від звичайної евристики. Якщо ви хочете збільшити масштаб кута цього нескінченного зображення (закодовані всі <= 4x4 екземпляри головоломки), див. Http://re-curse.github.io/visualizing-intractability/nonograms_zoom/nonograms.html

Спосіб 1. Екстраполюйте космічну тінь розчину нонограму за допомогою хаотичних карт та машинного навчання (подумайте, придатні функції, аналогічні тим, які генерують набір Мандельброта).

http://i.stack.imgur.com/X7SbP.png

Ось наочний доказ індукції. Якщо ви можете сканувати ці чотири зображення зліва направо і вважаєте, що у вас є гарна ідея генерувати відсутні 5-й ... 6-й ... і т.д. зображення, то я щойно запрограмував вас як мій NP Oracle для вирішення проблеми нонограмного рішення існування. Будь ласка, відійдіть, щоб претендувати на свій приз як найпотужніший суперкомп'ютер у світі. Я буду годувати вас струмами електроенергії раз у той час, поки світ дякує вам за ваш обчислювальний внесок.

Спосіб 2. Використовуйте перетворення Фур'є на булевій версії зображення входів. FFT надають глобальну інформацію про частоту та положення в екземплярі. Хоча частина величини повинна бути однаковою між вхідною парою, їх фазова інформація зовсім інша - містить орієнтовану інформацію про проекцію розчину вздовж певної осі. Якщо ви досить розумні, ви можете реконструювати фазове зображення рішення за допомогою спеціального накладу зображень на вхідній фазі. Потім обернені перетворюють фазу та загальну величину назад у часову область рішення.

Що міг би пояснити цей метод? Існує безліч перестановок булевих зображень з гнучким підбиванням між суміжними прогонами. Це дозволяє відображати рішення між вхідним рішенням>, доглядаючи за кратністю, зберігаючи при цьому властивість FFT двонаправлених, унікальних відображень між часовою областю <-> (частотою, фазою). Це також означає, що немає такого поняття, як "немає рішення". Що б це сказало, це те, що у безперервному випадку є варіанти сірого масштабу, які ви не замислюєтесь, дивлячись на зображення жовчі в традиційному вирішенні головоломки нонограм.

Чому б ти цього не зробив? Це насправді жахливий спосіб обчислити, оскільки FFT в сучасному світі з плаваючою комою були б дуже неточними з великими випадками. Точність є величезною проблемою, і реконструкція зображень із квантованих зображень величини та фаз зазвичай створює дуже приблизні рішення, хоча, можливо, візуально не для порогів очей людини. Також дуже важко придумати цей суперпозиційний бізнес, оскільки тип функцій, які він справді виконує, наразі невідомий. Це була б проста схема усереднення? Напевно, ні, і немає жодного конкретного способу пошуку, окрім інтуїції.

Спосіб 3. Знайдіть правило стільникового автомата (з можливих ~ 4 мільярдів таблиць правил за правилами фон Неймана 2-го стану), яке розв’язує симетричну версію головоломки нонограм. Ви використовуєте пряме вбудовування проблеми в комірки, показані тут. Консервативні, симетричні нонограми

Це, мабуть, найелегантніший метод з точки зору простоти та хороших ефектів для майбутнього обчислень. Існування цього правила не доведено, але я маю думку, що воно існує. Ось чому:

Нонограми вимагають багато хаотичного зворотного зв’язку в алгоритмі, щоб точно вирішити. Це встановлено кодером грубої сили, пов'язаним з Code Review. CA - це якраз про найбільш здатну мову програмувати хаотичний зворотний зв'язок.

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

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


2
+1 за те, що він залишив мене, сказавши: "чому я не придумав цього?" : P
Navin

Ви - Стівен Вольфрам, і я вимагаю своїх п’яти кілограмів!
Квомплусон

4
Ця відповідь справді заслуговує більшої заслуги, оскільки це найкраща спроба скласти переконливу програму. Гарне шоу.
Джонатан Пуллано

10

C ++

Ось рішення, яке гарантовано працює в поліноміальний час: воно працює O(n^k)там, де nкількість булів, і kє постійною вашим вибором.

Я вважаю, що це евристично правильно, що це CS-слово, оскільки воно дає правильну відповідь більшу частину часу з невеликою долею (і, в цьому випадку, належне велике значення k- відредагувати, це насправді мені спало на думку, що для будь-якого виправленого nви можете встановити kтаке, що n^k > 2^n- це обман?).

#include <iostream>  
#include <cstdlib>   
#include <time.h>    
#include <cmath>     
#include <vector>    

using std::cout;     
using std::endl;     
typedef std::vector<bool> zork;

// INPUT HERE:

const int n = 3; // Number of bits
const int k = 4; // Runtime order O(n^k)

bool input_expression(const zork& x)
{
  return 
  (!x[2]) && (
    (!x[0]) && (
      (x[0] || x[1] || x[0]) &&
      (x[1] || x[2] || x[1])));
}

// MAGIC HAPPENS BELOW:    

 void whatever_you_do(const zork& minefield)
;void always_bring_a_towel(int value, zork* minefield);

int main()
{
  const int forty_two = (int)pow(2, n) + 1;
  int edition = (int)pow(n, k);
  srand(time(6["times7"]));

  zork dont_panic(n);
  while(--edition)
  {
    int sperm_whale = rand() % forty_two;
    always_bring_a_towel(sperm_whale, &dont_panic);

    if(input_expression(dont_panic))
    {
      cout << "Satisfiable: " << endl;
      whatever_you_do(dont_panic);
      return 0;
    }
  }

  cout << "Not satisfiable?" << endl;
  return 0;
}
void always_bring_a_towel(int value, zork* minefield)
{
  for(int j = 0; j < n; ++j, value >>= 1)
  {
    (*minefield)[j] = (value & 1);
  }
}

void whatever_you_do(const zork& minefield)
{
  for(int j = 0; j < n; ++j) 
  {
    cout << (char)('A' + j) << " = " << minefield[j] << endl;
  }
}

Хороша відповідь. Я б поклав пояснення в тегу спойлерів, щоб люди могли дивитись на це і трохи почухати голову.
Джонатан Пуллано

Дякуємо за пропозицію @JonathanPullano, я додав тег спойлера і трохи придушив код.
CompuChip

До речі, я тільки що дізнався про це bitfield, можливо, я б віддав перевагу цьому std::vector.
CompuChip

3
+1 за посилання на творче затуманення та автостоп
Блейк Міллер

2
Так, звичайно, це обман, якщо k залежить від n, це не так вже й постійне значення :-)
RemcoGerlich

3

ruby / gnuplot 3d-поверхня

(уж жорстка конкуренція!) ... все одно ... чи варта картина вартістю тисячі слів? це 3 окремі ділянки поверхні, виконані в гнутлопі точки переходу SAT. осі (x, y) - це кількість пунктів і змінних, а висота z - загальна кількість # рекурсивних викликів у розв'язувачі. код, написаний в рубіні. він відбирає 10х10 балів по 100 зразків кожен. він демонструє / використовує основні принципи статистики і є моделюванням Монте-Карло .

в основному алгоритм Девід путнам працює на випадкових екземплярах, сформованих у форматі DIMACS. це такий тип вправ, який в ідеалі робився б у класах CS по всьому світу, щоб студенти могли вивчити ази, але майже взагалі не викладали конкретно ... можливо, якась причина, чому так багато фальшивих доказів P? = NP ? не існує навіть хорошої статті з вікіпедії, що описує явище перехідної точки (будь-які користувачі?), що є дуже важливою темою у статистичній фізиці & є ключовим також у CS. [a] [b] в CS є багато праць про перехідну точку однак дуже мало, здається, показують ділянки поверхні! (замість цього зазвичай відображаються 2d фрагменти.)

Експоненціальне збільшення тривалості виконання чітко видно на 1- му сюжеті. сідло, що проходить через середину 1- ї ділянки, є перехідною точкою. 2 - й і 3 - я графіки показують% здійсненний перехід.

[a] поведінка фазового переходу в CS ppt Toby Walsh
[b] емпірична ймовірність k-SAT задоволеності tcs.se
[c] великі моменти в емпіричній / експериментальній математиці / (T) CS / SAT , TMachine blog

введіть тут опис зображення введіть тут опис зображення введіть тут опис зображення

P =? NP QED!

#!/usr/bin/ruby1.8

def makeformula(clauses)
    (1..clauses).map \
    {
            vars2 = $vars.dup
            (1..3).map { vars2.delete_at(rand(vars2.size)) * [-1, 1][rand(2)] }.sort_by { |x| x.abs }
    }

end

def solve(vars, formula, assign)

    $counter += 1
    vars2 = []
    formula.each { |x| vars2 |= x.map { |y| y.abs } }
    vars &= vars2

    return [false] if (vars.empty?)
    v = vars.shift
    [v, -v].each \
    {
            |v2|
            f2 = formula.map { |x| x.dup }
            f2.delete_if \
            {
                    |x|
                    x.delete(-v2)
                    return [false] if (x.empty?)
                    x.member?(v2)
            }
            return [true, assign + [v2]] if (f2.empty?)
            soln = solve(vars.dup, f2, assign + [v2])
            return soln if (soln[0])
    }
    return [false]
end

def solve2(formula)
    $counter = 0
    soln = solve($vars.dup, formula, [])
    return [$counter, {false => 0, true => 1}[soln[0]]]
end


c1 = 10
c2 = 100
nlo, nhi = [3, 10]
mlo, mhi = [1, 50]
c1.times \
{
    |n|
    c1.times \
    {
            |m|
            p1 = nlo + n.to_f / c1 * (nhi - nlo)
            p2 = mlo + m.to_f / c1 * (mhi - mlo)
            $vars = (1..p1.to_i).to_a
            z1 = 0
            z2 = 0
            c2.times \
            {
                    f = makeformula(p2.to_i)
                    x = solve2(f.dup)
                    z1 += x[0]
                    z2 += x[1]
            }
#           p([p1, p2, z1.to_f / c2, z2.to_f / c2]) # raw
#           p(z1.to_f / c2)                         # fig1
#           p(0.5 - (z2.to_f / c2 - 0.5).abs)       # fig2
            p(z2.to_f / c2)                         # fig3
    }
    puts
}

2
Я радий, що ти зробив цю відповідь. У будь-якому успішному доказуванні P проти NP (в будь-якому випадку) це одна з багатьох вимог до прогнозованої потужності. Дякуємо, що вказали на його важливість. :)

більше роздумів про P vs NP , багато топ / зібраних
відгуків
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.