Question

J'ai entendu dire que l'une des motivations originales de McCarthy pour inventer Lisp était d'écrire un système de différenciation automatique. Malgré cela, mes recherches Google n'ont pas donné de bibliothèques / macros pour faire cela. Existe-t-il des bibliothèques Scheme / Common Lisp / Clojure (macros) pour prendre une fonction F et renvoyer une fonction dF / dx qui calcule la dérivée de F?

Je voudrais qu'il supporte les F avec plusieurs arguments. L'utilisateur choisirait lequel de ceux-ci est le x par rapport à différencier. Idéalement, le différenciateur fonctionnerait même pour les F et les x à valeurs vectorielles.

MODIFIER : plusieurs personnes ont mentionné la différenciation symbolique. La différence entre la différenciation symbolique et la différenciation automatique est subtile, mais elle est bien résumée dans Wikipedia , et en particulier dans cette image . Cette distinction n'est pas aussi forte dans lisp, où les expressions symboliques peuvent être transformées en programmes de travail en l'état, mais il reste une difficulté potentielle:

La différenciation symbolique nécessite que l'expression à différencier soit composée d'opérations avec des dérivées connues. Par exemple, quelqu'un a mentionné l'exemple de SICP d'une macro qui passe par des sexps simples comme (+ y (* (x y))), et utilise la règle de chaîne, ainsi que des connaissances sur la façon de différencier + et *, pour renvoyer un sexp qui représente le dérivé. J'en aurais besoin pour travailler avec des expressions comme (* (foo x y) (bar x)), où foo et bar peuvent à leur tour appeler d'autres fonctions dont les dérivés ne sont pas connus au moment de la différenciation.

Ce serait bien s'il y avait un moyen de prendre une expression comme (foo x y) et de la remplacer par son corps de fonction, en remplaçant toute mention des arguments par x et y de manière hygiénique. Y en a-t-il?

De plus, aucune des solutions ci-dessus ne résout les complications qui surviennent lors de la différenciation des fonctions à valeurs vectorielles par rapport aux arguments à valeurs vectorielles ... ce à quoi la plupart des implémentations d'autodifférenciation sont conçues.

Était-ce utile?

La solution

Il existe deux autres packages, tous deux pour la différenciation automatique dans Scheme.Le second est basé sur le premier, mais retravaillé comme un œuf de poule.Ceux-ci prennent en charge les modes avant et arrière.

Autres conseils

Alexey Radul écrit:

Eh bien, il y a le système de différenciation automatique dans Scmutils

http://groups.csail.mit. edu / mac / users / gjs / 6946 / linux-install.htm

(qui, par coïncidence, fait également une différenciation symbolique). Je ne connais aucune autre implémentation publiée, bien que vous puissiez consultez http://autodiff.org/ .

Il existe également une belle explication sur la façon de l'implémenter vous-même dans annexe de Structure et Interprétation de la Mécanique Classique

http://mitpress.mit.edu/sicm/

ainsi que dans la littérature académique. Le mode avant est particulièrement pas si difficile, même si vous devez faire attention pour éviter les perturbations confusion. Vous pouvez consulter les publications de Barak Pearlmutter et Jeffrey Mark Siskind, qui collaborent sur une Variante Lisp qui intègre AD et a publié sur problèmes environnants.

http://scholar.google.com/ savant? q= Barak + Pearlmutter + et + Jeffrey + Mark + Siskind

Si vous recherchez un système symbolique, vous pouvez essayer maxima (ou ici ).Il fonctionne sur un certain nombre de combinaisons de plates-formes Common-Lisp / OS, mais il s'agit plus d'un système complet que d'une bibliothèque.

La sortie de la console est correcte, mais elle peut produire une sortie assez belle lorsqu'elle est associée à texmacs .

Maxima 5.23.2 http://maxima.sourceforge.net
using Lisp GNU Common Lisp (GCL) GCL 2.6.8 (a.k.a. GCL)
Distributed under the GNU Public License. See the file COPYING.
Dedicated to the memory of William Schelter.
The function bug_report() provides bug reporting information.
(%i1) diff(sin(1/x),x);
                                        1
                                     cos(-)
                                         x
(%o1)                              - ------
                                        2
                                       x


EDIT

D'accord, on dirait que j'ai mal compris la question.Un peu de googler suggère qu'il existe des outils pour cela dans SCMUTILS ici , téléchargez ici , manuel d'utilisation ici (voir p24 et plus).

Il peut être intéressant que scmutlis ait maintenant été porté sur Clojure. Il reste encore beaucoup de travail à faire, mais le code des premiers chapitres du livre SICM semble bien fonctionner.

Les routines et les opérateurs de différenciation semblent également acceptables avec le peu de tests que j'ai fait, et il est même exempt de certains bogues qui semblent s'être glissés dans les versions ultérieures de scmutils.

Je pense que scmutils couvre les exigences de différenciation d'OP, car il gérera correctement les dérivés des fonctions connues et inconnues (littérales). Cette page donne les détails nécessaires pour voir dans quelle mesure il répond aux exigences: SICM - Dérivés - Notation

L'un des avantages de fonctionner sur la JVM, c'est que cela fonctionnera de manière autonome si nécessaire, pas besoin même d'installer Clojure!

Il est très proche du schéma original, des concessions minimales faites pour la syntaxe Clojure.

Vous pouvez le voir ici: https://github.com/littleredcomputer/sicmutils#sicmutils

===

Addendum: Voici un exemple de différenciation automatique dans le package SicmUtils Clojure. Ceci est un exemple courant circulant sur différents sites Internet, le code à différencier est

    function f(x)
      y = x;
      for i=1...100
        y = sin(x+y);
      return y

Après l'avoir un peu clarifié, nous avons

   > (defn inner [y] (fn[x] (sin (+ x y))))
   > (defn f100 [x] (nth (iterate (inner x) x) 100))
   ;; value of derivative at 6
   > ((D f100) 6)
    => 0.51603111348625
   ;; value of the 4th derivative at 1
   > (((expt D 4) f100) 1)
    => -1.7853200839806143

Voici une implémentation d'AD en commun lisp.

Il vaut la peine de vérifier Deriva, qui fait la différenciation automatique pour Clojure et Java:

Vous pouvez également être intéressé par expresso, qui concerne davantage la manipulation d'expressions numériques, mais qui possède encore des fonctionnalités de différenciation et pourrait probablement être adapté à la plupart des cas d'utilisation d'AD:

Google pour la "différenciation symbolique lisp" et vous trouverez de nombreux exemples, par exemple

http://mitpress.mit.edu/sicp/texte intégral / sicp / book / node39.html

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top