将方程树转换为系数矩阵?

时间:2016-06-09 13:51:04

标签: algorithm math expression-trees

给定一些lineqr(in)相等,将它转换为系数矩阵形式的简单算法是什么? 因此,例如给定((3(x+5)/(2(y-1)))<4(作为树,所以运算符顺序是明确定义的)如何有效地将其转换为3x-8y<-23或类似的东西? 任何暗示使用什么算法?

2 个答案:

答案 0 :(得分:1)

让我们看看你将如何手动完成这项工作

((3(x+5)/(2(y-1)))<4              
3 (x+ 5) < ( 2 ( y - 1) ) * 4     Multiply by bottom note 1
3 x + 5 < 8 y - 8                 Expand
3 x - 8 y + 5 < -8                Take 8 y across
3 x - 8 y < -13                   Take 5 across

这仅在2 (y-1)为正时才有效,否则您需要将小于号更改为大于号。

您可以使用两种基本策略。

  1. 将每个单独的节点转换为系数矩阵,然后对这些矩阵执行数学运算,以获得最终答案。

  2. 简化表达式,然后将其转换为系数矩阵。

  3. 让我们看一个没有分裂的表达,这使事情变得复杂。

    (3(x+5))*(2(y-1))<4  
    

    对于常数3,写入或系数矩阵为[3],对于x,[2 y,0]为2,写入[x,0]。将每个叶节点转换为系数给出

    ([3]*([x,0]+[5]))*([2]*([y,0]-[1]))<[4]
    

    处理树

    ([3]*[x,5])*([2]*[y,-1])<[4]
    [3 x,15]*[2 y,-2] < [4]
    [6 x y,-6 x, 30 y, -30] < [4]
    [6 x y,-6 x, 30 y, -34] < [0]
    

    要实际实现这一点,您需要一个系数矩阵类,它具有执行每个基本操作的方法。假设我们知道答案都是x和y中的多项式。我们的课可能类似

    class Polynomial {
        double data[][];
        int degX,degY;
        // Constructor from a constant
        Polynomial(double val) { 
            data = new double[1][1];
            data[0][0]=val;
            degX = degY = 0;
        }
        // Constructor from a variable
        Polynomial(String name) {
            if(name == "x") {
                data = new double[2][1];
                data[1][0]=1;
                degX=1; degY=0;
            } else if( name=="y") [
                data = new double[1][2];
                data[0][1]=1;
                degX=1; degY=0;
            }
        }
    
        // Add two polynomials
        Polynomial add(Polynomial A,Polynomial B) {
            int dX = max(A.degX,B.degX);
            int dY = max(A.degY,B.degY);
            double coeffs[][] = new double[dx+1][dy+1];
            for(int i=0;i<A.degX;++i)
                for(int j=0;j<A.degY;++j)
                    coeffs[i][j] += A.data[i][j]; 
            for(int i=0;i<B.degX;++i)
                for(int j=0;j<B.degY;++j)
                    coeffs[i][j] += B.data[i][j]; 
            return new Polynomial(coeffs,degX,degY);
        }
    
        // Multiply two polynomials
        Polynomial mul(Polynomial A,Polynomial B) {
            int dx = A.degX * B.degX;
            int dy = A.degY * B.degY;
            double coeffs[][] = new double[dx+1][dy+1];
            for(int i=0;i<A.degX;++i)
              for(int j=0;j<A.degY;++j)
                for(int k=0;k<B.degX;++k)
                  for(int l=0;l<A.degY;++l)
                    coeffs[i+k][j+l] = coeffs[i][j] * coeffs[k][l];
            return new Polynomial(coeffs,degX,degY);
        }
    }
    

    然后,您需要深度优先递归树遍历例程

    Polynomial walk(Node n) {
        if( isConstant(n) )
            return new Polynomial( n.value );
        if( isIdentifier(n) )
            return new Polynomial( n.name );
        if( node.op = "+" )
            return Polynomial.add( walk(n.left), walk(n.right) );
        if( node.op = "*" )
            return Polynomial.mul( walk(n.left), walk(n.right) );
    }
    

    分部使事情变得更加困难。

答案 1 :(得分:0)

您正在寻找能够进行代数简化的东西。有很多计算机代数系统(CAS),我建议SymPySage(都在Python中)。

请注意,您提供的示例((3(x+5)/(2(y-1)))<4 是线性不等式,因此CAS无法将其“转换为3x-8y<-23或等效的内容。”