detect multivatiate generator (decomposition?)

24 views
Skip to first unread message

Chris Smith

unread,
Dec 17, 2021, 9:13:17 PM12/17/21
to sympy
What is the best way to identify a multivariate change of variables for an expression? Consider the followin:
```
>>> c
3*y**4 + 6*y**3*z + 42*y**3 - 9*y**2*z**2 + 126*y**2*z + 148*y**2 - 12*y*z**3 +
589*y*z + 7*y + 12*z**4 - 168*z**3 + 586*z**2 + 14*z + 2
>>> factor(c-2)
(y + 2*z)*(y - z + 7)*(3*y**2 + 3*y*z + 21*y - 6*z**2 + 42*z + 1)
>>> factor(_.args[-1]-1)
3*(y + 2*z)*(y - z + 7)
>>> (x*(3*x+1)+2).subs(x,(y + 2*z)*(y - z + 7)).expand() == c
True
```

This is a bit like `horner` (but `horner` gives something else in this cse):
```
>>> horner(c)
y*(y*(y*(3*y + 6*z + 42) + z*(126 - 9*z) + 148) + z*(589 - 12*z**2) + 7) +
z*(z*(z*(12*z - 168) + 586) + 14) + 2
```
It is also a bit like `decompose` (but `decompose` doesn't work on multivariates).

The ability to identify this multivariate generator allows for a straightforward solution to the quartic in `y`:
```
>>> inv = solve(x - (y + 2*z)*(y - z + 7),y)
>>> xs = solve(x*(3*x+1)+2,x)
>>> ys = [i.subs(x, xi) for i in inv for xi in xs]
>>> ys
[-z/2 - sqrt(9*z**2 - 42*z + 145/3 - 2*sqrt(23)*I/3)/2 - 7/2, -z/2 - sqrt(9*z**2
 - 42*z + 145/3 + 2*sqrt(23)*I/3)/2 - 7/2, -z/2 + sqrt(9*z**2 - 42*z + 145/3 - 2
*sqrt(23)*I/3)/2 - 7/2, -z/2 + sqrt(9*z**2 - 42*z + 145/3 + 2*sqrt(23)*I/3)/2 -
7/2]
```
Without identifying the generator the equation can also be solved
```
>>> sol=solve(c,y)
>>> sol
[sqrt(3)*(-sqrt(3)*z - sqrt(27*z**2 - 126*z + 145 - 2*sqrt(23)*I) - 7*sqrt(3))/6
, sqrt(3)*(-sqrt(3)*z + sqrt(27*z**2 - 126*z + 145 - 2*sqrt(23)*I) - 7*sqrt(3))/
6, sqrt(3)*(-sqrt(3)*z - sqrt(27*z**2 - 126*z + 145 + 2*sqrt(23)*I) - 7*sqrt(3))
/6, sqrt(3)*(-sqrt(3)*z + sqrt(27*z**2 - 126*z + 145 + 2*sqrt(23)*I) - 7*sqrt(3)
)/6]
```
The solutions are the same (but in different form). e.g. for `z = 3`
```
>>> [i.subs(z, 3).n(2) for i in sol]
[-6.0 + 0.4*I, -4.0 - 0.4*I, -6.0 - 0.4*I, -4.0 + 0.4*I]
>>> [i.subs(z, 3).n(2) for i in ys]
[-6.0 + 0.4*I, -6.0 - 0.4*I, -4.0 - 0.4*I, -4.0 + 0.4*I]
```

/c

Chris Smith

unread,
Dec 18, 2021, 12:11:44 AM12/18/21
to sympy
wolfram alpha gives the following for `decompose c`:
```
(3*y**2 - 12*y*z**2 + 84*y*z + y + 12*z**4 - 168*z**3 + 586*z**2 + 14*z + 2) o (y**2 + y*z + 7*y)
```
and if you replace `y` in the first expression with the second expression it equals `c`. Written with the same semantics, the previous post results would be expressed as
```
(3*x**2 + x + 2) o (y**2 + y*z + 7*y - 2*z**2 + 14*z)
```
where `lhs.subs(x, rhs) == c`.

/c
Reply all
Reply to author
Forward
0 new messages