Я пишу программу на Python, и мне нужно найти производную функции (функция, выраженная в виде строки).
- Например:
x^2+3*x
- Его производная:
2*x+3
Есть ли какие-нибудь доступные скрипты или есть что-то полезное, что вы можете мне подсказать?
Я пишу программу на Python, и мне нужно найти производную функции (функция, выраженная в виде строки).
x^2+3*x
2*x+3
Есть ли какие-нибудь доступные скрипты или есть что-то полезное, что вы можете мне подсказать?
sympy делает это хорошо.
Если вы ограничены полиномами (что, по-видимому, так и есть), в основном будет три шага:
Если вам нужно обрабатывать многочлены, такие как a*x^15125 + x^2 + c
, использование dict
для списка коэффициентов может иметь смысл, но требует немного больше внимания при выполнении итераций по этому списку.
Вы можете найти то, что ищете, в уже предоставленных ответах. Однако я хотел бы дать краткое объяснение того, как вычислять символьные производные.
Бизнес основан на перегрузке операторов и цепном правиле производных. Например, производная от v^n
равна n*v^(n-1)dv/dx
, верно? Итак, если у вас есть v=3*x
и n=3
, какой будет производная? Ответ: если f(x)=(3*x)^3
, то производная:
f'(x)=3*(3*x)^2*(d/dx(3*x))=3*(3*x)^2*(3)=3^4*x^2
Цепное правило позволяет вам «связывать» операции: каждая отдельная производная проста, и вы просто «связываете» сложность. Другой пример, производная от u*v
это v*du/dx+u*dv/dx
, верно? Если вы получаете сложную функцию, вы просто связываете ее, скажем:
d/dx(x^3*sin(x))
u=x^3; v=sin(x)
du/dx=3*x^2; dv/dx=cos(x)
d/dx=v*du+u*dv
Как видите, дифференцирование — это всего лишь цепочка простых операций.
Теперь перегрузка оператора.
Если вы можете написать синтаксический анализатор (попробуйте Pyparsing), вы можете запросить его для оценки как функции, так и производной! Я сделал это (используя Flex/Bison) просто для удовольствия, и это довольно мощно. Чтобы вы поняли, производная вычисляется рекурсивно путем перегрузки соответствующего оператора и рекурсивного применения цепного правила, поэтому оценка "*"
будет соответствовать u*v для значения функции и u*der(v)+v*der(u)
для значения производной (попробуйте на C++, это тоже весело).
Так вот, я знаю, что вы не собираетесь писать свой собственный синтаксический анализатор - во что бы то ни стало используйте существующий код (посетите www.autodiff.org для автоматического различения кода Fortran и C/C++). Но всегда интересно узнать, как это работает.
Ваше здоровье,
Хуан
Символическая дифференциация — впечатляющее введение в предмет — по крайней мере, для неспециалистов. как и я :) Код написан на C++ кстати.
Лучше поздно, чем никогда?
Я всегда выполнял символическую дифференциацию на любом языке, работая с деревом синтаксического анализа. Но недавно мне также стало известно о другом методе, использующем комплексные числа. .
Подход с использованием дерева синтаксического анализа состоит в переводе следующего крошечного кода Lisp на любой язык, который вам нравится:
(defun diff (s x)(cond
((eq s x) 1)
((atom s) 0)
((or (eq (car s) '+)(eq (car s) '-))(list (car s)
(diff (cadr s) x)
(diff (caddr s) x)
))
; ... and so on for multiplication, division, and basic functions
))
и после него с соответствующим упрощением, чтобы избавиться от добавления 0, умножения на 1 и т. д.
Но комплексный метод, хотя и является полностью числовым, обладает определенным волшебным качеством. Вместо того, чтобы программировать вычисление F с двойной точностью, сделайте это комплексно с двойной точностью. Затем, если вам нужна производная вычисления по переменной X, задайте для мнимой части X очень маленькое число h, например 1e-100. Затем выполните расчет и получите результат R. Теперь реальный (R) — это результат, который вы обычно получаете, а imag (R)/h = dF/dX с очень высокой точностью!
Как это работает? Возьмем случай умножения комплексных чисел:
(a+bi)(c+di) = ac + i(ad+bc) - bd
Теперь предположим, что все мнимые части равны нулю, за исключением того, что нам нужна производная по a
. Мы устанавливаем b
на очень маленькое число h
. Теперь что мы получаем?
(a+hi)(c) = ac + hci
Таким образом, действительная часть этого числа равна ac
, как и следовало ожидать, а мнимая часть, разделенная на h
, равна c
, которая является производной от ac
по отношению к a
.
Подобные рассуждения, по-видимому, применимы ко всем правилам дифференциации.
Поищите автоматическое дифференцирование. Существуют инструменты для Python. Кроме того, это.
Если вы думаете о написании программы дифференцирования с нуля, не используя в качестве помощи другие библиотеки, тогда алгоритм/подход к вычислению производной любого алгебраического уравнения я описал в мой блог будет полезен.
Вы можете попробовать создать класс, который будет строго представлять предел, а затем оценивать его для (f(x)-f(a))/(x-a), когда x приближается к a. Это должно дать довольно точное значение предела.
если вы используете строку в качестве входных данных, вы можете разделить отдельные термины, используя + или - char в качестве разделителя, что даст вам отдельные термины. Теперь вы можете использовать степенное правило для решения каждого термина, скажем, у вас есть x ^ 3, что с использованием степенного правила даст вам 3x ^ 2, или предположим, что у вас есть более сложный термин, например a/(x^3) или a(x^ -3), снова вы можете выделить другие переменные как константу, и теперь решение для x^-3 даст вам -3a/(x^2). Одного степенного правила должно быть достаточно, однако оно потребует широкого использования факторизации.
Если какая-либо уже созданная библиотека не является достаточно сложной, потому что вам нужно анализировать и обрабатывать функции и выражения.
Само по себе это простая задача, поскольку она механическая и может быть выполнена алгоритмически, но вам нужна базовая структура для хранения функции.