6

I want to check for a polynomial whether it is a perfect square.

Using the functions for polynomial factoring and decomposition, this is possible by first applying FactorList, after which you can check all these terms whether there is a polynomial that has degree equal the half of the original polynomial and divides the original polynomial twice. However, this seems like unoptimal use of Mathematica and takes time as well, as we have to iterate through a list.

Using Sqrt (a bit naive, I know) combined with PolynomialQ does not work either as Mathematica (rightly) doesn't simplify this.

Hence, my question is: is there any relatively simple (i.e. easier/less computationally heavy) method for determining whether a polynomial is a square?

Edit: three small examples:

CheckIfSquare[x^2 - 1] should give False.

CheckIfSquare[x^2 - 2x + 1] should give True as $x^2 - 2x + 1 = (x-1)^2$.

CheckIfSquare[x^3] should give False, even though x^3 is not squarefree, it is not a square itself.

David G. Stork
  • 41,180
  • 3
  • 34
  • 96
Stapler
  • 163
  • 4

2 Answers2

7

A little trick I learned long, long ago.

CheckIfSquare[p_] := Simplify[D[p, x]^2] === Simplify[4 p]

x^2-1 returns False, x^2-2 x+1 returns True, x^3 returns False

As always, using equality on the result of a chain of calculations on approximate coefficients may fail. There might be other cases I haven't thought of where this can fail, I can't think of any at the moment. But it is just so cute. And it requires no factorization at all.

EDIT: Late last night I realize that I had forgotten the details of using this and had made a mistake in this. The original purpose of this trick was to rapidly see if it was possible to find a factor of a polynomial without needing to invoke full factorization and when the power of something like MMA wasn't available. The polynomial GCD of the polynomial and it's derivative would give that. It actually fails even for some quadratics like (2 x - 7)^2 and only works correctly when the derivative of the factor equals 1 and the polynomial is quadratic. Thanks for the comments letting everyone know that I made a mistake here and FactorSquareFreeList followed by processing the degrees returned from that should be used.

Bill
  • 12,001
  • 12
  • 13
  • Very elegant! I like this solution, and as I am using polynomials with rational coefficients, approximations should be no problem. – Stapler Jan 28 '17 at 12:30
  • 2
    I think this is only correct when p is quadratic. With n = Exponent[p, x], the degree of D[p, x]^2 is 2n-2 and the degree of 4p is n. – Greg Hurst Jan 28 '17 at 15:47
3

This code can be streamlined, but it seems to work:

CheckIfSquare[poly_] := 
 AllTrue[Transpose[Drop[FactorList[poly], 1]][[2]], EvenQ[#]&]

Check:

CheckIfSquare[x^2 - 1]

(* False *)

CheckIfSquare[x^2 - 2 x + 1] 

(* True *)

CheckIfSquare[x^3]

(* False *)

And....

CheckIfSquare[81 - 108 x + 54 x^2 - 12 x^3 + x^4]

(* True *)

...as 81 - 108 x + 54 x^2 - 12 x^3 + x^4 = (x-3)^4

Closely related, based on Daniel Lichtblau:

AllTrue[
 Drop[FactorSquareFreeList[(x + 1)^2 (x - 9)^4], 1]
 [[All, 2]], EvenQ]
David G. Stork
  • 41,180
  • 3
  • 34
  • 96