Quindi, ovviamente, P = NP [chiuso]


111

SAT è il problema nel determinare se un'espressione booleana può essere resa vera. Ad esempio, (A) può essere reso reale impostando A = TRUE, ma (A &&! A) non può mai essere vero. Questo problema è noto per essere NP-completo. Vedi soddisfazione booleana .

Il tuo compito è scrivere un programma per SAT che viene eseguito in tempo polinomiale, ma potrebbe non risolvere tutti i casi.

Per alcuni esempi, la ragione per cui non è realmente polinomiale potrebbe essere perché:

  1. Esiste un caso limite che non è ovvio ma ha un runtime scadente
  2. L'algoritmo in realtà non riesce a risolvere il problema in alcuni casi imprevisti
  3. Alcune funzionalità del linguaggio di programmazione che stai utilizzando in realtà hanno un tempo di esecuzione più lungo di quanto ti aspetteresti ragionevolmente di avere
  4. Il tuo codice in realtà fa qualcosa di totalmente diverso da quello che sembra stia facendo

È possibile utilizzare qualsiasi linguaggio di programmazione (o combinazione di lingue) desiderato. Non è necessario fornire una prova formale della complessità dell'algoritmo, ma almeno fornire una spiegazione.

Il criterio principale per giudicare dovrebbe essere quanto sia convincente il codice.

Questo è un concorso di popolarità, quindi vince la risposta più votata in una settimana.


11
Sarebbe meglio se si restringesse il dominio problematico, altrimenti si invocherebbe la nuvola di incertezza su ciò che è "noto". Perché non scegliere un singolo problema NP-difficile e concentrarsi su quello? Ciò ha il vantaggio di lasciare altri problemi simili aperti a domande future sulla stessa linea. Diverse domande ristrette possono fornire al sito un piacere e un intrattenimento molto più numerosi di uno ampio.
Jonathan Van Matre,

9
@ gnasher729: ho ottenuto il compilatore C # per risolvere un problema SAT; Lo considero un risultato ragionevolmente interessante.
Eric Lippert,

9
Sarebbe divertente se qualcuno risolvesse accidentalmente SAT in tempo polinomiale qui.
Turion,

5
Per decenni decenni di ricerca, milioni di premi e premi e tutte le donne e la fama che uno potrebbe avere - ma la vera motivazione per risolvere P = NP finirà per essere questa sfida PCG.
NothingsImpossible

3
Sto votando per chiudere questa domanda come fuori tema perché le sfide subdole non sono più benvenute su questo sito. meta.codegolf.stackexchange.com/a/8326/20469
cat

Risposte:


236

C #

Il tuo compito è quello di scrivere un programma per SAT che sembra essere eseguito in tempo polinomiale.

"Appare" non è necessario. Sono in grado di scrivere un programma che esegue davvero in tempo polinomiale per risolvere i problemi di SAT. Questo è abbastanza semplice in effetti.

MEGA BONUS: Se scrivi un solutore SAT che viene effettivamente eseguito in un tempo polinomiale, otterrai un milione di dollari! Ma ti preghiamo comunque di utilizzare un tag spoiler, in modo che altri possano chiederselo.

Eccezionale. Per favore, inviami il milione di dollari. Seriamente, ho un programma proprio qui che risolverà SAT con runtime polinomiale.

Vorrei iniziare affermando che risolverò una variazione del problema SAT. Ho intenzione di dimostrare come scrivere un programma che mostra la soluzione unica di qualsiasi problema 3-SAT . La valutazione di ciascuna variabile booleana deve essere unica affinché il mio solutore funzioni.

Iniziamo dichiarando alcuni semplici metodi e tipi di supporto:

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

Ora scegliamo un problema 3-SAT da risolvere. Diciamo

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

Parliamoci un po 'di più.

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

Lo codifichiamo in questo modo:

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 abbastanza sicuro quando eseguiamo il programma, otteniamo una soluzione a 3-SAT in tempo polinomiale. In effetti il ​​tempo di esecuzione è lineare nella dimensione del problema !

x1: false
x2: true
x3: false

Hai detto runtime polinomiale . Non hai detto nulla sul tempo di compilazione polinomiale . Questo programma impone al compilatore C # di provare tutte le possibili combinazioni di tipi per x1, x2 e x3 e di scegliere quella unica che non presenta errori di tipo. Il compilatore fa tutto il lavoro, quindi il runtime non deve. Nel 2007 ho esposto per la prima volta questa interessante tecnica sul mio blog: http://blogs.msdn.com/b/ericlippert/archive/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five.aspx Note questo ovviamente mostra che la risoluzione del sovraccarico in C # è almeno NP-HARD. Che si tratti di NP-HARD o in realtà indecidibile dipende da alcuni sottili dettagli su come funziona la convertibilità dei tipi in presenza di una contraddizione generica, ma questo è un argomento per un altro giorno.


95
Dovrai contattare l'istituto di matematica dell'argilla per i tuoi milioni di dollari. Ma non sono sicuro che saranno soddisfatti .
Jonathan Pullano,

15
Ovviamente qualsiasi problema SAT può essere trasformato in un problema equivalente 3-SAT, quindi questa restrizione è solo un inconveniente. Il problema più irritante con la mia "soluzione" è che richiede che il problema abbia una soluzione unica . Se non esiste una soluzione o più di una soluzione, il compilatore genera un errore.
Eric Lippert,

11
@EricLippert il requisito di unicità è ok. Puoi sempre ridurre SAT a Unique-SAT (SAT ma supponendo che gli ingressi abbiano 0 o 1 assegnazioni) usando una riduzione randomizzata del tempo polinomiale. Parole chiave: Isolamento Lemma, teorema di Valiant-Vazirani.
Diego de Estrada,

44
"Seriamente, ho un programma proprio qui che risolverà SAT con runtime polinomiale." - anche a me, ma purtroppo non rientra in questa casella di commento.
CompuChip

11
@Kobi: Sì, è uno scherzo.
Eric Lippert,

166

Multilingua (1 byte)

Il seguente programma, valido in molte lingue, principalmente funzionale ed esoterico, fornirà la risposta corretta per un gran numero di problemi di SAT e ha una complessità costante (!!!):

0

Sorprendentemente, il prossimo programma darà la risposta corretta per tutti i problemi rimanenti e ha la stessa complessità. Quindi devi solo scegliere il programma giusto e avrai la risposta corretta in tutti i casi!

1

6
Questo è fantastico Mi sono fatto una bella risata.
Karl Damgaard Asmussen,

2
Assolutamente fantastico ******!
The Blue Dog

78
Hmm. Adesso è facile. Tutto quello che devo fare è scrivere un programma che sceglierà il programma giusto!
Cruncher,

Precisamente ! :-)
Mau,

6
Ricorda xkcd.com/221 .
msh210

34

JavaScript

Usando il non determinismo iterato, SAT può essere risolto in tempo polinomiale!

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

Esempio di utilizzo:

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

Questo algoritmo controlla solo la formula booleana data mille volte con input casuali. Quasi sempre funziona per piccoli input, ma è meno affidabile quando vengono introdotte più variabili.

A proposito, sono orgoglioso di aver avuto l'opportunità di utilizzare due delle funzionalità più sottoutilizzate di JavaScript l'una accanto all'altra: evale with.


4
Questo è in realtà un metodo di prova ben consolidato. Credo che la libreria di Haskell QuickCheck abbia iniziato tutto il divertimento. Da allora è stato reintegrato in molte lingue.
John Tyree,

4
Penso che dovrebbe essere notato che, questo programma ha meno probabilità di restituire la risposta corretta, maggiore è l'espressione sat. Il 1000ciclo in for dovrebbe in qualche modo ridimensionare con le dimensioni di input (alcuni ridimensionamenti polinomiali non-O (1)).
Cruncher,

2
@Cruncher Per essere più precisi, maggiore è il numero di variabili, minore è la probabilità di restituire la risposta corretta. (es. un'espressione molto lunga con una singola variabile restituirà quasi sempre la risposta corretta)
Peter Olson

2
@TimSeguine Ammetto che il mio uso della parola "non deterministico" in questo contesto è nella migliore delle ipotesi dubbioso, proprio come l'affermazione secondo cui SAT può essere risolto in tempi polinomiali. So che non è corretto, è solo una parte del gioco dell'inganno.
Peter Olson,

4
@PaulDraper e poi chiamali sottoutilizzati! Mi sono fatta una bella risata!
Rob,

32

Mathematica + Quantum Computing

Potresti non sapere che Mathematica viene fornito con un computer quantistico a bordo

Needs["Quantum`Computing`"];

Il pendolarismo adiabatico quantistico codifica un problema da risolvere in un hamiltoniano (operatore di energia) in modo tale che il suo stato di energia minima ("stato fondamentale") rappresenti la soluzione. Pertanto l'evoluzione adiabatica di un sistema quantistico allo stato fondamentale dell'Hamiltoniano e la successiva misurazione fornisce la soluzione al problema.

Definiamo un subhamiltoniano che corrisponde a ||parti dell'espressione, con una combinazione appropriata di operatori di Pauli per le variabili e la sua negazione

inserisci qui la descrizione dell'immagine

Dove per un'espressione come questa

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

l'argomento dovrebbe apparire come

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

Ecco il codice per costruire tale argomento dall'espressione 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

Ora costruiamo un hamiltoniano completo, riassumendo i subhamiltoniani (la somma corrisponde a &&parti dell'espressione)

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

E cerca lo stato di energia più basso

QuantumEigensystemForm[H, -1]

inserisci qui la descrizione dell'immagine

Se abbiamo un autovalore di zero, allora l'autovettore è la soluzione

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

Sfortunatamente il sito ufficiale per il componente aggiuntivo "Quantum Computing" non è attivo e non riesco a trovare un posto per scaricarlo, l'ho ancora installato sul mio computer. Il componente aggiuntivo ha anche una soluzione documentata al problema SAT, su cui ho basato il mio codice.


19
Non ho idea di come funzioni questa risposta. +1
Jonathan Pullano

5
@XiaogeSu "Naturalmente".
Swish,

3
@XiaogeSu Evoluzione determinata dall'Hamiltoniano e naturalmente si evolve all'energia più bassa. Quindi, conoscendo lo spettro, possiamo presumere che il sistema finirà nello stato fondamentale.
Swish,

3
@XiaogeSu per andare allo stato fondamentale, bisogna anche avere un'interazione con l'ambiente che deeccita gli stati superiori, hai ragione. L'idea qui è che questa interazione è molto piccola, "adiabatica".
Turion,

3
La computazione QM adiabatica ha molte somiglianze con la ricottura simulata classica . ora implementato da Dwave . è simile a un sistema di raffreddamento / temperatura "energetico" che "trova / si deposita" nei minimi locali .
vzn

27

Tre approcci qui, tutti implicano una riduzione di SAT nella sua lingua franca geometrica 2D: puzzle logici nonogramma. Le celle nel puzzle della logica corrispondono a variabili SAT, vincoli alle clausole.

Per una spiegazione completa (e per favore rivedi il mio codice per i bug!) Ho già pubblicato alcune informazioni sui pattern all'interno dello spazio della soluzione nonogram. Vedi https://codereview.stackexchange.com/questions/43770/nonogram-puzzle-solution-space. Enumerare> 4 miliardi di soluzioni puzzle e codificarle per adattarle a una tabella di verità mostra modelli frattali: auto-somiglianza e soprattutto auto-affinità. Questa ridondanza affine dimostra la struttura del problema, sfruttabile per ridurre le risorse computazionali necessarie per generare soluzioni. Mostra anche la necessità di un feedback caotico all'interno di qualsiasi algoritmo di successo. Esiste un potere esplicativo nel comportamento di transizione di fase in cui le istanze "facili" sono quelle che si trovano lungo la struttura grossolana, mentre le istanze "difficili" richiedono un'ulteriore iterazione nei minimi dettagli, abbastanza nascosta dall'euristica normale. Se desideri ingrandire l'angolo di questa infinita immagine (tutte <= 4x4 istanze di puzzle codificate) vedi http://re-curse.github.io/visualizing-intractability/nonograms_zoom/nonograms.html

Metodo 1. Estrapolare l'ombra spaziale della soluzione nonogramma usando mappe caotiche e apprendimento automatico (pensa a funzioni di adattamento simili a quelle che generano il Set di Mandelbrot).

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

Ecco una prova visiva dell'induzione. Se è possibile eseguire la scansione di queste quattro immagini da sinistra a destra e pensi di avere una buona idea per generare i dispersi 5 ° 6 ° ... ... ecc immagini, poi ho appena programmato te come mio NP Oracle per il problema decisionale della soluzione di nonogram esistenza. Per favore, fai un passo avanti per rivendicare il tuo premio come il supercomputer più potente del mondo. Ogni tanto ti darò da mangiare scosse elettriche mentre il mondo ti ringrazia per i tuoi contributi computazionali.

Metodo 2. Utilizzare trasformazioni di Fourier sulla versione booleana degli input. Le FFT forniscono informazioni globali su frequenza e posizione all'interno di un'istanza. Mentre la porzione di magnitudo dovrebbe essere simile tra la coppia di input, le loro informazioni di fase sono completamente diverse - contenenti informazioni direzionali su una proiezione della soluzione lungo un asse specifico. Se sei abbastanza intelligente, potresti ricostruire l'immagine di fase della soluzione tramite una speciale sovrapposizione delle immagini di fase di input. Quindi inversa trasforma la fase e la grandezza comune nel dominio del tempo della soluzione.

Cosa potrebbe spiegare questo metodo? Esistono molte permutazioni delle immagini booleane con imbottitura flessibile tra sequenze contigue. Ciò consente una mappatura tra input -> soluzione che si occupa della molteplicità pur mantenendo la proprietà FFT di mappature bidirezionali e univoche tra il dominio del tempo <-> (frequenza, fase). Significa anche che non esiste "nessuna soluzione". Ciò che direbbe è che in un caso continuo, ci sono soluzioni in scala di grigi che non stai prendendo in considerazione quando guardi l'immagine bilevel della risoluzione tradizionale dei puzzle non con grammature.

Perché non lo faresti? È un modo orribile per calcolare effettivamente, poiché le FFT nel mondo in virgola mobile di oggi sarebbero altamente inaccurate con casi di grandi dimensioni. La precisione è un grosso problema e la ricostruzione di immagini di grandezza quantizzata e immagini di fase di solito crea soluzioni molto approssimative, anche se forse non visivamente per le soglie dell'occhio umano. È anche molto difficile inventare questo business di sovrapposizione, poiché il tipo di funzione che lo sta effettivamente facendo è attualmente sconosciuto. Sarebbe un semplice schema di media? Probabilmente no, e non esiste un metodo di ricerca specifico per trovarlo tranne l'intuizione.

Metodo 3. Trova una regola di automi cellulari (su una possibile ~ 4 miliardi di tabelle di regole per le regole a 2 stati di von Neumann) che risolva una versione simmetrica del puzzle nonogramma. Si utilizza un incorporamento diretto del problema nelle celle, mostrato qui. Nonogrammi conservativi e simmetrici

Questo è probabilmente il metodo più elegante, in termini di semplicità e buoni effetti per il futuro dell'informatica. L'esistenza di questa regola non è dimostrata, ma ho il sospetto che esista. Ecco perché:

I nonogrammi richiedono un sacco di feedback caotici nell'algoritmo per essere risolti esattamente. Ciò è stabilito dal codice della forza bruta collegato a Revisione del codice. CA è praticamente il linguaggio più capace per programmare feedback caotici.

Si guarda a destra, visivamente. La regola si evolverebbe attraverso l'incorporamento, la propagazione delle informazioni in senso orizzontale e verticale, interferendo, quindi si stabilizzerebbe in una soluzione che conservasse il numero di celle impostate. Questo percorso di propagazione segue il percorso (all'indietro) che normalmente si pensa quando si proietta l'ombra di un oggetto fisico nella configurazione originale. I nonogrammi derivano da un caso speciale di tomografia discreta, quindi immagina di stare seduto simultaneamente in due scanner CT a gattino ... questo è il modo in cui i raggi X si propongono di generare le immagini mediche. Naturalmente, ci sono problemi di confine: i bordi dell'universo CA non possono continuare a propagare informazioni oltre i limiti, a meno che non si consenta un universo toroidale. Questo lancia anche il puzzle come un problema di valore limite periodico.

Spiega molteplici soluzioni come stati transitori in un effetto che oscilla continuamente tra le uscite di scambio come ingressi e viceversa. Spiega le istanze che non hanno soluzione come configurazioni originali che non conservano il numero di celle impostate. A seconda del risultato effettivo della ricerca di una tale regola, può persino approssimare istanze irrisolvibili con una soluzione stretta in cui gli stati delle celle vengono conservati.


2
+1 per avermi lasciato dicendo "perché non ci ho pensato?" : P
Navin,

Sei Stephen Wolfram e rivendico le mie cinque sterline!
Quuxplusone,

4
Questa risposta merita davvero più credito, poiché è il miglior tentativo di realizzare un programma convincente . Bello spettacolo.
Jonathan Pullano,

10

C ++

Ecco una soluzione che è garantita per funzionare in tempo polinomiale: corre O(n^k)dove nè il numero di booleani ed kè una costante di tua scelta.

È euristicamente corretto, che credo sia CS-speak per "dà la risposta corretta per la maggior parte del tempo, con un po 'di fortuna" (e, in questo caso, un valore adeguatamente grande di k- modifica mi è venuto in mente che per ogni fisso nche puoi impostare in modo ktale che n^k > 2^n- è barare?).

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

Buona risposta. Vorrei inserire la spiegazione in un tag spoiler in modo che le persone possano fissarlo e grattarsi un po 'la testa.
Jonathan Pullano,

Grazie per il suggerimento @JonathanPullano, ho aggiunto un tag spoiler e offuscato un po 'il codice.
CompuChip

A proposito, ho appena scoperto bitfield, forse avrei preferito questo std::vector.
CompuChip

3
+1 per l'offuscamento creativo e i riferimenti
dell'autostoppista

2
Sì, certo, questo è barare, se k dipende da n non è una costante :-)
RemcoGerlich

3

superficie rubino / gnuplot 3d

(ooh concorrenza rigida!) ... comunque ... un'immagine vale più di mille parole? si tratta di 3 grafici di superficie separati realizzati in gnuplot del punto di transizione SAT. gli assi (x, y) sono la clausola e il conteggio delle variabili e l'altezza z è il numero totale di chiamate ricorsive nel solutore. codice scritto in rubino. campiona 10x10 punti a 100 campioni ciascuno. dimostra / utilizza i principi di base della statistica ed è una simulazione Monte Carlo .

è fondamentalmente un algoritmo davis putnam in esecuzione su istanze casuali generate in formato DIMACS. questo è il tipo di esercizio che idealmente dovrebbe essere fatto nelle lezioni di CS in tutto il mondo in modo che gli studenti possano imparare le basi ma quasi non è stato insegnato in modo specifico ... forse qualche ragione per cui ci sono così tante prove fasulle P? = NP ? non c'è nemmeno un buon articolo di Wikipedia che descriva il fenomeno del punto di transizione (qualche acquirente?) che è un argomento molto importante nella fisica statistica ed è fondamentale anche in CS. [a] [b] ci sono molti articoli in CS sul punto di transizione tuttavia pochissimi sembrano mostrare trame di superficie! (invece mostra in genere fette 2D).

l'aumento esponenziale runtime è evidente in 1 st trama. la sella che attraversa il centro del 1 ° trama è il punto di transizione. le 2 nd e 3 rd grafici mostrano la transizione soddisfacibile%.

[a] comportamento di transizione di fase in CS ppt Toby Walsh
[b] probabilità empirica di soddisfacibilità k-SAT tcs.se
[c] grandi momenti nella matematica empirica / sperimentale / (T) CS / SAT , blog di TMachine

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

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
Sono contento che tu abbia contribuito a questa risposta. In qualsiasi prova riuscita di P contro NP (in entrambi i casi) è uno dei molti requisiti per la potenza predittiva. Grazie per aver sottolineato la sua importanza. :)

più riflessioni su P vs NP , molti riferimenti migliori / raccolti, ecc.
vzn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.