【问题标题】:Extracting common terms with MathNet Symbolics使用 MathNet Symbolics 提取常用术语
【发布时间】:2015-09-25 21:50:08
【问题描述】:

我正在使用 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 吗?我尝试了RationalPolynomial 的各种功能组合,但一直无法超越这一点。

【问题讨论】:

    标签: c# symbolic-math math.net mathnet-numerics


    【解决方案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)
    

    不幸的是,很多单变量多项式和有理例程(例如新的无平方因式分解)还没有对应的多变量。单变量例程需要一个符号参数,而多变量例程需要一个符号集。

    【讨论】:

    • 太好了,谢谢。在这和我周末所做的一些工作之间(归结为对每个变量重复调用Rational.Simplify,然后查看它是否减少了操作数),我现在得到了更自然的结果。今天晚些时候我可能还有另一个问题,关于处理可能最好保留为十进制的有理数(例如:58916322729/2048000000000000000000000)。或者至少能够在Printing 等式时强制转换为十进制形式。
    • 如果我们有这样的变体,决定何时评估和舍入的规则是什么?只有所有有理数?所有术语包括不包括符号?是否也应该评估函数?
    • 我一直在思考这个问题。在我的特定用例中,它只在一种情况下真正需要。我会说 Print() 上的一个变体,它将有理数变为实数,或者能够在表达式中包含实数。我尝试了文档中提到的可变路径,但是由于可能的系数很多,这导致了具有数千个术语的表达式。如果图书馆方面没有简单的解决方案,我的计划是只寻找一对只有数字和 / 的括号,然后用小数替换它。
    • 引入一种新的表达式类型可能是可行的,我们称之为Constant,它的行为类似于符号,但有一个值和一些额外的自动简化规则来评估算术运算。然后解析器可以将十进制表达式解释为这样的常量而不是精确的有理数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 2015-01-31
    • 1970-01-01
    • 2012-09-04
    相关资源
    最近更新 更多