I'm trying to define a predicate function to identify if the expression is a geometric sequence. This is the function I came up with so far:

geometricSequenceQ[expr_, var_] := Module[{a}, a = (expr /. var -> #) &;
If[FullSimplify[a[1]*(a[2]/a[1])^(var - 1) == a[var],
Assumptions -> var \[Element] Integers && var > 0], True, False]]

But it doesn't seem to work correctly with inputs involving decimals:

In[5]:= geometricSequenceQ[(-1/2)^(5 n), n]
Out[5]= True

(-1/2)^(5 n) is indeed a geometric sequence with the common ratio of (-1/32). However:

In[6]:= geometricSequenceQ[(-0.5)^(5 n), n]
Out[6]= If[(-0.5)^(5 n) == (-0.03125)^n, True, False]

Why is the result different for exact and decimal inputs? Is there other function I can use instead of FullSimplify?

In[12]:= FullSimplify[(-1/2)^(5 n) == (-1/32)^n, 
 Assumptions -> n > 0 && n \[Element] Integers]
Out[12]= True

In[13]:= FullSimplify[(-0.5)^(5 n) == (-1/32)^n, 
 Assumptions -> n > 0 && n \[Element] Integers]
Out[13]= (-0.5)^(5 n) == (-(1/32))^n
  • $\begingroup$ as a workaround, wrap the expression inside FullSimplify in Rationalize $\endgroup$ – george2079 Jun 15 '17 at 15:44
  • $\begingroup$ Yes, it solves the issue with the sequence (-0.5)^(5n). But, for instance, geometricSequenceQ[(E/3.1)^(5 n), n] yields False. $\endgroup$ – roman465 Jun 15 '17 at 15:57
  • 3
    $\begingroup$ Testing for equality of floating point expression is always going to be problematic. You may need to resort to picking a specific value (or perhaps several) for n to test. Even then you might need to use a tolerance on the equality check. $\endgroup$ – george2079 Jun 15 '17 at 16:04
  • $\begingroup$ Have you thought of using pattern matching? `MatchQ[(E 3.3)^(2 n) , Power[a_?NumericQ, Times[n_?IntegerQ, _]]] (* true *). It will take a bit of work to get a pattern to match a few cases. $\endgroup$ – george2079 Jun 15 '17 at 16:10

The problem is that Simplify/FullSimplify don't have a rule to convert $(-0.1)^{5 n}$ to $(-0.00001)^n$ under the assumption that $n\in \mathbb{Z}$. Mathematica does know when it is valid to do so:

PowerExpand[(a^5)^n, Assumptions->True]

a^(5 n) E^(2 I n [Pi] Floor[1/2 - (5 Arg[a])/(2 [Pi])])

In particular, for $n\in \mathbb{Z}$:

PowerExpand[(a^5)^n, Assumptions->n ∈ Integers]

a^(5 n)

Here is a function that inverts PowerExpand for certain classes of Power objects:

InversePowerExpand[x_] := Replace[
    Power[a_Real, n_Integer z_] /; Refine[z ∈ Integers] -> Power[a^n, z]

Now, we can add this transformation function to Simplify/FullSimplify:

    n ∈ Integers,
    Simplify[(-.1)^(5n), TransformationFunctions->{Automatic, InversePowerExpand}]


I use Assuming[assum, Simplify[expr]] instead of the natural Simplify[expr, assum] because the Simplify assumptions don't get transferred to the transformation function InversePowerExpand automatically.

At any rate, for your question:

    n ∈ Integers,
        (-.5)^(5n) == (-1/32)^n,
        TransformationFunctions->{Automatic, InversePowerExpand}



Rationalize real numbers in expr.

geometricSequenceQ[expr_, var_] := 
 Module[{a, expr2 = expr /. z_Real :> Rationalize[z, 0]}, 
  a = (expr2 /. var -> #) &;
  If[FullSimplify[a[1]*(a[2]/a[1])^(var - 1) == a[var], 
    Assumptions -> var ∈ Integers && var > 0], True, False]]

geometricSequenceQ[#, n] & /@
 {(-1/2)^(5 n), (-0.5)^(5 n), (E/3.1)^(5 n)}

(*  {True, True, True}  *)
  • $\begingroup$ Thank you! This works for all sequences I've tested so far, but I don't think it will leave numeric constants (e.g., Pi, E) as exact: (-E*0.5)^(5 n) /. z_Real :> Rationalize[z, 0] results in (-(148561198/109305221))^(5 n), rather than (-E/2)^(5 n). I guess this may cause wrong result for more complex expressions.. Or am I missing something? $\endgroup$ – roman465 Jun 15 '17 at 16:48
  • $\begingroup$ @roman465 - I was mistaken. The division in (E/3.1) gets carried out before the rule gets applied. The change in behavior is the increased precision of Rationalize[#, 0]& compared to just Rationalize $\endgroup$ – Bob Hanlon Jun 15 '17 at 16:58
  • 1
    $\begingroup$ So I wrapped the expression with Unevaluated and set the HoldFirst attribute. Now it works just fine! geometricSequenceQ[expr_, var_] := Module[{a, expr2 = (Unevaluated[expr] /. z_Real :> Rationalize[z, 0])}, a = (expr2 /. var -> #) &; If[FullSimplify[a[1]*(a[2]/a[1])^(var - 1) == a[var], Assumptions -> var \[Element] Integers && var > 0], True, False]] SetAttributes[geometricSequenceQ, HoldFirst] $\endgroup$ – roman465 Jun 15 '17 at 17:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.