Showing posts with label sympy. Show all posts
Showing posts with label sympy. Show all posts

Sunday, September 20, 2020

problem identification for vectors and my current responses

I encountered a few issues with SymPy today. I'll explain what I found and what I plan to do about it.

I have an expression (1158485859) that, in Latex, is

\frac{-\hbar^2}{2m} \nabla^2 = {\cal H}

The \nabla^2 is represented in SymPy as Laplacian(), though an argument is required for the operator.

My solution: leave the SymPy representation as Pow(Symbol('nabla'), Integer(2))


Also on the topic of vectors, I encountered the expression

\vec{p} \cdot \vec{F}(\vec{r}, t) = a

In order to convert that to SymPy, I'd need to specify a basis for `\vec{p}` (e.g., `from sympy.vector import CoordSys3D`). For example, 

>>> N = CoordSys3D('N')
>>> p = Symbol('p_x')*N.i + Symbol('p_y')*N.j + Symbol('p_z')*N.k
>>> F = Symbol('F_x')*N.i + Symbol('F_y')*N.j + Symbol('F_z')*N.k
>>> p.dot(F)
F_x*p_x + F_y*p_y + F_z*p_z

However, that doesn't seem to extend to functions:

>>> p.dot(Function(F)(Symbol('r'), Symbol('t')))
Traceback (most recent call last):
...
TypeError: expecting string or Symbol for name

My solution: leave the SymPy representation as incorrect, using "multiplication" instead of "dot"

vectors in SymPy and use of dot cross and the Laplacian

Converting "\vec{\psi}(r, t)" into SymPy is feasible
Function('vecpsi')(Symbol('r'), Symbol('t'))
but I can't figure out how to apply the dot product with a vector:

>>> import sympy
>>> from sympy import *
>>> from sympy.vector import CoordSys3D, Del, curl, divergence, gradient
>>> Symbol('vecp').dot( Function('vecpsi')(Symbol('r'), Symbol('t')) )
Traceback (most recent call last):
AttributeError: 'Symbol' object has no attribute 'dot'

The issue is that a vector needs to be specified in a specific dimension (e.g., 3) and have specific coefficients with respect to the basis.

>>> N = CoordSys3D('N')
>>> v1 = Symbol('a')*N.i+Symbol('b')*N.j + Symbol('c')*N.k
>>> v2 = Symbol('f')*N.i+Symbol('g')*N.j + Symbol('k')*N.k
>>> v1.dot(v2)
a*f + b*g + c*k
>>> v1.cross(v2)
(b*k - c*g)*N.i + (-a*k + c*f)*N.j + (a*g - b*f)*N.k

see https://en.wikipedia.org/wiki/Del
>>> delop = Del()
>>> delop(Symbol('a'))
0
>>> delop(v1)
(Derivative(a*N.i + b*N.j + c*N.k, N.x))*N.i + (Derivative(a*N.i + b*N.j + c*N.k, N.y))*N.j + (Derivative(a*N.i + b*N.j + c*N.k, N.z))*N.k
>>> v1
a*N.i + b*N.j + c*N.k
>>> curl(v1)
0
>>> divergence(v1)
0
>>> Laplacian(v1)
Laplacian(a*N.i + b*N.j + c*N.k)

Also, operators can't be defined since using Laplacian requires an argument:
>>> Laplacian()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __new__() missing 1 required positional argument: 'expr'

Sunday, September 6, 2020

summary of SymPy hurdles for the Physics Derivation Graph



Friday, September 4, 2020

Latex symbols that are operators - how to create SymPy placeholder

{\cal H} in Latex is used for the Hamiltonian in the "1D particle in a box"
https://en.wikipedia.org/wiki/Hamiltonian_(quantum_mechanics)
Needs to be translated to a SymPy operator 
https://docs.sympy.org/latest/modules/physics/quantum/piab.html

The Laplace operator \nabla^2 in Latex is 
delop = Del()
delop.dot(delop())

representing the Laplace operator (nabla in Latex) in SymPy using Del

https://en.wikipedia.org/wiki/Laplace_operator
https://docs.sympy.org/latest/modules/vector/fields.html

>>> import sympy
>>> from sympy import *
>>> from sympy.parsing.latex import parse_latex
>>> from sympy.vector import Del


Original expression as Latex converted to SymPy to Latex:
>>> latex(eval(sympy.srepr(parse_latex("\\frac{-\\hbar^2}{2m} \\nabla = {\\calH}"))))
'- \\frac{\\hbar^{2} nabla}{2 m} = calH'

The first two conversions yield SymPy:
>>> sympy.srepr(parse_latex("\\frac{-\\hbar^2}{2m} \\nabla = {\\calH}"))
"Equality(Mul(Symbol('nabla'), Mul(Mul(Integer(-1), Pow(Symbol('hbar'), Integer(2))), Pow(Mul(Integer(2), Symbol('m')), Integer(-1)))), Symbol('calH'))"

This can be successfully evaluated as SymPy because the 'nabla' is a Symbol
>>> eval("Equality(Mul(Symbol('nabla'), Mul(Mul(Integer(-1), Pow(Symbol('hbar'), Integer(2))), Pow(Mul(Integer(2), Symbol('m')), Integer(-1)))), Symbol('calH'))")
Eq(-hbar**2*nabla/(2*m), calH)

However, replacing 'nabla' with 'Del' causes the eval to fail:
>>> eval("Equality(Mul(Del, Mul(Mul(Integer(-1), Pow(Symbol('hbar'), Integer(2))), Pow(Mul(Integer(2), Symbol('m')), Integer(-1)))), Symbol('calH'))")
Traceback (most recent call last):
...
  File "/usr/local/lib/python3.6/dist-packages/sympy/core/mul.py", line 307, in flatten
    b, e = o.as_base_exp()
AttributeError: type object 'Del' has no attribute 'as_base_exp'



Original expression to convert to SymPy:
>>> sympy.srepr(parse_latex("\\nabla^2 \\psi \\left( \\vec{r},t) \\right) = \\frac{i}{\\hbar} \\vec{p} \\cdot \\left( \\vec{ \\nabla} \\psi( \\vec{r},t) \\right)"))
"Mul(Pow(Symbol('nabla'), Integer(2)), Mul(Symbol('psi'), Mul(Symbol('right'), Function('left')(Mul(Symbol('r'), Symbol('vec')), Symbol('t')))))"


The Latex "\nabla" is SymPy's "Del". However, squaring Del isn't available
>>> sympy.latex(sympy.Pow(Del, sympy.Integer(2)), sympy.Symbol('x'))
...
AttributeError: type object 'Del' has no attribute '_eval_power'


The Laplacian operator is the dot product of two Del operators, so
>>> delop = Del()
>>> sympy.latex(delop.dot(delop(sympy.Function('\psi')(sympy.Symbol('r'), sympy.Symbol('t')))))
'0'


Evaluating definite integrals for humans versus SymPy breaks the Latex-to-SymPy mapping of steps

 In the process of fixing expressions and steps in the PDG database, I encountered a novel challenge.

Currently every step in the PDG has a set of Latex expressions. These expressions are provided by the user, converted to SymPy, and then the step is validated using SymPy. There is a one-to-one mapping of "what the user sees" to "what the CAS checks."

In a derivation there is a sequence like

    f = \int_a^b x dx

inference rule: carry out definite integration

    f = (x^2/2)|_a^b

inference rule: simplify

    f = 1/2 (b^2 - a^2)

It seems that SymPy doesn't support the middle expression and instead goes directly from the first to the last expression. That means there is an intermediary Latex expression that cannot be converted to Sympy, breaking the assumption of "what the human reads is one-to-one with what the CAS checks."

Accounting for the mismatch between Latex steps and CAS steps would make the already-messy graph structure more complicated. Some steps that are included for human readability would not be able to be specified to the CAS, nor would those steps be checked.

Saturday, May 9, 2020

dynamically build latex parser grammar based on symbols used in the Physics Derivation Graph

I've been using the Sympy Latex parser. After encountering a wide variety of issues, I realized a new strategy is needed.

The previous mindset was "make modifications to the ANTLR grammar as we encounter novel issues in Latex." That approach would constant process of catching up with whatever is in the Physics Derivation Graph.

Here is a different method that takes advantage of the information available in the Physics Derivation Graph to inform the ANTLR grammar.

The Physics Derivation Graph has a list of symbols in its database. We could leverage that list of symbols and build an ANTLR grammar specification that is based on the Physics Derivation Graph list of symbols.

The process would be
  1. get list of symbols from Physics Derivation Graph
  2. add those symbols into the ANTLR grammar
  3. when Sympy parses Latex, use the modified grammar specification
  4. when new symbols are added to the Physics Derivation Graph, go to step 1

Friday, May 1, 2020

sympy to AST using latex

Given an expression in Latex, extract the symbols:
based on https://stackoverflow.com/a/59843709/1164295

>>> import sympy
>>> from sympy.parsing.latex import parse_latex
>>> symp_lat = parse_latex('x^2 + a x + b = 0')

>>> symp_lat.atoms(sympy.Symbol)
{x, b, a}

Given an expression in Latex, generate the graphviz of the AST:
from https://docs.sympy.org/latest/tutorial/manipulation.html
see https://docs.sympy.org/latest/modules/printing.html#sympy.printing.dot.dotprint

>>> graphviz_of_AST_for_expr = sympy.printing.dot.dotprint(symp_lat)