Note to self: distinguish between roots and factors. All polynomials have 
roots but not all roots correspond to factors, e.g.

roots of *unfactorable* `x**2 + 5*x + 1` are `[-5/2 - sqrt(21)/2, -5/2 + 
sqrt(21)/2]` -- notice that we left the integer domain and needed to 
express solutions in terms of radicals. Roots of `x**2+5*x+6` are integers 
`[-3, -2]` suggesting that the factors are `x + 3` and `x + 2`. All 
quadratics can be written as `a*(x - r1)*(x - r2)` but that does not mean 
that those are factors (lower order expressions which divide the original 
evenly).

see also https://byjus.com/maths/factoring-polynomials/

On Friday, March 11, 2022 at 5:13:35 PM UTC-6 Chris Smith wrote:

> Given two expressions, `p` and `q`
>
> p = x*y + x + y*z
> q = p + z
>
> it is easy to show that `q = (x + z)*(y + 1)`. But I'm wanting to avoid 
> factoring but would like to know whether a solution for `x` from `p = 0` or 
> `q = 0` is a factor or not. For `q`, the root `x = -z` represent a simple 
> factor whereas the root of x = `-yz/(y + 1)` is different.
>
> I'm lacking the vocabulary to differentiate `-z` from `-yz/(y + 1)`. Is it 
> that the latter has a denominator while the former does not? (And since the 
> original expression had no denominator then the `-z` represents a "whole" 
> factor while the other root does not?)
>
> As an alternative to factoring, it seems like collection and 
> identification of similar subexpressions should allow a multivariate 
> expression to be written in terms of un-factored factors, e.g. `collect(q, 
> x) -> x*(y + 1) + y*z + z` and then use `factor_terms` on the non-x portion 
> of the expression to find a matching factor of `y + 1` so the expression 
> can be separated into two factors, one with `y` and one with `x` and `z`.  
> This works for less trivial expressions and can be done recursively 
> something like this:
>
> def sep(e):
>   free = e.free_symbols
>   if not free:return e
>   x = next(ordered(free))
>   c = collect(e.expand(),x)
>   if not c.is_Add:return c
>   i,d = c.as_independent(x)
>   d = d.func(*[factor_terms(di) for di in d.args])
>   i = factor_terms(i)
>   ia, a = i.as_independent(Add, as_Add=False)
>   if a==1:
>       return e
>   _a = sep(a)
>   D = Dummy()
>   return factor_terms(ia*D + d.xreplace({a:D})).subs(D, _a)
>
>  eq
> v**3*y*z**10 + 4*v**3*y*z**6 + 2*v**3*y*z**5 + 4*v**3*y*z**2 + 4*v**3*y*z 
> + v**3*y + v**3*z**10 + 4*v**3*z**6 + 2*v**3*z**5 + 4*v**3*z**2 + 4*v**3*z 
> + v**3 + 3*v**2*x*y*z**10 + 12*v**2*x*y*z**6 + 6*v**2*x*y*z**5 + 
> 12*v**2*x*y*z**2 + 12*v**2*x*y*z + 3*v**2*x*y + 3*v**2*x*z**10 + 
> 12*v**2*x*z**6 + 6*v**2*x*z**5 + 12*v**2*x*z**2 + 12*v**2*x*z + 3*v**2*x + 
> 3*v*x**2*y*z**10 + 12*v*x**2*y*z**6 + 6*v*x**2*y*z**5 + 12*v*x**2*y*z**2 + 
> 12*v*x**2*y*z + 3*v*x**2*y + 3*v*x**2*z**10 + 12*v*x**2*z**6 + 
> 6*v*x**2*z**5 + 12*v*x**2*z**2 + 12*v*x**2*z + 3*v*x**2 + x**3*y*z**10 + 
> 4*x**3*y*z**6 + 2*x**3*y*z**5 + 4*x**3*y*z**2 + 4*x**3*y*z + x**3*y + 
> x**3*z**10 + 4*x**3*z**6 + 2*x**3*z**5 + 4*x**3*z**2 + 4*x**3*z + x**3
>  sep(eq)
> (y + 1)*(v**3 + 3*v**2*x + 3*v*x**2 + x**3)*(z**10 + 4*z**6 + 2*z**5 + 
> 4*z**2 + 4*z + 1)
>  eq == _.expand()
> True
>
> (It always seems like `factor` is faster than this but factor can be slow, 
> too. And I don't really need the separated factors "factored" as much as I 
> just need them separated.
>
> So maybe that sort of function will answer the question...
>
> Any thoughts would be appreciated as to what might be the best way to know 
> when you have a solution that is a whole factors (not a rational factor -- 
> or whatever it should be called.)
>
> /c
>

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/6cb2b5b1-7d36-41da-a002-9b3e71d660d4n%40googlegroups.com.

Reply via email to