-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add general trig functions via taylor series #371
Add general trig functions via taylor series #371
Conversation
clifford/__init__.py
Outdated
@@ -258,17 +260,73 @@ def general_exp(x, max_order=15): | |||
for i in range(1, max_order): | |||
if np.any(np.abs(tmp.value) > _settings._eps): | |||
tmp = tmp*scaled * (1.0 / i) | |||
result += tmp | |||
result = result + tmp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the motivation for this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Motivation was that without this numba will not JIT our general_exp function:
No implementation of function Function(<built-in function iadd>) found for signature:
iadd(MultiVector(LayoutType(Layout([1, 1, 1], ids=BasisVectorIds.ordered_integers(3), order=BasisBladeOrder.shortlex(3), names=['', 'e1', 'e2', 'e3', 'e12', 'e13', 'e23', 'e123'])), float64), MultiVector(LayoutType(Layout([1, 1, 1], ids=BasisVectorIds.ordered_integers(3), order=BasisBladeOrder.shortlex(3), names=['', 'e1', 'e2', 'e3', 'e12', 'e13', 'e23', 'e123'])), float64))
@@ -589,11 +589,11 @@ def _hitzer_inverse(self): | |||
""" | |||
Performs the inversion operation as described in the paper :cite:`Hitzer_Sangwine_2017` | |||
""" | |||
tot = np.sum(self.sig != 0) | |||
tot = len(self.sig) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note this is needed to get the correct behaviour for the tan test, presumably this is the solution for degenerate metric algebras but it would be nice to see a proof of this
clifford/test/test_trig_functions.py
Outdated
@pytest.mark.parametrize('np_func,cmath_func', [(np.sin, cmath.sin), | ||
(np.cos, cmath.cos), | ||
(np.tan, cmath.tan), | ||
(np.sinh, cmath.sinh), | ||
(np.cosh, cmath.cosh), | ||
(np.tanh, cmath.tanh)]) | ||
def test_trig_Cl010(self, Cl010element, np_func, cmath_func): | ||
""" | ||
This tests the a clifford algebra isomorphic to the complex numbers | ||
""" | ||
for x in np.linspace(0, 2 * np.pi, 10): | ||
for y in np.linspace(0, 2 * np.pi, 10): | ||
complex_mv = x * Cl010element[0] + y * Cl010element[1] | ||
complex_value = x + 1j * y | ||
result = np_func(complex_mv) | ||
assert abs(result.value[0] + 1j * result.value[1] - cmath_func(complex_value)) < 1E-10 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sent you down the rabbit hole with cmath_func
here - np.cos
works on complex numbers just fine - I had falsely assumed your tests were using math.cos
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries, I'll remove the cmath import and we can just stick to numpy then :)
clifford/taylor_expansions.py
Outdated
|
||
|
||
@_numba_utils.njit | ||
def general_exp(x, max_order=15): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd argue you can now remove all the general_
prefixes
This will need a merge / rebase in order to pull in the doc build pinning |
1dcc4a7
to
519a07a
Compare
I rebased and force pushed, hopefully this now works |
@@ -99,7 +99,25 @@ def _newMV(self, newValue=None, *, dtype: np.dtype = None) -> 'MultiVector': | |||
# binary | |||
|
|||
def exp(self) -> 'MultiVector': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May as well copy this annotation to all the methods below it
I think my last comment is wondering whether we can make these look more like general_exp, and whether that improves the numerical stability. For instance, we could replace We can always use that for a follow-up PR though, now that this PR adds tests |
Yes I think this would be a good idea to look at, I am sure that there will be some useful gains
This is my thoughts too |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Earlier review was on mobile, apologies. A few small ends to tie up:
- I've made some doc suggestions above to try and steer users towards how to use this, and to tweak some formatting.
- This needs a release note, and it's easier to add it now than to add it in later
- The tests should cover some negative coefficients too!
clifford/taylor_expansions.py
Outdated
|
||
This file implements various Taylor expansions for useful functions of multivectors. | ||
For some algebra signatures there may exist closed forms of these functions which would likely be faster | ||
and more accurate. Nonetheless having pre-written taylor expansions for the general case is useful. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and more accurate. Nonetheless having pre-written taylor expansions for the general case is useful. | |
and more accurate. Nonetheless, having pre-written taylor expansions for the general case is useful. | |
.. note:: | |
Many of these functions are also exposed as :class:`~clifford.MultiVector` methods, | |
such as :meth:`clifford.MultiVector.sin`. This means that ``mv.sin()`` or even ``np.sin(mv)`` can be used | |
as a convenient interface to functions in this module, without having to import it directly. | |
For example:: | |
>>> from clifford.g3 import * | |
>>> import numpy as np | |
>>> np.sin(np.pi*e12/4) | |
# what does this give? |
clifford/taylor_expansions.py
Outdated
@_numba_utils.njit | ||
def exp(x, max_order=15): | ||
""" | ||
This implements the series expansion of e**mv where mv is a multivector |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implements the series expansion of e**mv where mv is a multivector | |
This implements the series expansion of :math:`\exp x` where :math:`x` is a multivector |
clifford/taylor_expansions.py
Outdated
def exp(x, max_order=15): | ||
""" | ||
This implements the series expansion of e**mv where mv is a multivector | ||
The parameter order is the maximum order of the taylor series to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter order is the maximum order of the taylor series to use | |
The parameter `max_order` is the maximum order of the taylor series to use |
clifford/taylor_expansions.py
Outdated
Note. It would probably be better to implement this as its own taylor series. This function | ||
is not JITed as currently we do not overload the truediv operator for multivectors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note. It would probably be better to implement this as its own taylor series. This function | |
is not JITed as currently we do not overload the truediv operator for multivectors. | |
.. note:: | |
It would probably be better to implement this as its own taylor series. This function | |
is not JITed as currently we do not overload the truediv operator for multivectors. |
clifford/taylor_expansions.py
Outdated
Note. It would probably be better to implement this as its own taylor series. This function | ||
is not JITed as currently we do not overload the truediv operator for multivectors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note. It would probably be better to implement this as its own taylor series. This function | |
is not JITed as currently we do not overload the truediv operator for multivectors. | |
.. note:: | |
It would probably be better to implement this as its own taylor series. This function | |
is not JITed as currently we do not overload the truediv operator for multivectors. |
clifford/test/test_trig_functions.py
Outdated
@@ -0,0 +1,86 @@ | |||
|
|||
from .. import Cl |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relative imports in tests are usually a bad idea - tests shouldn't assume they are part of the package.
from .. import Cl | |
from clifford import Cl |
clifford/test/test_trig_functions.py
Outdated
(np.cosh, np.sinh), | ||
(np.tanh, lambda x: (1 - np.tanh(x)**2))]) | ||
def test_derivatives(self, element, func, deriv_func): | ||
for x in np.linspace(0, 2*np.pi, 10): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do these fare outside [0, 2*pi]
? I'd be inclined to expand this to at least include some negative values,
for x in np.linspace(0, 2*np.pi, 10): | |
for x in np.linspace(-2*np.pi, 2*np.pi, 13): |
clifford/taylor_expansions.py
Outdated
>>> np.sin(np.pi*e12/4) | ||
>>> # Produces (0.86867^e12) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
>>> np.sin(np.pi*e12/4) | |
>>> # Produces (0.86867^e12) | |
>>> np.sin(np.pi*e12/4) | |
(0.86867^e12) |
docs/changelog.rst
Outdated
@@ -12,6 +12,10 @@ Changes in 1.4.x | |||
* Where possible, ``MultiVector``\ s preserve their data type in the dual, and | |||
the right and left complements. | |||
|
|||
* A new :mod:`clifford.taylor_expansions` is added to implement taylor series of various | |||
multivector function, starting with common trigonometric functions. These functions are | |||
additionally exposed via a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
additionally exposed via a | |
additionally exposed via an incomplete sentence that Hugo forgot to write. |
clifford/taylor_expansions.py
Outdated
taylor_expansions (:mod:`clifford.taylor_expansions`) | ||
================================================= | ||
|
||
.. versionadded:: 1.4.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.. versionadded:: 1.4.1 | |
.. versionadded:: 1.4.0 |
clifford/taylor_expansions.py
Outdated
================================================= | ||
taylor_expansions (:mod:`clifford.taylor_expansions`) | ||
================================================= |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
================================================= | |
taylor_expansions (:mod:`clifford.taylor_expansions`) | |
================================================= | |
===================================================== | |
taylor_expansions (:mod:`clifford.taylor_expansions`) | |
===================================================== |
Thanks @hugohadfield 🎉 |
No description provided.