LambertW Test 3

S = solve(x^5==5^x, x, to_poly_solve=true) 
tr_expr = S[4].rhs() 
N(tr_expr, digits=50) 

The purpose of the rest of this worksheet is, to act as a future cheat-sheet, for how to wrap Python

functions XYZ into SageMath. 'mpmath' will be used as an example.

from mpmath import mp, nstr, mpmathify, mpf 
from mpmath import lambertw as alambertw, ln as aln 
from sage.libs.mpmath.utils import mpmath_to_sage 
mp.prec = 512; mp.pretty = True 

One type of object which exists in SageMath is, a procedural function, which is

more formally called a Numerical Function. Even though they could take any set of

arguments, their future conversion into symbolic functions places special requirements.

def num_ln(self, x, **kwds): return mpmath_to_sage(aln(mpmathify(x)), 512) 

The version of lambert_w which is native to Sage, takes 2 arguments by default...

def num_lamb(self, x, y, **kwds): return mpmath_to_sage(alambertw(mpmathify(y)), 512) 

The following two Numerical Functions are shown, as an example of what to do, if the wrapped

package doesn't have the equivalent of the 'mpmathify()' function. It could happen, that the Symbolic Function

input, first needs to be approximated as a string.

In this case it's achieved, by not stating that a nested numerical approximation 'N()' should take place.

Because these Numerical Functions are only to be called, once a numerical value has been

requested of SageMath, the parameters of the main numerical approximation will also apply

to the String conversion within the Python Functions...

def num_ln2(self, x, **kwds): var('len') len = mp.dps + 10 convert_in = str(x) return sage_eval(nstr(aln(mpf(convert_in)), len)) 
def num_lamb2(self, x, y, **kwds): var('len') len = mp.dps + 10 convert_in = str(y) return sage_eval(nstr(alambertw(mpf(convert_in)), len)) 


The concept here is, that the numeric-functions-converted-into-symbolic-functions,

don't auto-evaluate. These will only evaluate once numerical answers are required...

Because they don't auto-evaluate, symbolic manipulations on them won't take place...


sym1 = function('sym_ln', nargs=1, evalf_func=num_ln2) 
sym2 = function('sym_lamb', nargs=2, evalf_func=num_lamb2) 


If auto-evaluation was desired, the keyword parameter identifying which Numeric Function to use, would be named

'eval_func' ...

x_expr = tr_expr.substitute_function(log, sym_ln).substitute_function(lambert_w, sym_lamb) 
num_lamb(0, 0, 5) 
num_ln(0, 5) 
N(x_expr, digits=50)