Можно ли использовать регулярные выражения для замены в sympy? - PullRequest
0 голосов
/ 23 января 2019

Предположим, у меня есть символьное вычисление в 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 операнда продукта, но оставляет все, что находится после продукта, без изменений, и его также следует удалить,

1 Ответ

0 голосов
/ 23 января 2019

Я понял, как фильтровать товары, используя 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_sr11 * err * erd_111* 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_rd0 * er0_r0100 * er0_d0 * er0* 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 * er1_r0- 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 * rd * er0 r0 * r0 * er0* 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_m01 * err_d0 * n0 * r0err_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 * er1_dr0 * n0 r0err_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_mul2 * er2_r2 * er2 * r2err_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 * r2 * r2p0 - 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_d9err_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 * r2 * r2 * r2 * r2 * r2err_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 + er_s1 * er0sp1 + 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)

, в результате чего:

print (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 * rd5 r1* 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 * n0 * p2 - n0 * p2 - n0 * p2 + n0 * p2 + n0 * p2 + n0 * p2 + n0 * p2 + n0 * p2err_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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...