FP für Simulation und Modellierung

12

Ich bin dabei, ein Simulations- / Modellierungsprojekt zu starten. Ich weiß bereits, dass OOP für diese Art von Projekten verwendet wird. Das Studium von Haskell hat mich jedoch dazu veranlasst, das FP-Paradigma für die Modellierung eines Komponentensystems zu verwenden. Lassen Sie mich näher darauf eingehen:

Angenommen, ich habe eine Komponente vom Typ A, die durch einen Datensatz (einen Parameter wie Temperatur oder Druck, eine PDE und einige Randbedingungen usw.) Gekennzeichnet ist, und eine Komponente vom Typ B, die durch einen anderen Datensatz (unterschiedlich) gekennzeichnet ist oder gleicher Parameter, unterschiedliche PDE und Randbedingungen). Nehmen wir außerdem an, dass die Funktionen / Methoden, die auf jede Komponente angewendet werden, identisch sind (z. B. eine Galerkin-Methode). Der veränderbare Zustand des Objekts würde für nicht konstante Parameter verwendet.

Wenn ich einen OOP-Ansatz verwenden würde, würde ich zwei Objekte erstellen, die die Daten jedes Typs kapseln, die Methoden zum Lösen der PDE (hier würde die Vererbung zur Wiederverwendung von Code verwendet) und die Lösung für die PDE.

Wenn ich andererseits einen FP-Ansatz verwenden würde, würde jede Komponente in Datenteile und die Funktionen zerlegt, die auf die Daten wirken würden, um die Lösung für die PDE zu erhalten. Nicht konstante Parameter würden als Funktionen von etwas anderem (z. B. Zeit) übergeben oder durch eine Art von Veränderlichkeit (Emulation der Veränderlichkeit usw.) Ausgedrückt. Dieser Ansatz erscheint mir einfacher, wenn ich annehme, dass lineare Operationen an Daten trivial wären.

Wäre die Implementierung des FP-Ansatzes tatsächlich einfacher und einfacher zu verwalten (Hinzufügen einer anderen Art von Komponente oder einer neuen Methode zur Lösung des PDE) als die OOP?

Ich habe einen C ++ / Fortran-Hintergrund und bin kein professioneller Programmierer. Korrigieren Sie mich daher in allen Fällen, in denen ich mich geirrt habe.

heaptobesquare
quelle

Antworten:

7

Gute Frage, ich habe ähnlich gedacht. Historisch gesehen entstand das OO-Paradigma aus der Notwendigkeit einer Computersimulation - siehe die Geschichte von Simula - und obwohl frühe OO-Sprachen wie Smalltalk von Leuten geschrieben wurden, die wussten, was sie taten (z. B. Alan Kay), ist OO jetzt wohl überbeansprucht und bringt viel zu viel zufällige Komplexität .

Im Allgemeinen sind Programme im FP-Stil kürzer, einfacher zu testen und einfacher zu ändern als OO-Programme. Wie Rob Harrop es in seinem Vortrag formulierte: Ist die Zukunft funktional? , Sie können nie einfacher als Funktionen und Daten erhalten; die beiden komponieren unendlich, um die Abstraktionen aufzubauen, die benötigt werden. Eine Möglichkeit, Ihre Frage zu beantworten (oder wiederhole ich sie nur? :), besteht darin, zu fragen, wie die Funktion auf höchster Ebene und die Eingabedaten auf höchster Ebene -> Ausgabedaten aussehen. Anschließend können Sie diese "Alpha" -Funktionen und Datentypen in die nächste Abstraktionsebene aufteilen und nach Bedarf wiederholen.

Eine andere Perspektive (keine vollständigen Antworten) auf Ihre Frage ist das Betrachten dieses Threads (Haftungsausschluss, ich habe damit begonnen) auf StackOverflow. Einige der Antworten sind sehr interessant: /programming/3431654/how-does- Funktionsprogrammierung für Simulationen

Meine eigene Meinung an dieser Stelle ist, es sei denn, Sie modellieren eine Situation, in der es wirklich diskrete Objekte gibt, die nur auf bestimmte Weise interagieren (z. B. ein Modell eines Computernetzwerks) - und somit direkt die Fähigkeiten eines sauberen, nachrichtenbasierten Netzwerks abbilden. Passing-Paradigma OO-Sprache - es ist einfacher, FP zu gehen. Beachten Sie, dass erfahrene Entwickler auch in der Spiele-Programmier-Community, in der Simulationen sehr verbreitet sind und Leistungsanforderungen im Vordergrund stehen, vom OO-Paradigma abweichen und / oder mehr FP verwenden, z. B. diese HN-Diskussion oder John Carmacks Kommentare zu FP

Limist
quelle
Es ist gut zu wissen, dass ich nicht der einzige bin, der an OOP in der Simulation zweifelt, und ich danke Ihnen für die Beantwortung meiner Frage! Ich hatte John Carmacks Kommentare zu FP gelesen und dachte darüber nach, einige FP-Aspekte in C ++ zu implementieren (die Objekte zu kopieren oder die Eingaben zu sammeln und an eine Funktion zu übergeben), aber ich weiß auch nicht, ob ich mein Projekt mit C ++ starten soll Anstelle einer FP-Sprache wie Haskell sind FP-Aspekte integriert, und Sie können die Veränderlichkeit nur dann zum Ausdruck bringen, wenn sie benötigt wird. Haben Sie Clojure oder FP im Allgemeinen weiter verwendet, da Sie ein ähnliches Problem / eine ähnliche Frage hatten?
heaptobesquare
@heaptobesquare - Ja, ich habe meinen Clojure-fu ständig hochgefahren, um Simulationen darin zu schreiben. Noch nicht bereit zum Zeigen, aber ich sehe keine Show-Stopper, und Clojures Design ist wunderschön pragmatisch, z. B. können Sie Transienten / Mutationen verwenden, falls erforderlich, und die Agenten eignen sich gut für asynchrone Aspekte. Irgendwann (ohne Versprechen, wann) schreibe ich einen Artikel zum Thema ...
Limist
Ich habe mir Clojure angesehen, kann aber nicht sagen, dass ich S-Ausdrücke mag. Ich weiß, dass es praktisch ist (Lisp-Code sind Daten), aber ist es einfach, sich daran zu gewöhnen?
heaptobesquare
@heaptobesquare - s-expressions / Lisp-Syntax ist eigentlich sehr einfach zu gewöhnen; Wählen Sie zuerst einen guten Editor (Emacs oder vim, meine Stimme ist für Emacs, siehe dev.clojure.org/display/doc/Getting+Started+with+Emacs ), der einen Modus für Clojure hat, und holen Sie sich ein gutes Buch (z. B. Programming Clojure) ) und fange an zu hacken. Spätestens nach ein paar Wochen tritt die Syntax in den Hintergrund, wie es sich gehört. Sie ist so perfekt konsistent, dass Sie weniger exponentiell daran denken und mentale Zyklen für wichtigere Dinge freigeben. :)
Limist
Ich werde es dann auf jeden Fall versuchen. Immerhin ist Lisps Homoikonizität interessant.
heaptobesquare
2

IMHO für fast jede Aufgabe von angemessener Komplexität kann die Frage "ist ein FP-Stil oder OOP-Stil die bessere Wahl" nicht objektiv beantwortet werden. In einer solchen Situation lautet die Frage in der Regel nicht "entweder FP oder OOP", sondern wie die besten Teile beider Paradigmen zur Lösung Ihres Problems kombiniert werden können.

Das Problem, das Sie oben skizziert haben, scheint sehr mathematisch zu sein, und ich gehe davon aus, dass Sie einige Matrixoperationen benötigen werden. OOP ist sehr gut für die Modellierung abstrakter Datentypen geeignet, und Matrixberechnungen können leicht als "Matrixobjekte" mit Operationen auf Matrizen implementiert werden. Wenn Sie dies so implementieren, dass alle Matrixoperationen Teil einer Matrixklasse sind, können Sie Dinge zusammenhalten, die zusammen gehören, und so eine gute Gesamtstruktur aufrechterhalten.

Andererseits sind PDEs Gleichungen für Funktionen, und die Lösung kann wieder funktionieren. Die Verwendung eines funktionalen Ansatzes für diese Art von "Komponenten" mag hier natürlich erscheinen. Diese Funktionen können Matrixparameter haben, die ein Beispiel für die Kombination von OOP und FP zeigen. Ein weiteres Beispiel wäre eine Matrixklassenimplementierung, bei der mithilfe von Funktionswerkzeugen jedem Element Ihrer Matrix eine bestimmte Operation zugeordnet wird. Also auch hier ist es nicht "OOP versus FP", sondern "OOP kombiniert mit FP", die Ihnen die besten Ergebnisse bringt.

Doc Brown
quelle
Vielen Dank für Ihre Antwort! Wenn ich also C ++ verwenden würde, würde ich nur die Daten (das sind Parameter, Randbedingungen und die PDE in Matrixform) der Komponente in ein Objekt einkapseln und die Funktionen definieren (sogar einige Funktionen höherer Ordnung, im Fall a Parameter ist eine Funktion von etwas anderem), außerhalb des Bereichs des Objekts, die auf die Daten des Objekts arbeiten würde, effizient sein?
heaptobesquare
@ heaptobesquare: ehrlich gesagt kann ich dir nicht sagen, ob es in deinem Fall effizient sein wird. Probieren Sie es aus, denken Sie groß, fangen Sie klein an. Beginnen Sie mit der Programmierung eines "Tracer-Codes" ( artima.com/intv/tracer.html ), um herauszufinden, was am besten funktioniert und was nicht. Und wenn Sie zu einer Situation kommen, in der Sie bemerken, dass etwas nicht richtig funktioniert, überarbeiten Sie.
Doc Brown
Haskell hat die Hmatrix-Bibliothek, die Bindungen für die BLAS / LAPACK-Bibliotheken darstellt, und eine sehr schöne Syntax dafür, die ich persönlich einem OOP-Ansatz vorziehen würde.
Paul
@paul: Danke, ich werde es mir auf jeden Fall ansehen! Sind Haskell-Bibliotheken im Allgemeinen konsistent und inhaltsreich? Die Wikis sagen das, aber ist das eine Tatsache?
heaptobesquare
@heaptobesquare: Die einzige Haskell-Bibliothek, die ich bis zu einem gewissen Grad verwendet habe, ist Parsec (ich habe damit einen Assembler geschrieben), aber ich habe es geliebt, sie zu verwenden. Ich habe nur Hmatrix und die Haskell OpenGL-Bindungen mit GHCI untersucht, aber sie scheinen ganz nett zu sein. Hmatrix sieht fast so prägnant aus wie MATLAB (das ich ziemlich oft benutzt habe) - das speziell für diese Art von Dingen entwickelt wurde. Meiner begrenzten Erfahrung nach sind die Bibliotheken konsistent - das liegt daran, dass Haskell auf einer kleinen Anzahl einfacher Bausteine ​​aufgebaut ist - und sie sind auch reichhaltig, weil Haskeller nicht gerne weltliche Dinge tun :)
paul