Hallo,
ich möchte ein C++ Programm versuchen zu schreiben wo Bedingungen aus
verschiedenen vorgefertigten Modulen (Funktionen, Operatoren(> < && ||))
per Zufall zusammengestellt werden und dann ausgeführt werden.
Als grobes Beispiel es gibt 100 Funktionen mit Rückgabewerten (genannt
FR) und es gibt Operatoren wie < > && || und es gibt weitere 100
Funktionen mit bestimmten Aktionen (genannt FA). Nun soll random daraus
eine Kombination erstellt werden können wie zB:
if(FR1() > FR2() && FR4 < FR8 && FR1 < FR9)
{
FA3();
}
Meine Frage wäre wie würde man das grundsätzlich angehen von der
Datenstruktur? In welcher Datenstruktur erzeugt man so eine
Aneinanderreihung von Funktionen und Operatoren die miteinander zur
Laufzeit dynamisch kombiniert ausgeführt werden sollen? Und wie setzt
man das um damit auch das Programm performant bleibt?
Ein Ansatz wäre sicherlich auf Stringbasis die Code-Module nach
funktionierenden Regeln zusammenstellen zu lassen und dann zur Laufzeit
zu Libs zu kompilieren und einzubinden (zb dlopen()). Etwa wie in dieser
Ansatz:
https://stackoverflow.com/questions/11016078/is-it-possible-to-create-a-function-dynamically-during-runtime-in-c/11016382#11016382
Meine Frage wäre, geht so etwas auch ohne besondere Perfomance-Verluste
direkt in C++ mit Hilfe irgendwelcher dynamisch erstellten
Datenstrukturen welche dann den entsprechenden Codeablauf von Funktionen
und Operatoren abgearbeiten können? Wo packe ich sozusagen die
Kombination solcher Module rein was als Ganzes dann natürlich noch
ausführbar sein soll?
Grüße
Du hast was prinzipielles bei compilieren vs. Laufzeit nicht verstanden.
CPPDYN schrieb:> Meine Frage wäre wie würde man das grundsätzlich angehen
Man programmiert einen Interpreter.
Was du suchst ist eine "embedded scripting language", sprich eine
Skriptsprache die eingebunden und ausgeführt werden kann. Eine Liste
solcher Sprachen gibt es etwa hier:
https://github.com/dbohdan/embedded-scripting-languages
Der prominenteste Vertreter ist wohl Lua, der vor allem in der
Spieleindustrie sehr häufig zum Einsatz kommt. Zu Lua würde ich auch
persönlich raten weil:
-) Der Core sehr klein ist. (~200kB)
-) Die Community groß und die Entwicklung im Gegensatz zu vielen anderen
Vertretern auf der Liste aktiv ist.
-) Die C++ Bindings in Form von sol2 (https://github.com/ThePhD/sol2) so
ziemlich das Beste sind was es gibt.
/edit
Deutsche Sprache...
Klingt interessant allerdings hab ich quasi nur von C++ eine Ahnung.
Wäre das was ich will nicht auch direkt in C++ möglich ohne auf eine
andere Sprache zurückgreifen zu müssen?
Performancemäßig klingt das auch nicht gut: "Interpretierter Code ist in
etwa fünf bis 20 Mal langsamer als kompilierter Code"
https://de.wikipedia.org/wiki/Interpreter#Eigenschaften
In einem Array aus Funktionszeigern alle 100 Funktionen ablegen und dann
diese per Zufall aufrufen?
Natürlich müssen dann diese Funktionen die gleiche Signatur haben.
Dirk K. schrieb:> Kannst auch mal nach dem Command-Pattern> suchen, ein ähnliches Problem hab ich mal> damit gelöst.>> merciless
Meinst du damit OOP also per virtuelle Funktionen etc etwas bauen?
CPPDYN schrieb:> if(FR1() > FR2() && FR4 < FR8 && FR1 < FR9)> {> FA3();> }
Bei dem Durcheiander voon Funktionsaufrufen und Variablen habe ich so
meine Zweifel ...
> Meine Frage wäre wie würde man das grundsätzlich angehen von der> Datenstruktur?
... aber schau dir mal
https://www.gnu.org/software/libmatheval/
an. Du baust einen String zusammen, der dann interpretiert wird.
leo
zitter_ned_aso schrieb:> In einem Array aus Funktionszeigern alle 100 Funktionen ablegen und dann> diese per Zufall aufrufen?>> Natürlich müssen dann diese Funktionen die gleiche Signatur haben.
interessanter Ansatz das wäre sogar ein performant, aber wie würde man
dann das mit den Verknüpfungen der Funktionen per Operatoren machen?
Muss ich nochmal überlegen...
CPPDYN schrieb:> dann das mit den Verknüpfungen der Funktionen per Operatoren machen?
Genauso mit Zeigern?
Erst mal Funktionen erzeugen:
1
2
boolfoo_and(int(fp1)(void),int(fp2)(void)){
3
returnfp1()&&fp2();
4
}
5
6
boolfoo_or(int(fp1)(void),int(fp2)(void)){
7
returnfp1()||fp2();
8
}
9
10
usw.
Und dann auch diese in einem Array von Funktionszeigern unterbringen.
Aber wie kann es
CPPDYN schrieb:> und es gibt weitere 100> Funktionen mit bestimmten Aktionen (genannt FA).
100 Funktionen geben? Da steht doch eine if-Anweisung. Und diese hat nur
zwei Zustände (true/false). Wie können diese 100 Fuktionen auf zwei
Zustände verteilt werden? Auch per Zufall?
zitter_ned_aso schrieb:> 100 Funktionen geben? Da steht doch eine if-Anweisung. Und diese hat nur> zwei Zustände (true/false). Wie können diese 100 Fuktionen auf zwei> Zustände verteilt werden? Auch per Zufall?
war natürlich erstmal nur ein Beispiel, aber ja im Grunde alles per
Zufall, aus den 100 Funktionen mit Rückgabewert wird in Kombi mit
zufälligen Operatoren eine Bedingung gemacht bei der auch wiederum
zufällig sein kann wieviele Bedingungen aneinandergehängt werden (durch
zB && ||). Wenn dann Bedingung erfüllt ist, dann soll eine der
Aktionsfunktionen ausgeführt werden die auch wiederum zufällig gewählt
ist...
Interessanter Ansatz mit den Funktionszeigern weil das auch schön
low-level ist. Die Frage wäre auch ob man dann auch langfristig
Verzweigungen (verschachtelte ifs... erzeugen könnte). Muss später mal
ein paar Sachen testen... :-)
CPPDYN schrieb:> aber ja im Grunde alles per> Zufall, aus den 100 Funktionen mit Rückgabewert wird in Kombi mit> zufälligen Operatoren eine Bedingung gemacht bei der auch wiederum> zufällig sein kann wieviele Bedingungen aneinandergehängt werden (durch> zB && ||). Wenn dann Bedingung erfüllt ist, dann soll eine der> Aktionsfunktionen ausgeführt werden die auch wiederum zufällig gewählt> ist...
Klingt nach Kunst.
CPPDYN schrieb:> Dirk K. schrieb:>> Kannst auch mal nach dem Command-Pattern>> suchen, ein ähnliches Problem hab ich mal>> damit gelöst.>>>> merciless>> Meinst du damit OOP also per virtuelle Funktionen etc etwas bauen?
Hier ein Beispiel (ziemlich Pseudocode):
Ich habe damit komplexe mathematische Formeln
flexibel in einer DB abgelegt und zur Laufzeit
die Formel mit Hilfe von einzelnen Commands
zusammengestöpselt. Jede Formel lag als
Baumstruktur in einer Tabelle abgelegt.
So konnte man durch Änderungen in der DB
die Berechnungsvorschrift ändern, ohne neu
kompilieren zu müssen. Hochperformant ist
das natürlich nicht, aber sehr flexibel.
Wenn es dir ums lösen von mathematischen Ausdrücken geht, kannst du z.B.
auch GNU Octave einbinden und das die Auswertung erledingen lassen. Oder
Python. Bei beiden kannst du dir die Implementierung anschauen, wie man
einen Interpreter schreibt.
Es kommt sehr darauf an was du genau erreichen möchtest, einfache
logische Operationen?, das komplette Typenspektrum von C++?, Funktionen
mit n Parametern, Nur Ints oder auch Float, Strings? Was bedeutet für
dich Performanz, genau so schnell wie kompiliert?
Wenn du dein Ziel so abstrakt laesst ist es schwierig dir konkrete Tips
zu geben
Falls es nur einfache Operationen sind könntest du damit den Code
dynamisch erzeugen, mit relativ gleicher Performanz
https://asmjit.com
Das geht prinzipiell auch per Textfresser: 2 Coderümpfe erstellen, und
den random-Code dazwischenschieben, compilieren, ausführen.
Aber ich fürchte, ich weiss nicht, wozu, also kann ich auch nicht ahnen,
worauf es Dir ankommt.
Das haben einige sehr erfolgreich bereits umgesetzt, ist lange her.
Herausgekommen sind dabei so Sachen wie Python , Java , Perl ,
Lua ...
Nur zu: richtig gute C++ Programmierer welche das Rad nochmals erfinden
sind immer gefragt!
Programmiersprachentheaterintendant schrieb:> Das haben einige sehr erfolgreich bereits umgesetzt, ist lange her.> Herausgekommen sind dabei so Sachen wie [...] , Perl ,> [...] ...
Ich habe es gewusst, Perl ist eine rein zufällige Kombination von
Operatoren und Funktionen!
Nimm einen std::vector auf std::function<> und shuffle() den, dann
schreib für die Operatoren irgendwas, was zwei Argumente nimmt und einen
zufälligen Operator drauf anwendet. Wenn das was du beschreibst
tatsächlich alles ist was du machen willst, gibt es wirklich einen
Haufen einfache Lösungen für das Problem.
mh schrieb:> Programmiersprachentheaterintendant schrieb:>> Das haben einige sehr erfolgreich bereits umgesetzt, ist lange her.>> Herausgekommen sind dabei so Sachen wie [...] , Perl ,>> [...] ...>> Ich habe es gewusst, Perl ist eine rein zufällige Kombination von> Operatoren und Funktionen!
Natürlich stimmt das so, auch wenn Du nur die Syntax meinst :-) (ich
auch!)
Die Zufälligkeit ist aber auch ganz bestimmt der
interessante/schwierige Teil an der Fragestellung des TOs...