I found that Internal`PolynomialFunctionQ
performs much better than PolynomialQ
.
Here is a huge random polynomial in 12 variables with around 120k terms:
myPoly = Product[(RandomInteger[{-2, 2}] + RandomInteger[{-2, 2}] a +
RandomInteger[{-6, 6}] b + RandomInteger[{-6, 6}] c +
RandomInteger[{-6, 6}] d + RandomInteger[{-6, 6}] e +
RandomInteger[{-2, 2}] f + RandomInteger[{-1, 1}] g +
RandomInteger[{-6, 6}] h + RandomInteger[{-6, 6}] i +
RandomInteger[{-6, 6}] j + RandomInteger[{-6, 6}] k +
RandomInteger[{-1, 1}] l), {go, 1, 8}] // Expand;
Let's make it not a polynomial in a
by replacing the 1000th term with Sin[a]
:
myPoly = ReplacePart[myPoly, 1000 -> Sin[a]];
So, now let's see how Internal`PolynomialFunctionQ
and PolynomialQ
perform:
AbsoluteTiming[Internal`PolynomialFunctionQ[myPoly, a]]
AbsoluteTiming[Internal`PolynomialFunctionQ[myPoly, b]]
AbsoluteTiming[Internal`PolynomialFunctionQ[myPoly, {a, b, c, d, e, f, g, h, i, j, k, l}]]
AbsoluteTiming[Internal`PolynomialFunctionQ[myPoly, {b, c, d, e, f, g, h, i, j, k, l}]]
(* {0.033989, False} *)
(* {0.032627, True} *)
(* {0.056368, False} *)
(* {0.074603, True} *)
and
AbsoluteTiming[PolynomialQ[myPoly, a]]
AbsoluteTiming[PolynomialQ[myPoly, b]]
AbsoluteTiming[PolynomialQ[myPoly, {a, b, c, d, e, f, g, h, i, j, k, l}]]
AbsoluteTiming[PolynomialQ[myPoly, {b, c, d, e, f, g, h, i, j, k, l}]]
(* {3.98786, False} *)
(* {4.00939, True} *)
(* {3.222, False} *)
(* {3.32597, True} *)
It seems like Internal`PolynomialFunctionQ
performs 100 times better than PolynomialQ
when checking for polynomialness in one variable, and about 50 times better for multiple variables.
Is anyone aware of this? Is Internal`PolynomialFunctionQ
a low-level version of PolynomialQ
?
Answer
First note they are not equivalent:
PolynomialQ[x + x[1], x]
Internal`PolynomialFunctionQ[x + x[1], x]
(*
True
False
*)
Second note that PolynomialQ
does a lot of checking:
Trace[
PolynomialQ[x^2 Sin[y], x],
TraceInternal -> True]
If you care to, you can verify that every factor of every term seems to be checked:
With[{e = (a + 2 b + 3 c + 4 y)^2 // Expand},
Trace[
PolynomialQ[e, x],
TraceInternal -> True]
]
What exactly this checking consists of seems to be inaccessible. I've seen Integrate`FakeIntervalElement
before, but I don't know what it's for or why it is used here.
On the OP's example, 600,000 expressions are checked, I suppose:
Count[myPoly, a | b | c | d | e | f | g | h | i | j | k | l, Infinity]
(* 602194 *)
Probably Internal`PolynomialFunctionQ
is meant for a narrower range of use and goes straight to work on determining whether the variables appear only in nonnegative powers, etc.
Comments
Post a Comment