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 *)
lct /: Format[lct[x_], OutputForm] := InputForm[lct[x]]– Carl Woll May 29 '22 at 23:02FormataffectedToStringbut didn't put it together withInputFormandOutputForm. – Michael E2 May 30 '22 at 02:08