Un programma orientato agli oggetti può essere visto come una macchina a stati finiti?


13

Questa potrebbe essere una domanda filosofica / fondamentale, ma voglio solo chiarirla.

Nella mia comprensione, una macchina a stati finiti è un modo di modellare un sistema in cui l'output del sistema non dipenderà solo dagli input correnti, ma anche dallo stato corrente del sistema. Inoltre, come suggerisce il nome, una macchina a stati finiti può essere segmentata in un numero N finito di stati con il rispettivo stato e comportamento.

Se questo è corretto, ogni singolo oggetto con dati e membri di funzione non dovrebbe essere uno stato nel nostro modello orientato agli oggetti, rendendo qualsiasi progetto orientato agli oggetti una macchina a stati finiti?

Se questa non è l'interpretazione di un FSM nella progettazione di oggetti, cosa significano esattamente le persone quando implementano un FSM nel software? mi sto perdendo qualcosa?

Grazie


6
Computer + software è una macchina a stati purché si limiti la memoria, lo spazio su disco e altri tipi di archiviazione (come Internet). Non appena è consentita l'interfacciamento con Internet o altro hardware esterno (implica una memoria illimitata), questo diventa più simile a una macchina Turing. Hai mai sentito parlare di una frase "Turing completo"? Ad ogni modo, i programmi funzionali e quelli orientati all'obj finiscono entrambi come codice assembly. Non conosco Haskel (un linguaggio funzionale puro) / monadi, ma deve esserci una relazione interessante tra questo e una macchina di Turing.
Giobbe

Aggiungendo al punto Jobs, qualsiasi forma di non determinismo supera anche i modelli sia della macchina a stati che di Turing. Su Internet, hai più macchine non sincronizzate, perdita di dati attraverso connessioni imperfette, ecc. Anche con un semplice computer single-core, hai input non deterministici da parte dell'utente, ma normalmente ignori quel problema e fai finta di tutto l'input era noto in anticipo.
Steve314,

@ Steve314: Formalmente, gli automi deterministici sono in un unico stato. Ogni input porta a un nuovo stato. Per gli automi non deterministici, ogni input può portare a più stati. Un automa non deterministico con stati N può essere emulato da un automa deterministico con stati 2 ^ N.
Kevin Cline,

@cline - In questo caso, hai assolutamente ragione, ma penso che quello che avevo in mente fosse il tipo di concorrenza e variazione temporale che si verificano in una macchina del mondo reale - cose come un core che funziona un po 'più lentamente perché è troppo caldo , l'ora esatta in cui i dati si trovano sotto la testina di lettura, ecc. Tutto ciò si adatta al modello di automi finiti non deterministico che descrivi, ovviamente, quindi sei assolutamente corretto, ma il numero di stati sarà follemente enorme. Immagino che avrei potuto avere misure continue come quelle temperature in mente come parte dello stato del sistema (non solo conseguenze).
Steve314,

Risposte:


16

Qualsiasi programma a thread singolo in esecuzione su una macchina con una quantità finita di memoria può essere modellato come una macchina a stati finiti. Uno stato particolare nella macchina a stati finiti rappresenterà i valori specifici di tutta la memoria rilevante: variabili locali, variabili globali, memoria heap, dati attualmente scambiati nella memoria virtuale, persino il contenuto dei file pertinenti. In altre parole, ce ne saranno molte stati in quel modello di stati finiti, anche per programmi abbastanza banali.

Anche se l'unico stato del programma è una singola variabile globale di un tipo intero a 32 bit, ciò implica almeno 2 ^ 32 (più di 4 miliardi) di stati. E questo non tiene nemmeno conto del contatore del programma e dello stack di chiamate.

Un modello di automa a spinta è più realistico per questo tipo di cose. È come un automa finito, ma ha un concetto integrato di pila. Tuttavia, non è proprio uno stack di chiamate come nella maggior parte dei linguaggi di programmazione.

C'è una spiegazione di Wikipedia , ma non impantanarti nella sezione definizione formale.

Gli automi push-down vengono utilizzati per modellare calcoli generali. Le macchine di Turing sono simili , ma IIRC non identiche, sebbene le loro capacità di calcolo siano equivalenti .

Grazie a Kevin Cline per aver segnalato l'errore sopra - come sottolinea anche Wikipedia , gli automi push-down sono più potenti delle macchine a stati finiti, ma meno potenti delle macchine di Turing.

Onestamente non so dove questo peto cervello è venuto da - io faccio sapere che contesto grammatiche sensibili sono più potenti di contesto di libero, e che le grammatiche sensibili al contesto non può essere analizzato utilizzando un semplice automa push-down. So anche che mentre è possibile analizzare qualsiasi grammatica libera dal contesto inequivocabile in tempo lineare, in genere ci vuole più di un automa (deterministico) di push down per farlo. Quindi, come potrei finire per credere che un automa a spinta sia equivalente a una macchina di Turing è bizzarro.

Forse stavo pensando a un automa push-down con qualche macchinario aggiuntivo aggiunto, ma sarebbe come contare un automa finito equivalente a un automa push-down (basta aggiungere e sfruttare uno stack).

Gli automi push-down sono importanti per l'analisi. Li conosco abbastanza bene in quel contesto, ma non li ho mai davvero studiati come modelli informatici di calcolo, quindi non posso fornire molti più dettagli di quanti ne abbia già.

È possibile modellare un singolo oggetto OOP come macchina a stati finiti. Lo stato della macchina sarà determinato dagli stati di tutte le variabili membro. Normalmente, si contano solo gli stati validi tra le chiamate al metodo (non durante). Ancora una volta, in genere avrai molti stati di cui preoccuparti: è qualcosa che potresti usare come modello teorico, ma non vorrai enumerare tutti quegli stati, tranne forse in un caso banale.

È abbastanza comune, tuttavia, modellare alcuni aspetti dello stato di un oggetto usando una macchina a stati finiti. Un caso comune è l'intelligenza artificiale per gli oggetti di gioco.

Questo è anche ciò che di solito viene fatto quando si definisce un parser usando un modello di automa push-down. Sebbene ci sia un insieme finito di stati in un modello di stato, questo modella solo una parte dello stato del parser: informazioni aggiuntive sono memorizzate in variabili extra insieme a quello stato. Questo risolve, ad esempio, il problema dei 4 miliardi di stati per un intero: non elencare tutti quegli stati, ma solo la variabile intera. In un certo senso fa ancora parte dello stato dell'automa push-down, ma è un approccio molto più gestibile che in effetti disegnare 4 miliardi di bolle di stato su un diagramma.


1
"È possibile modellare un singolo oggetto OOP come macchina a stati finiti". Vero, ma debole. Non è possibile". È una questione di definizione. Il compito di un linguaggio di programmazione consiste nell'esprimere un FSM in una notazione ordinata. OOP è un'implementazione di un FSM con notazione più semplice per tutti i vari stati.
S. Lott,

1
@ S.Lott - Sì, ma la maggior parte delle persone non pensa a un oggetto OOP come espressione di un FSM, almeno non la maggior parte delle volte. L'uso del nome "macchina dello stato" tende a implicare che si sta utilizzando un'implementazione specifica, come il modello di progettazione dello stato o una variabile membro ID stato. La "modellazione come macchina a stati" spesso implica anche qualcosa sulla specifica o sulla documentazione di progettazione, distinta dall'implementazione di quella classe. Pertanto, modellare una classe come modello a stati finiti soggettivamente significa qualcosa di diverso dal fornire semplicemente il codice sorgente per la classe.
Steve314,

"la gente non pensa". Vero. E un problema profondo. Tutti i programmi sono macchine a stati. Hanno molti stati. Questo è ciò che richiede il test "Turing Complete" per un linguaggio di programmazione. È una regola molto, molto forte (e assoluta). Invece di suggerire che è "possibile", è più come "necessario" e "sufficiente".
S. Lott,

1
-1: Gli automi push-down NON sono potenti come le macchine Turing.
Kevin Cline,

1
@kevin cline - grazie - e cosa stavo pensando !!! A cura di colpire quel bit fuori. Nonostante ciò che ho detto sullo studio formale, lo so meglio di così e allora avrei dovuto conoscerlo meglio.
Steve314,

5

Il problema non è se qualcosa "è" o "non" è una macchina a stati finiti. Una macchina a stati finiti è un modello mentale che può essere utile per comprendere qualcosa se quella cosa può essere pensata come tale.

Tipicamente il modello di macchina a stati finiti si applica a cose con un piccolo numero di stati, come una grammatica regolare, o il sequencer di istruzioni di un computer.


1

Per rispondere direttamente alla tua domanda: quasi certamente no. Non sembra esserci una teoria matematica formale per OOP nel modo in cui il calcolo lambda e / o la logica combinatoria sono alla base della programmazione funzionale, o Turing Machines alla base della normale programmazione imperativa.

Vedi questa domanda StackOverflow per ulteriori informazioni.

La mia ipotesi è che la mancanza di una teoria matematica sottostante sia il motivo per cui tutti sanno cos'è un "oggetto" quando ne vedono uno, ma nessuno vede "oggetti" più o meno come tutti gli altri.


0

No, praticamente non comunque. Una macchina a stati finiti normalmente ricorda solo un dato: il suo stato attuale.

Un'applicazione tipica di un FSM è il lexing o l'analisi. Ad esempio, quando stiamo facendo lexing, è (normalmente) abbastanza facile codificare le azioni per ogni possibile input in termini di stato corrente e il valore dell'input.

Ad esempio, potremmo avere uno stato NUMBER in cui stiamo leggendo le cifre di un numero. Se il prossimo carattere che leggiamo è una cifra, restiamo nello stato NUMERO. Se si tratta di uno spazio o di una scheda, restituiremmo le cifre e poi passeremmo allo stato WHITE_SPACE, o qualcosa in quell'ordine.

Ora, è certamente vero che in un tipico FSM (specialmente uno che è implementato nel software) finiamo con bit e pezzi che tecnicamente non si adattano perfettamente a un FSM mescolato con lo stesso FSM. Ad esempio, quando leggiamo le cifre di un numero, spesso salverai la posizione della prima cifra, quindi quando arrivi alla fine puoi facilmente calcolare il valore del numero.

Lo stesso FSM ha alcune limitazioni: non ha alcun meccanismo di conteggio. Considera, ad esempio, una lingua che utilizzava "/ " per iniziare un commento e " /" per terminare un commento. Il suo lexer avrebbe probabilmente uno stato COMMENTO in cui è entrato quando ha visto un token '/ '. A questo punto non ha modo (a parte l'aggiunta di un altro stato come COMMENT2) per rilevare un altro "/ " e rendersi conto che si tratta di un commento nidificato. Piuttosto, nello stato del commento, riconoscerà */come dire di lasciare lo stato del commento e qualsiasi altra cosa lo lascia nello stato del commento.

Come già detto, è certamente potrebbe includere uno stato comment2 per un commento nidificato - e in questo, uno stato comment3, e così via. Ad un certo punto, tuttavia, ti stancherai di aggiungere più stati e questo determinerà la profondità di annidamento massima consentita per i commenti. Con qualche altra forma di parser (cioè non una macchina allo stato puro, ma qualcosa che ha un po 'di memoria per farla contare) puoi semplicemente monitorare direttamente la profondità di annidamento, quindi rimani nello stato COMMENTO fino a raggiungere un token di commento vicino che bilancia il primo, quindi il tuo contatore torna a 0 e lasci lo stato COMMENTO.

Come ho detto, tuttavia, quando aggiungi un contatore del genere, quello che hai non è più un vero e proprio FSM. Allo stesso tempo, in realtà è abbastanza vicino - in particolare, abbastanza vicino da poter simulare il contatore semplicemente aggiungendo più stati.

In un caso tipico, tuttavia, quando qualcuno parla dell'implementazione di un FSM nel software, lo manterrà ragionevolmente "puro". In particolare, il software reagirà all'input corrente in base solo allo stato corrente e al valore dell'input stesso. Se la reazione dipende da molto altro, di solito non la chiameranno una macchina a stati (almeno se sanno di cosa stanno parlando).


"il suo stato attuale" può includere una grande quantità di informazioni. Un FSM può contare banalmente avendo stati per ogni numero che conterà. È finito (a differenza di una macchina di Turing) ma è ancora perfettamente in grado di contare. Penso che potresti aver bisogno di un esempio migliore.
S. Lott,

il software nel tuo cellulare è una raccolta di macchine di stato orribilmente complesse che ricordano molti dati e li interpretano in base allo stato attuale.
Mawg dice di reintegrare Monica il

-2

Non credo che la risposta accettata sia completamente corretta.

Non è possibile modellare un programma arbitrario scritto in un linguaggio Turing Complete, orientato o meno agli oggetti, come una macchina a stati finiti. Quasi tutti i linguaggi per computer moderni, come Java, C ++ o Smalltalk, sono Turing Complete.

Ad esempio, non è possibile creare una macchina a stati finiti per riconoscere una sequenza di oggetti in cui sono presenti n istanze di un oggetto seguite da n istanze di un altro oggetto poiché le macchine a stati finiti non sono in grado di scrivere n in una variabile. Possono solo leggere l'input e passare a uno stato.


ciò si limita a ripetere i punti fatti e spiegati nelle risposte postate 3 anni fa, ad esempio in questo
moscerino del
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.