2010-10-05 11 views
22

मैं जैसे वैध अजगर वाक्य रचना के साथ तार बदलने की आवश्यकता:परिवर्तित लेटेक्स करने के लिए एक अजगर संख्यात्मक अभिव्यक्ति

$1+2^{x+y}$ 

मैं sympy की लेटेक्स समारोह लेकिन यह कोशिश की है:

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

और बराबर LaTeX मिल इसके स्ट्रिंग फॉर्म की बजाय वास्तविक अभिव्यक्ति को संसाधित करता है:

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

लेकिन ऐसा करने के लिए, यह भी एक्स और वाई को "प्रतीकों" के रूप में घोषित करने की आवश्यकता है।

मैं कुछ और सीधे आगे चाहता हूं, कंपेलर मॉड्यूल से पार्सर के साथ अधिमानतः काम करने योग्य।

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

इतना ही नहीं बल्कि, क्यों: मैं इतना है कि मैं उन्हें mathjax के साथ एक वेबपेज में दिखा सकते हैं उन लेटेक्स snipptes उत्पन्न करने के लिए की जरूरत है।

+0

एक महत्वपूर्ण भेद यह है कि आप इन अभिव्यक्तियों का मूल्यांकन नहीं कर रहे हैं, बल्कि उनके साथ दस्तावेज़ लेआउट करने के लिए। यह कह रहा है कि आप माता-पिता को 'x + y' के आसपास ब्रेसिज़ के साथ प्रतिस्थापित करना चाहते थे, लेकिन निश्चित रूप से अन्य जगहें हैं जहां माता-पिता को संरक्षित करने की आवश्यकता होगी। मुझे लगता है कि आपको कुछ समझने की ज़रूरत है कि आप क्या पार्स करने की कोशिश कर रहे हैं और जब आप पूरा कर लेंगे तो यह कैसा दिखना चाहिए। फिर आप यह सोचना शुरू कर सकते हैं कि एक उपयुक्त पार्सर के बाद यह परिवर्तन कैसे प्राप्त किया जा सकता है। इससे आपको यह निर्धारित करने में भी मदद मिलेगी कि पार्सर को क्या करना होगा। – PaulMcG

उत्तर

10

आप sympy.latexeval के साथ उपयोग कर सकते हैं:

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

तुम अब भी प्रतीक के रूप में चर घोषित करने के लिए है, लेकिन अगर यह सच में एक समस्या है, यह तुलना में यह करने के लिए सब कुछ पार्स करने के लिए एक पार्सर लिखने के लिए बहुत आसान है और लेटेक्स को खरोंच से उत्पन्न करें।

+0

धन्यवाद टॉम 10। सरल, लेकिन सुरुचिपूर्ण। मेरा मूल कार्यान्वयन कुछ हद तक इस तरह से चला गया: एस = "1 + 2 ** (x + y)" eval ('sympy.latex (% s)'% s) चर को पहले प्रतीकों में बदलने के बाद। – fccoelho

3

tom10 के जवाब पर निर्माण करने के लिए आप एक शब्दकोश है कि प्रतीकों पैदा करते हैं और उपयोग करें कि जब eval बुला जाएगा परिभाषित कर सकते हैं:

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

तो अगर आप का उपयोग

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

आप चिंता करने की ज़रूरत नहीं होना चाहिए चर के लिए पूर्व-निर्माण प्रतीक के बारे में।

+0

धन्यवाद जियोफ, शानदार! नीचे मेरे फिक्स देखें। – fccoelho

4

बस ज्योफ गन्ने का उत्कृष्ट जवाब देने के लिए एक छोटे से ठीक:

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

पहले यह dict के लिए नया आइटम जोड़ने नहीं होगा। अब आप अपने अभिव्यक्ति के साथ इस का उपयोग कर सकते हैं:

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

और आप इसे आगे LaTeX को परिवर्तित करने से पहले इसे सरल कर सकते हैं:

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

और आप इस मिल:

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

अगर किसी के पास कोई समाधान नहीं है जिसमें सिम्पी शामिल नहीं है, तो कृपया पोस्ट करें! मैं सिर्फ इस छोटे से काम के लिए अपने ऐप के साथ sympy खींचना नहीं चाहता! (लेकिन मैं इस तरह से स्वीकार करता हूं कि कुछ अन्य सीएएस बीमियोथ के ऋषि पर निर्भर रहना) – fccoelho

16

यहाँ एक नहीं बल्कि है लंबी लेकिन अभी भी अपूर्ण विधि जिसमें किसी भी तरह से सिम्पी शामिल नहीं है। यह (-b-sqrt(b**2-4*a*c))/(2*a) का उदाहरण जो \frac{- b - \sqrt{b^{2} - 4 \; a \; c}}{2 \; a} में अनुवाद किया और के रूप में

alt text

यह मूल रूप से एएसटी बनाता है और यह लेटेक्स गणित एएसटी नोड्स से मेल खाती उत्पादन चलता renders हो जाता है कवर करने के लिए काफी है। वहां क्या विचार है कि इसे कम करने वाले स्थानों में इसे विस्तारित करने के बारे में पर्याप्त जानकारी दी जानी चाहिए।


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) 

+0

वाह! यह बहुत अद्भुत है! धन्यवाद जियोफ! इसे अभी तक परीक्षण नहीं किया है, लेकिन इसे विभिन्न प्रकार के उदाहरणों के खिलाफ परीक्षण किए जाने के बाद कोड का एक बहुत ही उपयोगी टुकड़ा बनना चाहिए। – fccoelho

+0

ध्यान दें कि फ़ंक्शन कॉल के लिए उपयोग किए गए '\ operatorname' कमांड के लिए amsmath की आवश्यकता होती है। गणित के लिए आपको उचित विस्तार जोड़ने की आवश्यकता है http://www.mathjax.org/resources/docs/?tex.html#amsmath-and-amssymbol –

+0

धन्यवाद। माइनस ईजे के साथ एक समस्या है: "3- (1 + 2)" -> 3 - 1 + 2. > elif self.prec (n.op) == self.prec (n.right) डालें और isinstance (n.op, ast.Sub): > दाएं = आर '\ बाएं (% s \ दाएं)'% self.visit (n.right) दूसरे में अगर visit_BinOp() – Edoot

9

आप SymPy का उपयोग कर सकते हैं। बस पहले स्ट्रिंग को sympify() फ़ंक्शन पर पास करें, जो इसे एक वैध SymPy अभिव्यक्ति में परिवर्तित कर देगा (यानी, आपके लिए प्रतीक बनाएं, आदि)। तो तुम sympify() के लिए एक शॉर्टकट कर सकता है

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

S() है भी, जैसे कि, latex(S('1+2**(x+y)')) भी काम करता है।

संबंधित मुद्दे