Ask Your Question

JesterEE's profile - activity

2021-02-08 11:55:37 +0200 received badge  Famous Question (source)
2021-02-08 11:55:37 +0200 received badge  Notable Question (source)
2021-02-08 11:55:37 +0200 received badge  Popular Question (source)
2015-03-31 11:16:08 +0200 received badge  Good Answer (source)
2015-03-02 22:21:57 +0200 commented answer substitute x*y by u

Also interesting, using the above Symbolic ring example, if one factors first to expose two instances of x*y, the subs() function will only replace one.

sage: _ = var('x,y,u')
sage: f = x*y + x^2*y^2 + x*y^2
sage: f.factor()
sage: f.factor().subs({x*y:u})
(x*y + y + 1)*x*y
(u + y + 1)*x*y
2015-02-25 22:52:22 +0200 commented answer Solve for variable but variable is still in answer

@wzawzdb, from the Sympy solvers documentation Use solve() to solve algebraic equations. We suppose all equations are equaled to 0, so solving x**2 == 1 translates into the following code: Run code block in SymPy Live

>>> from sympy.solvers import solve
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> solve(x**2 - 1, x)
[-1, 1]
2015-02-21 22:39:27 +0200 received badge  Autobiographer
2015-02-21 22:14:27 +0200 answered a question LaTeX Input

I was actually working on something similar recently (Regular Expression Replacement in Sage). I got my function working and modified it to suit your needs.

Please see the code and test output below or in this Sage Worksheet.

Note that this is just a WIP solution; far from catch all. Your LaTeX will likely be much more complicated than the equation you entered as a sample, and the regular expression parser needs to be made aware of all those syntactic nuances (especially pairs of enclosing delimiters). This can be done by altering the OrderedDict(adict) in class make_xlat or by passing it as the udict argument to latex2func(s, udict). Also note that this replacer will try and operate on the LaTeX function with all the grammatical symbols at once. So in it's current form, there's no way to tell the replacer to find and replace something before something else.

What you really need is an all encompassing grammar for LaTeX equations. As @fredericc said, this is really not a simple thing to do, but if you feel so inclined, in the past I found that pyparsing is quite capable. Other popular parsing packages include PLY and PyBison.

image description

import re
from collections import OrderedDict
def latex2func(s, udict=OrderedDict()):
    class make_xlat(object):
        def __init__(self, *args, **kwargs):
            self.adict = OrderedDict((
                    ('\left'   , ''),
                    (r'\right' , ''),
                    (r'\cdot'  , '*'),
                    ('^'       , '**'),
                    (' '       , ''),
                    ('{'       , '('),
                    ('}'       , ')'),
                    (r'(\d+)([A-Za-z]\d*\w*)' , r'\1*\2'),
                    (r'\((\d+)\)' , r'\1'),
                    ))
            self.adict.update(*args, **kwargs)
            self.grp_lookup = self.make_grp_lookup()
            self.rx = self.make_rx()
        def make_grp_lookup(self):
            grps = {}
            for k,v in self.adict.iteritems():
                i = max(grps.keys())+1 if grps else 0
                grps.update({i+j: k for j in xrange(len(re.findall(r'\\\d+', v)))})
            return grps
        def make_rx(self):
            l = []
            for k, v in self.adict.iteritems():
                if not re.search(r'\\\d+', v):
                    l.append(''.join(map(re.escape, k)))
                else:
                    l.append(k)
            return re.compile('|'.join(l))
        def one_xlat(self, match):
            try: # Simple string replacement
                return self.adict[match.group(int(0))]
            except: # Subpattern group replacement
                i, m = zip(*[(i, v) for i, v in enumerate(match.groups()) if v is not None])
                t = self.adict[self.grp_lookup[i[0]]] # Assumes all indicies are the same, if not, something went wrong
                for i, g in enumerate(m):
                    t = t.replace(r'\{}'.format(i+1), g)
                return t
        def __call__(self, txt):
            return self.rx.sub(self.one_xlat, txt)


    translate = make_xlat(udict)
    while translate(s) is not s:
        s = translate(s)
    s = s.split('=')
    args = re.sub('.*\((.*)\)', r'\1', s[0])
    eqn = s[1]
    return eval('lambda {}: {}'.format(args, eqn))


_ = var('x')
tests = {
    r'f\left(x\right)=x^{3}-10 \cdot x^{2}+31x-30' : x**3-10*x**2+31*x-30,
    }

for k,v in tests.iteritems():
    show('$ {} $'.format(k), display=False)
    for _x in xrange(11):
        print('x = {}'.format(_x))
        print('  LaTeX Implementation: {}'.format(latex2func(k)(_x)))
        print('  Sage Implementation: {}'.format(v.substitute(x=_x)))

f(x)=x^3−10⋅x^2+31x ...
(more)
2015-02-18 02:41:25 +0200 received badge  Nice Answer (source)
2015-02-17 22:32:24 +0200 received badge  Editor (source)
2015-02-17 22:29:54 +0200 commented answer re.complile failure in a SageWS (Vertical Bar character)

@William Stein Thanks for the quick response and showing multiple solutions to my issue! From the Traceback error I would have been chasing may tail unless you intervened.

@kcrisman Ya that's odd to me as well ... maybe someone can share when the preprocessor can and can't handle the coercion.

2015-02-17 22:24:45 +0200 received badge  Supporter (source)
2015-02-17 22:24:43 +0200 received badge  Scholar (source)
2015-02-17 10:51:43 +0200 received badge  Student (source)
2015-02-17 10:30:31 +0200 received badge  Teacher (source)
2015-02-17 08:02:37 +0200 answered a question How can I print equations just like latex?

I was looking for the same thing and found these comments on the issue.

This works with a _few_ functions, but not all.

This is probably the best answer on why it does this simplification (and why there's no way to stop it)

As far as the simplification mechanisms, you can look at this page. There are a number of them spread throughout that highlight different means:

If you're looking to just reproduce the same text as your input, unfortunately I have found no better way than writing it out in LaTeX as a initial condition step so Sage doesn't mangle the form. This is a quick latex renderer that I modified from a this post on ask.sagemath

def latexrender(s):
    try:
        pic = text("$" + s.replace('$','\$') + "$",(0,0),axes=False,figsize=1,color='black',fontsize=20)
        pic.show()
    except:
        latexrender(latex(s))
    return
2015-02-17 07:29:24 +0200 asked a question re.complile failure in a SageWS (Vertical Bar character)

I was trying to use a Python Cookbook recipe (https://www.safaribooksonline.com/lib...) for multiple regular expression matches and substitutions in a Sagemath Cloud Sage Worksheet (final usage is for altering the __latex_/_repr_ attributes of an object). The code from the cookbook is below:

import re
def multiple_replace(txt, adict):
    rx = re.compile('|'.join(map(re.escape, adict)))
    def one_xlat(match):
        return adict[match.group(0)]
    return rx.sub(one_xlat, txt)


txt = "Larry Wall is the creator of Perl"
adict = {
  "Larry Wall" : "Guido van Rossum",
  "creator" : "Benevolent Dictator for Life",
  "Perl" : "Python",
}

print(multiple_replace(txt, adict))

When I run this code in the Worksheet I get the error:

Error in lines 13-13
Traceback (most recent call last):
  File "/projects/PROJECT/sagemathcloud/sage_server.py", line 873, in execute
    exec compile(block+'\n', '', 'single') in namespace, locals
  File "", line 1, in <module>
  File "", line 5, in multiple_replace
  File "", line 4, in one_xlat
IndexError: no such group

If I run the same code on a Sagemath Cloud IPython Notebook, Windows/Linux Python 2.7 session, or Windows/Linux Python 3.4 session the code outputs the correct result.

I started debugging and found that Sage doesn't like the '|' in the compiled string. If I change the character to another (e.g. ',') I no longer get the error ... though the code no longer functions with anything other than the '|'. I also tried to substitute '|' with unichr(int('007c', 16)) which results in the same error.

Has anyone seen anything like this before? I tried to search for it, but it seems so niche I didn't find any results. Any ideas for a workaround?

Thanks Matt