Библиотека за автоматично диференциране в Scheme / Common Lisp / Clojure

Чувал съм, че една от първоначалните мотивации на Маккарти да изобрети Lisp е била да напише система за автоматично диференциране. Въпреки това моите търсения в Google не дадоха никакви библиотеки/макроси за това. Има ли някакви библиотеки Scheme/Common Lisp/Clojure (макроси) за вземане на функция F и връщане на функция dF/dx, която изчислява производната на F?

Бих искал да поддържа F с множество аргументи. Потребителят ще избере кое от тях е x, за да се разграничи по отношение на. В идеалния случай диференциаторът би работил дори за F и x с векторни стойности.

РЕДАКТИРАНЕ: Няколко души споменаха символична диференциация. Разликата между символното диференциране и автоматичното диференциране е фина, но е обобщена добре в Wikipedia, и по-специално в тази снимка. Това разграничение не е толкова силно в lisp, където символните изрази могат да бъдат превърнати в работещи програми, каквито са, но остава потенциална трудност:

Символното диференциране изисква изразът, който се диференцира, да бъде съставен от операции с известни производни. Например, някой спомена примера на SICP за макрос, който прехвърля прости sexps като (+ y (* (x y))) и използва верижното правило, заедно със знания как да се разграничат + и *, за да върне sexp, който представлява производното. Това ще ми трябва, за да работя с изрази като (* (foo x y) (bar x)), където foo и bar могат на свой ред да извикват други функции, чиито производни не са известни по време на диференциране.

Това би било добре, ако има начин да вземете израз като (foo x y) и да го замените с неговото тяло на функцията, замествайки всяко споменаване на аргументите с x и y по хигиеничен начин. Е там?

Също така, нито едно от горните не се отнася до усложненията, които възникват при диференциране на функции с векторни стойности по отношение на аргументи с векторни стойности... за което са предназначени повечето реализации на автодиференциране.


person SuperElectric    schedule 03.02.2011    source източник
comment
Тагът numerical-methods не е подходящ за вашия въпрос, защото това, което искате, е символна диференциация. Намирането на производната на функция f при x чрез числено диференциране би било просто изчисление на (f(x+dx)-f(x))/dx за някаква малка стойност на dx.   -  person Curd    schedule 04.02.2011
comment
@curd: С добавянето на тага numerical-methods не исках да намекна, че търся начин за извършване на числено диференциране, което, разбира се, не съм. Просто имах предвид, че въпросът се отнася до функции, свързани с числените изчисления (например оценяване на символни изрази, които прилагат числени методи).   -  person SuperElectric    schedule 04.02.2011
comment
С теб съм. Разочароващ е начинът, по който всеки път, когато споменавам автоматична диференциация, хората я бъркат със символична диференциация и често отказват да чуят, че има разлика. Това със сигурност е числен метод и със сигурност не е числено диференциране.   -  person sigfpe    schedule 29.04.2011


Отговори (7)


Има два други пакета, и двата за автоматично разграничаване в Scheme. Второто е базирано на първото, но преработено като кокоше яйце. Те поддържат както режим напред, така и режим назад.

person Barak A. Pearlmutter    schedule 10.04.2013

Алексей Радул пише:

Е, има автоматична система за диференциране в Scmutils

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

(което по съвпадение също прави символична диференциация). Не знам за други пуснати реализации, въпреки че може да проверите http://autodiff.org/ .

Има и хубаво обяснение как да го приложите сами в приложение към Структура и интерпретация на класическата механика

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

както и в академичната литература. Конкретно режимът напред не е толкова труден, въпреки че трябва да внимавате, за да избегнете объркване при смущения. Може да се консултирате с публикациите на Barak Pearlmutter и Jeffrey Mark Siskind, които си сътрудничат по високоефективен вариант на Lisp, който включва AD и публикуват по свързани проблеми.

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

person Gregory Marton    schedule 04.02.2011
comment
Благодаря ти! Едно последно нещо: можете ли да дефинирате или може би да предоставите справка за термина объркване на смущения? Не съм запознат с термина. - person SuperElectric; 05.02.2011
comment
Добре, сам намерих отговора от тази статия: eprints.nuim.ie/archive/ 00000566/01/Perturbation.pdf тези реализации (...) могат да изчислят крайно неправилни резултати, когато операторът за диференциране се приложи към функция, която сама използва този оператор. Основната причина за този проблем е объркване на смущенията, неуспех да се разграничат различни смущения, въведени от различни извиквания на оператора за диференциране. След това обсъждаме как може да се избегне объркването на смущенията. - person SuperElectric; 06.02.2011

Ако търсите символна система, можете да опитате maxima (или тук). Той работи на няколко комбинации от Common-Lisp/OS платформа, но е по-скоро цялостна система, отколкото библиотека.

Конзолният изход е ОК, но може да произведе доста добре изглеждащ изход, когато е съчетан с 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

РЕДАКТИРАНЕ

Добре, изглежда не съм разбрал въпроса. Малко гугъл подсказва, че има някои инструменти за това в SCMUTILS тук, изтеглете тук, ръководство за потребителя тук (вижте стр.24 нататък).

person clstrfsck    schedule 03.02.2011
comment
Благодаря, но външните инструменти за символно разграничаване не са това, което търся. Редактирах въпроса, за да изясня това. - person SuperElectric; 04.02.2011
comment
Трябва да е възможно да се използва Maxima като библиотека от всяка обикновена lisp програма (и по този начин може да се използва отвътре в макрос), така че в крайна сметка не е толкова външна. - person SK-logic; 04.02.2011
comment
Проблемът е символичността. Търся макрос, който приема функция F и връща функция F'. Имам предвид функция с възможност за оценка, която приема числови аргументи, а не символен израз. - person SuperElectric; 29.12.2011

Може да представлява интерес, че scmutlis вече е пренесен в Clojure. Има още много работа за вършене, но кодът в първите глави на книгата SICM изглежда работи добре.

Процедурите за диференциране и операторите също изглеждат добре с малкото тестване, което направих, и дори е без някои грешки, които изглежда са се промъкнали в по-късните версии на scmutils.

Мисля, че scmutils покрива изискванията за диференциране на OP, тъй като ще обработва правилно производни както на известни, така и на неизвестни (буквални) функции. Тази страница предоставя необходимите подробности, за да видите колко добре отговаря на изискванията: SICM - Деривати - Нотация

Едно от предимствата на работата на JVM е, че ще работи като самостоятелна, ако е необходимо, няма нужда дори да инсталирате Clojure!

Тя е много близка до оригиналната схема, направени са минимални отстъпки за синтаксиса на Clojure.

Можете да го видите тук: https://github.com/littleredcomputer/sicmutils#sicmutils

===

Допълнение: Ето пример за автоматично разграничаване в пакета SicmUtils Clojure. Това е често срещан пример, циркулиращ в различни интернет сайтове, кодът, който трябва да се разграничи, е

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

След като го Clojurify малко имаме

   > (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
person Alex Gian    schedule 24.01.2016

Ето внедряване на AD в обикновен лисп.

person sigfpe    schedule 28.04.2011

Струва си да проверите Deriva, която прави автоматично диференциране както за Clojure, така и за Java:

Може също да се интересувате от expresso, което е повече за манипулиране на числови изрази, но все пак има някои функции за диференциране и вероятно може да бъде адаптирано към повечето случаи на използване на AD:

person mikera    schedule 04.11.2013

Потърсете в Google „lisp symbolic differentiation“ и ще намерите много примери, напр.

http://mitpress.mit.edu/sicp/full-text/sicp/book/node39.html

person Curd    schedule 03.02.2011
comment
Редактирах въпроса, за да стане ясно защо тези примери не предоставят всичко, което търся. - person SuperElectric; 04.02.2011