Nottolino quantistico
In una sua conferenza, il Premio Nobel per la fisica Richard P. Feynman descrive un nottolino quantistico, e spiega il perchè tale meccanismo non può generare il moto perpetuo.
Il nottolino di Feynman consiste in una ruota dentata, una molla, un dente d'arresto, un asse con delle pale. L'asse si collega alla ruota dentata, la quale viene tenuta in posizione dal dente e dalla molla. I denti della ruota sono arcuati, in maniera da consentire la rotazione in un solo verso, opponendo resistenza al moto nel verso opposto incastrandosi nel dente, spinto verso il basso dalla molla. Il tutto è immerso in un gas.
L'agitazione termica delle molecole di gas le fa urtare contro le pale. Gli urti nel verso corretto, se sufficientemente potenti, fanno scattare di un dente il meccanismo. Nel verso opposto vengono ostacolati dal dente di arresto. Tuttavia questo contrasto genera calore, e ben presto molla e dente sono talmente caldi da non poter più ostacolare nulla, e la ruota resta alla mercè del moto browniano.
Non è dunque possibile utilizzare una tale macchina per il moto perpetuo, in accordo ai principi della termodinamica. Tuttavia, esiste un metodo per riuscire a ricavare un lavoro dall'agitazione termica, a patto di accettare qualche volta di compiere un lavoro opposto, e di fornire comunque energia al sistema dall'esterno in maniera casuale.
Come è possibile? L'importante è avere una struttura con un andamento di potenziale a dente di sega, in cui la distanza tra un massimo e il minimo successivo sia minore che nel verso opposto. Inoltre, deve essere presente un meccanismo frenante e una sorgente di energia casuale.
Alcuni esempi di meccanismi del genere sono le pompe ioniche cellulari: solitamente consistono di una proteina a forma di imbuto, che alterna una configurazione a canale chiuso in cui lo ione è fortemente accoppiato al canale ad una a canale aperto in cui lo ione interagisce debolmente con il canale. Il moto browniano delle molecole è allora sufficiente a spingere lo ione in senso contrario al gradiente elettrochimico. Il passaggio da uno stato all'altro viene solitamente effettuato grazie alla combustione di una molecola di ATP.
Tutto questo sembra poco probabile, eppure è possibile simularne gli effetti con un semplice gioco "da tavolo". Ipotizziamo una serie di 5 caselle alternate, bianche e nere. La pedina, posta inizialmente al centro, si sposta in base al risultato del lancio di due dadi e del colore della casella di partenza.
Ad esempio
| Mossa | Bianco | Nero |
| Avanti | 7, 11 | 11 |
| Indietro | 2, 3, 12 | 2, 4, 12 |
Lanciando 2 dadi, abbiamo 6 possibilità che venga 7, 2 che esca 11, 1 per il 12 e il 2, 2 per il 3, 3 per il 4.
Iniziamo con la pedina sul nero al centro. Le probabilità di vincere sono il prodotto delle possibilità di andare avanti dal bianco al nero, moltiplicate per quelle in avanti dal nero al bianco: dunque . Le possibilità di perdere sono invece . Si perde dunque 100 volte ogni 80 vittorie.
Supponiamo ora di avere un altro insieme di regole:
| Mossa | Bianco | Nero |
| Avanti | 11 | 7, 11 |
| Indietro | 2, 4, 12 | 2, 3, 12 |
Le probabilità di vittoria sono le stesse. Ora facciamo intervenire il processo casuale: applichiamo ora le une o le altre regole in base al risultato del lancio di una moneta (testa o croce). Se ricalcoliamo le probabilità di vittoria, risultano allora il prodotto della media delle mosse in avanti dal bianco per quelle di mosse in avanti dal nero:
Errore del parser (errore di sintassi): {\displaystyle \frac{8+2}{2} × \frac{8+2}{2} = 25} .
Quelle di sconfitta, similmente, saranno
Errore del parser (errore di sintassi): {\displaystyle \frac{4+5}{2} × \frac{4+5}{2} = 20,25} .
Otteniamo quindi 81 sconfitte ogni 100 vittorie!
Per i più increduli, ecco un programma in C++ che simula 100.000 partie al gioco, con una serie di 32 caselle. Per modificare questi parametri, basta cambiare i valori delle variabili partite_da_giocare e Dimensione Otteniamo la vittoria circa 83 volte su 100, pur partendo dalla casella 16, in cui bastano 15 passi per perdere e ne servono 16 per vincere.
/* codice */
/* Copyright BlakWolf 2004 */
/* Released under Gnu GPL V. 2 or later, at your option */
#include <set> /* contenitore per regole */
#include <cstdlib> /* rand() e srand() */
#include <ctime> /* time() */
#include <iostream>
/*
* Pedina
* contiene la posizione sulla scacchiera
*/
struct Pedina {
unsigned int posizione;
};
/*
* Regola
* associa un risultato del dado
* ad uno spostamento
* */
struct Regola {
unsigned int Lancio;
int Spostamento;
Regola( const unsigned int& lancio, const int& spostamento) :
Lancio(lancio),
Spostamento(spostamento) {}
inline bool operator< (const Regola& r) const {
return (Lancio < r.Lancio);
}
inline bool operator== (const Regola& r) const {
return (Lancio == r.Lancio);
}
};
/* Insieme di regole
* Contiene un insieme di regole del gioco
* e le applica in funzione del tiro del dado
*/
class Ruleset {
public:
typedef std::set<Regola> Container;
typedef Container::iterator Iterator;
private:
Container regole;
public:
Ruleset(Iterator from, Iterator to);
int Applica(unsigned int& Lancio);
~Ruleset(){};
};
/* Inserisce le regole nel contenitore
*/
Ruleset::Ruleset(Ruleset::Iterator from, Ruleset::Iterator to){
for (Iterator it = from; it != to; ++it)
regole.insert(*it);
}
/* Se trova una regola la applica, e ritorna lo spostamento
* altrimenti ritorna 0 (spostamento nullo)
*/
int Ruleset::Applica(unsigned int& Lancio){
Iterator it = regole.find(Regola(Lancio, 0)) ;
if (it == regole.end())
return 0;
return (it->Spostamento);
}
int main() {
unsigned int Dimesione = 30; /* lunghezza del percorso */
int partite_da_giocare = 100000; /* partite */
int Croce;
unsigned int Lancio;
Ruleset::Container Contenitore;
// set n. 1 di regole per i quadrati pari
// se escono 7 o 11, avanza di 1, se escono 2 3 12 indietreggia di 1
Contenitore.insert(Regola(7, 1));
Contenitore.insert(Regola(11, 1));
Contenitore.insert(Regola(2, -1));
Contenitore.insert(Regola(3, -1));
Contenitore.insert(Regola(12, -1));
Ruleset Bianchi_a(Contenitore.begin(), Contenitore.end());
// set n. 1 di regole per i quadrati dispari
// vedi sopra
Contenitore.clear();
Contenitore.insert(Regola(11, 1));
Contenitore.insert(Regola(2, -1));
Contenitore.insert(Regola(4, -1));
Contenitore.insert(Regola(12, -1));
Ruleset Neri_a(Contenitore.begin(), Contenitore.end());
// set n. 2 di regole per i quadrati pari
Contenitore.clear();
Contenitore.insert(Regola(11, 1));
Contenitore.insert(Regola(2, -1));
Contenitore.insert(Regola(4, -1));
Contenitore.insert(Regola(12, -1));
Ruleset Bianchi_b(Contenitore.begin(), Contenitore.end());
// set n. 2 di regole per i quadrati dispari
Contenitore.clear();
Contenitore.insert(Regola(7, 1));
Contenitore.insert(Regola(11, 1));
Contenitore.insert(Regola(2, -1));
Contenitore.insert(Regola(3, -1));
Contenitore.insert(Regola(12, -1));
Ruleset Neri_b(Contenitore.begin(), Contenitore.end());
int Contatore = 0; // partite giocate
int Vittorie = 0; // partite vinte
Pedina p;
p.posizione = Dimesione / 2 ; /* Inizia la partita con la pedina al
centro */
std::srand(std::time(0)); /* Randomizzazione del seme */
while (Contatore < partite_da_giocare){
Croce = (std::rand()>>8) & 1; // pari o dispari
Lancio = (std::rand()>>8) % 6 + 1; // dado 1
Lancio += (std::rand()>>8) % 6 + 1; // dado 2
if (Croce) { /* Esce Croce */
if (p.posizione & 1) { /* Casella Dispari */
p.posizione += Bianchi_a.Applica(Lancio);
} else /* Casella Pari */
p.posizione += Neri_a.Applica(Lancio);
} else { /* Esce testa */
if (p.posizione & 1) { /* Casella Dispari */
p.posizione += Bianchi_b.Applica(Lancio);
} else /* Casella Pari */
p.posizione += Neri_b.Applica(Lancio);
}
if (p.posizione == Dimesione) { /* vittoria */
p.posizione = Dimesione / 2; /* Rimetti il pedone al centro */
++Vittorie;
++Contatore
}
if (p.posizione == 0) { /* sconfitta */
p.posizione = Dimesione / 2;
++Contatore;
}
}
std::cout << "Vittorie " << Vittorie << " Giocate " << Contatore << "
("; std::cout << 100. * Vittorie / Contatore << "%)" << std::endl;
}
/* fine */