可以使用正则表达式替换sympy吗?

时间:2019-01-23 10:35:40

标签: python regex sympy

假设我在sympy中有一个符号计算,该计算通过向数字添加错误来修改数字的基本算术运算:

from sympy import * 

p0,p1,p2 = symbols("p0:3")
ep0,ep1,ep2 = symbols("ep0:3")
x0,x1,x2 = symbols("x0:3")
ex0,ex1,ex2 = symbols("ex0:3")
q0,q1,q2 = symbols("q0:3")
eq0,eq1,eq2 = symbols("eq0:3")
r0,r1,r2 = symbols("r0:3")
er0,er1,er2 = symbols("er0:3")
n0,n1,n2 = symbols("n0:3")
en0,en1,en2 = symbols("en0:3")

p = Matrix([p0,p1,p2])
x = Matrix([x0,x1,x2])
q = Matrix([q0,q1,q2])
r = Matrix([r0,r1,r2])
n = Matrix([n0,n1,n2])

errors = []

def fl_op(a,b,op,e):
    return op(a,b)*(1 + e)

def fl_add(a,b):
    # Append an addition error to the global list of errors
    errors.append(symbols("err_add" + str(len(errors)+1)))
    return fl_op(a,b, lambda x,y : x + y, errors[-1]) 

def fl_sub(a,b):
    # Append an addition error to the global list of errors
    errors.append(symbols("err_sub" + str(len(errors)+1)))
    return fl_op(a,b, lambda x,y : x - y, errors[-1]) 

def fl_mul(a,b):
    # Append an addition error to the global list of errors
    errors.append(symbols("err_mul" + str(len(errors)+1)))
    return fl_op(a,b, lambda x,y : x * y, errors[-1]) 

def fl_div(a,b):
    # Append an addition error to the global list of errors
    errors.append(symbols("err_div" + str(len(errors)+1)))
    return fl_op(a,b, lambda x,y : x / y, errors[-1]) 

def fl_vsub(va,vb):
    assert (len(va) == len(vb))
    return [fl_sub(va[i],vb[i]) for i in range(len(va))]

def fl_vadd(va,vb):
    assert (len(va) == len(vb))
    return [fl_add(va[i],vb[i]) for i in range(len(va))]

def fl_vsum(va):
    return fl_add(fl_add(va[0],va[1]),va[2])

def fl_dot(va,vb):
    assert (len(va) == len(vb))
    return fl_vsum([fl_mul(va[i],vb[i]) for i in range(len(va))])

dotSub  = fl_sub(fl_dot(r,n), fl_dot(p,n))
dotSub = simplify(dotSub)
vSubDot = fl_dot(fl_vsub(r,p),n)
vSubDot = simplify(vSubDot)

print(expand(dotSub))

打印语句的结果是:

  

-err_add10 * err_add9 * err_mul6 * err_sub11 * n0 * p0-err_add10 * err_add9 * err_mul6 * n0 * p0-   err_add10 * err_add9 * err_mul7 * err_sub11 * n1 * p1-   err_add10 * err_add9 * err_mul7 * n1 * p1-err_add10 * err_add9 * err_sub11 * n0 * p0   -err_add10 * err_add9 * err_sub11 * n1 * p1-err_add10 * err_add9 * n0 * p0-err_add10 * err_add9 * n1 * p1-err_add10 * err_mul6 * err_sub11 * n0 * p0-   err_add10 * err_mul6 * n0 * p0-err_add10 * err_mul7 * err_sub11 * n1 * p1-   err_add10 * err_mul7 * n1 * p1-err_add10 * err_mul8 * err_sub11 * n2 * p2-   err_add10 * err_mul8 * n2 * p2-err_add10 * err_sub11 * n0 * p0-   err_add10 * err_sub11 * n1 * p1-err_add10 * err_sub11 * n2 * p2-   err_add10 * n0 * p0-err_add10 * n1 * p1-err_add10 * n2 * p2 +   err_add4 * err_add5 * err_mul1 * err_sub11 * n0 * r0 +   err_add4 * err_add5 * err_mul1 * n0 * r0 +   err_add4 * err_add5 * err_mul2 * err_sub11 * n1 * r1 +   err_add4 * err_add5 * err_mul2 * n1 * r1 + err_add4 * err_add5 * err_sub11 * n0 * r0 +   err_add4 * err_add5 * err_sub11 * n1 * r1 + err_add4 * err_add5 * n0 * r0 +   err_add4 * err_add5 * n1 * r1 + err_add4 * err_mul1 * err_sub11 * n0 * r0 +   err_add4 * err_mul1 * n0 * r0 + err_add4 * err_mul2 * err_sub11 * n1 * r1 +   err_add4 * err_mul2 * n1 * r1 + err_add4 * err_sub11 * n0 * r0 +   err_add4 * err_sub11 * n1 * r1 + err_add4 * n0 * r0 + err_add4 * n1 * r1 +   err_add5 * err_mul1 * err_sub11 * n0 * r0 + err_add5 * err_mul1 * n0 * r0 +   err_add5 * err_mul2 * err_sub11 * n1 * r1 + err_add5 * err_mul2 * n1 * r1 +   err_add5 * err_mul3 * err_sub11 * n2 * r2 + err_add5 * err_mul3 * n2 * r2 +   err_add5 * err_sub11 * n0 * r0 + err_add5 * err_sub11 * n1 * r1 +   err_add5 * err_sub11 * n2 * r2 + err_add5 * n0 * r0 + err_add5 * n1 * r1 +   err_add5 * n2 * r2-err_add9 * err_mul6 * err_sub11 * n0 * p0-   err_add9 * err_mul6 * n0 * p0-err_add9 * err_mul7 * err_sub11 * n1 * p1-   err_add9 * err_mul7 * n1 * p1-err_add9 * err_sub11 * n0 * p0-   err_add9 * err_sub11 * n1 * p1-err_add9 * n0 * p0-err_add9 * n1 * p1 +   err_mul1 * err_sub11 * n0 * r0 + err_mul1 * n0 * r0 + err_mul2 * err_sub11 * n1 * r1 +   err_mul2 * n1 * r1 + err_mul3 * err_sub11 * n2 * r2 + err_mul3 * n2 * r2-   err_mul6 * err_sub11 * n0 * p0-err_mul6 * n0 * p0-err_mul7 * err_sub11 * n1 * p1-   err_mul7 * n1 * p1-err_mul8 * err_sub11 * n2 * p2-err_mul8 * n2 * p2-   err_sub11 * n0 * p0 + err_sub11 * n0 * r0-err_sub11 * n1 * p1 + err_sub11 * n1 * r1   -err_sub11 * n2 * p2 + err_sub11 * n2 * r2-n0 * p0 + n0 * r0-n1 * p1 + n1 * r1-n2 * p2 + n2 * r2

所有err_术语互不相同,但是它们的乘积可以忽略。做这个的最好方式是什么? subs中的sympy函数是否可以接受所有err_项的乘积的规则,使乘积等于0?是否可以重载用于符号符号的算术运算符*来检查两个乘积运算符的名称是否都以err_开头并以符号0得出结果?

不可能很快为err_项的乘积指定所有可能的组合,因为组合的数量增长很快。

如果使用python.regex解析字符串以排除所有乘积,可能会更容易。怎么办?

我尝试了以下python regex,但它对字符串没有影响:

import regex
dotSubStr = str(expand(dotSub))
re.sub("[+,-,\s]err_*\*err_*\s",'', dotSubStr)

提取第一个产品适用于

re.sub("err_(add|sub|mul|div)\d+\*err_(add|sub|mul|div)\d+",'', dotSubStr)
  

'-** n0 * p0-* err_mul6 * n0 * p0-** n1 * p1-* err_mul7 * n1 * p1-   * err_sub11 * n0 * p0-* err_sub11 * n1 * p1-* n0 * p0-* n1 * p1-* err_sub11 * n0 * p0-* n0 * p0-* err_sub11 * n1 * p1-* n1 * p1-* err_sub11 * n2 * p2-* n2 * p2-* n0 * p0-* n1 * p1-* n2 * p2-err_add10 * n0 * p0-err_add10 * n1 * p1-err_add10 * n2 * p2 + ** n0 * r0 + * err_mul1 * n0 * r0 + ** n1 * r1 + * err_mul2 * n1 * r1 + * err_sub11 * n0 * r0 + * nr * sub1 * n1 * r1 + * n0 * r0 + * n1 * r1 + * err_sub11 * n0 * r0 + * n0 * r0 + * err_sub11 * n1 * r1 + * n1 * r1 + * n0 * r0 + * n1 * r1 + err_add4 * n0 * r0 + err_add4 * n1 * r1 + * err_sub11 * n0 * r0 + * n0 * r0 + * err_sub11 * n1 * r1 + * n1 * r1 + * err_sub11 * n2 * r2 + * n2 * r2 + * n0 * r0 + * n1 * r1 + * n2 * r2 + err_add5 * n0 * r0 + err_add5 * n1 * r1 + err_add5 * n2 * r2-* err_sub11 * n0 * p0-* n0 * p0-* err_sub11 * n1 * p1-* n1 * p1-* n0 * p0-* n1 * p1-err_add9 * n0 * p0-err_add9 * n1 * p1 + * n0 * r0 + err_mul1 * n0 * r0 + * n1 * r1 + err_mul2 * n1 * r1 +   * n2 * r2 + err_mul3 * n2 * r2-* n0 * p0-err_mul6 * n0 * p0-* n1 * p1-err_mul7 * n1 * p1-* n2 * p2-err_mul8 * n2 * p2-err_sub11 * n0 * p0 +   err_sub11 * n0 * r0-err_sub11 * n1 * p1 + err_sub11 * n1 * r1-err_sub11 * n2 * p2   + err_sub11 * n2 * r2-n0 * p0 + n0 * r0-n1 * p1 + n1 * r1-n2 * p2 + n2 * r2'

因此,如果表达式最多具有3个乘积操作数,则此操作将删除乘积,但在乘积完好后保留所有内容,因此也应将其删除。

1 个答案:

答案 0 :(得分:0)

我弄清楚了如何使用regex过滤产品,以便在有人需要时回答。

从带有算术表达式的起始字符串开始:

  

-err_add10 * err_add9 * err_mul6 * err_sub11 * n0 * p0-err_add10 * err_add9 * err_mul6 * n0 * p0-   err_add10 * err_add9 * err_mul7 * err_sub11 * n1 * p1-   err_add10 * err_add9 * err_mul7 * n1 * p1-err_add10 * err_add9 * err_sub11 * n0 * p0   -err_add10 * err_add9 * err_sub11 * n1 * p1-err_add10 * err_add9 * n0 * p0-err_add10 * err_add9 * n1 * p1-err_add10 * err_mul6 * err_sub11 * n0 * p0-   err_add10 * err_mul6 * n0 * p0-err_add10 * err_mul7 * err_sub11 * n1 * p1-   err_add10 * err_mul7 * n1 * p1-err_add10 * err_mul8 * err_sub11 * n2 * p2-   err_add10 * err_mul8 * n2 * p2-err_add10 * err_sub11 * n0 * p0-   err_add10 * err_sub11 * n1 * p1-err_add10 * err_sub11 * n2 * p2-   err_add10 * n0 * p0-err_add10 * n1 * p1-err_add10 * n2 * p2 +   err_add4 * err_add5 * err_mul1 * err_sub11 * n0 * r0 +   err_add4 * err_add5 * err_mul1 * n0 * r0 +   err_add4 * err_add5 * err_mul2 * err_sub11 * n1 * r1 +   err_add4 * err_add5 * err_mul2 * n1 * r1 + err_add4 * err_add5 * err_sub11 * n0 * r0 +   err_add4 * err_add5 * err_sub11 * n1 * r1 + err_add4 * err_add5 * n0 * r0 +   err_add4 * err_add5 * n1 * r1 + err_add4 * err_mul1 * err_sub11 * n0 * r0 +   err_add4 * err_mul1 * n0 * r0 + err_add4 * err_mul2 * err_sub11 * n1 * r1 +   err_add4 * err_mul2 * n1 * r1 + err_add4 * err_sub11 * n0 * r0 +   err_add4 * err_sub11 * n1 * r1 + err_add4 * n0 * r0 + err_add4 * n1 * r1 +   err_add5 * err_mul1 * err_sub11 * n0 * r0 + err_add5 * err_mul1 * n0 * r0 +   err_add5 * err_mul2 * err_sub11 * n1 * r1 + err_add5 * err_mul2 * n1 * r1 +   err_add5 * err_mul3 * err_sub11 * n2 * r2 + err_add5 * err_mul3 * n2 * r2 +   err_add5 * err_sub11 * n0 * r0 + err_add5 * err_sub11 * n1 * r1 +   err_add5 * err_sub11 * n2 * r2 + err_add5 * n0 * r0 + err_add5 * n1 * r1 +   err_add5 * n2 * r2-err_add9 * err_mul6 * err_sub11 * n0 * p0-   err_add9 * err_mul6 * n0 * p0-err_add9 * err_mul7 * err_sub11 * n1 * p1-   err_add9 * err_mul7 * n1 * p1-err_add9 * err_sub11 * n0 * p0-   err_add9 * err_sub11 * n1 * p1-err_add9 * n0 * p0-err_add9 * n1 * p1 +   err_mul1 * err_sub11 * n0 * r0 + err_mul1 * n0 * r0 + err_mul2 * err_sub11 * n1 * r1 +   err_mul2 * n1 * r1 + err_mul3 * err_sub11 * n2 * r2 + err_mul3 * n2 * r2-   err_mul6 * err_sub11 * n0 * p0-err_mul6 * n0 * p0-err_mul7 * err_sub11 * n1 * p1-   err_mul7 * n1 * p1-err_mul8 * err_sub11 * n2 * p2-err_mul8 * n2 * p2-   err_sub11 * n0 * p0 + err_sub11 * n0 * r0-err_sub11 * n1 * p1 + err_sub11 * n1 * r1   -err_sub11 * n2 * p2 + err_sub11 * n2 * r2-n0 * p0 + n0 * r0-n1 * p1 + n1 * r1-n2 * p2 + n2 * r2

regex可以这样删除所有err_*项的所有乘积:

import re
dotSubFinal = re.sub("(err_(add|sub|mul|div)\d+\*){2,}",'del', dotSubStr)
dotSubFinal = re.sub("[+-]\s*del[npr]\d\*[npr]\d",'', dotSubFinal)
dotSubFinal = re.sub("\s{2,}",'', dotSubFinal)

导致:

打印(dotSubFinal)

  

-err_add10 * n0 * p0-err_add10 * n1 * p1-err_add10 * n2 * p2 + err_add4 * n0 * r0 + err_add4 * n1 * r1 + err_add5 * n0 * r0 + err_add5 * n1 * r1 + er2 * n0 * p0-   err_add9 * n1 * p1 + err_mul1 * n0 * r0 + err_mul2 * n1 * r1 +   err_mul3 * n2 * r2- err_mul6 * n0 * p0- err_mul7 * n1 * p1- err_mul8 * n2 * p2-   err_sub11 * n0 * p0 + err_sub11 * n0 * r0-err_sub11 * n1 * p1 + err_sub11 * n1 * r1   -err_sub11 * n2 * p2 + err_sub11 * n2 * r2-n0 * p0 + n0 * r0-n1 * p1 + n1 * r1-n2 * p2 + n2 * r2