[Я пиарюсь] Что нового в AngouriMath 1.2?

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
03-Мар-2021 15:33

Приветствую. Последние 7 месяцев я работал над крупнейшим обновлением AngouriMath. И есть о чем рассказать.В двух словах о том, что происходитВ ноябре 2019-го понял, что этому миру, точнее миру дотнета, немного не хватает библиотеки символьной алгебры для упрощений выражений, решения уравнений, для вывода латеха, и так далее. Поэтому я решил создать такую.Но ведь есть же...Слыша про то, что я делаю, разные люди предлагают разные решения. Переписать SymPy, сделать обертку над SageMath для дотнета, спиратить Wolfram|Alpha, использовать примитивный mathnet.symbolics (о примитивности говорят они сами).Но все это имеет либо ограничения, либо сложности. То же, над чем работаю я, это очень легковесная библиотека, написанная и оптимизированная для .NET. Опен-сорсная, конечно. (под MIT) Обновление 1.2В августе один из главных контрибьюторов @HappyPig375 помог переписать на тото момент существенную часть библиотеки на нормальную иерархию типов. Теперь на каждый оператор или фукцию есть отдельный тип. Это был переломный момент, до которого библиотека была медленная, неуклюжая, и совершенно неочевидная. А теперь пройдемся по тому, что с тех пор было сделано.Выражение - это recordНапример, вот так выглядит объявление оператора суммы
public sealed partial record Sumf(Entity Augend, Entity Addend) : NumericNode
Благодаря этому мы можем легко применять новый pattern matching:
internal static Entity CommonRules(Entity x) => x switch
{
    // (a * f(x)) * g(x) = a * (f(x) * g(x))
    Mulf(Mulf(Number const1, Function func1), Function func2) => func1 * func2 * const1,
    // (a/b) * (c/d) = (a*c)/(b*d)
    Mulf(Divf(var any1, var any2), Divf(var any3, var any4)) => any1 * any3 / (any2 * any4),
    // a / (b / c) = a * c / b
    Divf(var any1, Divf(var any2, var any3)) => any1 * any3 / any2,
(это пример паттернов, которые работают при упрощении выражения)МатематикаЗдесь будут описаны фичи, которые связаны непосредственно с математикой.Новые функцииДобавлены секанс, косеканс, арксеканс, арккосеканс как отдельные ноды.Добавлены 12 гиперболических функций, которые не имеют своих нод и возвращают свое символьное представление (sinh(x)как (e.Pow(x) - e.Pow(-x)) / 2).Добавлены Abs и Signum. Синтаксис abs решено было сделать так: (|x|). Это позволяет делать похоже на то, как мы делаем ручками на бумаге, и в то же время позволяет избежать двусмысленности (так как | симметричная, и с ней могут быть проблемы).Добавлена функция Phi (функция Эйлера).
WriteLine(@"phi(8)".EvalNumerical());
WriteLine(@"(|-3 + 4i|)".EvalNumerical());
WriteLine(@"sinh(3)".Simplify());
WriteLine(@"sec(0.5)".Simplify());
Выведет
4
5
(e ^ 3 - 1 / e ^ 3) / 2
sec(1/2)
ДоменыОни позволяют ограничивать область определения каждой ноды. Если нода вышла за домен, она превращается в NaN, который делает все выражение неопределенным. В качестве доступных доменов - SpecialSet, о которых позже.Булева алгебра и логикаНаконец-то добавлены логические операторы. Хотя я думал сначала сделать через какие-то символы, в какой-то момент стало очевидно, что операторы должны быть буквенные. Поэтому синтаксис таков: not, or, xor, and, implies.Чтобы проверить, вычисляемое ли выражение в Boolean, нужно использовать EvaluableBoolean. Аналогично тому, как мы используем EvaluableNumerical чтобы понять, коллапсится ли выражение в Number.
WriteLine(@"(true or b) implies c".Simplify());
(выведет c)Знаки равенства и неравенстваОни сами по себе коллапсятся в Boolean, если их значение очевидно. Добавлены очевидные знаки: =, <, >, <=, >=.А еще можно делать комбинации неравенств при парсинге. Например, a > b > c как парсится, так и понимается (a > b > c то же, что a > b and b > c).
WriteLine(@"a < b >= c".Simplify());
(Выведет a < b and b >= c)МножестваДобавлены множества. Они парсятся и имеют свои ноды.Самый простой тип множества - FiniteSet, как можно догадаться, конечное множество. С ним все просто. Вот пример синтаксиса: { 1, 2, 3 }.Интервалы/отрезки тоже имеют привычный синтаксис: [1; 2] для отрезка, (1; 2) для интервала, [1; 2) для полуинтервала, как и (1; 2]. Комплексные интервалы были убраны за ненадобностью и громоздкостью.SpecialSet это "захардкоденные" множества. Сейчас есть CC, RR, QQ, ZZ, BB для комплексных, действительных, рациональных, целых, и булевых соответственно.ConditionalSet записывается в set-builder notation, вот пример: { x : x > 0 and x^2 = y } (все такие x, что положительные и их квадрат равен y).
WriteLine(@"({ 1, 2 } \/ { 5 }) /\ { x : x in [2; 3] and x > 0 } ".Simplify());
(Выведет { 2 })Пределы улучшеныДобавлены правила преобразования по первому замечательному, второму замечательному. И правило Лопиталя.
WriteLine("tan(a x) / (b x)".Limit("x", 0));
WriteLine("(sin(t) - t) / t3".Limit("t", 0));
(Выведет a / b и -1/6 соответственно)Нода "Provided"Позволяет установить условия на выражение, в каких случаях оно вообще определено. Например, квадратный корень на действительных мы определяем как sqrt(x) provided x >= 0. Если подставить отрицательный x, выражение станет NaN.Если такая нода встречается в конечном множестве, то если она станет NaN, то просто исключится из множества. Это единственное место, где NaN как ребенок не превращает родительское выражение в NaN.Кусочно-заданная функцияPiecewise - это последовательность из Provided. В отличии от классической кусочно-заданной, в этой есть порядок, и при вычислении значения Piecewise, мы возвращаем первый Provided такой, что его предикат истинен.Вот пример того, как мы можем определить действительный модуль числа с помощью Piecewise:
Entity abs = "piecewise(x provided x > 0, -x provided x <= 0)";
WriteLine(abs.Substitute("x", 3).EvalNumerical());
WriteLine(abs.Substitute("x", -3).EvalNumerical());
(Выведет 3 в обоих случаях)Проще и удобнее использоватьА здесь фичи, благодаря которым библиотеку стало проще и/или безопаснее использовать.Исключения обобщены и отрефактореныТеперь все исключения, которые выбрасывает библиотека, так или иначе наследуются от AngouriMathBaseException. Так как никакого p/invoke-а или чего-то еще страшного библиотека не производит, можно быть уверенными, что все то, что находится под AngouriMathBaseException, не вредит системе или пользовательским данным. Иначе говоря, при обработке исключений, теперь можно последним catch-ем указать именно это исключение (если надо).Производительность улучшенаВообще, за это время производительность прыгала очень много. Но она все равно сильно лучше, чем было в 1.1.0.5. Здесьможно найти отчет о производительности по коммитам.F# поддерживаетсяТеперь API AngouriMath доступен и для замечательного языка F#. Впрочем, вряд ли оно настолько же функциональное, но многие фичи обертка над F# имеет. Если что-то сложное, из него можно обратиться к самой библиотеке.InteractiveНекоторое время назад я делал пост о том, как AngouriMath выглядит в Jupyter. Сам по себе AngouriMath.Interactive просто преобразывает ILatexiseable в LaTeX-код и рендерит его с помощью MathJax (подробности в той статье).
Простой пример использования AngouriMath.Interactive в JupyterМногопоточностьВсе вычисления происходят строго в одном потоке. Кто я такой, чтобы ваши ядра воровать? Более того, все методы потокобезопасны. Настройки локальны для каждого потока ([ThreadStatic]), о которых чуть позже.Основная фича обновления - теперь можно прервать вычисления в случае, если вам уже давно не нужен результат работы Solve или Simplify, и вам нужно просто вернуться уже и выдать пользователю ошибку.Новые настройкиКажется, это их третья реинкарнация. Не могу сказать, что я обожаю текущий дизайн, но лучшего пока нет. Чтобы поставить новое значение, пишем
using var _ = MaxExpansionTermCount.Set(10);
// какой-то код
Тогда эта настройка автоматически откатится до предыдущей по окончании области (то, что возвращает Set, является IDisposable).Пока всеСпасибо за внимание. Если эта статья помогла хотя бы одному человеку, значит я уже не зря писал. Задавайте вопросы, будет приятно ответить. Это очень кратенькое изложение, потому что лонгриды по узкой теме вряд ли кому зайдут.Если кто-то хочет стать контрибьютором, я буду этому очень рад (пишите мне или сразу форкайте и улучшайте).Ссылки
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_ja_piarjus (Я пиарюсь), #_csharp, #_obnovlenie (обновление), #_ja_piarjus (
Я пиарюсь
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 13:12
Часовой пояс: UTC + 5