Yes, you can pass a function of the form usermethod[expr, k]
to Method
, although I cannot find any documentation for it:
Sum[expr, k, Method -> usermethod]
The specification usermethod
should be a Symbol
or a string. A non-string is passed through ToExpression[ToString[usermethod]]
, so if it is a non-symbol expression, it needs to make the round-trip unaltered. A good way to do this is to use SetOptions
on ToString
to set FormatType -> InputForm
. A string value for usermethod
is passed directly through ToExpression
and putting string quotes around a complicated expression for usermethod
can be an easier way than SetOptions
. See multitest
, lct
and the Update below for examples.
The return values are handled thus:
Result |
Meaning |
True |
Converges |
False |
Diverges |
$Failed |
Indeterminate; SumConvergence unevaluated |
unevaluated |
Indeterminate; SumConvergence unevaluated |
Garbage |
Garbage |
An example of garbage:
foo[expr_, k_] := Umm ...;
SumConvergence[1 - Cos[Pi/n], n, Method -> foo]
(* Umm ... *)
It is as though the test is treated as successful and the user-defined return value is assumed to have some meaning for the user.
Example: Bertrand's test
bertrand[expr_, k_] := Module[{ratio, res},
ratio = Together[(expr /. k -> k + 1)/expr];
res = Limit[Log[k] (k (1/ratio - 1) - 1), k -> Infinity];
res > 1 /; FreeQ[res, Limit | Indeterminate] && res != 1
];
SumConvergence[1 - Cos[Pi/n], n, Method -> bertrand]
(* True *)
The Automatic
method is unsuccessful:
SumConvergence[1 - Cos[Pi/n], n, Method -> Automatic]
(* SumConvergence[1 - Cos[π/n], n, Method -> Automatic] *)
Example: Multiple tests
Unfortunately, one cannot specify a list of methods for SumConvergence[]
to try (even though Automatic
tries many, many tests).
multitest // ClearAll;
multitest[tests_List][expr_, k_] :=
Catch[
With[{res = SumConvergence[expr, k, Method -> #]},
If[FreeQ[res, SumConvergence], Throw@res]] & /@ tests;
$Failed];
SumConvergence[1 - Cos[Pi/n], n,
Method -> "multitest[{Automatic, bertrand}]"]
(* True *)
One limitation on multitest
is that the methods in tests
are passed through ToExpression
/ToString
twice. Since these are not strictly inverse operations, some things are difficult to manage (see below).
Example: Limit Comparison Test
lct // ClearAll;
lct[expr2_][expr_, k_] :=
Module[{res2, res1, res},
res2 = SumConvergence[Abs@expr2, k];
(res1 = Limit[Abs[expr/expr2], k -> Infinity];
res = $Failed;
If[res2 && TrueQ[0 <= res1 < Infinity],
res = True,
If[! res2 && TrueQ[0 < res1 <= Infinity],
res = False]];
res
) /; MatchQ[res2, True | False]
];
SumConvergence[1 - Cos[Pi/n], n, Method -> "lct[1/n^2]"]
(* True *)
Limitations
The following fails, because ToExpression
is called twice:
SumConvergence[1 - Cos[Pi/n], n,
Method -> multitest[{"lct[1/n]", "lct[1/n^2]"}]]
Here's how the second lct
gets clobbered:
ToExpression@ToString@ToExpression@"lct[1/n^2]"
(* lct[n] *)
By the way, ToString[expr, InputForm]
is more reliable....
Update: Fix to the limitations
Finally remembering the obvious, I checked the docs on ToString
, and a workaround stared me in the face: There's an option one set to get ToString
to use InputForm
:
Internal`InheritedBlock[{ToString},
SetOptions[ToString, FormatType -> InputForm];
SumConvergence[1 - Cos[Pi/n], n,
Method -> multitest[{lct[1/n], lct[1/n^2]}]]]
(* True *)