Извлечение общих терминов с помощью MathNet Symbolics

Я использую MathNet Symbolics для обработки части символической алгебры программы, над которой я работаю. Обычно используется создание пары символьных формул, а затем разделение этих двух формул. Это работает довольно хорошо большую часть времени. Однако иногда делать более сложные упрощения не хочется. Например:

                       (512*r*t*w + 2048*r*t^2*w)
-----------------------------------------------------------------------
(512*r*t*w + 512*r^2*t*w + 3072*r*t^2*w + 3072*r^2*t^2*w + 1024*r*t^3*w)

Немного поработав, я смог исключить w из уравнения, как и во всех терминах сверху и снизу:

                    (512*r*t + 2048*r*t^2)
--------------------------------------------------------------
(512*r*t + 512*r^2*t + 3072*r*t^2 + 3072*r^2*t^2 + 1024*r*t^3)

Однако я не могу понять, как заставить его найти общие термины:

         (512*r*t)*(1 + 4*t)
--------------------------------------
(512*r*t)(1 + r + 6*t + 6*r*t + 2*t^2)

И исключить эти термины:

         (1 + 4*t)
-----------------------------
(1 + r + 6*t + 6*r*t + 2*t^2)

Я использую Wolfram Alpha в качестве золотого стандарта для проверки своей работы. Код из LinqPad, над которым я работал большую часть дня, позволил мне исключить w:

var h1 = MathNet.Symbolics.Infix.ParseOrUndefined("(1/8)*r*t*w + (1/2)*r*t^2*w");
var h2 = MathNet.Symbolics.Infix.ParseOrUndefined("(1/8)*r*t*w + (1/8)*r^2*t*w + (3/4)*r*t^2*w + (3/4)*r^2*t^2*w + (1/4)*r*t^3*w");

Infix.Print(Rational.Expand(h1/h2)).Dump();  //Prints (512*r*t*w + 2048*r*t^2*w)/(512*r*t*w + 512*r^2*t*w + 3072*r*t^2*w + 3072*r^2*t^2*w + 1024*r*t^3*w)
var tot = Rational.Expand(h1 / h2);

var simplified = true;
do
{
    simplified=false;
    foreach (var v in Rational.Variables(tot))
    {
        var result = Polynomial.Divide(v, h1, h2);
        if (!result.Item1.Equals(MathNet.Symbolics.Expression.Zero))
        {
            simplified = true;
            tot = result.Item1;
            break;
        }
    }
}while(simplified);
tot = Rational.Expand(tot);

Infix.Print(tot).Dump();  //Prints (512*r*t + 2048*r*t^2)/(512*r*t + 512*r^2*t + 3072*r*t^2 + 3072*r^2*t^2 + 1024*r*t^3)

Может ли кто-нибудь подсказать мне, как работать с MathNet? Я пробовал различные комбинации функций из Rational и Polynomial и не смог продвинуться дальше этой точки.


person Matt Sieker    schedule 25.09.2015    source источник


Ответы (1)


Я только что опубликовал новый выпуск Math.NET Symbolics v0.6.0. который включает новую процедуру Rational.Reduce, которая удаляет такие распространенные простые факторы (также выполняемые как часть Rational.Expand):

var h1 = Infix.ParseOrThrow("(1/8)*r*t*w + (1/2)*r*t^2*w");
var h2 = Infix.ParseOrThrow("(1/8)*r*t*w + (1/8)*r^2*t*w + (3/4)*r*t^2*w + (3/4)*r^2*t^2*w + (1/4)*r*t^3*w");

var q1 = h1/h2;
Infix.Print(q1);
// returns: ((1/8)*r*t*w + (1/2)*r*t^2*w)/((1/8)*r*t*w + (1/8)*r^2*t*w + (3/4)*r*t^2*w + (3/4)*r^2*t^2*w + (1/4)*r*t^3*w)

var q2 = Rational.Expand(q1);
Infix.Print(q2);
// returns: (1 + 4*t)/(1 + r + 6*t + 6*r*t + 2*t^2)

К сожалению, многие одномерные полиномиальные и рациональные процедуры, такие как новая бесквадратная факторизация, еще не имеют многомерного аналога. Одномерные подпрограммы ожидают один параметр символа, тогда как многомерные ожидают набор символов.

person Christoph Rüegg    schedule 29.09.2015
comment
Отлично, спасибо. Между этим и некоторой работой, которую я проделал на выходных (сводясь к повторным вызовам Rational.Simplify для каждой переменной, а затем проверяя, уменьшились ли операнды), теперь я получаю гораздо более естественные результаты. Сегодня у меня может возникнуть еще один вопрос, касающийся рациональных чисел, которые лучше оставить десятичными (пример: 58916322729/204800000000000000000000000). Или, по крайней мере, иметь возможность принудительно использовать десятичную форму при Printсоставлении уравнения. - person Matt Sieker; 30.09.2015
comment
Если бы у нас был такой вариант, каковы были бы правила, чтобы решить, когда оценивать и округлять? Только рациональные числа? Все термины без символов? Следует ли также оценивать функции? - person Christoph Rüegg; 01.10.2015
comment
Я обдумывал это. В моем конкретном случае это действительно необходимо только в одном условии. Я бы сказал либо вариант Print(), который превращает рациональные числа в вещественные числа, либо возможность включать в выражение действительные числа. Я попробовал переменный маршрут, упомянутый в документах, но из-за большого количества возможных коэффициентов это привело к выражениям с тысячами терминов. Если на стороне библиотеки нет простого решения, мой план состоял в том, чтобы просто искать пары скобок только с числами и / в них, а затем заменять их десятичной дробью. - person Matt Sieker; 01.10.2015
comment
Возможно, будет целесообразно ввести новый тип выражения, назовем его Constant, который ведет себя как символ, но имеет значение и некоторые дополнительные правила автоматического упрощения для оценки арифметических операций. Затем синтаксический анализатор может интерпретировать десятичные выражения как такую ​​константу, а не как точное рациональное число. - person Christoph Rüegg; 02.10.2015