Wolfram Computation Meets Knowledge

Limits without Limits in Version 11.2

Limits lead image

Here are 10 terms in a sequence:

Table[(2/(2 n + 1)) ((2 n)!!/(2 n - 1)!!)^2, {n, 10}]

And here’s what their numerical values are:

N[%]

But what is the limit of the sequence? What would one get if one continued the sequence forever?

In Mathematica and the Wolfram Language, there’s a function to compute that:

DiscreteLimit[(2/(2 n + 1)) ((2 n)!!/(2 n - 1)!!)^2, n -> \[Infinity]]

Limits are a central concept in many areas, including number theory, geometry and computational complexity. They’re also at the heart of calculus, not least since they’re used to define the very notions of derivatives and integrals.

Mathematica and the Wolfram Language have always had capabilities for computing limits; in Version 11.2, they’ve been dramatically expanded. We’ve leveraged many areas of the Wolfram Language to achieve this, and we’ve invented some completely new algorithms too. And to make sure we’ve covered what people want, we’ve sampled over a million limits from Wolfram|Alpha.

Let’s talk about a limit that Hardy and Ramanujan worked out in 1918. But let’s build up to that. First, consider the sequence a(n) that is defined as follows:

a[n_] := (-1)^n/n

Here is a table of the first ten values for the sequence.

Table[a[n], {n, 1, 10}]

The following plot indicates that the sequence converges to 0 as n approaches Infinity.

DiscretePlot[a[n], {n, 1, 40}]

The DiscreteLimit function, which was introduced in Version 11.2, confirms that the limit of this sequence is indeed 0.

DiscreteLimit[a[n], n -> \[Infinity]]

Many sequences that arise in practice (for example, in signal communication) are periodic in the sense that their values repeat themselves at regular intervals. The length of any such interval is called the period of the sequence. As an example, consider the following sequence that is defined using Mod.

a[n_] := Mod[n, 6]

A plot of the sequence shows that the sequence is periodic with period 6.

DiscretePlot[a[n], {n, 0, 20}]

In contrast to our first example, this sequence does not converge, since it oscillates between 0 and 5. Hence, DiscreteLimit returns Indeterminate in this case.

DiscreteLimit[a[n], n -> \[Infinity]]

The new Version 11.2 functions DiscreteMinLimit and DiscreteMaxLimit can be used to compute the lower and upper limits of oscillation, respectively, in such cases. Thus, we have:

DiscreteMinLimit[a[n], n -> \[Infinity]]

DiscreteMaxLimit[a[n], n -> \[Infinity]]

DiscreteMinLimit and DiscreteMaxLimit are often referred to as “lim inf” and “lim sup,” respectively, in the mathematical literature. The traditional underbar and overbar notations for these limits are available, as shown here.

 \!\(\*UnderscriptBox[\(\[MinLimit]\), \(n\* UnderscriptBox["\[Rule]",  TemplateBox[{}, "Integers"]]\[Infinity]\)]\) a[n]

 \!\(\*UnderscriptBox[\(\[MaxLimit]\), \(n\* UnderscriptBox["\[Rule]",  TemplateBox[{}, "Integers"]]\[Infinity]\)]\) a[n]

Our next example is an oscillatory sequence that is built from the trigonometric functions Sin and Cos, and is defined as follows.

a[n_] := Sin[2 n]^2/(2 + Cos[n])

Although Sin and Cos are periodic when viewed as functions over the real numbers, this integer sequence behaves in a bizarre manner and is very far from being a periodic sequence, as confirmed by the following plot.

DiscretePlot[a[n], {n, 1, 100}]

Hence, the limit of this sequence does not exist.

DiscreteLimit[a[n], n -> \[Infinity]]

However, it turns out that for such “densely aperiodic sequences,” the extreme values can be computed by regarding them as real functions. DiscreteMinLimit uses this method to return the answer 0 for the example, as expected.

DiscreteMinLimit[a[n], n -> \[Infinity]]

Using the same method, DiscreteMaxLimit returns a rather messy-looking result in terms of Root objects for this example.

DiscreteMaxLimit[a[n], n -> \[Infinity]]

The numerical value of this result is close to 0.8, as one might have guessed from the graph.

N[%]

Discrete limits also occur in a natural way when we try to compute the value of infinitely nested radicals. For example, consider the problem of evaluating the following nested radical.

Nested radical

The successive terms in the expansion of the radical can be generated by using RSolveValue, since the sequence satisfies a nonlinear recurrence. For example, the third term in the expansion is obtained as follows.

RSolveValue[{r[n + 1] == Sqrt[2 + r[n]], r[1] == Sqrt[2]}, r[3], n]

The value of the infinitely nested radical appears to be 2, as seen from the following plot that is generated using RecurrenceTable.

ListPlot[RecurrenceTable[{r[n + 1] == Sqrt[2 + r[n]],      r[1] == Sqrt[2]}, r[n], {n, 2, 35}]]

Using Version 11.2, we can confirm that the limiting value is indeed 2 by requesting the value r(∞) in RSolveValue, as shown here.

RSolveValue[{r[n + 1] == Sqrt[2 + r[n]], r[1] == 2},   r[\[Infinity]], n]

The study of limits belongs to the branch of mathematics called asymptotic analysis. Asymptotic analysis provides methods for obtaining approximate solutions of problems near a specific value such as 0 or Infinity. It turns out that, in practice, the efficiency of asymptotic approximations often increases precisely in the regime where the corresponding exact computation becomes difficult! A striking example of this phenomenon is seen in the study of integer partitions, which are known to grow extremely fast as the size of the number increases. For example, the number 6 can be partitioned in 11 distinct ways using IntegerPartitions, as shown here.

IntegerPartitions[6] // TableForm

Length[%]

The number of distinct partitions can be found directly using PartitionsP as follows.

PartitionsP[6]

As noted earlier, the number of partitions grows rapidly with the size of the integer. For example, there are nearly 4 trillion partitions of the number 200.

PartitionsP[200]

N[%]

In 1918, Hardy and Ramanujan provided an asymptotic approximation for this number, which is given by the following formula.

asymp[n_] := E^(\[Pi] Sqrt[(2 n)/3])/(4 n Sqrt[3])

The answer given by this estimate for the number 200 is remarkably close to 4 trillion.

asymp[200] // N

With a much larger integer, we get an even better approximation for the number of partitions almost instantaneously, as seen in the following example.

PartitionsP[2000000000] // N // Timing

N[asymp[2000000000] , 20] // Timing

Finally, we can confirm that the asymptotic estimate approaches the number of partitions as n tends to Infinity using DiscreteLimit, which is aware of the Hardy–Ramanujan formula discussed above.

 \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] 0\)]\) Sin[x]/x

Formally, we say that exact and approximate formulas for the number of partitions are asymptotically equivalent as n approaches Infinity.

Asymptotic notions also play an important rule in the study of function limits. For instance, the small-angle approximation in trigonometry asserts that “sin(x) is nearly equal to x for small values of x.” This may be rephrased as “sin(x) is asymptotically equivalent to x as x approaches 0.” A formal statement of this result can be given using Limit, which computes function limits, as follows.

 \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] 0\)]\) Sin[x]/x

This plot provides visual confirmation that the limit is indeed 1.

Plot[Sin[x]/x, {x, -20, 20}, PlotRange -> All]

The above limit can also be calculated using L’Hôspital’s rule by computing the derivatives, cos(x) and 1, of the numerator and denominator respectively, as shown here.

Limit[Cos[x]/1, x -> 0]

L’Hôspital’s rule gives a powerful method for evaluating many limits that occur in practice. However, it may require a large number of steps before arriving at the answer. For example, consider the following limit.

 \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] \[Infinity]\)]\) x^6/E^  x

That limit requires six repeated applications of L’Hôspital’s rule to arrive at the answer 0, since all the intermediate computations give indeterminate results.

Table[ \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] \[Infinity]\)]\) \!\( \*SubscriptBox[\(\[PartialD]\), \({x, n}\)] \*SuperscriptBox[\(x\), \(6\)]\)/ \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] \[Infinity]\)]\) \!\( \*SubscriptBox[\(\[PartialD]\), \({x, n}\)] \*SuperscriptBox[\(E\), \(x\)]\), {n, 0, 10}]

Thus, we see that L’Hôspital’s rule has limited utility as a practical algorithm for finding function limits, since it is impossible to decide when the algorithm should stop! Hence, the built-in Limit function uses a combination of series expansions and modern algorithms that works well on inputs involving exponentials and logarithms, the so-called “exp-log” class. In fact, Limit has received a substantial update in Version 11.2 and now handles a wide variety of difficult examples, such as the following, in a rather comprehensive manner (the last two examples work only in the latest release).

 \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] \[Infinity]\)]\)   Gamma[x + 1/2]/(Gamma[x] Sqrt[x])

 \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] \[Infinity]\)]\) (  Log[x] (-Log[Log[x]] + Log[Log[x] + Log[Log[x]]]))/  Log[Log[x] + Log[Log[Log[x]]]]

 \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] \[Infinity]\)]\) E^E^E^  PolyGamma[PolyGamma[PolyGamma[x]]]/x

 \!\(\*UnderscriptBox[\(\[Limit]\), \(x \[Rule] \[Infinity]\)]\)   E^(E^x + x^2) (-Erf[E^-E^x - x] - Erf[x])

As in the cases of sequences, the limits of periodic and oscillatory functions will often not exist. One can then use MaxLimit and MinLimit, which, like their discrete counterparts, give tight bounds for the oscillation of the function near a given value, as in this classic example.

f[x_] := Sin[1/x]

Plot[f[x], {x, -1, 1}]

The graph indicates the function oscillates rapidly between –1 and 1 near 0. These bounds are confirmed by MaxLimit and MinLimit, while Limit itself returns Indeterminate.

{Limit[f[x], x -> 0], MinLimit[f[x], x -> 0], MaxLimit[f[x], x -> 0]}

In the previous example, the limit fails to exist because the function oscillates wildly around the origin. Discontinuous functions provide other types of examples where the limit at a point may fail to exist. We will now consider an example of such a function with a jump discontinuity at the origin and other values. The function is defined in terms of SquareWave and FresnelS, as follows.

g[x_] := (SquareWave[x] FresnelS[x])/x^3

This plot shows the jump discontinuities, which are caused by the presence of SquareWave in the definition of the function.

Plot[{g[x], -Pi/6, Pi/6}, {x, -2, 2},   ExclusionsStyle -> Directive[Red, Dashed]]

We see that the limiting values of the function at 0, for instance, depend on the direction from which we approach the origin. The limiting value from the right (“from above”) can be calculated using the Direction option.

Limit[g[x], x -> 0, Direction -> "FromAbove"]

Similarly, the limit from the left can be calculated as follows.

Limit[g[x], x -> 0, Direction -> "FromBelow"]

The limit, if it exists, is the “two-sided” limit for the function that, in this case, does not exist.

Limit[g[x], x -> 0, Direction -> "TwoSided"]

By default, Limit computes two-sided limits in Version 11.2. This is a change from earlier versions, where it computed the limit from above by default. Hence, we get an Indeterminate result from Limit, with no setting for the Direction option.

Limit[g[x], x -> 0]

Directional limits acquire even more significance in the multivariate case, since there are many possible directions for approaching a given point in higher dimensions. For example, consider the bivariate function f(x,y) that is defined as follows.

f[x_, y_] := (x y)/(x^2 + y^2)

The limiting value of this function at the origin is 0 if we approach it along the x axis, which is given by y=0, since the function has the constant value 0 along this line.

f[x, 0]

Similarly, the limiting value of the function at the origin is 0 if we approach it along the y axis, which is given by x=0.

f[0, y]

However, the limit is 1/2 if we approach the origin along the line y=x, as seen here.

f[x, y] /. {y -> x}

More generally, the limiting value changes as we approach the origin along different lines y=m x.

f[x, y] /. {y -> m x} // Simplify

The directional dependence of the limiting value implies that the true multivariate limit does not exist. In Version 11.2, Limit handles multivariate examples with ease, and quickly returns the expected answer Indeterminate for the limit of this function at the origin.

Limit[f[x, y], {x, y} -> {0, 0}]

A plot of the surface z=f(x,y) confirms the behavior of the function near the origin.

Plot3D[f[x, y], {x, -4, 4}, {y, -4, 4}]

This example indicates that, in general, multivariate limits do not exist. In other cases, such as the following, the limit exists but the computation is subtle.

f[x_, y_] := (x^2 + y^2)/(3^(Abs[x] + Abs[y]) - 1)

This plot indicates that the limit of this function at {0,0} exists and is 0, since the function values appear to approach 0 from all directions.

Plot3D[f[x, y], {x, -1, 1}, {y, -1, 1}, PlotRange -> All]

The answer can be confirmed by applying Limit to the function directly.

Limit[f[x, y], {x, y} -> {0, 0}]

A rich source of multivariate limit examples is provided by the steady stream of inputs that is received by Wolfram|Alpha each day. We acquired around 100,000 anonymized queries to Wolfram|Alpha from earlier years, which were then evaluated using Version 11.2 . Here is a fairly complicated example from this vast collection that Limit handles with ease in the latest version.

f[x_, y_] := Cos[Abs[x] Abs[y]] - 1

Plot3D[f[x, y], {x, -3, 3}, {y, -3, 3}]

Limit[f[x, y], {x, y} -> {0, 0}]

It is a sheer joy to browse through the examples from Wolfram|Alpha, so we decided to share 1,000 nontrivial examples from the collection with you. Sample images of the examples are shown below. The five notebooks with the examples can be downloaded here.

Downloadable notebooks

Version 11.2 evaluates 90% of the entire collection in the benchmark, which is remarkable since the functionality for multivariate limits is new in this release.

Limits pie chart

Version 11.2 also evaluates a higher fraction (96%) of an even larger collection of 1,000,000 univariate limits from Wolfram|Alpha when compared with Version 11.1 (94%). The small percentage difference between the two versions can be explained by noting that most Wolfram|Alpha queries for univariate limits relate to a first or second course in college calculus and are easily computed by Limit in either version.

Limit has been one of the most dependable functions in the Wolfram Language ever since it was first introduced in Version 1 (1988). The improvements for this function, along with DiscreteLimit and other new functions in Version 11.2, have facilitated our journey through the world of limits. I hope that you have enjoyed this brief tour, and welcome any comments or suggestions about the new features.


Download this post as a Computable Document Format (CDF) file. New to CDF? Get your copy for free with this one-time download.

Comments

Join the discussion

!Please enter your comment (at least 5 characters).

!Please enter your name.

!Please enter a valid email address.

1 comment

  1. I like your blogs because they concern fundamental mathematics which is the core and the heart of Mathematica.
    Thanks!

    Reply