Предположим, у меня есть символьное вычисление в 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)) *
результат оператора print такой:
-err_add10 * err_add9 * err_mul6 * err_sub11 * n0 * p0 - err_add10 * err_add9 * err_mul6 * n0 * p0 - err_add10 * err_md7 * err_md7 *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_ad_0_1err_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_dr8 * er2_dr2 * er2p2 - 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_dd * * er2err_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_add * * er1rd1 * r1 r4err_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_sub1 * er1 * r1 * r1 * r1n0 * 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 + er1 * er1 er1 errerr_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 + er1 nr * er1err_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_dd0 * er1_dr9err_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_sub1 * r1 * r1 * r1 * r1заблуждаться_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_ul2 - err_mul8n2 * 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 + n1 * r0 - n0 * r0 -p1 + n1 * r1 - n2 * p2 + n2 * r2
Все члены err_
отличаются друг от друга, но их произведения можно игнорировать.Каков наилучший способ сделать это?Может ли функция subs
в sympy
принять что-то вроде правила для произведения всех терминов err_
, которое делает произведение равным 0?Можно ли перегрузить арифметический оператор *
для символов sympy, чтобы проверить, начинается ли имя обоих операндов продукта с err_
, а в результате - с символом 0?
Указание всех возможных комбинаций для продуктовerr_
условия быстро становятся невозможными, потому что число комбинаций растет чрезвычайно быстро.
Возможно, было бы проще, если бы строка анализировалась с использованием python.regex
, чтобы исключить все продукты.Как это будет работать?
Я пробовал следующий питон 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 + * err_sub11 * 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 *err_sub11 * n2 * r2 - n0 * p0 + n0 * r0 - n1 * p1 + n1 * r1 - n2 * p2 + n2 * r2 '
Таким образом, это удаляет продукт, если выражение имеет максимально 3 операнда продукта, но оставляет все, что находится после продукта, без изменений, и его также следует удалить,