SymPy: How to return an expression in terms of other expression(s)?

笑着哭i 提交于 2019-12-18 17:28:00

问题


I'm fairly new to SymPy and have what might be a basic question. Or I might simply be misinterpreting how SymPy is supposed to be used.

Is there a way to create an expression that is not represented by atoms, but by a combination of other expressions?

Example:

>>> from sympy.physics.units import *
>>> expr1 = m/s
>>> expr2 = mile/hour
>>> expr1
m/s
>>> expr2
1397*m/(3125*s)
>>> expr1.in_terms_of([mile,hour]) #in my dreams?
3125*mile/(1397*hour)
>>> 

On a side note: Can I find an 'official' PDF (or other printable) version of the complete SymPy documentation? (I'm under draconian Internet usage restrictions at work and am tired of doing work at home on the weekend.)

Update:

This is what I ended up with following Prelude's suggestion, however it's not likely to get much use like this as it feels dirty. Comments and WTF's welcome.

def in_terms_of(self, terms):
    expr2 = eval(str(self), physics.units.__dict__)
    converter = {}
    for term in terms:
        term_expr = physics.units.__dict__[term]
        coeff = term_expr.as_coeff_terms()[0]
        unit = physics.units.Unit('my_'+term, term)
        converter[term_expr/coeff] = unit/coeff
    return str(expr2.subs(converter))

Usage:

>>> x = in_terms_of('J',['gram','mile','hour'])
>>> x
'9765625000*mile**2*gram/(1951609*hour**2)'
>>> in_terms_of(x,['J'])
'J'

回答1:


Checking the source for sympy.physics.units you can see that all units are defined in terms of meters, kilograms, seconds, amperes, kelvins, moles and candelas. These are the base units.

Then a mile is defined as 5280 feet, and a foot is defined as 0.3048 meters.

So all expressions using non-base units will have the non-base units replaced with the base units.

You can define your own units which you can subsitute into an expression when you need an expression to use particular units:

import sympy.physics.units as units
from sympy import Rational

my_mile = units.Unit('my_mile', 'mile')
my_hour = units.Unit('my_hour', 'hour')

Then define a dictionary which will substitute the base units for your new units.

converter = {units.m: my_mile/Rational('1609.344'),
             units.s: my_hour/Rational('3600')}

Perform all your calculations using the base units. Then if you want a value using miles and hours, you can substitute your new units into the expression.

v = 10*units.miles/units.hour
print v # = 2794*m/(625*s)

print v.subs(converter) # = 10*mile/hour

Use ars answer for getting the docs. Sympy's repository is here: https://github.com/sympy/sympy

There is a README file in the docs folder which describes how to create html docs.




回答2:


there's also quantities:

In [1]: from quantities import *
In [2]: v = 1397*m / (3125*s)
In [3]: v
Out[3]: array(0.44704) * m/s
In [8]: v.units = mile/hour
In [9]: v
Out[9]: array(1.0) * mi/h



回答3:


In sympy units you convert from expr1 to expr2 by dividing:

In [120]: import sympy.physics.units as units

In [121]: expr1 = units.m / units.s

In [122]: expr2 = units.miles / units.hour

In [123]: a = (1397/3125) * expr1 / expr2

In [124]: a
Out[124]: 1

The only issue is that you end up with a dimensionless quantity. You might also consider the Quantities package for this type of thing:

In [125]: import quantities as pq

In [126]: a = pq.Quantity(1397/3125, 'm/s')

In [127]: a
Out[127]: array(0.44703999999999999) * m/s

In [128]: a.units = pq.mile / pq.hour

In [129]: a
Out[129]: array(1.0) * mi/h

There's also Unum.

I don't know of a PDF version of the sympy docs, but you might be able to check the distribution out from their repository and use Sphinx to generate a PDF for yourself.



来源:https://stackoverflow.com/questions/2038100/sympy-how-to-return-an-expression-in-terms-of-other-expressions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!