Source code for bertini._calculus
# This file is part of Bertini 2.
#
# bertini/_calculus.py is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# bertini/_calculus.py is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with bertini/_calculus.py. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright(C) Bertini2 Development Team
#
# See <http://www.gnu.org/licenses/> for a copy of the license,
# as well as COPYING. Bertini2 is provided with permitted
# additional terms in the b2/licenses/ directory.
"""Symbolic calculus over function trees (top-level ``bertini`` helpers)."""
import numpy as _np
from bertini._pybertini import system as _pybsys
from bertini._pybertini.function_tree import AbstractNode as _AbstractNode
__all__ = ['jacobian']
[docs]
def jacobian(functions, variables):
"""The symbolic Jacobian of ``functions`` with respect to ``variables``.
``J[i, j]`` is the partial derivative of ``functions[i]`` with respect to ``variables[j]``,
returned as a 2-D numpy object array of function-tree nodes -- always 2-D, even for a single
function, so it is ready to ``numpy.vstack`` onto a coefficient row and ``@`` a vector of
variables. This is purely symbolic (it builds expression trees via differentiation); it does
not evaluate. For a whole :class:`~bertini.System` use :meth:`bertini.System.jacobian`, which
is homogenization-aware.
Parameters
----------
functions : node or iterable of nodes
A single expression node or a sequence of them (a list or numpy object array).
variables : iterable of Variable
The variables to differentiate with respect to (a list, a numpy object array such as
:func:`bertini.variables`, or a :class:`~bertini.VariableGroup`).
Examples
--------
>>> import bertini as pb # doctest: +SKIP
>>> x, y, z = pb.Variable('x'), pb.Variable('y'), pb.Variable('z') # doctest: +SKIP
>>> J = pb.jacobian([x*y, x - z], [x, y, z]) # doctest: +SKIP
>>> J.shape # doctest: +SKIP
(2, 3)
"""
if isinstance(functions, _AbstractNode):
functions = [functions]
else:
functions = list(functions)
variables = list(variables)
rows = _pybsys.symbolic_jacobian(functions, variables)
arr = _np.array(rows, dtype=object)
if arr.ndim != 2: # empty function list collapses to 1-D; restore the (m, n) shape
arr = arr.reshape(len(functions), len(variables))
return arr