def get_tf_scalar_evaluator(): return scalar_sector.get_scalar_manifold_evaluator( to_scaled_constant=( lambda x, scale=1: tf.constant(numpy.array(x) * scale)), expm=tf_cexpm.cexpm, einsum=tf.einsum, eye=lambda n: tf.constant(numpy.eye(n), dtype=tf.complex128), trace=tf.linalg.trace, concatenate=lambda ts: tf.concat(ts, 0), complexify=lambda a: tf.cast(a, tf.complex128), re=tf.math.real, im=tf.math.imag, conjugate=tf.math.conj)
mpmath.mpf.shape = () mpmath.mpc.shape = () # Observe that our E7-definitions have 'numerically exact' structure constants. # # So, it actually makes sense to take these as defined, and lift them to mpmath. # # >>> set(e7.t_a_ij_kl.reshape(-1)) # >>> {(-2+0j), (-1+0j), -2j, -1j, 0j, 1j, 2j, (1+0j), (2+0j)} # `mpmath` does not work with numpy.einsum(), so for that reason alone, # we use opt_einsum's generic-no-backend alternative implementation. mpmath_scalar_manifold_evaluator = scalar_sector.get_scalar_manifold_evaluator( frac=lambda p, q: mpmath.mpf(p) / mpmath.mpf(q), to_scaled_constant=( lambda x, scale=1: numpy.array( x, dtype=mpmath.ctx_mp_python.mpc) * scale), # Wrapping up `expm` is somewhat tricky here, as it returns a mpmath # matrix-type that numpy does not understand. expm=lambda m: numpy.array(mpmath.expm(m).tolist()), einsum=lambda spec, *arrs: opt_einsum.contract(spec, *arrs), # trace can stay as-is. eye=lambda n: numpy.eye(n) + mpmath.mpc(0), complexify=lambda a: a + mpmath.mpc(0), # re/im are again tricky, since numpy.array(dtype=object) # does not forward .real / .imag to the contained objects. re=lambda a: numpy.array([z.real for z in a.reshape(-1)]).reshape(a.shape), im=lambda a: numpy.array([z.imag for z in a.reshape(-1)]).reshape(a.shape))