Библиотека С# для упрощения и решения алгебры

В Интернете существует немало алгоритмов и упростителей алгебры (например, порядочный на алгебре .com). Тем не менее, я ищу что-то, что я могу подключить к С# как часть более крупного проекта (я делаю свой собственный калькулятор, но, очевидно, я бы попросил разрешения и т.д.).

В идеале я бы использовал код вроде:

String s = MathLib.Simplify("5x*(500/x^2*(sqrt(3)/4)+1)+2x^2+(sqrt(3)/2)*x^2");

И 's' упростится до: "1082.532/x+5*x+2.866*x^2"

(точность 3dp там, но это может измениться, если нужно).

Решение для конкретной переменной тоже было бы неплохо. Мне нужно что-то легкое и быстрое слишком (расчеты, такие как выше, будут предпочтительно составлять менее 5 мс, включая задержку запуска).

После некоторых исследований такие программы, как Sage, Octave или Mathematica, вероятно, переборщит (мое приложение будет только небольшим < 200k exe, вероятно). Dotnumerics.com или Mathdotnet.com могут быть подходящими, но первый, похоже, не упоминает алгебраическое упрощение, а отсутствие документации и примеров в последнем случае отключается. Мне интересно, есть ли подходящие альтернативы. Большой список можно найти здесь: http://en.wikipedia.org/wiki/Comparison_of_computer_algebra_systems

Ответы

Ответ 1

Мне удалось успешно позвонить в SymPy, чтобы сделать это с С#. SymPy обеспечивает относительно прочную упрощенную функцию, с которой у меня был хороший успех. Теперь я не совсем уверен, как упаковать это красиво (не нужно устанавливать ironpython), или даже насколько жестким может быть прямой порт кода.

  • Установите IronPython
  • Получить SymPy
  • Добавьте эти ресурсы в свой проект
    • IronPython.dll
    • IronPython.Modules.dll
    • Microsoft.Dynamic.dll
    • Microsoft.Scripting.dll
  • Код С# следующим образом:

    var engine = Python.CreateEngine();
    var paths = engine.GetSearchPaths();
    paths.Add(@"c:\program files (x86)\ironpython 2.7\lib");
    paths.Add(@"c:\Development\sympy");
    engine.SetSearchPaths(paths);
    
    // expression to simplify
    var expr = "0 + 1 * 1 * (x - 2) / (1 - 2) * (x - 3) / (1 - 3) * (x - 4) / (1 - 4) + 8 * 1 * (x - 1) / (2 - 1) * (x - 3) / (2 - 3) * (x - 4) / (2 - 4) + 27 * 1 * (x - 1) / (3 - 1) * (x - 2) / (3 - 2) * (x - 4) / (3 - 4) + 64 * 1 * (x - 1) / (4 - 1) * (x - 2) / (4 - 2) * (x - 3) / (4 - 3)";
    
    var scope = engine.CreateScope();
    var script = engine.CreateScriptSourceFromString(@"
    from sympy import *
    import clr
    from System import String
    
    expr = simplify('" + expr + @"')
    result = clr.Convert(expr, String)
    ");
    
    script.Execute(scope);
    
    // prints "x**3"
    Console.WriteLine(scope.GetVariable("result"));
    

Ответ 2

В есть вопрос о том, что есть связанный вопрос SO. Хотя никто, кроме того, что mathdotnet, падает на пересечение символики (вид упрощения, о котором вы просите выше), легкий вес, и доступность на .Net.

Я вижу вы уже нашли форум mathdotnet. Обратите внимание, что несколько его разработчиков являются пользователями SO:

Это может добавить поддержку, которую вы просите.

Ответ 3

Symbolism - это библиотека С#, которая реализует автоматическое упрощение алгебраических выражений.

Следуя вашему выражению примера, выполните следующую команду:

var x = new Symbol("x");

(5 * x * (500 / (x ^ 2) * (sqrt(3.0) / 4) + 1) + 2 * (x ^ 2) + (sqrt(3.0) / 2) * (x ^ 2))
    .AlgebraicExpand()
    .Disp();

отображает это на консоли:

1082.5317547305483 / x + 5 * x + 2.8660254037844384 * (x ^ 2)

Ответ 4

Попробовали ли вы создать несколько простых классов, реализующих алгоритм Shunting Yard Algorithm (обратная польская нотация), чем обрабатывать постфиксную нотацию, используя обработка стека обработка стека?