Skip to content

Commit

Permalink
Changes implementation to SymPy
Browse files Browse the repository at this point in the history
  • Loading branch information
jirikuncar committed Jul 6, 2017
1 parent cd77fa2 commit 824479a
Show file tree
Hide file tree
Showing 22 changed files with 339 additions and 351 deletions.
17 changes: 7 additions & 10 deletions .travis.yml
Expand Up @@ -25,6 +25,7 @@ language: python

python:
- '2.7'
- '3.6'

sudo: true

Expand All @@ -38,25 +39,21 @@ env:
- secure: KwansI0JAlS1EZe0yPP16mLf16tdy3uT6thiFral7VLA+PsfiEYJbjnkaDBKu/ICB70KK46EA7rJ4bpof0RKDyadTKY1nixDrIVPhFIQaqAuUILmsPmFcS7xzh0DPCz8C1SK01jqJgzutztFCQkQfYjHUL6pHM9x46mImsJLyqmKjT74GGGt29iINkO2jK54WmJWb79G9eWNCGtNCepEXEwQvReD7Bs9oR/ErZULugfZTCsPGMQa40rOt+tW6rYg32hJkGZBU52dUk5VqopLV4eQopkrEvk+5mURewUj+QR59i92jhtHtGqpcl4gGlSRKteII0dNF2KFHLGViOEsSjbKfdcjCnvRawypeEJVvtTizBL2N5zL4Zku56QRZhDSOia/ZyCgXBLQJpxUM/9OxI7c7X87qQGCwvTTg3UqBbYw8NLcuz4UTn0eNXTkguW3w6v9QXpMyiJDIthvSAAuj5JhKKeNrrqCQazSfozjj10YJeZxoMXtm6cjbGhAOJVBBLFEEre33cqv52CrS5aK3Pr5mHIXpNkMVBZpCfzF0e/OHPliSqSsOPeoeKxqLYnJQf/EmGnEPf9LSYSxIxiIdSMrCdlkZf2ysRVSp73BM1w9vOO0vpp2KOQYT58XNc/ex1XE2uh77I48F6SFwYnsTutzyNMKzCqnyTp2STeD/aE=

before_install:
- >
if [ ! -f SageMath/sage ] ; then
wget -O - http://mirror.switch.ch/mirror/sagemath/linux/64bit/sage-7.6-Ubuntu_12.04-x86_64.tar.bz2 | tar xjf -;
SageMath/sage -pip install -U pip setuptools;
fi
- travis_retry SageMath/sage -pip install twine wheel coveralls
- travis_retry pip install twine wheel coveralls
- travis_retry pip install check-manifest pydocstyle
- travis_retry pip install https://github.com/sympy/sympy/archive/1.1.zip

install:
- SageMath/sage -pip install -e .[all]
- pip install -e .[all]

script:
- SageMath/sage setup.py test
- SageMath/sage setup.py build_sphinx
- python setup.py test
- python setup.py build_sphinx
- pydocstyle essm
- check-manifest

after_script:
- SageMath/sage -sh -c coveralls
- coveralls

after_success:
- ./gh-pages.sh
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Expand Up @@ -93,6 +93,7 @@ def get_attr(obj, value, *args, **kwargs):
extensions = ['matplotlib.sphinxext.plot_directive',
'sphinxcontrib.bibtex',
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
Expand Down
5 changes: 2 additions & 3 deletions essm/__init__.py
Expand Up @@ -89,6 +89,5 @@

from __future__ import absolute_import

from .bases import convert, expand_units

__all__ = ('convert', 'expand_units')
from sympy import E as e
from sympy import Eq, solve, sqrt
16 changes: 8 additions & 8 deletions essm/_generator.py
Expand Up @@ -26,10 +26,10 @@
from collections import defaultdict

import pkg_resources
from isort import SortImports
from yapf.yapflib.yapf_api import FormatCode

from isort import SortImports
from sage import all as sage_all
import essm

from .variables import Variable

Expand Down Expand Up @@ -78,9 +78,9 @@ class {name}(Variable):
"""

# CONSTANTS = re.compile(r'\b(e|pi)\b')
SAGE_IMPORTS = re.compile(
_IMPORTS = re.compile(
r'\b({0})\b'.format(
'|'.join(name for name in dir(sage_all) if not name.startswith('_'))))
'|'.join(name for name in dir(essm) if not name.startswith('_'))))
"""Regular expression to find sage-specific constants and functions."""


Expand Down Expand Up @@ -197,7 +197,7 @@ def var(
# register all imports of units
if units:
if units != 1:
for arg in units.args():
for arg in units.args:
self._imports['essm.variables.units'].add(str(arg))

def write(self, filename):
Expand Down Expand Up @@ -313,14 +313,14 @@ def eq(self, name, expr, doc='', parents=None, variables=None):
self.eqs.append(context)

# register all imports
for arg in expr.args():
for arg in expr.args:
if str(arg) not in internal_variables and\
arg in Variable.__registry__:
self._imports[Variable.__registry__[arg].__module__].add(
str(arg))

for match in re.finditer(SAGE_IMPORTS, str(expr)) or []:
self._imports['sage.all'].add(match.group())
for match in re.finditer(_IMPORTS, str(expr)) or []:
self._imports['essm'].add(match.group())

def write(self, filename):
"""Serialize itself to a filename."""
Expand Down
76 changes: 18 additions & 58 deletions essm/bases.py
Expand Up @@ -23,68 +23,28 @@

import warnings

from sage.all import SR, Expression

class RegistryType(type):
"""Base registry operations."""

def expand_units(expr, units=None, simplify_full=True):
"""Expand units of all arguments in expression."""
from .variables._core import Variable

units = units or Variable.__units__
used_units = {}
# Need to multiply units with variable,
# so that we can devide by the symbolic equation later:
for variable in expr.arguments():
used_units[variable] = variable * units[variable]

result = convert(Expression(SR, expr.subs(used_units) / expr))
if simplify_full:
result = result.simplify_full()
return result


def convert(expr):
"""Convert a given expression."""
op = expr.operator()
ops = expr.operands()
if op:
return op(*(convert(o) for o in ops))
return expr.convert() if hasattr(expr, 'convert') else expr


class BaseExpression(Expression):
"""Add definition and instance documentation."""

def __init__(self, expr, definition, units=None):
"""Initialize expression."""
super(BaseExpression, self).__init__(SR, expr)
self.definition = definition
self.__units__ = units or getattr(definition, '__units__', None)

def register(self):
def __setitem__(cls, expr, definition):
"""Register expression in registry."""
if self in self.definition.__registry__:
if expr in cls.__registry__:
warnings.warn(
'"{0}" will be overridden by "{1}"'.format(
self.definition.__registry__[self].__module__ + ':' +
self.definition.name,
self.definition.__module__ + ':' + str(self), ),
cls.__registry__[expr].__module__ + ':' +
cls.__registry__[expr].name,
definition.__module__ + ':' + str(cls), ),
stacklevel=2)
self.definition.__registry__[self] = self.definition
return self

def expand_units(self, simplify_full=True):
"""Expand units of all arguments in expression."""
return expand_units(self, self.__units__, simplify_full=simplify_full)

def short_units(self):
"""Return short units of equation."""
from .variables.units import SHORT_UNIT_SYMBOLS
return self.expand_units().subs(SHORT_UNIT_SYMBOLS)

def convert(self):
"""Convert itself using custom ``convert`` function."""
return convert(self)
cls.__registry__[expr] = definition


__all__ = ('BaseExpression', 'convert', 'expand_units')
def __delitem__(cls, expr):
"""Remove a expr from the registry."""
if expr in cls.__registry__:
warnings.warn(
'"{0}" will be unregistered.'.format(
cls.__registry__[expr].__module__),
stacklevel=2)
del cls.__registry__[expr]
else:
raise KeyError(expr)
38 changes: 22 additions & 16 deletions essm/equations/_core.py
Expand Up @@ -21,16 +21,19 @@

from __future__ import absolute_import

from sage.all import SR
from sage.misc.latex import latex
import warnings

from ..bases import BaseExpression, convert
import six
from sympy.core.relational import Eq

from ..bases import RegistryType
from ..transformer import build_instance_expression
from ..variables import Variable
from ..variables._core import BaseVariable
from ..variables.units import derive_quantity, unit_symbols


class EquationMeta(type):
class EquationMeta(RegistryType):
r"""Equation interface.
Defines an equation with a docstring and internal variables,
Expand Down Expand Up @@ -97,36 +100,39 @@ def __new__(cls, name, parents, dct):

instance = super(EquationMeta, cls).__new__(
cls, name, parents, dct)
instance.expr = expr = BaseEquation(
build_instance_expression(instance, expr),
instance,
units=Variable.__units__, ).register()

expanded_units = expr.expand_units()
if not expanded_units:
raise ValueError(
'Invalid expression units: {0}'.format(expanded_units))
expr = build_instance_expression(instance, expr)
instance.expr = expr = BaseEquation(instance, expr)
instance[expr] = instance

return expr

return super(EquationMeta, cls).__new__(cls, name, parents, dct)


@six.add_metaclass(EquationMeta)
class Equation(object):
"""Base type for all equations."""

__metaclass__ = EquationMeta
__registry__ = {}

@classmethod
def args(cls):
"""Return equation arguments from registry if exist."""
return tuple(
Variable.__registry__.get(arg, arg) for arg in cls.expr.args())
Variable.__registry__.get(arg, arg)
for arg in cls.expr.atoms(BaseVariable))


class BaseEquation(BaseExpression):
class BaseEquation(Eq):
"""Add definition and short unit."""

def __new__(cls, definition, expr):
if not isinstance(expr, Eq):
return expr
self = super(BaseEquation, cls).__new__(cls, *expr.args)
self.definition = definition
return self

@property
def __doc__(self):
return self.definition.__doc__
Expand Down
4 changes: 3 additions & 1 deletion essm/equations/chamber/insulation.py
Expand Up @@ -21,6 +21,8 @@

from __future__ import absolute_import

from essm import Eq

from ...variables.chamber.insulation import A_i, L_i, Q_i, dT_i, lambda_i
from .._core import Equation

Expand All @@ -31,7 +33,7 @@ class eq_Qi(Equation):
:cite:`schymanski_leaf-scale_2017`
"""

expr = Q_i == dT_i * lambda_i * A_i / L_i
expr = Eq(Q_i, dT_i * lambda_i * A_i / L_i)
"""Describe how you got the equation."""


Expand Down

0 comments on commit 824479a

Please sign in to comment.