C/C++ symbolische Mathematik beibringen...
-
Jester schrieb:
Nur, wie findet man welche Regeln Sinn machen?
die klassische antwort heißt hier "neuronale netze". *grins*
Woran sieht man, daß man fertig ist mit vereinfachen?
wenn alle möglichkeiten gemacht wurden.
Wie sieht man, daß die scheinbar unsinnige Regelanwendung nach 5 weiteren Umformungen plötzlich eine geniale Vereinfachung ermöglicht?
einfach bis suchtiefe 5 alle regeln zulassen. tiefer werden nur regeln verfolgt, die zu "vereinfachengen" geführt haben, wobei "vereinfachung" was einfach messbares wie knotenanzahl im baum oder strlen(ausgabe) ist.
-
Jo, klingt vernünftig. Jetzt brauchen wir nur noch jemanden, der's implementiert. :p
-
Ich kann die 2 Stündchen leider nicht opfern, sonst würde ich das implementieren
.
-
ths schrieb:
Also im Prinzip hast du ja Recht: "Nur" analysieren und bewerten. Aber
das wird richtig heftig... wie man in dem Dokument sieht.Von der Mathematik her ist es ja nicht so heftig. Ausserdem arbeitet das Programm nur dumm irgendwelche Möglichkeiten ab. Die Hauptschwierigkeit besteht imho darin, die einzelnen Gesetze in eine Form zu bringen, die das Programm versteht und darin, den Term zu bewerten.
-
MaSTaH schrieb:
Ich kann die 2 Stündchen leider nicht opfern, sonst würde ich das implementieren
.
der suchbaum ist nicht das ding. der sucher auch nicht. heuristiken wachsen mit der beschäftigung am problem und sind anfangs nichtmal relevant.
die transformationsregeln sind ein ding. die sauber hinschreiben zu können kannste in c++/java verbacken. da muss ne neue sprache her (oder lisp, wie immer).
wir brauchen allein mehr als ne woche, um nen mathematiker einzufangen, der uns sinnvolle regeln erzählt. eventuell ist es sogar für jeden nichtmathematiker unmöglich nen mathematiker einzufangen. fatales problem.
-
Das war auch nicht ganz ernst gemeint. Ich dachte das war klar
.
-
Ein paar Links zum Thema:
(CAS == Cumputer Algebra System)
Erklärung, wie man ein CAS erstellt (allgemein):
http://www.math.wpi.edu/IQP/BVCalcHist/calctoc.htmlEin kostenloses CAS, mit Quellcode in C++:
http://yacas.sourceforge.net/Nochmal kostenloses CAS, mit Quellcode:
http://maxima.sourceforge.net/index.shtmlFür alle, die Lisp und Prolog noch nicht kennen:
http://de.wikipedia.org/wiki/PROLOG
http://de.wikipedia.org/wiki/Lisp(PROLOG ist ja echt der Hammer -- werd mich mal mit beiden beschäftigen)
-
Oh -- was interessantes:
Ladet euch mal das Prolog-Arbeitsbuch runter:
http://www.bildung-mv.de/download/fortbildungsmaterial/arbeitsbuch_prolog.pdfAuf Seite 68 wird erklärt, wie man Prolog das Differenzieren (symbolisch!!!)
beibringt!Also GENAU das, was wir suchen. Ist doch schonmal was. Wie kann ich aber
Prolog in eine grafische C / C++ / Java - Oberfläche einbinden?
-
Symbolisches Differenzieren ist trivial.
-
mfdg schrieb:
Symbolisches Differenzieren ist trivial.
Symbolisches integrieren auch
Und alles andere auch... für einen
Menschen. Jedes Problem für sich ist doch kein ProblemNur alles jederzeit
zu ermöglichen in einem Programm ... das ist doch das Problem
-
ths schrieb:
mfdg schrieb:
Symbolisches Differenzieren ist trivial.
Symbolisches integrieren auch
Und alles andere auch... für einen
Menschen. Jedes Problem für sich ist doch kein ProblemNur alles jederzeit
zu ermöglichen in einem Programm ... das ist doch das Problemwar eher anders gemeint, nehme ich an. in zwei oder drei bildschirmen voll mit lisp baut man nen symbolischen ableiter. als übung für anfänger findet man den in büchern.
symbolischen integrieren hingegen ist gemein. so gemein, daß ich noch kein computeralebrasystem gesehen habe, das mich in dieser hinsicht befriedigte. mußte oft in büchern nachgucken und rumprobieren, bis ich ne umformung gefunden hatte, von der ausgegend das prog es schaffte. zum glück ist aber differenzieren trivial, und darum konnte ich mit dem prog immer die probe machen.
-
Ist das sooo gemein zu programmieren?
Ich habs noch nicht
probiertIch werde es mal mit der Prädikatenlogik mit Prolog
probieren ... 1,5 Wochen Semester-Ferien hab ich ja noch
-
ths schrieb:
Ist das sooo gemein zu programmieren?
Ich habs noch nicht
probiertIch werde es mal mit der Prädikatenlogik mit Prolog
probieren ... 1,5 Wochen Semester-Ferien hab ich ja nochbeim differenzieren hat man halt 5 regeln und für sin(x), cos(x) exp(x) und noch ein paar ne direkte formel und fertig.
beim integrieren stehen ja bereits in der formelsammlung 30 seiten mit wissenswerten integralen. und das fiese ist, daß selbst nach reinklopfen der 30 seiten der rechner noch relativ blind ist (aber endlich anständig lahm).
beim differenzieren kann man immer direkt die ableitung hinschreiben. eventuell müssen nachher unterterme weiter abgeleitet werden.
beim integrieren kann man evtl erst ne formel benutzen, nachdem! man 5 zauberhafte umformungen getan hat. udn die methoden, die der mensch benutzt, erscheinen so willkürlich und vage. "mal was substituieren". jo, soll der rechner doch alle möglichen teilterme mal substituieren und inegration durch substitution probieren. er hat ja keinen blick dafür, zu sehen, was vielversprechende substitutionsopfer sind.
also mir erscheint es nicht einfach.
-
Ich arbeite gerade das Differential-Beispiel von Prolog durch. Immerhin
hab ich noch nie was mit Prolog gemacht. Wenn ich es dann kapiert habe,
wie Prolog das macht, werde ich die Integration anfagenMal sehen,
wo ich auf Probleme stoße...Aber substituieren und partielle Integration... könnten mit Prolog
schwer werden. Da braucht man dann, die schon öfter erwähnte, Heuristik
-
volkard schrieb:
beim integrieren kann man evtl erst ne formel benutzen, nachdem! man 5 zauberhafte umformungen getan hat. udn die methoden, die der mensch benutzt, erscheinen so willkürlich und vage. "mal was substituieren". jo, soll der rechner doch alle möglichen teilterme mal substituieren und inegration durch substitution probieren. er hat ja keinen blick dafür, zu sehen, was vielversprechende substitutionsopfer sind.
Ich frage mich, ob man beim symbolischen Intergrieren vielleicht besser mit Potenzreihen arbeiten könnte.
...also in der Art:
1. Funktion in Potenzreihe entwickeln bzw. Potenzreihen der "Teilfunktionen" betrachten und gesamt vereinfachen.
2. Potenzreihe integrieren.
3. Potenzreihe wieder in bekannte Funktionen "zerlegen"....nur so ne undurchdachte Idee.
-
...nach etwas drüber nachdenken -> dumme Idee.
-
Das ist echt blöd... es gibt kein Prolog-Forum
Also das Differenzieren geht ohne Probleme -- sehr beeindruckend.
Auch das automatische Vereinfachen von Termen geht. Was nicht geht,
ist beides gleichzeitigDafür brauch ich mal nen Prolog-Experten
Differenzieren in 16 Zeilen (!!!) :
d(X,X,1). d(C,X,0) :- atomic(C), C \= X. d(pot(U,N),X,N*pot(U,N1)*DU) :- N>1, N1 is N-1, d(U,X,DU). d(pot(U,N),X,N*pot(U,N1)*DU) :- N<0, N1 is N-1, d(U,X,DU). d(sin(U),X,cos(U)*DU) :- d(U,X,DU). d(cos(U),X,0-sin(U)*DU) :- d(U,X,DU). d(exp(U),X,exp(U)*DU) :- d(U,X,DU). d(log(U),X,(1/X)*DU) :- d(U,X,DU). d(U+C,X,DU) :- atomic(C), C \= X, d(U,X,DU), !. d(C+U,X,DU) :- atomic(C), C \= X, d(U,X,DU), !. d(F+G,X,DF+DG) :- d(F,X,DF), d(G,X,DG). d(U-C,X,DU) :- atomic(C), C \= X, d(U,X,DU), !. d(C-U,X,0-DU) :- atomic(C), C \= X, d(U,X,DU), !. d(F-G,X,DF-DG) :- d(F,X,DF), d(G,X,DG). d(F*G,X,DF*G+F*DG) :- d(F,X,DF), d(G,X,DG). d(F/G,X,(G*DF-F*DG)/(G*G)) :- d(F,X,DF), d(G,X,DG).
Das Vereinfachen der Terme ist etwas länglicher:
vereinfacht(T,T) :- atomic(T). vereinfacht(T,V) :- T=L*R, vereinfacht(L,L1), vereinfacht(R,R1), m(L1*R1,V). vereinfacht(T,V) :- T=L+R, vereinfacht(L,L1), vereinfacht(R,R1), a(L1+R1,V). vereinfacht(T,V) :- T=L-R, vereinfacht(L,L1), vereinfacht(R,R1), s(L1-R1,V). a(X+0,X) :- !. a(0+X,X) :- !. a(X+Y,Z) :- integer(X), integer(Y), Z is X+Y. a(Y+X+W,V) :- integer(Y), integer(W), a(Y+W,Z), a(Z+X,V). a(X+Y+W,V) :- integer(Y), integer(W), a(Y+W,Z), a(Z+X,V). a(Y+X+W,V) :- a(Y+W,Z), Z \= Y+W, a(Z+X,V), !. a(X+Y+W,V) :- a(Y+W,Z), Z \= Y+W, a(Z+X,V), !. a(X+X,V) :- m(2 * X,V), !. a(Y*X+X,V) :- a(Y+1,W), m(W*X,V), !. a(X+Y*X,V) :- a(Y+1,W), m(W*X,V), !. a(Y*X+Z*X,V) :- a(Y+Z,W), m(W*X,V), !. a(X+Y,Y+X) :- integer(Y), !. a(X+Y,X+Y). /* Default-Klausel */ s(X-0,X) :- !. s(X-Y,Z) :- integer(X), integer(Y), Z is X-Y, !. s(X-X,0) :- !. s(X-Y-W,V) :- integer(Y), integer(W), a(Y+W,Z), s(X-Z,V), !. s(Y-X-W,V) :- integer(Y), integer(W), s(Y-W,Z), s(Z-X,V), !. s(X-Y-W,V) :- s(Y+W,Z), Z \= Y+W, s(X-Z,V), !. s(Y-X-W,V) :- s(Y-W,Z), Z \= Y-W, s(Z-X,V), !. s(Y+X-W,V) :- integer(Y), integer(W), s(Y-W,Z), a(Z+X,V), !. s(Y+X-W,V) :- s(Y-W,Z), Z \= Y-W, a(X+Z,V), !. s(X+Y-W,V) :- s(Y-W,Z), Z \= Y-W, a(X+Z,V), !. s(Y*X-X,V) :- s(Y-1,W), m(W*X,V), !. s(X-Y*X,V) :- s(1-Y,W), m(W*X,V), !. s(Y*X-Z*X,V) :- s(Y-Z,W), m(W*X,V), !. s(X-Y,X-Y). /* Default-Klausel */ m(0*X,0) :- !. m(X*0,0) :- !. m(1*X,X) :- !. m(X*1,X) :- !. m(X*Y,Z) :- integer(X), integer(Y), Z is X*Y, !. m(X*Y*W,V) :- integer(Y), integer(W), m(Y*W,Z), m(Z*X,V), !. m(Y*X*W,V) :- integer(Y), integer(W), m(Y*W,Z), m(Z*X,V), !. m(X*Z,Z*X) :- integer(Z), !. m(X*Y,X*Y) :- !. /* Default-Klausel */
Das Problem ist nun, dass "der Vereinfacher" sin(U), cos(U) etc. nicht
als Atom anerkennt. Ist auch richtig. Wenn man jetzt statt sin(U)
'sin(U)' schreiben würde, wäre sin(U) auch ein Atom -- es würde gehen.
Aber dann kann man sin(U) nicht mehr differenzierenMan muss also die erste Zeile "des Vereinfachers" ändern. Wenn ich
vereinfacht(T,T) :- atomic(T) | compound(T). nehme, geht es.
Nur auf compound(T) trifft alles zu -- auch die zu vereinfachen
Terme :p Geht also auch nicht.Wie auch immer...
==================================
Ich habe mal drüber nachgedacht, wies mit der Integration wäre:
Integration durch Substitution und partielle Integration wäre
kein Problem...Substitution
Zwei Möglichkeiten:- Man kann ihn immer substituieren lassen. Mein Gott: Dann substituiert
er halt auch x zu x im einfachen Fall! Davon geht die Welt nicht unter.
Beim differenzieren wird auch immer die Kettenregel benutzt, auch wenn es
nicht nötig wäre --> auch kein Problem. - Oder man überprüft einfach mit atomic() oder var() ob
in der Funktion eine weitere steht, wie:
sin(x) --> atomic(X) ist true --> nicht substituieren
sin(x^2) (heisst im Code: sin(pot(x,2))) --> atomic ist false --> substituieren... etc.
Die partielle Integration an sich ist ja kein Problem: Differenzieren
kann er ja schon -- das ist eine VoraussetzungMan muss sich eine Bedingung
ausdenken, ab wann er versuchen soll es partiell zu machen... Sollte nicht
das Problem sein.Integrieren, elementar:
Kann er schon, ähnlich, wie es Jester vorher gesagt hatteIst ja auch
logisch: Die einfache Integration ist nur die Umkehrung der Differentiation.
Gibt man dem Programm die Ableitung vor, und lässt ihm die Aufleitung suchen,
so findet er sie ab und zu -- nicht immerAlso könnte man schon das erste Prädikat für die Integration aus dem
Stehgreif hinschreiben:integral(I,X,V) := d(V,X,I).
Das ist der Grundstein. Dann muss man halt die ganzen Besonderheiten
berücksichtigen...Aber erstmal will ich, dass der Vereinfacher mit dem Differenzierer zusammen
arbeitetErst dann kann man auf dem Gesamtergebnis den Integrierer
definieren...Gibt es hier einen Prolog-Expertern
- Man kann ihn immer substituieren lassen. Mein Gott: Dann substituiert
-
Nachtrag (der andere Beitrag war schon zu lang):
Es gibt für Prolog ein C++- und Java-Interface
Wir können dann also eine GUI basteln, und eine
beliebige Eingabe an Prolog weiterleiten...Dann catch man die Ausgabe von Prolog und gibt
sie in der GUI wieder aus. Wenn der User noch
ein numerisches Ergebnis möchte, oder ein grafisches
Ergebnis, dann wird die Ausgabe noch geparst und
man setzt für die Variablen Werte ein ... bla bla.Die Ausgabe könnte man in Java mit einem StringTokenizer
auseinander nehmen...
-
haste wo ein kleines prolog zum downloaden? dann probiere ich's mal.
-
Ja, SWI-Prolog ist kostenlos.
http://www.swi-prolog.org/Einfach installieren, und die Quellcodes als .pro oder .pl Datei
in deinen Prolog-Ordner packen. Bei mir wurde der Prolog-Ordner
auf dem Desktop erzeugt. Dort kommen nur Quellcodes hinein.Das Programm wird natürlich schön sauber im Order Programme
installiert, klar.Nach dem Start von Prolog musst du jede Quellcode-Datei einzel
mit consult(DATEINAME). laden. Aber ohne die Dateiendung!
Und immer den Punkt mitschreiben!Differenzieren kannst du mit:
d(FUNKTION,Variable,Ziel). <-- Punkt nicht vergessen!"Funktion" ist klar. x^y geht mit pot(x,y) --> x^2 => pot(x,2)
cos(..), sin(..), exp(..) .... etc. ist klar. In der Funktion
alles klein schreiben!"Variable" ist die zu differenzierende Variable, __kleingeschrieben__!
Also z. B.: "x".Und Ziel ist eine __großgeschriebene__ Variable. Name ist egal.
Beispiel:
d(pot(x,2),x,V).
d((sin(pot(x,2))*pot(x,5))/cos(x),x,V).Vereinfachen kannst du mit:
vereinfacht(ALT,NEU).Beispiel:
vereinfach(0*x+5,V).Viel Spaß. Danke das du es auch probierst
Ich werde mich jetzt ins
Usenet begeben -- dort gibt es Prolog-Bereiche