Skip to content
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

heyoka updates #161

Merged
merged 2 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/api_exsys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Expression system
:toctree: autosummary_generated

expression
make_vars
16 changes: 16 additions & 0 deletions doc/breaking_changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ heyoka.py 4 includes several backwards-incompatible changes.
API/behaviour changes
~~~~~~~~~~~~~~~~~~~~~

Changes to :py:func:`~heyoka.make_vars()`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The :py:func:`~heyoka.make_vars()` function now returns a single expression (rather than a list of expressions)
if a single argument is passed in input. This means that code such as

.. code-block:: python

x, = make_vars("x")

needs to be rewritten like this:

.. code-block:: python

x = make_vars("x")

Terminal events callbacks
^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
5 changes: 5 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ New
Changes
~~~~~~~

- **BREAKING**: the :py:func:`~heyoka.make_vars()` function
now returns a single expression (rather than a list of expressions)
if a single argument is passed in input
(`#161 <https://github.com/bluescarni/heyoka.py/pull/161>`__).
This is a :ref:`breaking change <bchanges_4_0_0>`.
- **BREAKING**: the signature of callbacks for terminal events
has been simplified
(`#158 <https://github.com/bluescarni/heyoka.py/pull/158>`__).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
"outputs": [],
"source": [
"# The state (using km as unit length)\n",
"xC, yC, zC, vxC, vyC, vzC, xD, yD, zD, vxD, vyD, vzD, = hy.make_vars(\"xC\", \"yC\", \"zC\", \"vxC\", \"vyC\", \"vzC\", \"xD\", \"yD\", \"zD\", \"vxD\", \"vyD\", \"vzD\")\n",
"xC, yC, zC, vxC, vyC, vzC, xD, yD, zD, vxD, vyD, vzD = hy.make_vars(\"xC\", \"yC\", \"zC\", \"vxC\", \"vyC\", \"vzC\", \"xD\", \"yD\", \"zD\", \"vxD\", \"vyD\", \"vzD\")\n",
"\n",
"# Parameters\n",
"mu = 398600.4418 #km^3/sec^2 \n",
Expand Down
2 changes: 1 addition & 1 deletion doc/notebooks/Comparing coordinate systems.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@
"\n",
"# Additional dynamical variable to\n",
"# integrate t(tau).\n",
"t, = hy.make_vars(\"t\")\n",
"t = hy.make_vars(\"t\")\n",
"\n",
"ta_del_e = hy.taylor_adaptive(\n",
" [(L, dL_dt*dt_dtau),\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
"lx, ly = hy.make_vars(\"lambda_x\", \"lambda_y\")\n",
"\n",
"# the control\n",
"u, = hy.make_vars(\"u\")\n",
"u = hy.make_vars(\"u\")\n",
"\n",
"# and the dynamics fx, fy\n",
"fx = hy.par[0]*x - hy.par[1]*x*y - x * hy.par[4] * u\n",
Expand Down
6 changes: 3 additions & 3 deletions doc/notebooks/definite_integrals.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
],
"source": [
"import heyoka as hy, numpy as np\n",
"x, = hy.make_vars(\"x\")\n",
"x = hy.make_vars(\"x\")\n",
"\n",
"# Integrate sin(t) between 0 and pi.\n",
"ta = hy.taylor_adaptive([(x, hy.sin(hy.time))], [0.])\n",
Expand Down Expand Up @@ -161,7 +161,7 @@
{
"data": {
"text/plain": [
"-0.012382281847117878"
"-0.012382281847117866"
]
},
"execution_count": 4,
Expand Down Expand Up @@ -260,7 +260,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.13"
"version": "3.10.13"
}
},
"nbformat": 4,
Expand Down
6 changes: 3 additions & 3 deletions doc/notebooks/elp2000.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion doc/notebooks/ffnn.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
],
"source": [
"# We create the symbols for the network inputs (only one in this first simple case)\n",
"x, = hy.make_vars(\"x\")\n",
"x = hy.make_vars(\"x\")\n",
"\n",
"# We define as nonlinearity a simple linear layer\n",
"linear = lambda inp: inp\n",
Expand Down
6 changes: 3 additions & 3 deletions doc/notebooks/vsop2013.ipynb

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions heyoka/_test_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class expression_test_case(_ut.TestCase):
def test_basic(self):
from . import expression as ex, core
from . import make_vars
import numpy as np

with_real128 = hasattr(core, "real128")
Expand All @@ -20,6 +21,24 @@ def test_basic(self):
if with_real128:
real128 = core.real128

# Minimal make_vars() testing.
with self.assertRaises(ValueError) as cm:
make_vars()
self.assertTrue(
"At least one argument is required when invoking 'make_vars()'"
in str(cm.exception)
)

x = make_vars("x")
self.assertTrue(isinstance(x, ex))
self.assertEqual(x, ex("x"))

l = make_vars("x", "y")
self.assertTrue(isinstance(l, list))
x, y = l
self.assertEqual(x, ex("x"))
self.assertEqual(y, ex("y"))

# Constructors.
self.assertEqual(ex(), ex(0))
self.assertEqual(ex(123), ex(123.0))
Expand Down
20 changes: 20 additions & 0 deletions heyoka/docstrings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,26 @@
namespace heyoka_py::docstrings
{

std::string make_vars()
{
return R"(make_vars(*args: str) -> expression | list[expression]

Create expressions from strings.

This function will return one or more :py:class:`~heyoka.expression`
instances constructed from the input arguments. If a single argument
is supplied, a single expression is returned. Otherwise, a list of
expressions (one for each argument) is returned.

:param args: the input string(s).

:returns: one or more expressions constructed from *args*.

:raises ValueError: if the number of *args* is zero.

)";
}

std::string lagrangian()
{
return R"(lagrangian(L: expression, qs: list[expression], qdots: list[expression], D: expression = expression(0.)) -> list[tuple[expression, expression]]
Expand Down
3 changes: 3 additions & 0 deletions heyoka/docstrings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
namespace heyoka_py::docstrings
{

// Expression system.
std::string make_vars();

// Lagrangian/Hamiltonian mechanics.
std::string lagrangian();
std::string hamiltonian();
Expand Down
26 changes: 19 additions & 7 deletions heyoka/expose_expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

#include "common_utils.hpp"
#include "custom_casters.hpp"
#include "docstrings.hpp"
#include "pickle_wrappers.hpp"

namespace heyoka_py
Expand Down Expand Up @@ -319,13 +320,24 @@ void expose_expression(py::module_ &m)
"arg"_a);

// make_vars() helper.
m.def("make_vars", [](const py::args &v_str) {
py::list retval;
for (auto o : v_str) {
retval.append(hey::expression(py::cast<std::string>(o)));
}
return retval;
});
m.def(
"make_vars",
[](const py::args &v_str) -> std::variant<hey::expression, py::list> {
if (py::len(v_str) == 0u) {
py_throw(PyExc_ValueError, "At least one argument is required when invoking 'make_vars()'");
}

if (py::len(v_str) == 1u) {
return hey::expression(py::cast<std::string>(v_str[0]));
}

py::list retval;
for (auto o : v_str) {
retval.append(hey::expression(py::cast<std::string>(o)));
}
return retval;
},
docstrings::make_vars().c_str());

// Math functions.

Expand Down