FP per simulazione e modellazione


12

Sto per iniziare un progetto di simulazione / modellazione. So già che OOP è utilizzato per questo tipo di progetti. Tuttavia, studiare Haskell mi ha fatto considerare di usare il paradigma FP per modellare un sistema di componenti. Lasciami elaborare:

Diciamo che ho un componente di tipo A, caratterizzato da un insieme di dati (un parametro come temperatura o pressione, un PDE e alcune condizioni al contorno, ecc.) E un componente di tipo B, caratterizzato da un diverso insieme di dati (diverso o stesso parametro, PDE e condizioni al contorno differenti). Supponiamo anche che le funzioni / i metodi che verranno applicati su ciascun componente siano uguali (ad esempio un metodo Galerkin). Lo stato mutabile dell'oggetto verrebbe utilizzato per parametri non costanti.

Se dovessi usare un approccio OOP, creerei due oggetti che incapsulerebbero i dati di ciascun tipo, i metodi per risolvere il PDE (l'ereditarietà sarebbe usata qui per il riutilizzo del codice) e la soluzione al PDE.

D'altra parte, se dovessi usare un approccio FP, ogni componente verrebbe suddiviso in parti di dati e funzioni che agirebbero sui dati al fine di ottenere la soluzione per il PDE. I parametri non costanti sarebbero passati come funzioni di qualcos'altro (tempo per esempio) o espressi da un qualche tipo di mutabilità (emulazione della mutabilità, ecc.) Questo approccio mi sembra più semplice supponendo che le operazioni lineari sui dati sarebbero banali.

Per concludere, implementare l'approccio FP sarebbe effettivamente più semplice e più facile da gestire (aggiungere un diverso tipo di componente o un nuovo metodo per risolvere il pde) rispetto a quello OOP?

Vengo da un background C ++ / Fortran, inoltre non sono un programmatore professionista, quindi correggimi su tutto ciò che ho sbagliato.

Risposte:


7

Bella domanda, ho pensato in modo simile. Storicamente, il paradigma OO è nato dalla necessità di una simulazione al computer - vedi la storia di Simula - e nonostante i primi linguaggi OO come Smalltalk siano stati fatti da persone che sapevano cosa stavano facendo (ad esempio Alan Kay), OO è ora discutibilmente sovrautilizzato e porta troppa complessità accidentale .

Generalmente, i programmi in stile FP saranno più brevi, più facili da testare e più facili da modificare rispetto ai programmi OO. Come ha affermato Rob Harrop nel suo discorso, Il futuro è funzionale? , non puoi mai essere più semplice di funzioni e dati; i due si compongono all'infinito, per costruire qualunque astrazione sia necessaria. Quindi un modo per rispondere alla tua domanda (o sto semplicemente riaffermandola? :) è chiedere: Qual è la funzione di livello più alto e come appaiono i dati di input di livello più alto -> output-data? Quindi puoi iniziare a scomporre quelle funzioni "alfa" e tipi di dati nel livello successivo di astrazioni, e ripetere se necessario.

Un'altra prospettiva (non proprio le risposte) sulla tua domanda è quella di guardare questo thread (disclaimer, l'ho iniziato) su StackOverflow, alcune delle risposte sono molto interessanti: /programming/3431654/how-does- funzionale-programmazione-applica-to-simulazioni

La mia opinione a questo punto è, a meno che tu non stia modellando una situazione in cui ci sono davvero oggetti discreti che interagiscono solo in modi definiti (ad esempio un modello di una rete di computer) - e quindi mappano direttamente le capacità di un messaggio pulito, linguaggio OO del paradigma del passaggio: è più semplice utilizzare FP. Si noti che anche nella comunità di programmazione di giochi - in cui le simulazioni sono molto diffuse e i requisiti di prestazione sono fondamentali - gli sviluppatori esperti si stanno allontanando dal paradigma OO e / o utilizzano più FP, ad esempio vedere questa discussione HN o i commenti di John Carmack su FP


È bello sapere che non sono l'unico a dubitare di OOP in simulazione e grazie per aver risposto alla mia domanda! Avevo letto i commenti di John Carmack su FP e ho pensato di implementare alcuni aspetti di FP su C ++ (copiare gli oggetti, o raccogliere l'input e passarlo a una funzione) ma poi non so se dovrei iniziare il mio progetto con C ++ invece di un linguaggio FP, come Haskell, poiché gli aspetti FP sono integrati e si esprime mutabilità solo quando è necessario. Hai continuato a usare Clojure o FP in generale, considerando che hai avuto un problema / domanda simile?
heaptobesquare,

@heaptobesquare - Sì, ho costantemente aumentato il mio Clojure-fu con l'obiettivo di scrivere simulazioni al suo interno. Niente è ancora pronto per essere mostrato, ma non vedo alcun ostacolo, e il design di Clojure è meravigliosamente pragmatico, ad esempio puoi usare transitori / mutazione se necessario, inoltre i suoi agenti sono adatti agli aspetti asincroni. Ad un certo punto (nessuna promessa quando) scriverò un articolo sull'argomento ...
limist

Ho dato un'occhiata a Clojure ma non posso dire di amare le espressioni S. So che è pratico (il codice Lisp è dato) ma è facile abituarsi?
heaptobesquare,

@heaptobesquare - la sintassi s-expressions / Lisp è in realtà molto facile abituarsi; prima di tutto scegli un buon editor (Emacs o vim, il mio voto è per Emacs, vedi dev.clojure.org/display/doc/Getting+Started+with+Emacs ) che ha una modalità per Clojure, prendi un buon libro (ad es. Programmazione Clojure ) e inizia l'hacking. Dopo un paio di settimane al massimo, la sintassi si dissolverà in secondo piano, come dovrebbe - è così perfettamente coerente che ci penserai esponenzialmente meno spesso e libererai cicli mentali per cose più importanti. :)
limist

Allora ci proverò sicuramente. L'homoiconicity di Lisp è interessante dopo tutto.
heaptobesquare il

2

IMHO per quasi tutte le attività di ragionevole complessità la domanda "è uno stile FP o OOP la scelta migliore" non può essere risolta in modo obiettivo. In genere, in una situazione del genere la domanda non è "né FP o OOP", ma come combinare le parti migliori di entrambi i paradigmi per risolvere il problema.

Il problema che hai scovato sopra sembra essere molto matematico, e immagino selvaggiamente che avrai bisogno di alcune operazioni con la matrice. OOP è ottimo per la modellazione di tipi di dati astratti e il calcolo della matrice può essere facilmente implementato come "oggetti matrice" con operazioni su matrici. L'implementazione in un modo in cui tutte le operazioni di matrice fanno parte di una classe di matrice ti aiuta a tenere insieme le cose che appartengono insieme, mantenendo così una buona struttura generale.

D'altra parte, i PDE sono equazioni sulle funzioni e la soluzione potrebbe essere di nuovo funzionale. Quindi l'utilizzo di un approccio funzionale per quel tipo di "componenti" può sembrare naturale qui. Tali funzioni possono avere parametri di matrice, che mostrano un esempio di come combinare OOP e FP. Un altro esempio potrebbe essere l'implementazione di una classe di matrici, che utilizza strumenti funzionali per mappare una determinata operazione su ogni elemento della tua matrice. Quindi anche qui non è "OOP contro FP" ma "OOP combinato con FP" che ti dà i migliori risultati.


La ringrazio per la risposta! Quindi, se io dove usare C ++, incapsulerei solo i dati (ovvero parametri, condizioni al contorno e PDE in forma di matrice) del componente in un oggetto e definendo le funzioni (anche alcune di ordine superiore, nel caso in cui un parametro è una funzione di qualcos'altro), al di fuori dell'ambito dell'oggetto, che opererebbe sui dati dell'oggetto, sarebbe efficiente?
heaptobesquare,

@heaptobesquare: onestamente, non posso dirti se sarà efficace nel tuo caso. Fai una prova, pensa in grande, inizia in piccolo. Inizia a programmare del "codice tracer" ( artima.com/intv/tracer.html ) per scoprire cosa funziona meglio e cosa no. E se vieni in una situazione in cui noti che qualcosa non funziona correttamente, rifletti.
Doc Brown,

Haskell ha la libreria Hmatrix, che è un collegamento per le librerie BLAS / LAPACK, e una sintassi molto bella per essa, che sceglierei personalmente su un approccio OOP.
paul

@paul: grazie, lo darò sicuramente un'occhiata! Le librerie Haskell sono generalmente coerenti e ricche di contenuti? I wiki lo dicono ma è un dato di fatto?
heaptobesquare,

@heaptobesquare: L'unica libreria Haskell che ho usato in qualsiasi misura è Parsec (l'ho usato per scrivere un assemblatore), ma mi è piaciuto molto usarlo. Ho fatto solo esplorazioni GHCI di Hmatrix e gli attacchi OpenGL di Haskell, ma sembrano abbastanza belli. Hmatrix sembra essere quasi conciso come MATLAB (che ho usato un po ') - che è stato creato appositamente per quel genere di cose. Dalla mia esperienza limitata le biblioteche sono coerenti - questo perché Haskell è costruito su un piccolo numero di semplici blocchi - e sono anche ricchi perché agli Haskeller non piace fare cose banali :)
paul
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.