This is the python script used to do the symbolic calculations that were mentioned in a footnote in article 79649

#!/usr/bin/env python3

# ================================================================
#  This script does symbolic calculations for article 79649
#
#  Written by Randy S (2023)
# ================================================================

import copy
from math import factorial

# https://docs.sympy.org/latest/index.html
from sympy import symbols, Eq, solveset, expand, simplify

dims = 5
maxn = 14

# ===================================================================
def show_term_in_LaTeX( term ):

    output = '&'

    if term['coef'] > 0:
        output += '+'
    output += str( term['coef'] ) + '\\frac{'
    Vexp = 1
    for k in range(len(term['Vfactors'])):
        if Vexp > 1:
            Vexp -= 1
        else:
            output += 'g_{' + str( term['Vfactors'][k] ) + '}'
            Vexp = 1
            while k+Vexp < len(term['Vfactors']) and term['Vfactors'][k+Vexp] == term['Vfactors'][k]:
                Vexp += 1
            if Vexp > 1:
                output += '^{' + str(Vexp) + '}'
    output += '}{(1+g_2)^{' + str( term['Dexp'] ) + '}}'

    print( output )
    print( '\cr')

# ===================================================================
def show_bterms_in_LaTeX( n, terms ):

    print( '\\begin{align*}' )
    print( '\\beta_{' + str(n) + '} &= ' )
    print( '(' + str(n) + ' - ' + str(int(n/2-1)) + 'd)g_{' + str(n) + '} ' )
    print( '\cr')
    for k in range(len(terms)):
        show_term_in_LaTeX( terms[k] )
    print( '\end{align*}' )

# ===================================================================
def has_odds( term ):

    any_odd = False

    for k in range(len(term['Vfactors'])):
        if term['Vfactors'][k] % 2 == 1:
            any_odd = True

    return any_odd

# ===================================================================
def solve_for_highest_g( n, terms ):

    result = []
    for k in range(len(terms)):
        newterm = copy.deepcopy( terms[k] )
        if newterm['Vfactors'][0] > n:
            # replace with the tree-level term
            newterm['Dexp'] = -1
            newterm['coef'] = -(n - int(n/2-1)*dims)
            newterm['Vfactors'] = []
            newterm['Vfactors'].append(n)
        else:
            newterm['Dexp'] -= 1
            newterm['coef'] *= -1
        result.append( newterm )

    return result

# ===================================================================
def discard_odds( terms ):

    result = []
    for k in range(len(terms)):
        if not has_odds( terms[k] ):
            result.append( copy.deepcopy( terms[k] ) )

    return result

# ===================================================================
def take_deriv_of_one_term( term ):

    result = []

    # append the term that comes from the derivative hitting the denominator
    newfactors = copy.deepcopy( term['Vfactors'] )
    newfactors.append(3)
    result.append( {'Dexp': term['Dexp']+1, \
                    'Vfactors': newfactors, \
                    'coef': -term['Dexp'] * term['coef'] } )

    # append the terms that come from the derivative hitting each factor in the numerator
    for k in range(len(term['Vfactors'])):
        newterm = copy.deepcopy( term )
        newterm['Vfactors'][k] = newterm['Vfactors'][k] + 1
        result.append( newterm )

    return result

# ===================================================================
def consolidate_result( result, result_single ):

    for k in range(len(result_single)):
        result_single[k]['Vfactors'].sort( reverse = True )

    for k in range(len(result_single)):
        found_match = False
        for j in range(len(result)):

            if result_single[k]['Vfactors'] == result[j]['Vfactors']:
                # these terms have the same factors, so consolidate them
                result[j]['coef'] += result_single[k]['coef']
                found_match = True
        if not found_match:
            result.append( result_single[k] )

# ===================================================================
def take_deriv( terms ):

    result = []
    for k in range(len(terms)):
        result_single = take_deriv_of_one_term( terms[k] )
        consolidate_result( result, result_single )

    return result

# ===================================================================
def construct_beta_for_SymPy( n, bterms, g ):

    k = int(n/2-1)
    result = (n-k*dims) * g[n]
    for k in range(len(bterms)):
        thisterm = bterms[k]['coef']
        for j in range(bterms[k]['Dexp']):
            thisterm = thisterm/(1+g[2])
        for j in range(len(bterms[k]['Vfactors'])):
            thisterm = thisterm * g[bterms[k]['Vfactors'][j]]
        result = result + thisterm

    return result

# ===================================================================
def do_calculations_with_SymPy( beta, g ):

    # abbreviation
    d = dims

    print( '' )
    for n in range(2,maxn+1,2):
        print( 'beta[' + str(n) + '] = ', beta[n] )

    # solve the equation beta[n] = 0 for g[n+2]
    geqtmp = ['']*(maxn+3)
    for n in range(2,maxn+1,2):
        geqtmp[n+2] = solveset( beta[n], g[n+2] )

    # extract the one-and-only solution in each case
    geq = ['']*(maxn+3)
    geq[2] = g[2]
    for n in range(2,maxn+1,2):
        geq[n+2] = list(geqtmp[n+2])[0]

    print( '' )
    for n in range(2,maxn+1,2):
        print( 'beta[' + str(n) + '] = 0 implies g' + str(n+2) + ' = ', geq[n+2] )

    # express all of the geq's entirely in terms of g2
    for n in range(2,maxn+1,2):
        for k in range(n,2,-2):
            geq[n+2] = geq[n+2].subs( g[k], geq[k] )

    for n in range(2,maxn+1,2):
        geq[n+2] = expand( geq[n+2] )

    print( '' )
    for n in range(2,maxn+1,2):
        print( 'beta[n] = 0 for all n implies g' + str(n+2) + ' = ', geq[n+2] )

    print( '' )
    print( 'h[n]\equiv g[n]/n!' )
    for n in range(2,maxn+1,2):
        print( 'h[' + str(n+2) + '] = ', simplify(geq[n+2]/factorial(n+2)) )

    # calculate ratios to study convergence of the series
    ratio = ['']*(maxn+3)
    for n in range(2,maxn+1,2):
        ratio[n] = simplify( geq[n+2]/(geq[n]*(n+2)*(n+1)) )

    print( '' )
    print( 'r[n]\equiv (g[n+2]/(n+2)!)/(g[n]/n!)' )
    for n in range(2,maxn+1,2):
        print( 'r[' + str(n) + '] = ', ratio[n] )

# ===================================================================
#   Main program

# ---------------------------------
#  Initialize variables for SymPy
#
#  manual version: g = symbols( 'g0 g1 g2 g3 g4 g5 g6' )
# ---------------------------------
g = ['']*(maxn+3)
for n in range(2,maxn+3,2):
    g[n] = symbols( 'g' + str(n) )

beta = ['']*(maxn+1)

# ---------------------------------
#  Initialize my home-grown symbolic calculation
#
#  start with the first derivative of log(D)
# ---------------------------------
terms = [{'Dexp': 1, 'coef': 1, 'Vfactors': [3]}]

# ---------------------------------
#  Construct the beta-functions by
#  calculating higher derivatives iteratively
#  using my home-grown symbolic calculations
# ---------------------------------
for n in range(2,maxn+1):
    terms = copy.deepcopy( take_deriv( terms ) )
    if n%2 == 0:
        #  bterms = terms in \beta_n(\vec g)
        bterms = copy.deepcopy( discard_odds( terms ) )
        show_bterms_in_LaTeX( n, bterms )
        beta[n] = construct_beta_for_SymPy( n, bterms, g )
        print( '' )
        print( '\\begin{verbatim}' )
        print( 'beta[' + str(n) + '] = ', beta[n] )
        print( '\\end{verbatim}' )
        print( '' )

# ---------------------------------
#  Use SymPy to solve the conditions beta[n] = 0
# ---------------------------------
print( '\\begin{verbatim}' )
do_calculations_with_SymPy( beta, g )
print( '\\end{verbatim}' )