Этот проект перешел на повышение (математика/дифференциация/Autodiff), и этот репозиторий больше не обновляется.
Ветвь | Трэвис | Приложение | Codecov.io |
---|---|---|---|
master | |||
develop |
Autodiff-это библиотека C ++ только для заголовка, которая облегчает автоматическую дифференциацию (режим вперед) математических функций отдельных и множественных переменных.
Эта реализация основана на расширении серии Тейлорской серии аналитической функции F в точке X₀ :
Основной идеей Autodiff является замена чисел полиномами при оценке F (x₀) . Заменив число x₀ полиномом первого порядка x₀+ε , и используя тот же алгоритм для вычисления F (x₀+ε) , полученный полином в ε содержит производные функции f '(x₀) , f' (x₀) , f '' '(x₀) , ... в коэффициентах. Каждый коэффициент равен производной его соответствующего порядка, разделенного на факториал Ордена.
Предположим более подробно, предположим, что кто -то заинтересован в расчете первых N -производных F в X₀ . Без потери точности для расчета производных, все термины o (ε n+1 ) , которые включают способности ε больше N, могут быть отброшены. (Это связано с тем, что каждый термин в полиноме зависит только от равных и более низких терминов в рамках арифметических операций.) В соответствии с этими правилами усечения F обеспечивает полиномиальное в полиномиальное преобразование:
Способность C ++ перегружать операторов и функции позволяет создавать класс fvar
, который представляет полиномы в ε . Таким образом, тот же алгоритм F , который вычисляет числовое значение y₀ = f (x₀) , при написании для принятия и возврата переменных общего (шаблона) типа, также используется для расчета полиномиального ʃ n y n εⁿ = f (x₀+ ε) . Деривативы f (n) (x₀) затем встречаются из продукта соответствующего факториала n! и коэффициент y n :
#include <boost/math/distianiation/autodiff.hpp> #include <iostream> шаблон <typename t> T fourth_power (t const & x) { T x4 = x * x; // RETVAL в операторе*() использует память X4 через NRVO. x4 *= x4; // Нет копий x4 в рамках оператора*= () даже в квадрате. возврат x4; // x4 использует память y в main () через nrvo.} int main () {с использованием пространства имен Boost :: Math :: Distriation; ConstexPR unsigned order = 5; // Производная высочайшего порядка для рассчитываемости. Auto const x = make_fvar <Double, Order> (2.0); // Найти производные при x = 2. auto const y = fourth_power (x); для (без знака i = 0; i <= order; ++ i) std :: cout << "y.derivative (" << i << ") =" << y.dervative (i) << std :: endl; возврат 0; }/*Выход: Y.Derivative (0) = 16y.divative (1) = 32y.divative (2) = 48y.divative (3) = 48y.divative (4) = 24y.divative (5) = 0*//
Вышеуказанное рассчитывается
#include <boost/math/distryation/autodiff.hpp> #include <boost/multiprecision/cpp_bin_float.hpp> #include <iostream> Использование пространства имен y ,: math :: distriation; template <typename w, typename x, typename y ,:: Typename z> PROMOTE <W, x, y, z> f (const w & w, const x & x, const y & y, const z & z) {с использованием пространства имен Std; return exp (w * sin (x * log (y) / z) + sqrt (w * z / (x * y))) + w * w / tan (z); } int main () {с использованием float50 = boost :: Multiprecision :: cpp_bin_float_50; ConstexPR без знака NW = 3; // максимальный порядок производной для расчета для w ConstexPR без знака nx = 2; // максимальный порядок производной для расчета для x ConstexPR без подписи NY = 4; // максимальный порядок производной для расчета для y ConstexPR без знака NZ = 3; // максимальный порядок производной для расчета для z // объявить 4 независимых переменных вместе в STD :: Tuple. auto const переменные = make_ftuple <float50, nw, nx, ny, nz> (11, 12, 13, 14); Auto const & w = std :: get <0> (переменные); // до северо -западных производных при W = 11 Auto const & x = std :: get <1> (переменные); // до производных NX при x = 12 Auto const & y = std :: get <2> (переменные); // до Нью -Йорка Деривативы в y = 13 Auto const & z = std :: get <3> (переменные); // до Новой Зеландии в z = 14 Auto const v = f (w, x, y, z); // рассчитано по символической дифференциации Mathematica. Float50 Const Ответ ("1976.319600747777717779881875290418720908121189218755"); std :: cout << std :: setPrecision (std :: numeric_limits <float50> :: digits10) << "Mathematica:" << respons << 'n' << "autodiff:" << v.derivative (nw, nx, ny, nz) << 'n' << std :: setprecision (3) << "Относительная ошибка:" << (v.derivative (NW, NX, NY, NZ) / Ответ - 1) << 'N'; возврат 0; }/*Вывод: Mathematica: 1976.319600747777777798818752904187209081211892188Autodiff: 1976.31960074777717777881875290418720977717777788187529041872097118921877788187529041872097771777778818752904187209777777778818729нтечный
#Include <boost/math/distriation/autodiff.hpp> #include <iostream> с использованием имен -пространств https://en.wikipedia.org/wiki/greeks_(finance)#formulas_for_eurotean_option_greeks// Стандартное нормальное кумулятивное распределение функция. X phi (x const & x) {return 0.5 * erfc (-one_div_root_two <x> () * x); } enum class cp {call, put}; // Предполагается, что нулевой годовой дивидендный доход (q = 0). PROMETE <PROCE, SIGMA, TAU, RATE> BLACK_SCHOLES_OPTION_PRICE (CP CP, Double K, Цена const & s, Sigma const & Sigma, Тау const & tau, Скорость const & r) {с использованием пространства имен Std; Auto const d1 = (log (s / k) + (r + sigma * sigma / 2) * tau) / (sigma * sqrt (tau)); Auto const d2 = (log (s / k) + (r - sigma * sigma / 2) * tau) / (sigma * sqrt (tau)); Switch (cp) {case cp :: call: return s * phi (d1)-exp (-r * tau) * k * phi (d2); case cp :: put: return exp (-r * tau) * k * Phi (-d2)-s * phi (-d1); } } int main () {double const k = 100,0; // цена удара. Auto const s = make_fvar <Double, 2> (105); // цена акций. Double const sigma = 5; // Волатильность. Double const tau = 30,0 / 365; // время до истечения срока годы. (30 дней). Double const r = 1,25 / 100; // Процентная ставка. auto const call_price = black_scholes_option_price (cp :: call, k, s, sigma, tau, r); auto const put_price = black_scholes_option_price (cp :: put, k, s, sigma, tau, r); std :: cout << "Black-scholes Call Price =" << call_price.divative (0) << 'n' << "Black-scholes proce =" << put_price.divative (0) << 'n' << "call delta =" << call_price.price.divative (1) << 'n' << "put delta =" << put_price.divative (1) << 'n' << "Call Gamma =" << call_price .Derivative (2) << 'n' << "put gamma =" << put_price.dervative (2) << 'n'; возврат 0; }/*Вывод: цена вызова Black-Scholes = 56,5136black-scholes Prot = 51,4109CALL Дельта = 0,773818PUT Дельта = -0,226182CAL
См. Пример/black_scholes.cpp для более крупного списка автоматически рассчитанных на опционных греков.
Приведенные выше примеры иллюстрируют некоторые преимущества использования Autodiff:
Устранение избыточности кода. Существование n отдельных функций для расчета производных является формой избыточности кода, причем все обязательства, которые с ним связаны:
Изменения в одной функции требуют дополнительных изменений в других функциях. В приведенном выше примере, рассмотрите, насколько больше и межзависимой приведенная выше кодовая база будет, если для каждого греческого значения записана отдельная функция.
Зависимости от производной функции для другой цели сломатся, когда будут внесены изменения в исходную функцию. То, что не нужно существовать, не может сломаться.
Код раздувается, снижает концептуальную целостность. Контроль над эволюцией кода проще/безопаснее, когда база кода меньше и может быть интуитивно схватить.
Точность производных по сравнению с методами конечных различий. Методы конечных различий с одной итерацией всегда включают в себя свободную переменную Δx , которая должна быть тщательно выбрана для каждого приложения. Если Δx слишком мал, то числовые ошибки становятся большими. Если Δx слишком велик, то математические ошибки становятся большими. С помощью Autodiff нет свободных переменных для установки, и точность ответа, как правило, превосходит методы конечных различий даже при лучшем выборе Δx .
Дополнительные данные в руководстве Autodiff.
Распространено по лицензии на программное обеспечение Boost, версия 1.0.
Только заголовок.
Оптимизирован для C ++ 17. Также компилируются и протестированы с помощью C ++ 11, C ++ 14 и предложены стандарты C ++ 20.
Вся память выделяется в стеке.
Имя | Цель |
---|---|
doc | документация |
example | примеры |
include | заголовки |
test | модульные тесты |
Ошибки отчета: Обязательно упомянули версию, платформу и компилятор Boost. Небольшой образец компилируемого кода для воспроизведения проблемы также всегда хорош.
Отправьте свои патчи в качестве запросов на притяжение против развития филиала. Обратите внимание, что отправив исправления, вы соглашаетесь лицензировать свои модификации по лицензии на программное обеспечение Boost, версия 1.0.