C# библиотека для упрощения и решения алгебры
В сети есть довольно много решателей и упрощателей алгебры (например, приличный на algebra.com). Тем не менее, я ищу что-то, что можно подключить к C# в рамках более крупного проекта (я делаю свой собственный калькулятор, но, очевидно, я бы попросил разрешения и т. Д.).
В идеале я бы использовал такой код:
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
4 ответа
Мне удалось успешно позвонить в SymPy, чтобы сделать это из C#. SymPy предоставляет относительно надежную функцию упрощения, с которой у меня был хороший успех. Теперь я не совсем уверен, как правильно это упаковать (не нужно устанавливать ironpython) или даже насколько сложным может быть прямой порт кода.
- Установить IronPython
- Получить SymPy
- Добавьте эти ресурсы в ваш проект
- IronPython.dll
- IronPython.Modules.dll
- Microsoft.Dynamic.dll
- Microsoft.Scripting.dll
C# код выглядит следующим образом:
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"));
Символизм - это библиотека C#, которая реализует автоматическое упрощение алгебраических выражений.
Следуя вашему примеру выражения, следующая программа:
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)
Существует много ответов, которые можно найти в связанном вопросе SO. Хотя ни один, ни другой, кроме mathdotnet, попадают на пересечение символики (вид упрощения, о котором вы просите выше), легковесности и доступности в.Net.
Я вижу, вы уже нашли форум mathdotnet. Обратите внимание, что пара его разработчиков являются SO пользователями:
- Christoph Rüegg
- Joannes Vermorel (хотя Охлох говорит, что он больше привязан к разделу чисел)
Это может дополнить поддержку, о которой вы просите.
Вы пытались создать несколько простых классов, реализующих алгоритм Shunting Yard(обратная польская запись), чем обрабатывать запись постфикса с использованием стековой обработки стека?