Então, obviamente, P = NP [fechado]

111

SAT é o problema de determinar se uma expressão booleana pode ser verdadeira. Por exemplo, (A) pode ser verdadeiro, configurando A = TRUE, mas (A &&! A) nunca pode ser verdadeiro. Esse problema é conhecido por ser NP-completo. Consulte Satisfação booleana .

Sua tarefa é escrever um programa para SAT que seja executado em tempo polinomial, mas pode não resolver todos os casos.

Para alguns exemplos, o motivo pelo qual não é realmente polinomial pode ser porque:

  1. Há um caso extremo que não é óbvio, mas tem um tempo de execução ruim
  2. O algoritmo realmente falha em resolver o problema em alguns casos inesperados
  3. Alguns recursos da linguagem de programação que você está usando têm, na verdade, um tempo de execução mais longo do que você esperaria razoavelmente
  4. Seu código realmente faz algo totalmente diferente do que parece estar fazendo

Você pode usar qualquer linguagem de programação (ou combinação de linguagens) que desejar. Você não precisa fornecer uma prova formal da complexidade do seu algoritmo, mas deve pelo menos fornecer uma explicação.

O principal critério para julgar deve ser o quão convincente é o código.

Este é um concurso de popularidade, por isso vence a resposta mais bem classificada em uma semana.

Jonathan Pullano
fonte
11
Seria melhor se você restringisse o domínio do problema, caso contrário, invocaria a nuvem de incerteza em torno do que é "conhecido". Por que não escolher um único problema NP-difícil e focar nisso? Isso tem a vantagem de deixar outros problemas em aberto para futuras perguntas na mesma linha. Várias perguntas restritas podem fornecer muito mais prazer e entretenimento contínuos ao site do que uma ampla.
Jonathan Van Matre
9
@ gnasher729: Eu peguei o compilador C # para resolver um problema de SAT; Considero isso uma conquista razoavelmente interessante.
precisa
9
Seria divertido se alguém resolvesse acidentalmente o SAT em tempo polinomial aqui.
Turion
5
@Turion décadas de pesquisa, milhões de recompensas e prêmios e todas as mulheres e fama que alguém poderia ter - mas a verdadeira motivação para resolver P = NP acabará sendo esse desafio do PCG.
NothingsImpossible
3
Estou votando para encerrar esta questão como fora de tópico, porque os desafios secretos não são mais bem-vindos neste site. meta.codegolf.stackexchange.com/a/8326/20469
cat

Respostas:

236

C #

Sua tarefa é escrever um programa para SAT que pareça executar em tempo polinomial.

"Aparece" é desnecessário. Eu posso escrever um programa que realmente seja executado em tempo polinomial para resolver problemas de SAT. Isso é bastante simples, de fato.

MEGA BONUS: Se você escrever um solucionador de SAT que realmente seja executado em tempo polinomial, você receberá um milhão de dólares! Mas use uma tag de spoiler de qualquer maneira, para que outros possam se perguntar sobre isso.

Impressionante. Por favor me envie o milhão de dólares. Sério, eu tenho um programa aqui que resolverá o SAT com tempo de execução polinomial.

Deixe-me começar afirmando que vou resolver uma variação do problema do SAT. Vou demonstrar como escrever um programa que exibe a solução exclusiva de qualquer problema 3-SAT . A avaliação de cada variável booleana deve ser exclusiva para o meu solucionador funcionar.

Começamos declarando alguns métodos e tipos auxiliares simples:

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) { }

Agora vamos escolher um problema 3-SAT para resolver. Digamos

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

Vamos parênteses isso um pouco mais.

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

Codificamos isso assim:

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))))))));
}

E com certeza, quando executamos o programa, obtemos uma solução para o 3-SAT em tempo polinomial. De fato, o tempo de execução é linear no tamanho do problema !

x1: false
x2: true
x3: false

Você disse que o tempo de execução polinomial . Você não disse nada sobre o tempo de compilação polinomial . Este programa força o compilador C # a tentar todas as combinações de tipos possíveis para x1, x2 e x3 e escolher a única que não apresenta erros de tipo. O compilador faz todo o trabalho, portanto, o tempo de execução não precisa. Exibi pela primeira vez esta interessante técnica no meu blog em 2007: http://blogs.msdn.com/b/ericlippert/archive/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five.aspx Observação claro que este exemplo mostra que a resolução de sobrecarga em C # é pelo menos NP-HARD. Seja NP-HARD ou realmente indecidível depende de certos detalhes sutis de como a conversibilidade de tipo funciona na presença de contravariância genérica, mas isso é assunto para outro dia.

Eric Lippert
fonte
95
Você terá que entrar em contato com o Instituto de Matemática Argila por seu milhão de dólares. Mas não tenho certeza de que eles ficarão satisfeitos .
Jonathan Pullano
15
É claro que qualquer problema SAT pode ser transformado em um problema 3-SAT equivalente, portanto, essa restrição é apenas um inconveniente. O problema mais irritante com minha "solução" é que exige que o problema tenha uma solução única . Se não houver solução ou mais de uma solução, o compilador emitirá um erro.
precisa
11
@EricLippert, o requisito de exclusividade está ok. Você sempre pode reduzir SAT para Unique-SAT (SAT, mas supondo que as entradas tenham atribuições 0 ou 1) usando uma redução aleatória de tempo polinomial. Palavras-chave: Lema de isolamento, teorema de Valiant-Vazirani.
Diego de Estrada
44
"Sério, eu tenho um programa aqui que resolverá o SAT com tempo de execução polinomial." - eu também, mas infelizmente não cabe nesta caixa de comentários.
CompuChip
11
@Kobi: Sim, essa é a piada.
precisa
166

Multi-idioma (1 byte)

O programa a seguir, válido em vários idiomas, principalmente funcionais e esotéricos, fornecerá a resposta correta para um grande número de problemas de SAT e possui complexidade constante (!!!):

0

Surpreendentemente, o próximo programa dará a resposta correta para todos os problemas restantes e tem a mesma complexidade. Então, você só precisa escolher o programa certo e terá a resposta correta em todos os casos!

1
Mau
fonte
6
Isso é incrível. Eu tive uma boa risada.
Karl Damgaard Asmussen 18/03
2
Absolutamente f ****** brilhante!
The Blue Dog
78
Hmm. Agora é fácil. Tudo o que preciso fazer é escrever um programa que escolha o programa certo!
Cruncher
Precisamente! :-) #
1957 Mau
6
Remanescente de xkcd.com/221 .
Msh210
34

Javascript

Usando o não determinismo iterado, o SAT pode ser resolvido em tempo polinomial!

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;
}

Exemplo de uso:

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

Esse algoritmo apenas verifica a fórmula booleana mil vezes com entradas aleatórias. Quase sempre funciona para pequenas entradas, mas é menos confiável quando mais variáveis ​​são introduzidas.

A propósito, tenho orgulho de ter tido a oportunidade de utilizar dois dos recursos mais subutilizados do JavaScript, um ao lado do outro: evale with.

Peter Olson
fonte
4
Este é realmente um método de teste bem estabelecido. A biblioteca QuickCheck de Haskell começou toda a diversão, acredito. Desde então, foi reimplementado em vários idiomas.
precisa
4
Eu acho que deve-se notar que, é menos provável que este programa retorne a resposta correta, maior a expressão sat. O 1000loop for deve, de alguma forma, ser escalonado com o tamanho da entrada (algum escalonamento polinomial que não seja O (1)).
Cruncher
2
@Cruncher Para ser mais preciso, quanto maior o número de variáveis, menor a probabilidade de retornar a resposta correta. (por exemplo, uma expressão muito longa com uma única variável quase sempre retornar a resposta correta)
Peter Olson
2
@TimSeguine Admito que meu uso da palavra "não determinístico" nesse contexto seja duvidoso, na melhor das hipóteses, assim como a alegação de que o SAT pode ser resolvido em tempo polinomial. Eu sei que não está correto, é apenas parte do jogo da decepção.
Peter Olson
4
@PaulDraper e chame-os de subutilizados! Eu ri muito bem!
22414 Rob
32

Mathematica + Computação Quântica

Talvez você não saiba que o Mathematica vem com um computador quântico a bordo

Needs["Quantum`Computing`"];

A computação adiabática quântica codifica um problema a ser resolvido em um hamiltoniano (operador de energia) de forma que seu estado de energia mínima ("estado fundamental") represente a solução. Portanto, a evolução adiabática de um sistema quântico para o estado fundamental do Hamiltoniano e a medição subsequente dão a solução para o problema.

Definimos um subhamiltoniano que corresponde a ||partes da expressão, com combinação apropriada de operadores de Pauli para variáveis ​​e sua negação

insira a descrição da imagem aqui

Onde para expressões como esta

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

o argumento deve parecer

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

Aqui está o código para construir esse argumento a partir da expressão 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

Agora construímos um hamiltoniano completo, resumindo os subhamiltonianos (o somatório corresponde a &&partes da expressão)

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

E procure o menor estado de energia

QuantumEigensystemForm[H, -1]

insira a descrição da imagem aqui

Se obtivemos um valor próprio de zero, o vetor próprio é a solução

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

Infelizmente, o site oficial do complemento "Quantum Computing" não está ativo e não consigo encontrar um lugar para fazer o download, mas ainda o instalei no meu computador. O complemento também possui uma solução documentada para o problema SAT, na qual baseei meu código.

swish
fonte
19
Não tenho ideia de como essa resposta funciona. 1
Jonathan Pullano
5
@XiaogeSu "Naturalmente".
swish
3
@XiaogeSu Evolução determinada pelo Hamiltoniano e, naturalmente, evolui para a energia mais baixa. Portanto, conhecendo o espectro, podemos assumir que o sistema acabará no estado fundamental.
swish
3
@XiaogeSu, para ir ao estado fundamental, é preciso também ter uma interação com o ambiente que desencadeia os estados superiores, você está certo. A idéia aqui é que essa interação seja muito pequena, "adiabática".
Turion 22/03
3
A computação QM adiabática tem muitas semelhanças com o recozimento simulado clássico . agora implementado pela Dwave . é semelhante a um sistema de temperatura / energia "resfriado" que "encontra / se instala" em mínimos locais .
vzn
27

Três abordagens aqui, todas envolvem uma redução do SAT em sua língua franca geométrica 2D: quebra-cabeças lógicos não programáticos. As células no quebra-cabeça lógico correspondem a variáveis ​​SAT, restrições a cláusulas.

Para uma explicação completa (e para revisar meu código quanto a erros!), Eu já publiquei algumas dicas sobre padrões dentro do espaço de solução que não é do programa. Consulte https://codereview.stackexchange.com/questions/43770/nonogram-puzzle-solution-space. Enumerar mais de 4 bilhões de soluções de quebra-cabeças e codificá-las para caber em uma tabela de verdade mostra padrões fractais - auto-similaridade e especialmente auto-afinidade. Essa redundância afim demonstra estrutura dentro do problema, explorável para reduzir os recursos computacionais necessários para gerar soluções. Também mostra a necessidade de feedback caótico em qualquer algoritmo bem-sucedido. Há um poder explicativo no comportamento da transição de fase, em que instâncias "fáceis" são aquelas que se encontram ao longo da estrutura grossa, enquanto instâncias "difíceis" exigem iteração adicional em detalhes, bastante ocultos às heurísticas normais. Se você deseja ampliar o canto desta imagem infinita (todas as instâncias de quebra-cabeça <= 4x4 codificadas), consulte http://re-curse.github.io/visualizing-intractability/nonograms_zoom/nonograms.html

Método 1. Extrapole a sombra do espaço da solução não-programa usando mapas caóticos e aprendizado de máquina (pense em funções de ajuste semelhantes às que geram o conjunto Mandelbrot).

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

Aqui está uma prova visual de indução. Se você pode escanear essas quatro imagens da esquerda para a direita e achar que tem uma boa idéia para gerar as 5as ... 6as ... etc. imagens ausentes, acabei de programá- lo como meu oracle NP para o problema de decisão da solução de nonogram existência. Por favor, avance para reivindicar seu prêmio como o supercomputador mais poderoso do mundo. De vez em quando, alimentarei você com eletricidade, enquanto o mundo agradece por suas contribuições computacionais.

Método 2. Use Transformadas de Fourier na versão de imagem booleana das entradas. As FFTs fornecem informações globais sobre frequência e posição em uma instância. Embora a porção de magnitude deva ser semelhante entre o par de entrada, suas informações de fase são completamente diferentes - contendo informações direcionadas sobre uma projeção de solução ao longo de um eixo específico. Se você for esperto o suficiente, poderá reconstruir a imagem da fase da solução através de uma superposição especial das imagens da fase de entrada. Transforme inversamente a fase e a magnitude comum de volta ao domínio do tempo da solução.

O que esse método poderia explicar? Existem muitas permutações das imagens booleanas com preenchimento flexível entre execuções contíguas. Isso permite um mapeamento entre a solução de entrada -> cuidando da multiplicidade, mantendo a propriedade das FFTs de mapeamentos bidirecionais e únicos entre o domínio do tempo <-> (frequência, fase). Isso também significa que não existe "nenhuma solução". O que diria é que, em um caso contínuo, existem soluções em escala de cinza que você não está considerando ao olhar para a imagem em dois níveis da resolução tradicional de quebra-cabeças sem programa.

Por que você não faria isso? É uma maneira horrível de calcular, pois as FFTs no mundo atual de ponto flutuante seriam altamente imprecisas em grandes instâncias. A precisão é um grande problema, e a reconstrução de imagens de magnitude quantificada e de fase geralmente cria soluções muito aproximadas, embora talvez não visualmente para os limiares do olho humano. Também é muito difícil criar esse negócio de superposição, pois o tipo de função que está realizando atualmente é desconhecido. Seria um esquema simples de média? Provavelmente não, e não há método de pesquisa específico para encontrá-lo, exceto a intuição.

Método 3. Encontre uma regra de autômato celular (de um possível ~ 4 bilhões de tabelas de regras para regras de dois estados de von Neumann) que resolva uma versão simétrica do quebra-cabeça do não-programa. Você usa uma incorporação direta do problema nas células, mostrada aqui. Nonogramas simétricos conservadores

Este é provavelmente o método mais elegante, em termos de simplicidade e bons efeitos para o futuro da computação. A existência desta regra não está comprovada, mas tenho um palpite de que ela existe. Aqui está o porquê:

Os nonogramas requerem muito feedback caótico no algoritmo para serem resolvidos exatamente. Isso é estabelecido pelo código de força bruta vinculado à Revisão de Código. A CA é a linguagem mais capaz de programar feedback caótico.

Ele parece bem, visualmente. A regra evoluiria através de uma incorporação, propagaria informações horizontal e verticalmente, interferiria e depois se estabilizaria em uma solução que conservasse o número de células definidas. Essa rota de propagação segue o caminho (para trás) em que você normalmente pensa ao projetar a sombra de um objeto físico na configuração original. Os nonogramas derivam de um caso especial de tomografia discreta; imagine-se sentado simultaneamente em dois tomógrafos com ponta de gatinho. É assim que os raios X se propagariam para gerar as imagens médicas. É claro que existem problemas de fronteira - as bordas do universo da CA não podem manter a propagação de informações além dos limites, a menos que você permita um universo toroidal. Isso também lança o quebra-cabeça como um problema periódico de valor-limite.

Explica várias soluções como estados transitórios em um efeito de oscilação contínua entre a troca de saídas como entradas e vice-versa. Explica instâncias que não têm solução como configurações originais que não conservam o número de células definidas. Dependendo do resultado real de encontrar essa regra, ela pode até aproximar instâncias insolúveis com uma solução próxima em que os estados das células são conservados.

Comunidade
fonte
2
+1 para deixar me dizendo "por que não eu acho disso?" : P
Navin 24/03
Você é Stephen Wolfram e reivindico minhas cinco libras!
Quuxplusone
4
Essa resposta realmente merece mais crédito, pois é a melhor tentativa de criar um programa convincente . Bom show.
Jonathan Pullano
10

C ++

Aqui está uma solução que é garantida para ser executada em tempo polinomial: ela é executada em O(n^k)que né o número de booleanos e ké uma constante de sua escolha.

É heuristicamente correto, o que eu acredito ser de fala CS, "dá a resposta correta na maioria das vezes, com um pouco de sorte" (e, nesse caso, um valor adequadamente grande de k- editar , ocorreu-me que para qualquer fixo nvocê pode definir de ktal forma n^k > 2^n- isso é trapaça?).

#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;
  }
}
CompuChip
fonte
Boa resposta. Eu colocaria a explicação em uma etiqueta de spoiler para que as pessoas possam encará-la e coçar um pouco a cabeça.
Jonathan Pullano 19/03/2014
Obrigado pela sugestão @ JonathanPullano, adicionei uma tag de spoiler e ofusquei o código um pouco.
CompuChip
A propósito, eu acabei de descobrir bitfield, talvez eu preferisse isso std::vector.
CompuChip
3
+1 para a ofuscação criativo e referências do Mochileiro
Blake Miller
2
Sim, claro que é batota, se k depende de n não é muito de um :-) constante
RemcoGerlich
3

superfície 3d ruby ​​/ gnuplot

(ooh forte concorrência!) ... enfim ... uma imagem vale mais que mil palavras? estas são três parcelas de superfície separadas feitas no gnuplot do ponto de transição SAT. os eixos (x, y) são cláusula e contagem variável e a altura z é o número total de chamadas recursivas no solucionador. código escrito em ruby. amostras 10 x 10 pontos em 100 amostras cada. demonstra / usa princípios básicos de estatística e é uma simulação de Monte Carlo .

é basicamente um algoritmo de davis putnam executando em instâncias aleatórias geradas no formato DIMACS. esse é o tipo de exercício que idealmente seria feito nas aulas de ciências da computação em todo o mundo para que os alunos aprendessem o básico, mas quase não é ensinado especificamente ... talvez alguma razão para haver tantas provas falsas de P? = NP ? nem sequer há um bom artigo na Wikipedia descrevendo o fenômeno do ponto de transição (alguém que se interessa?), que é um tópico muito importante na física estatística e é fundamental também no CS. [a] [b] existem muitos artigos no CS sobre o ponto de transição no entanto, poucos parecem mostrar gráficos de superfície! (em vez disso, normalmente mostra fatias 2D).

o aumento exponencial em tempo de execução é claramente evidente em 1 r terreno. o selim que passa pelo meio de um r trama é o ponto de transição. os 2 nd e 3 rd gráficos mostram a transição satisfatível%.

[a] comportamento de transição de fase no CS ppt Toby Walsh
[b] probabilidade empírica de satisfação do k-SAT tcs.se
[c] grandes momentos em matemática empírica / experimental / (T) CS / SAT , TMachine blog

insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui

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
}
vzn
fonte
2
Estou feliz que você tenha contribuído com esta resposta. Em qualquer prova bem-sucedida de P versus NP (de qualquer maneira), é um dos muitos requisitos para poder preditivo. Obrigado por apontar sua importância. :)
mais reflexões sobre P vs NP , muitos top / refs recolhidos, etc
vzn