subindex font python math latex

font - subindex python



Convertir una expresión numérica de python a LaTeX (5)

Aquí hay un método bastante largo pero aún incompleto que no involucra a Sympy de ninguna manera. Es suficiente para cubrir el ejemplo de (-b-sqrt(b**2-4*a*c))/(2*a) que se traduce a /frac{- b - /sqrt{b^{2} - 4 /; a /; c}}{2 /; a} /frac{- b - /sqrt{b^{2} - 4 /; a /; c}}{2 /; a} /frac{- b - /sqrt{b^{2} - 4 /; a /; c}}{2 /; a} y rinde como

Básicamente, crea el AST y lo hace produciendo la matemática de látex que corresponde a los nodos AST. Lo que hay debe dar suficiente idea de cómo extenderlo en los lugares que le faltan.

import ast class LatexVisitor(ast.NodeVisitor): def prec(self, n): return getattr(self, ''prec_''+n.__class__.__name__, getattr(self, ''generic_prec''))(n) def visit_Call(self, n): func = self.visit(n.func) args = '', ''.join(map(self.visit, n.args)) if func == ''sqrt'': return ''/sqrt{%s}'' % args else: return r''/operatorname{%s}/left(%s/right)'' % (func, args) def prec_Call(self, n): return 1000 def visit_Name(self, n): return n.id def prec_Name(self, n): return 1000 def visit_UnaryOp(self, n): if self.prec(n.op) > self.prec(n.operand): return r''%s /left(%s/right)'' % (self.visit(n.op), self.visit(n.operand)) else: return r''%s %s'' % (self.visit(n.op), self.visit(n.operand)) def prec_UnaryOp(self, n): return self.prec(n.op) def visit_BinOp(self, n): if self.prec(n.op) > self.prec(n.left): left = r''/left(%s/right)'' % self.visit(n.left) else: left = self.visit(n.left) if self.prec(n.op) > self.prec(n.right): right = r''/left(%s/right)'' % self.visit(n.right) else: right = self.visit(n.right) if isinstance(n.op, ast.Div): return r''/frac{%s}{%s}'' % (self.visit(n.left), self.visit(n.right)) elif isinstance(n.op, ast.FloorDiv): return r''/left/lfloor/frac{%s}{%s}/right/rfloor'' % (self.visit(n.left), self.visit(n.right)) elif isinstance(n.op, ast.Pow): return r''%s^{%s}'' % (left, self.visit(n.right)) else: return r''%s %s %s'' % (left, self.visit(n.op), right) def prec_BinOp(self, n): return self.prec(n.op) def visit_Sub(self, n): return ''-'' def prec_Sub(self, n): return 300 def visit_Add(self, n): return ''+'' def prec_Add(self, n): return 300 def visit_Mult(self, n): return ''//;'' def prec_Mult(self, n): return 400 def visit_Mod(self, n): return ''//bmod'' def prec_Mod(self, n): return 500 def prec_Pow(self, n): return 700 def prec_Div(self, n): return 400 def prec_FloorDiv(self, n): return 400 def visit_LShift(self, n): return ''//operatorname{shiftLeft}'' def visit_RShift(self, n): return ''//operatorname{shiftRight}'' def visit_BitOr(self, n): return ''//operatorname{or}'' def visit_BitXor(self, n): return ''//operatorname{xor}'' def visit_BitAnd(self, n): return ''//operatorname{and}'' def visit_Invert(self, n): return ''//operatorname{invert}'' def prec_Invert(self, n): return 800 def visit_Not(self, n): return ''//neg'' def prec_Not(self, n): return 800 def visit_UAdd(self, n): return ''+'' def prec_UAdd(self, n): return 800 def visit_USub(self, n): return ''-'' def prec_USub(self, n): return 800 def visit_Num(self, n): return str(n.n) def prec_Num(self, n): return 1000 def generic_visit(self, n): if isinstance(n, ast.AST): return r'''' % (n.__class__.__name__, '', ''.join(map(self.visit, [getattr(n, f) for f in n._fields]))) else: return str(n) def generic_prec(self, n): return 0 def py2tex(expr): pt = ast.parse(expr) return LatexVisitor().visit(pt.body[0].value)

Necesito convertir cadenas con una sintaxis de python válida como:

''1+2**(x+y)''

y obtén el equivalente de LaTeX:

$1+2^{x+y}$

He probado la función de látex de sympy pero procesa la expresión real, en lugar de la forma de cadena de la misma:

>>> latex(1+2**(x+y)) ''$1 + 2^{x + y}$'' >>> latex(''1+2**(x+y)'') ''$1+2**(x+y)$''

pero incluso para hacer esto, se requiere que xey sean declarados como tipo "símbolos".

Quiero algo más sencillo, preferiblemente factible con el analizador desde el módulo compilador.

>>> compiler.parse(''1+2**(x+y)'') Module(None, Stmt([Discard(Add((Const(1), Power((Const(2), Add((Name(''x''), Name(''y''))))))))]))

Por último, pero no menos importante, el por qué: necesito generar esos fragmentos de látex para poder mostrarlos en una página web con mathjax.


Para basarse en la respuesta de tom10, puede definir un diccionario que genere símbolos y utilizarlo al llamar a eval:

from collections import defaultdict class GenerateSymbols(defaultdict): def __missing__(self, key): return sympy.Symbol(key)

Entonces si usas

sympy.latex(eval(''1+2**(x+y)'',GenerateSymbols()))

no debería tener que preocuparse por la creación previa de símbolos para las variables.


Puedes usar sympy.latex con eval :

s = "1+2**(x+y)" sympy.latex(eval(s)) # prints ''$1 + {2}^{x + y}$''

Aún tiene que declarar las variables como símbolos, pero si esto es realmente un problema, es mucho más fácil escribir un analizador para hacer esto que analizar todo y generar el látex desde cero.


Puedes usar SymPy. Simplemente pase la cadena a la función sympify() primero, que la convertirá en una expresión SymPy válida (es decir, cree los Símbolos por usted, etc.). Para que pudieras hacer

>>> latex(sympify(''1+2**(x+y)'')) 1 + 2^{x + y}

S() también es un acceso directo a sympify() , es decir, el latex(S(''1+2**(x+y)'')) también funciona.


Sólo una pequeña solución a la excelente respuesta de Geoff Reedy:

class GenerateSymbols(defaultdict): def __missing__(self, key): self[key] = sympy.Symbol(key) return self[key]

Antes de que no agregaría el nuevo elemento al dict. Ahora puedes usar esto con tu expresión:

d= GenerateSymbols() eq = ''(-b-sqrt(b**2-4*a*c))/(2*a)''

y puede simplificarlo aún más antes de convertirlo a LaTeX:

sympy.latex(sympy.simplify(eval(eq,d)))

y obtienes esto:

''$- //frac{b + //operatorname{sqrt}//left(- 4 a c + b^{2}//right)}{2 a}$''