# Import python modules
import os,sys,copy,itertools,re
import numpy as np
[docs]def groupsort(groups,args):
'''
Get unique args from groups and sort in same order as in args
'''
sort = [v for v in args]
sets = {u:[v for v in groups if groups[v] == u] for u in set([groups[v] for v in groups])}
groups = list(sorted(sets,key=lambda u: min([sort.index(v) if v in sort else len(sort)+list(sets).index(u)
for v in sets[u]])))
return groups
[docs]def icombinations(iterable,n,unique=False):
'''
Get all combinations of p number of non-negative integers that sum up to at most n
Args:
iterable (iterable): Number of integers or iterable of length p
n (int,iterable): Maximum number of elements, or allowed number of elements
unique (bool): Return unique combinations of integers and q = choose(p+n,n) else q = (p^(n+1)-1)/(p-1)
Returns:
combinations (list): All combinations of iterable with q list of lists of length up to n, or lengths in n
'''
iterable = list(iterable)
p = len(iterable)
n = range(n+1) if isinstance(n,(int,np.integer)) else n
combinations = []
for i in n:
combos = list((tuple(sorted(j,key=lambda i:iterable.index(i))) for j in itertools.product(iterable,repeat=i)))
if unique:
combos = sorted(set(combos),key=lambda i:combos.index(i))
combinations.extend(combos)
return combinations
[docs]def findstring(string,strings,types,prefixes,labels,replacements,default=None,regex=False,usetex=True):
'''
Check if string in strings dictionary
Args:
string(str): String to be checked if in strings dictionary
strings(dict): Dictionary of string keys with replacement strings values
types(dict): Dictionary of variable types that strings may start with, with template values in order to determine how to render strings
prefixes(dict): Dictionary of prefix types that strings may start with, with template values in order to determine how to render strings
labels(dict): Dictionary of label prefixes for string templates to render strings
default (str,None): default return value if string not in strings
regex (bool): perform regex processing to find string pattern in strings
Returns:
Returned string based on logic of whether string is in strings
'''
if default is None:
default = string
latex = None
func = lambda string,latex,iloc,labels,strings:latex
iloc = None
funcs = []
ilocs = []
prefixs = []
_string = string
isprefix = any([string.startswith('%s%s'%(prefix,DELIMITER)) for prefix in prefixes])
# print('finding',string,isprefix)
while(isprefix):
for prefix in prefixes:
if string.startswith(prefix):
func = prefixes[prefix]
# print('startswith',prefix,func)
if DELIMITER in string:
iloc = string.split(DELIMITER)[1]
string = DELIMITER.join(string.split(DELIMITER)[2:])
else:
iloc = ''
#print('modified',string,iloc)
prefixs.append(prefix)
funcs.append(func)
ilocs.append(iloc)
isprefix = any([string.startswith('%s%s'%(prefix,DELIMITER)) for prefix in prefixes])
prefixs = prefixs[::-1]
funcs = funcs[::-1]
ilocs = ilocs[::-1]
# print(ilocs)
for typed in types:
for label in types[typed]:
# print('Trying',string,typed,label,string in types[typed][label])
if string in types[typed][label] and (any([p==typed or '%ss'%(p)==typed for p in prefixs]) or (len(prefixs)==0) or all([(p not in types) and ('%ss'%(p) not in types) for p in prefixs])):
latex = types[typed][label][string]
# print('found latex',typed,label,latex)
if latex is not None:
break
if latex is not None:
break
if latex is None:
latex = strings.get(string,string)
typed = None
label = None
#print('final latex',latex)
for func,iloc in zip(funcs,ilocs):
latex = func(string,latex,iloc,labels,strings)
_latex = latex
for t in replacements:
latex = latex.replace(t,replacements[t])
#print('returning',latex)
if not regex:
return latex
for string in strings:
restring = re.compile(r'%s'%(string))
restring = restring.search(string)
try:
restring = restring.group(0)
except:
continue
try:
parser = strings.get(string)
if not callable(parser):
replacement = parser
parser = lambda s:s
else:
replacement = string
return parser(re.sub(string,result,string))
except:
return string
return default
[docs]def isnumber(s):
'''
Check if object is a float or integer number
Args:
s(object): Object to be checked as number
Returns:
Boolean of whether object s is a number
'''
try:
s = float(s)
return True
except:
try:
s = int(s)
return True
except:
return False
[docs]def scinotation(number,decimals=2,base=10,order=2,zero=True,scilimits=[-1,1],usetex=True):
'''
Put number into scientific notation string
Args:
number (str,int,float): Number to be processed
decimals (int): Number of decimals in base part of number
base (int): Base of scientific notation
order (int): Max power of number allowed for rounding
zero (bool): Make numbers that equal 0 be the int representation
scilimits (list): Limits on where not to represent with scientific notation
usetex (bool): Render string with Latex
Returns:
String with scientific notation format for number
'''
if not isnumber(number):
return str(number)
try:
number = int(number) if int(number) == float(number) else float(number)
except:
string = number
return string
maxnumber = base**order
if number > maxnumber:
number = number/maxnumber
if int(number) == number:
number = int(number)
string = str(number)
if zero and number == 0:
string = '%d'%(number)
elif isinstance(number,(int,np.integer)):
string = str(number)
# if usetex:
# string = r'\textrm{%s}'%(string)
elif isinstance(number,(float,np.float)):
string = '%0.*e'%(decimals,number)
string = string.split('e')
basechange = np.log(10)/np.log(base)
basechange = int(basechange) if int(basechange) == basechange else basechange
flt = string[0]
exp = str(int(string[1])*basechange)
if int(exp) in range(*scilimits):
flt = '%0.*f'%(decimals,float(flt)/(base**(-int(exp))))
string = r'%s'%(flt)
else:
string = r'%s%s'%(flt,r'\cdot %d^{%s}'%(base,exp) if exp!= '0' else '')
if usetex:
string = r'%s'%(string.replace('$',''))
else:
string = string.replace('$','')
return string
# Texify strings
[docs]class Texify(object):
'''
Render strings as Latex strings
Args:
texstrings(dict): Dictionary of text strings with Latex string values
texargs(dict): Dictionary of arguments and settings used in Latex rendering
texlabels(dict): Dictionary of modifier strings for Latex rendering
labels(dict): Dictionary of label prefixes for string templates for Latex rendering
usetex(bool): Render as Latex strings, or render as text strings
'''
def __init__(self,texstrings={},texargs={},texlabels={},usetex=True):
args_default = {
'bases':{'monomial':1,'polynomial':0,'taylorseries':1,'derivative':1,'expansion':1},
'order':2,
'basis':3,
'selection':tuple(range(1+1)),
'iloc':[0,None],
'unique':True,
'operators':['partial','delta','Delta','d'],
'weights':['stencil'],
'inputs': {'%s%d'%(x,i):r'{%s_{%d}}'%(x,i) for x in ['x'] for i in range(5)},
'outputs': {'%s%d'%(x,i):r'{%s_{%d}}'%(x,i) for x in ['y'] for i in range(3)},
'terms': {'%s%d'%(x,i):r'{%s_{%d}}'%(x,i) for x in ['x'] for i in range(3)},
# 'groups':{**{'%s%d'%(x,i):r'{%s_{%d}}'%(x,i) for x in ['x'] for i in range(5)}},
'constants':{},
'texreplacements':{r'\\\\':'\\\\'},
'replacements':{DELIMITER:'',r'\\\\':'','\\':'','textrm':'','_':r'\_','^{}':'','^':r'\^~',
r'frac':'',r'}{{delta':r'}/{{delta',r'}{{partial':r'}/{{partial','abs':''},
}
args_special = {'inputs':{},'outputs':{},'constants':{},'order':1,'basis':1}
args_keyed = ['iloc']
args_dependent = {'groups': lambda args:groupsort(args.get('groups',{x: args['inputs'].get(x) for x in args['inputs']}),args['inputs']),
'selection': lambda args: tuple(range(args['order'] if not isinstance(args.get('selection'),(int,np.integer)) else args.get('selection')+1)) if not isinstance(args.get('selection'),(np.ndarray,list)) else args['selection'] }
args = {}
args.update(texargs)
args.update({k:v for k,v in args_default.items() if k not in args})
args.update({k:v for k,v in args_special.items() if args.get(k) is None})
args.update({k: list(set([i for u in (args.get(k,{}) if isinstance(args.get(k),dict) else ([i for i in args.get(k,[])] if isinstance(args.get(k),list) else [args.get(k)]))
for i in ((args.get(k,{}).get(u) if (
isinstance(args.get(k,{}).get(u),(list,tuple,np.ndarray))) else (
[args.get(k,{}).get(u)])) if isinstance(args.get(k),dict) else ([i for i in args.get(k,[])] if isinstance(args.get(k),list) else [args.get(k)]))]))
for k in args_keyed})
for k in args_dependent:
args[k] = args_dependent[k](args)
# Modifying
labels = {
'abs': r'{\abs{%s}}',
'bar': r'{\bar{%s}}',
'tilde': r'{\tilde{%s}}',
'hat': r'{\hat{%s}}',
'brackets':r'{(%s)}',
'leftrightbrackets':r'{\left({%s}\right)}',
'squarebrackets':r'{[{%s}]}',
'leftrightsquarebrackets':r'{\left[{%s}\right]}',
'curlybrackets':r'{\{{%s}\}}',
'leftrightcurlybrackets':r'{\left\{{%s}\right\}}',
'superscript':r'{%s}^{%s}',
'subscript':r'{%s}_{%s}',
'supersubscript':r'{%s}_{%s}^{%s}',
'partial':r'\partial',
'func':r'%s(%s)',
'd': r'd',
'delta':r'\delta',
'Delta':r'\Delta',
'gamma':r'\gamma',
'derivative':r'{\frac{{%s}^{%s}%s}{%s {%s}^{%s}}}',
'nderivative':r'{\frac{{%s}^{%s}%s}{%s}}',
'coefficient': r'{%s}^{%s}',
'factorial': r'{%s!}'
}
labels.update(texlabels)
prefixes = {
'variable': lambda string,latex,iloc,labels,strings: latex,
'constant': lambda string,latex,iloc,labels,strings: labels['func']%(latex,'%s'%(','.join(['{%s}_{%s}'%(v,str(iloc) if iloc not in [None,'None',str(None)] else '') for v in args['groups']]))),
'subscript': lambda string,latex,iloc,labels,strings: r'{%s}_{%s}'%(latex,str(iloc)),
'superscript': lambda string,latex,iloc,labels,strings: r'{%s^{%s}'%(latex,str(iloc)),
'monomial': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex),
'polynomial': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex),
'chebyshev': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex),
'legendre': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex),
'hermite': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex),
'expansion': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex.replace('True',str(iloc) if iloc not in [None,'None',str(None)] else '')),
'taylorseries': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex.replace('True',str(iloc) if iloc not in [None,'None',str(None)] else '')),
'derivative': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex),
'difference': lambda string,latex,iloc,labels,strings: r'{%s}'%(latex),
'deltavar': lambda string,latex,iloc,labels,strings: r'%s{%s}'%(labels['delta'],latex),
'Deltavar': lambda string,latex,iloc,labels,strings: r'%s{%s}'%(labels['Delta'],latex),
'coefficient': lambda string,latex,iloc,labels,strings: labels['coefficient']%(labels['gamma'],latex),
'factorial': lambda string,latex,iloc,labels,strings: labels['factorial']%(str(iloc)),
'iteration': lambda string,latex,iloc,labels,strings: r'{%s}^{(%s)}'%(latex,iloc),
}
# Types
def variables(variable,strings,args,labels,usetex):
'''
Variable string patterns
Args:
variable(str,list): Type of variable for variables (inputs,outputs,terms)
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of label prefixes for string templates for Latex rendering
Returns:
Dictionary of rendered string patterns
'''
if isinstance(variable,str):
variables = {x: strings.get(x,args[variable][x]) for x in args[variable]}
else:
variables = {x: strings.get(x,args[v][x]) for v in variable for x in args[v]}
func = labels['superscript']
values = variables
return values
def constants(variable,strings,args,labels,usetex):
'''
Variable string patterns
Args:
variable(str,list): Type of variable for constants (inputs,outputs,terms)
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
prefix__iloc__variable
with prefixes
[constant]
which becomes
variable
'''
if isinstance(variable,str):
variables = {x: strings.get(x,args[variable][x]) for x in args[variable]}
else:
variables = {x: strings.get(x,args[v][x]) for v in variable for x in args[v]}
func = labels['superscript']
values = variables
return values
def derivative(symbol,strings,args,labels,usetex):
'''
Derivative string patterns
Args:
symbol(str): String key for labels on which derivative symbol to use (partial,delta,Delta)
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
operation_0__operation_1__...__operation_order-1__order__function__variable_0__variable_1__...__variable_order-1__weight_0__weight_1__...__weight_order-1
which becomes
\frac{operation function}{operation_0 variable_0 ... operation_order-1 variable_order-1} operation order_0 variable_0 ... operation_order-1 variable_order-1
'''
inputs = {x: strings.get(x,args['inputs'][x]) for x in args['inputs']}
outputs = {y: strings.get(y,args['outputs'][y]) for y in args['outputs']}
delimiter = DELIMITER
func = labels['nderivative']
Symbol = labels[symbol]
values = {}
if args['bases'].get('derivative'):
values = {
delimiter.join([
delimiter.join([o]*j),
str(j),
y,
delimiter.join([u for u in x]),
delimiter.join([w]*j)
]):func%(Symbol,str(j) if j>1 else '','%s'%(outputs[y]),
' '.join([r'%s %s'%(Symbol,inputs[v]) for v in x]) if len(set([v for v in x]))>1 else r'{%s %s}^{%s}'%(Symbol,inputs[[v for v in x][0]],str(j) if j>1 else ''),
)if usetex else (
'd^%s%s/%s'%(str(j) if j>1 else '',y,''.join(['d%s'%(v) for v in x]))
)
for o in [o for o in args['operators'] if o in [symbol]]
for j in range(1,args['order']+1)
for y in outputs
for x in icombinations(inputs,[j],unique=args['unique'])
for w in args['weights']
}
return values
def expansion(iloc,symbol,Symbol,strings,args,labels,usetex):
'''
Expansion string patterns
Args:
iloc(int,None): location of Expansion
symbol(str): String key for labels on which derivative symbol to use (partial,delta,Delta)
symbol(str): String key for labels on which delta symbol to use (partial,delta,Delta)
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
prefix__iloc__operation_0__operation_1__...__operation_order-1__order__function__variable_0__variable_1__...__variable_order-1__weight_0__weight_1__...__weight_order-1
with prefixes
[expansion]
which becomes
\frac{operation function}{operation_0 variable_0 ... operation_order-1 variable_order-1} operation order_0 variable_0 ... operation_order-1 variable_order-1
'''
inputs = {x: strings.get(x,args['inputs'][x]) for x in args['inputs']}
outputs = {y: strings.get(y,args['outputs'][y]) for y in args['outputs']}
delimiter = DELIMITER
func = labels['nderivative']
symbol = labels[symbol]
Symbol = labels[Symbol]
values = {}
if args['bases'].get('expansion'):
values.update({
delimiter.join([
delimiter.join([o]*j),
str(j),
y,
delimiter.join([u for u in x]),
delimiter.join([w]*j)
]):('%s'%(
func%(
symbol,
str(j) if j>1 else '',
'%s%s'%(outputs[y],'(%s)'%(','.join(['{%s}_{%s}'%(v,str(iloc) if iloc is not None else '') for v in args['groups']]))),
' '.join([r'{%s %s}^{%s}'%(symbol,inputs[v],str(i) if i>1 else '') for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))]))
) if usetex else (
'd^%s%s/%s'%(
str(j) if j>1 else ''),
y,
''.join(['d%s'%(v) for v in x]),
))
for o in args['operators']
for j in range(1,args['order']+1)
for y in outputs
for x in icombinations(inputs,[j],unique=args['unique'])
for w in args['weights']
})
return values
def taylorseries(iloc,symbol,Symbol,strings,args,labels,usetex):
'''
Taylorseries string patterns
Args:
iloc(int,None): location of Taylorseries
symbol(str): String key for labels on which derivative symbol to use (partial,delta,Delta)
symbol(str): String key for labels on which delta symbol to use (partial,delta,Delta)
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
prefix__iloc__operation_0__operation_1__...__operation_order-1__order__function__variable_0__variable_1__...__variable_order-1__weight_0__weight_1__...__weight_order-1
with prefixes
[taylorseries]
which becomes
\frac{1}{order !} \frac{operation function}{operation_0 variable_0 ... operation_order-1 variable_order-1} operation order_0 variable_0 ... operation_order-1 variable_order-1
'''
inputs = {x: strings.get(x,args['inputs'][x]) for x in args['inputs']}
outputs = {y: strings.get(y,args['outputs'][y]) for y in args['outputs']}
delimiter = DELIMITER
func = labels['nderivative']
symbol = labels[symbol]
Symbol = labels[Symbol]
values = {}
if args['bases'].get('taylorseries'):
values.update({
delimiter.join([
delimiter.join([o]*j),
str(j),
y,
delimiter.join([u for u in x]),
delimiter.join([w]*j)
]):('%s%s%s'%(
(r'%s%s'%(
(labels['coefficient']%(labels['gamma'],
''.join([r'{{%s}^{%s}}'%(inputs[v],str(i) if i>1 else '')
for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))]))),
(r'\frac{1}{%s}'%(''.join([labels['factorial']%(i) if i > 1 else '' for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))])
if args['unique'] else labels['factorial']%(j))
if (j>1 and ((not args['unique']) or any([i!=1 for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))]))) else '')
)) if j>0 else '',
func%(
symbol,
str(j) if j>1 else '',
'%s%s'%(outputs[y],'(%s)'%(','.join(['{%s}_{%s}'%(v,str(iloc) if iloc is not None else '') for v in args['groups']]))),
' '.join([r'{%s %s}^{%s}'%(symbol,inputs[v],str(i) if i>1 else '') for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))])),
' '.join([r'{%s %s}^{%s}'%(Symbol,inputs[v],str(i) if i>1 else '') for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))
])
) if usetex else (
'%s d^%s%s/%s %s'%(
('%s**{%s} %s'%(
'g',
''.join([r'{{%s}^{%s}}'%(inputs[v],str(i) if i>1 else '')
for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))]),
(r'1/%s'%(''.join([labels['factorial']%(i) if i > 1 else '' for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))])
if args['unique'] else labels['factorial']%(j)) if (j>1 and ((not args['unique']) or any([i!=1 for i,v in sorted([(list(x).count(v),v) for v in set([v for v in x])],key=lambda v:list(x).index(v[1]))]))) else '') if j>0 else ''
) if j>0 else ''),
str(j) if j>1 else '',
y,
''.join(['d%s'%(v) for v in x]),
' '.join(['d%s'%(v) for v in x])
)))
for o in args['operators']
for j in range(1,args['order']+1)
for y in outputs
for x in icombinations(inputs,[j],unique=args['unique'])
for w in args['weights']
})
# values.update({
# delimiter.join([
# delimiter.join([o]*j),
# str(j),
# y,
# delimiter.join([u for u in x]),
# delimiter.join([w]*j)
# ]):'%s%s%s'%(
# r'%s\frac{1}{%s}'%(labels['coefficient']%(labels['gamma'],''.join([r'%s'%(inputs[v]) for v in x]) if len(set([v for v in x]))>1 else r'{%s}^{%s}'%(inputs[[v for v in x][0]],str(j) if j>1 else '')
# ),''.join([labels['factorial']%(i) if i > 1 else '' for i in [list(x).count(v) for v in set([v for v in x])]]) if args['unique'] else labels['factorial']%(j)) if (j>1 and ((not args['unique']) or any([i!=1 for i in [list(x).count(v) for v in set([v for v in x])]]))) else (
# labels['coefficient']%(labels['gamma'],''.join([r'%s'%(inputs[v]) for v in x]) if len(set([v for v in x]))>1 else r'{%s}^{%s}'%(inputs[[v for v in x][0]],str(j) if j>1 else ''))),
# func%(symbol,str(j) if j>1 else '','%s%s'%(outputs[y],'(%s)'%(','.join(['{%s}_{%s}'%(v,str(iloc) if iloc is not None else '') for v in args['groups']]))),
# ' '.join([r'%s %s'%(symbol,inputs[v]) for v in x]) if len(set([v for v in x]))>1 else r'{%s %s}^{%s}'%(symbol,inputs[[v for v in x][0]],str(j) if j>1 else '')),
# ' '.join([r'%s %s'%(Symbol,inputs[v]) for v in x]) if len(set([v for v in x]))>1 else r'{%s %s}^{%s}'%(Symbol,inputs[[v for v in x][0]],str(j) if j>1 else '')
# ) if usetex else (
# '%s d^%s%s/%s %s'%('1/%s!'%(str(j)) if j>1 else '',str(j) if j>1 else '',y,''.join(['d%s'%(v) for v in x]), ' '.join(['d%s'%(v) for v in x]))
# )
# for o in args['operators']
# for j in range(1,args['order']+1)
# for y in outputs
# for x in icombinations(inputs,[j],unique=args['unique'])
# for w in args['weights']
# })
return values
def monomials(variable,replacements,strings,args,labels,usetex):
'''
Monomial string patterns
Args:
variable(str,list): Type of variable for monomials (inputs,outputs,terms)
replacements(dict): Replacements for variable strings
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
prefix__iloc__variable_power
with prefixes
[monomial]
which becomes
{variable}^{power}
'''
if isinstance(variable,str):
variables = copy.deepcopy(list(args[variable]))
for i,v in enumerate(variables):
for r in replacements:
variables[i] = variables[i].replace(r,replacements[r])
variables = {x: strings.get(x,args[variable].get(x)) for x in variables}
else:
variables = copy.deepcopy({v:[x for x in args[v]] for v in variable})
for i,v in enumerate(variables):
for j,x in enumerate(variables[v]):
for r in replacements:
variables[v][j] = variables[v][j].replace(r,replacements[r])
variables = {x: strings.get(x,args[v].get(x)) for v in variables for x in variables[v]}
if usetex:
func = labels['superscript']
else:
func = '%s^%s'
delimiter = '_'
constant = r''
values = {}
if args['bases'].get('monomial'):
values.update({delimiter.join([x,str(j)]):func%(variables[x],str(j) if j>1 else '') if j>0 else constant
for j in range(args['order']+1)
for x in variables
})
return values
def polynomial(variable,replacements,strings,args,labels,usetex):
'''
Polynomial string patterns
Args:
variable(str,list): Type of variable for polynomial (inputs,outputs,terms)
replacements(dict): Replacements for variable strings
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
prefix__iloc__variable_0_power_0-variable_1_power_1-...-variable_order-1_power_order-1
with prefixes
[polynomial]
which becomes
{variable_0}^{power_0} {variable_1}^{power_1} ... {variable_order-1}^{power_order-1}
'''
if isinstance(variable,str):
variables = copy.deepcopy(list(args[variable]))
for i,v in enumerate(variables):
for r in replacements:
variables[i] = variables[i].replace(r,replacements[r])
variables = {x: strings.get(x,args[variable].get(x)) for x in variables}
else:
variables = copy.deepcopy({v:[x for x in args[v]] for v in variable})
for i,v in enumerate(variables):
for j,x in enumerate(variables[v]):
for r in replacements:
variables[v][j] = variables[v][j].replace(r,replacements[r])
variables = {x: strings.get(x,args[v].get(x)) for v in variables for x in variables[v]}
if usetex:
func = labels['superscript']
else:
func = '%s^%s'
if isinstance(args['selection'],tuple):
I = itertools.product(args['selection'],repeat=len(variables))
else:
I = args['selection']
if not isinstance(I,list):
I = list(I)
splitter = '-'
delimiter = '_'
constant = r'1'
if usetex:
separator = ''
else:
separator = ' '
values = {}
if args['bases'].get('polynomial'):
values.update({
splitter.join([delimiter.join([x,str(j)]) for x,j in zip(variables,i)]):
separator.join([func%(variables[x],str(j) if j>1 else '') if j>0 else '' for x,j in zip(variables,i)]) if sum(i)>0 else constant
for i in I
})
return values
def chebyshev(variable,replacements,strings,args,labels,usetex):
'''
Chebyshev string patterns
Args:
variable(str,list): Type of variable for Chebyshev polynomial (inputs,outputs,terms)
replacements(dict): Replacements for variable strings
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
prefix__iloc__variable_order
with prefixes
[chebyshev]
which becomes
T_{order}(variable)
'''
if isinstance(variable,str):
variables = copy.deepcopy(list(args[variable]))
for i,v in enumerate(variables):
for r in replacements:
variables[i] = variables[i].replace(r,replacements[r])
variables = {x: strings.get(x,args[variable].get(x)) for x in variables}
else:
variables = copy.deepcopy({v:[x for x in args[v]] for v in variable})
for i,v in enumerate(variables):
for j,x in enumerate(variables[v]):
for r in replacements:
variables[v][j] = variables[v][j].replace(r,replacements[r])
variables = {x: strings.get(x,args[v].get(x)) for v in variables for x in variables[v]}
if usetex:
func = labels['subscript']
else:
func = '%s_%s'
symbol = 'T'
delimiter = '_'
constant = r'1'
values = {}
if args['bases'].get('chebyshev'):
values.update({delimiter.join([x,str(j)]):r'%s(%s)'%(func%(symbol,str(j)),variables[x]) if j>0 else constant
for j in range(args['order']+1)
for x in variables
})
return values
def hermite(variable,replacements,strings,args,labels,usetex):
'''
Hermite string patterns
Args:
variable(str,list): Type of variable for Hermite polynomial (inputs,outputs,terms)
replacements(dict): Replacements for variable strings
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
prefix__iloc__variable_order
with prefixes
[hermite]
which becomes
H_{order}(variable)
'''
if isinstance(variable,str):
variables = copy.deepcopy(list(args[variable]))
for i,v in enumerate(variables):
for r in replacements:
variables[i] = variables[i].replace(r,replacements[r])
variables = {x: strings.get(x,args[variable].get(x)) for x in variables}
else:
variables = copy.deepcopy({v:[x for x in args[v]] for v in variable})
for i,v in enumerate(variables):
for j,x in enumerate(variables[v]):
for r in replacements:
variables[v][j] = variables[v][j].replace(r,replacements[r])
variables = {x: strings.get(x,args[v].get(x)) for v in variables for x in variables[v]}
if usetex:
func = labels['subscript']
else:
func = '%s_%s'
symbol = 'H'
delimiter = '_'
constant = r'1'
values = {}
if args['bases'].get('hermite'):
values.update({delimiter.join([x,str(j)]):r'%s(%s)'%(func%(symbol,str(j)),variables[x]) if j>0 else constant
for j in range(args['order']+1)
for x in variables
})
return values
def legendre(variable,replacements,strings,args,labels,usetex):
'''
Legendre string patterns
Args:
variable(str,list): Type of variable for Legendre polynomial (inputs,outputs,terms)
replacements(dict): Replacements for variable strings
strings(dict): String patterns with text string keys and Latex string values
args(dict): Dictionary of arguments and settings used in Latex rendering
labels(dict): Dictionary of modifier strings for Latex rendering
Returns:
Dictionary of rendered string patterns
For example:
strings have notation:
prefix__iloc__variable_order
with prefixes
[legendre]
which becomes
L_{order}(variable)
'''
if isinstance(variable,str):
variables = copy.deepcopy(list(args[variable]))
for i,v in enumerate(variables):
for r in replacements:
variables[i] = variables[i].replace(r,replacements[r])
variables = {x: strings.get(x,args[variable].get(x)) for x in variables}
else:
variables = copy.deepcopy({v:[x for x in args[v]] for v in variable})
for i,v in enumerate(variables):
for j,x in enumerate(variables[v]):
for r in replacements:
variables[v][j] = variables[v][j].replace(r,replacements[r])
variables = {x: strings.get(x,args[v].get(x)) for v in variables for x in variables[v]}
if usetex:
func = labels['subscript']
else:
func = '%s_%s'
symbol = 'L'
delimiter = '_'
constant = r'1'
values = {}
if args['bases'].get('legendre'):
values.update({delimiter.join([x,str(j)]):r'%s(%s)'%(func%(symbol,str(j)),variables[x]) if j>0 else constant
for j in range(args['order']+1)
for x in variables
})
return values
texstrings.update({s.replace('partial',r):texstrings[s].replace(r'\delta',r'\%s'%r if r not in ['d'] else r) for s in texstrings for r in args['operators']})
funcs = {
'misc': lambda strings,args,labels,usetex:{
'default':{
'complexity_':r'N_{\textrm{terms}}',
'coef_':labels['abs']%(labels['gamma']),
'data':r'\mathcal{D}_{\textrm{data}}',
'intercept_':r'\beta',
'term_':r'\frac{\partial f}{\partial x}',
'loss':r'\textrm{Loss}',
'State': r'\textrm{State}',
'radius':r'r'},
'strings':texstrings,
},
'variables': lambda strings,args,labels,usetex: {'%s_%s'%(k,'_'.join(list(set(list(r.values()))))): monomials(k,r,strings,args,labels,usetex) for k in ['inputs','outputs','terms',['inputs','terms']] for r in [{'partial':x} for x in args['operators'] if x not in ['partial']]},
'constants': lambda strings,args,labels,usetex: {'%s_%s'%(k,'_'.join(list(set(list(r.values()))))): monomials(k,r,strings,args,labels,usetex) for k in ['inputs','outputs','terms',['inputs','terms']] for r in [{'partial':x} for x in args['operators'] if x not in ['partial']]},
'derivative': lambda strings,args,labels,usetex: {'%s'%(k): derivative(k,strings,args,labels,usetex) for k in args['operators']},
'expansion': lambda strings,args,labels,usetex: {'%s_%s_%s'%(str(i),k,K): expansion(i,k,K,strings,args,labels,usetex) for i in args['iloc'] for k,K in [('partial','Delta'),('delta','delta'),('Delta','Delta'),('d','Delta')]},
'taylorseries': lambda strings,args,labels,usetex: {'%s_%s_%s'%(str(i),k,K): taylorseries(i,k,K,strings,args,labels,usetex) for i in args['iloc'] for k,K in [('partial','Delta'),('delta','delta'),('Delta','Delta'),('d','Delta')]},
'monomials': lambda strings,args,labels,usetex: {'%s_%s'%(k,'_'.join(list(set(list(r.values()))))): monomials(k,r,strings,args,labels,usetex) for k in ['inputs','outputs','terms',['inputs','terms']] for r in [{'partial':x} for x in args['operators'] if x not in ['partial']]},
'polynomial': lambda strings,args,labels,usetex: {'%s_%s'%(k,'_'.join(list(set(list(r.values()))))): polynomial(k,r,strings,args,labels,usetex) for k in ['inputs','outputs','terms',['inputs','terms']] for r in [{'partial':x} for x in args['operators'] if x not in ['partial']]},
'chebyshev': lambda strings,args,labels,usetex: {'%s_%s'%(k,'_'.join(list(set(list(r.values()))))): chebyshev(k,r,strings,args,labels,usetex) for k in ['inputs','outputs','terms',['inputs','terms']] for r in [{'partial':x} for x in args['operators'] if x not in ['partial']]},
'hermite': lambda strings,args,labels,usetex: {'%s_%s'%(k,'_'.join(list(set(list(r.values()))))): hermite(k,r,strings,args,labels,usetex) for k in ['inputs','outputs','terms',['inputs','terms']] for r in [{'partial':x} for x in args['operators'] if x not in ['partial']]},
'legendre': lambda strings,args,labels,usetex: {'%s_%s'%(k,'_'.join(list(set(list(r.values()))))): legendre(k,r,strings,args,labels,usetex) for k in ['inputs','outputs','terms',['inputs','terms']] for r in [{'partial':x} for x in args['operators'] if x not in ['partial']]},
}
strings = {}
types = {}
strings.update(texstrings)
for func in funcs:
values = funcs[func](strings,args,labels,usetex)
types[func] = values
strings.update({s: values[k][s] for k in values for s in values[k] if s not in strings})
self.args = args
self.strings = strings
self.labels = labels
self.types = types
self.prefixes = prefixes
self.usetex = usetex
return
[docs] def texify(self,string,texstrings={},texargs={},texlabels={},usetex=True):
'''
Render string as Latex string
Args:
string(str): String to be rendered
texstrings(dict): Dictionary of text strings with Latex string values
texargs(dict): Dictionary of arguments and settings used in Latex rendering
texlabels(dict): Dictionary of modifier strings for Latex rendering
usetex(bool): Render as Latex strings, or render as text strings
Returns:
Latex rendered string
'''
_string = string
usetex = usetex if self.usetex is None else self.usetex
String = ""
if not isinstance(string,tuple):
string = (string,)
string = list(((scinotation(s,decimals=3,zero=True,usetex=usetex) for s in string)))
for texstring in texstrings:
self.strings['misc']['strings'].update({texstring:texstrings[texstring]})
self.args.update(texargs)
self.labels.update(texlabels)
replacements = self.args['texreplacements'] if usetex else self.args['replacements']
for s in string:
s = scinotation(s,decimals=3,zero=True,usetex=usetex)
if (0) and (s not in self.strings):
#print('texify',s,s in self.strings,findstring(s,self.strings,self.types,self.prefixes,self.labels,s))
pass
s = findstring(s,self.strings,self.types,self.prefixes,self.labels,replacements,s,usetex=usetex)
String = ' - '.join([String,s]) if len(String)>0 else s
if usetex:
String = '\n'.join([r'$%s$'%(s.replace('$','')) if len(s)>0 else s for s in String.split('\n')])
else:
String = '\n'.join([r'%s'%(s.replace('$','')) if len(s)>0 else s for s in String.split('\n')])
return String