Понадобилась мне как-то библиотека на c#, которая умеет делать символьные вычисления (время от времени дополняю возможностями одну математическую программу). Всякие исходники в сети найти можно и на разных языках, но вот что-то попроще и попонятнее найти не удавалось. Обратил внимание на Jasymca (Java Symbolic Calculator).

Задача


Для реализации аналога Mathcad'овского блока odesolve в программе SMath Studio понадобилось решать уравнения относительно производных. Каких-то особых ограничений на решаемую систему ОДУ нет. То, что задаёт пользователь в относительно произвольном виде должно преобразовываться к виду, удобному для численного решения ОДУ. Выглядеть это должно так:



Обойтись возможностями языка c# мне тут оказалось трудным в общем случае. Не помешала бы помощь символьного движка.

Конвертация исходников


Посмотрел на исходники апплета. Вроде не очень страшно, но нужен конвертер Java в c#. В то время, когда я этим только начал заниматься нашёлся один более менее рабочий онлайновый ресурс, который сейчас вспомнить не удалось. Похоже, что это был ресурс от Tangible Software Solutions, т.к. комментарии в исходниках похожи на те, которые делает их текущий конвертер в виде программы.
Всё хорошо, но одно плохо. Ресурс конвертировал бесплатно только ограниченный размер исходника. Правда ограничение на количество строк. Очень странно, подумал я, и слепил в каждом файле все содержимое в одну строку. Далее бесплатно преобразовал однострочные исходники в c# эквивалент и восстановил нормальный вид в Visual Studio при помощи автоматического форматирования.

Доработка напильником


Надо ли говорить, что автоматический конвертер преобразует по большей части форму, а вот с содержанием нужно ещё поработать. На тот момент я понял, что мне явно не хватает уровней в обоих языках, чтобы разрешить все проблемы компиляции. Время шло, почитывал Джона Скита. Товарищ Скит внушил решимости.

В процессе борьбы за компилируемость добрым словом вспоминал конвертер. Он сделал почти всю нудную работу. Не осилил он только математическую часть в некоторых моментах. Касалось это большого класса JMath. Преобразования double в hex представление и обратно упирались в некоторых случаях в ограничение для метода BitConverter.Int64BitsToDouble(), который не работает с некоторыми unsigned long константами, например -0 (0x8000000000000000). Тут опять пришёл на помощь товарищ Скит, не без помощи которого удалось представить это значение как 1.0 / double.NegativeInfinity. Вообще, эта арифметика «бесконечно малых» до сих пор не даёт мне покоя, т.к. я не уверен в правильном интерпретировании всего того, что автор Jasymca имел в виду.

После исправления некоторых смысловых ошибок, замены работы с типами и их экземплярами и добавления консольного интерфейса удалось таки этот проект запустить. Давно хотел посмотреть на внутреннюю кухню подобных символьных программ. Одно дело какой-нибудь Symbolic C++ и совсем другое — Java или C#. Порог вхождения гораздо ниже.

На момент написания заметки выглядит калькулятор так:



Исполняемый файл доступен в репозитории. Требуется .Net 2.0. Есть зависимость от LinqBridge для работы Linq в .Net 2.0 (библиотека приложена там же).

Работает практически всё из документации автора Jasymca. Исключение составляет работа с графикой, т.е. построение графиков функций. Думаю, что проще будет написать эту часть заново, чем портировать. Не включены функции, зависящие от сторонних библиотек (LAPACK и пр.). Также присутствуют глюки, которые будут со временем вычищаться.

Заключение


Проект создавался для любителей символьной математики. При желании может быть приведён к библиотеке и использоваться в собственных проектах, где требуется несложная численная или символьная математика: работа с комплексными числами, интегрирование, дифференцирование, решение уравнений и пр. Автор Jasymca позиционировал программу как учебное пособие для тех, кто хочет создать свою программу, выполняющую символьные вычисления:
Jasymca has been developed for teaching mathematics, especially to facilitate a fast and easy entrance to computer mathematics. One of the main obstacles are pocket calculators, which prevent many students from using computers for math. Pocket calculaters are cheap and portable, while CAS-programs are often expensive and always require at least a laptop to run. Jasymca is free software and runs on almost any system equipped with a microprocessor: from mobile phones and pdas to windows/linux/macos computers, even on game consoles or internet routers.
Надеюсь, что c# вариант исходников будет полезен в чём-то и вам.

Ссылки


1. Jasymca (Java Symbolic Calculator).
2. Исходники Jasymca (zip).
3. Jasymca 2.0 — Symbolic Calculator for Java (Manual, pdf).
4. Обзор подобных Java библиотек.
5. Репозиторий проекта.

Комментарии (12)


  1. gnaeus
    09.02.2019 18:23

    А Math.NET Symbolics не подходит для такого?


    1. ViacheslavMezentsev Автор
      09.02.2019 18:37

      Все современное требует .Net 4.5 и выше, а нужно .Net 2.0, так как SMath Studio минимально поддерживает эту версию. Это если я захочу этим требованиям следовать.
      Посмотрел, что-то пока он выглядит хуже по функционалу, чем этот калькулятор, судя по тестам в репозитории.
      Мне-то ещё нужен исходник (библиотека), которую я смогу сам дополнять и мне хватит для этого знаний. Этот калькулятор поддерживает загрузку .m-файлов, которые имеет даже у себя в ресурсах, где часть функций реализована в виде пользовательских подпрограмм.

      В прочих случаях почему бы и нет. Жаль только, что подобные математические библиотеки содержат только что-то примитивное, а как только надо жёсткое ОДУ посчитать, то обратно к фортрану нужно возвращаться.


      1. KvanTTT
        09.02.2019 18:49

        Зачем нужна поддержка древнего .Net 2.0?


        1. ViacheslavMezentsev Автор
          09.02.2019 18:59

          Так сложилось исторически и остаётся до сих пор. Если программа может работать даже только с .Net 2.0, то и дополнения к ней желательно должны поддерживать такую возможность. Это необязательное требование.
          Библиотека LinqBridge не нужна для .Net 3.5 и выше, где Linq уже встроен. Просто меняем .Net и удаляем зависимость.


      1. FoggyFinder
        09.02.2019 22:33

        Да, пока возможностей в Math.NET Symbolics не так и много, но исходники открыты, а код легко читаем. Будет здорово расширить функционал.


        Жаль только, что подобные математические библиотеки содержат только что-то примитивное, а как только надо жёсткое ОДУ посчитать, то обратно к фортрану нужно возвращаться.

        Да, увы, OpenSource библиотеки, особенно которые поддерживаются небольшим числом разработчиков, редко когда подходят для сложных сценариев.


  1. dimka11
    09.02.2019 20:52

    Использовать C++ библиотеки не вариант?


    1. ViacheslavMezentsev Автор
      09.02.2019 21:23
      +1

      Не вариант. У меня очень богатый опыт подключения неуправляемого кода к c# проекту. Всё выглядит всегда как костыли с побочными эффектами.

      Из минусов:
      — зависимость от ОС;
      — зависимость от разрядности;
      — наличие знаний C++/CLI и/или маршалинга;
      — сложный состав проекта (зависит от исходников C/C++);
      — особые проблемы использования стороннего кода (например, использование неуправляемых указателей на callback функции для всех решателей с пользовательскими функциями или отсутствие дополнительного параметра void * data для пользовательских данных);
      — …

      В общем, жди подвоха и приготовь костыли.


  1. Taraflex
    09.02.2019 21:41

    Не пробовали конвертацию байт кода, вместо исходников?
    weblog.ikvm.net


    1. ViacheslavMezentsev Автор
      09.02.2019 21:58

      Не пробовал. В идеале хочется иметь одну Visual Studio и всё остальное, написанное на одном языке и везде работающее. Мечты.
      Жаль только, что C# не настолько быстродействующий как C/C++. Между прочим, некоторые конверторы с фортрана на C# очень хорошо себя показали (DotNumerics).


      1. KvanTTT
        09.02.2019 22:15
        +2

        В идеале хочется иметь одну Visual Studio и всё остальное, написанное на одном языке и везде работающее. Мечты.

        Чем Rider не устраивает?


        Жаль только, что C# не настолько быстродействующий как C/C++.

        Какой производительности по сравнению с плюсами там не хватает? Там даже современные векторные инструкции уже поддерживаются (AVX). Хотя с учетом того, что вы до сих пор поддерживаете .Net 2.0, ни о какой производительности не может идти никакой речи.


        1. ViacheslavMezentsev Автор
          09.02.2019 22:41

          Чем Rider не устраивает?
          Так это мечты, а в реальности нужна поддержка C++/CLI и решений вперемешку (C#, C++/CLI). Думается, что только студия это умеет.

          Какой производительности по сравнению с плюсами там не хватает?
          Такой, чтобы применять в embedded проектах на Linux'ах, например. Пробовали и отказались в пользу Qt


      1. FoggyFinder
        09.02.2019 22:35

        Жаль только, что C# не настолько быстродействующий как C/C++.

        Сейчас ведется активная разработка CoreRT.