Skip to main content

calculus and analysis - How do I obtain the correct double limit?


The command


Limit[(Sin[x^2] + Sin[y^2])/ (x - y) /. x -> 0, y -> 0]
(*

0
*)

I think that Mathematica finds the iterated limit instead of the double limit. It should be noted that WolframAlpha produces the correct answer, when asking for



"limit (sin(x^2)+sin(y^2))/(x-y) as x->0 and y->0"



enter image description here



Answer



Let



f = (Sin[x^2] + Sin[y^2])/(x - y)

be the function in question.


As pointed out in the answers to this question, finding multivariable limits automatically computationally is full of pitfalls. The idea behind the function lim in this answer was to use Maximum and Minimum to find bounds on the function and apply the squeeze theorem. It fails here because Maximum and Minimum fail on f. However the concept is sound. The first two methods below apply this concept. A third method of testing for nonexistence is included at the end.



A nonrigorous way to go is to get numerical evidence.


NMaximize[{f, -0.01 < x < 0.01 && -0.01 < y < 0.01}, {x, y}]


NMaximize::cvdiv: Failed to converge to a solution. The function may be unbounded. >>


{1.53512*10^13, {x -> 0.00893814, y -> 0.00893814}}

NMinimize[f, -0.01 < x < 0.01 && -0.01 < y < 0.01}, {x, y}]


NMinimize::cvdiv: Failed to converge to a solution. The function may be unbounded. >>

{-2.44609*10^11, {x -> -0.0085679, y -> -0.0085679}}


It appears the function diverges. How close to {0, 0} to restrict {x, y} would have to be decided in each particular case.


One can automatically check smaller and smaller neighborhoods:


limitExistQ[f_, vars_, point_, epsilon_: 0.001, delta0_: 0.1] :=
Module[{notExists},
NestWhile[#/10 &,
delta0,
(notExists =
First @ NMaximize[{f, And @@ MapThread[Less, {point - #, vars, point + #}]}, vars] -
First @ NMinimize[{f, And @@ MapThread[Less, {point - #, vars, point + #}]}, vars] >= epsilon) &,
1, 5];

! notExists]

Example:


limitExistQ[f, {x, y}, {0, 0}]


NMaximize::cvdiv: Failed to converge to a solution. The function may be unbounded. >>
NMinimize::cvdiv: Failed to converge to a solution. The function may be unbounded. >>
,,,


False

It is still only approximate, as can be seen from varying epsilon and delta0 in the following limit, which exists:


limitExistQ[(x^3 + y^3)/(x^2 + y^2), {x, y}, {0, 0}]


True

limitExistQ[(x^3 + y^3)/(x^2 + y^2), {x, y}, {0, 0}, 10^-6]



False

limitExistQ[(x^3 + y^3)/(x^2 + y^2), {x, y}, {0, 0}, 10^-6, 0.001]


True


Sometimes, the method in the referenced answer can be adapted by substituting Taylor polynomial approximations to the numerator or denominator of the function, since rational functions are easier to deal with than transcendental or algebraic functions. For it to be rigorous, you have to know (be able to prove) that the limit of the approximation is the same as the limit of the function.



For instance, one might know how to bound the error of the Taylor approximation and deduce that the error is negligible. In the case of the function in the question, there is in the numerator Sin[x^2], whose Taylor series at x == 0 is alternating and absolutely decreasing for Abs[x] < 1. It follows that the numerator of f is bounded successive Taylor polynomials (for example, of degrees 2 and 6 in this case).


Below is code for handling such cases. The first functions replace the numerator and/or the denominator with a Taylor polynomial approximation, unless it is already a polynomial or the degree specified is Infinity. The variable deg in getApproximations is a list of two degrees: the degree to be used for approximating the function to be maximized, typically a lower bound, and the degree to be used for approximating the function to be minimized, typically an upper bound. (If one wants different degrees for the numerators and denominators, adapt as desired.)


  (* does not expand polynomials -- change if desired *)
makeApproximation[f0_, deg0_, vars_, centers_] :=
If[deg0 === Infinity || PolynomialQ[f0, vars], f0,
Normal@Series[f0,
Sequence @@ MapThread[{#1, #2, deg0} &, {vars, centers}]]
];
getApproximations[f_, deg_List, vars_, centers_] :=
Module[{num, den, minNum, maxNum, minDen, maxDen},

{num, den} = {Numerator[#], Denominator[#]} &@Together[f];
{minNum, maxNum} = makeApproximation[num, #, vars, centers] & /@ deg;
{minDen, maxDen} = makeApproximation[den, #, vars, centers] & /@ deg,
{minNum, maxNum, minDen, maxDen}
];

The modification to use polynomial approximations is as follows. The Print statements are included to reveal a little of what's going on and may be omitted.


serlim[f0_, deg_, vars_List -> point_List] := 
Module[{lim0, d, max, min, minNum, maxNum, minDen, maxDen},
{minNum, maxNum, minDen, maxDen} = getApproximations[f0, deg, vars, point];

max = Maximize[{maxNum/maxDen,
0 < d < 1 && And @@ MapThread[-d <= #1 - #2 <= d &, {vars, point}]},
vars, Reals];
If[Head[max] === Maximize,(*Maximize failed to find a max*)
Return[$Failed], max = Simplify[First @ max, d > 0];
Print[Row @ {"Max ", max}];
min = Minimize[{minNum/minDen,
0 < d < 1 && And @@ MapThread[-d <= #1 - #2 <= d &, {vars, point}]},
vars, Reals];
If[Head[min] === Minimize,(*Minimize failed to find a min*)

Return[$Failed], min = Simplify[First @ min, d > 0]]];
Print[Row @ {"Min ", min}];
lim0 = Limit[max, d -> 0];
If[lim0 == Limit[min, d -> 0], lim0, "Does not exist."]]

Here is the result of applying it to f


serlim[f, {2, 6}, {x, y} -> {0, 0}]


Max \[Piecewise]   \[Infinity]    d$1011674 < 1

-\[Infinity] True

Min \[Piecewise] -\[Infinity] d$1011674 < 1
\[Infinity] True

"Does not exist."

The approximations being used are constructed from


getApproximations[f, {2, 6}, {x, y}, {0, 0}]



{x^2 + y^2, x^2 - x^6/6 + y^2 - y^6/6, x - y ,  x - y}
(* minNum , maxNum , minDen, maxDen *)

Thus serlim is maximizing the lower bound (x^2 - x^6/6 + y^2 - y^6/6) / (x - y) and minimizing the upper bound (x^2 + y^2) / (x - y). Since they do not converge to the same finite number, the limit does not exist.


Edit: Remark on the present case. In fact, for −1<x,y<1, x≠y, we can easily deduce that our function lies between (x2+y2)/[3(x−y)] and (x2+y2)/(x−y). If (x2+y2)/(x−y) goes to infinity then both bounds go to infinity and f with them. Hence this somewhat faster calculation may be used to determine the limit does not exist:


serlim[f, {2, 2}, {x, y} -> {0, 0}]


This will work sometimes. We find the curve along which the denominator is zero, and approach along various paths approaching the curve. It is reliable if it finds the limit does not exist, but otherwise it is unreliable.



rule = Reduce[1/f == 0, {x, y}] // ToRules // First


y -> x

If[Equal @@ #, First[#], "Does not exist."] &@
With[{sub = First[rule] -> Last[rule] + delta},
Table[
Limit[f /. sub /. {x -> t, y -> t}, t -> 0],
{delta, {t, t^2, t^5, t^10, E^(-1/t^2)}}]]



"Does not exist."

Solve might be used in place of Reduce. Sometimes there may be many solutions corresponding to many curves where the denominator is zero; the code above would have to be adapted to handle such cases.


Comments

Popular posts from this blog

mathematical optimization - Minimizing using indices, error: Part::pkspec1: The expression cannot be used as a part specification

I want to use Minimize where the variables to minimize are indices pointing into an array. Here a MWE that hopefully shows what my problem is. vars = u@# & /@ Range[3]; cons = Flatten@ { Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; Minimize[{Total@((vec1[[#]] - vec2[[u[#]]])^2 & /@ Range[1, 3]), cons}, vars, Integers] The error I get: Part::pkspec1: The expression u[1] cannot be used as a part specification. >> Answer Ok, it seems that one can get around Mathematica trying to evaluate vec2[[u[1]]] too early by using the function Indexed[vec2,u[1]] . The working MWE would then look like the following: vars = u@# & /@ Range[3]; cons = Flatten@{ Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; NMinimize[ {Total@((vec1[[#]] - Indexed[vec2, u[#]])^2 & /@ R...

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

What is and isn't a valid variable specification for Manipulate?

I have an expression whose terms have arguments (representing subscripts), like this: myExpr = A[0] + V[1,T] I would like to put it inside a Manipulate to see its value as I move around the parameters. (The goal is eventually to plot it wrt one of the variables inside.) However, Mathematica complains when I set V[1,T] as a manipulated variable: Manipulate[Evaluate[myExpr], {A[0], 0, 1}, {V[1, T], 0, 1}] (*Manipulate::vsform: Manipulate argument {V[1,T],0,1} does not have the correct form for a variable specification. >> *) As a workaround, if I get rid of the symbol T inside the argument, it works fine: Manipulate[ Evaluate[myExpr /. T -> 15], {A[0], 0, 1}, {V[1, 15], 0, 1}] Why this behavior? Can anyone point me to the documentation that says what counts as a valid variable? And is there a way to get Manpiulate to accept an expression with a symbolic argument as a variable? Investigations I've done so far: I tried using variableQ from this answer , but it says V[1...