pytensor 2.38.3__tar.gz → 3.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytensor-2.38.3/pytensor.egg-info → pytensor-3.0.0}/PKG-INFO +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/creating_a_numba_jax_op.rst +13 -16
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/creating_an_op.rst +76 -79
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/op.rst +68 -124
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/pipeline.rst +49 -46
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/applications/normalizing_flows_in_pytensor.ipynb +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/autodiff/vector_jacobian_product.ipynb +13 -13
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/introduction/pytensor_intro.ipynb +5 -4
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/scan/scan_tutorial.ipynb +156 -146
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/internal/metadocumentation.rst +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/debugmode.rst +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/function.rst +5 -5
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/io.rst +23 -162
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/nanguardmode.rst +3 -3
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/config.rst +0 -36
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/index.rst +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/scan.rst +57 -38
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/index.rst +2 -1
- pytensor-3.0.0/doc/library/tensor/linalg.rst +72 -0
- pytensor-3.0.0/doc/library/tensor/nlinalg.rst +16 -0
- pytensor-3.0.0/doc/library/tensor/random.rst +119 -0
- pytensor-3.0.0/doc/library/tensor/slinalg.rst +16 -0
- pytensor-3.0.0/doc/library/xtensor/random.md +22 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/optimizations.rst +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/conditions.rst +0 -8
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/debug_faq.rst +2 -169
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/examples.rst +44 -87
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/gradients.rst +26 -26
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/index.rst +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/loop.rst +16 -15
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/modes.rst +0 -3
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/modes_solution_1.py +0 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/printing_drawing.rst +0 -2
- pytensor-3.0.0/doc/tutorial/prng.rst +603 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pyproject.toml +1 -1
- pytensor-3.0.0/pytensor/__init__.py +41 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/_version.py +3 -3
- pytensor-3.0.0/pytensor/basic.py +42 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/breakpoint.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/__init__.py +15 -13
- pytensor-3.0.0/pytensor/compile/aliasing.py +260 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/builders.py +260 -200
- {pytensor-2.38.3/pytensor/compile → pytensor-3.0.0/pytensor/compile/debug}/debugmode.py +35 -71
- pytensor-3.0.0/pytensor/compile/debug/dump.py +75 -0
- {pytensor-2.38.3/pytensor/compile → pytensor-3.0.0/pytensor/compile/debug}/profiling.py +1 -1
- pytensor-3.0.0/pytensor/compile/executor.py +871 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/io.py +7 -3
- pytensor-3.0.0/pytensor/compile/maker.py +741 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/mode.py +15 -32
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/ops.py +5 -31
- pytensor-2.38.3/pytensor/compile/function/pfunc.py → pytensor-3.0.0/pytensor/compile/rebuild.py +63 -211
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/sharedvalue.py +4 -3
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/configdefaults.py +162 -256
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/configparser.py +1 -32
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/d3viz.py +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/formatting.py +3 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/gradient.py +177 -189
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/__init__.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/basic.py +126 -79
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/destroyhandler.py +48 -64
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/features.py +166 -134
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/fg.py +230 -60
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/op.py +139 -204
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/replace.py +11 -6
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/basic.py +3 -3
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/unify.py +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/utils.py +0 -20
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/ifelse.py +21 -16
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/basic.py +8 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/basic.py +4 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/cmodule.py +2 -10
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/__init__.py +1 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/basic.py +3 -3
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/elemwise.py +1 -1
- pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/__init__.py +8 -0
- pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/constructors.py +12 -0
- pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/decomposition.py +140 -0
- pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/inverse.py +20 -0
- pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/products.py +21 -0
- pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/solvers.py +89 -0
- pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/summary.py +20 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/scalar.py +0 -11
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/subtensor.py +3 -33
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/ops.py +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/__init__.py +6 -3
- pytensor-3.0.0/pytensor/link/mlx/dispatch/basic.py +210 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/blas.py +14 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/einsum.py +14 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/elemwise.py +132 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/__init__.py +7 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/decomposition.py +176 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/inverse.py +24 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/products.py +22 -0
- pytensor-2.38.3/pytensor/link/mlx/dispatch/slinalg.py → pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/solvers.py +3 -41
- pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/summary.py +46 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/pad.py +37 -0
- pytensor-3.0.0/pytensor/link/mlx/dispatch/scalar.py +180 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/subtensor.py +5 -18
- pytensor-2.38.3/pytensor/link/mlx/dispatch/core.py → pytensor-3.0.0/pytensor/link/mlx/dispatch/tensor_basic.py +30 -81
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/linker.py +2 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/__init__.py +1 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/basic.py +4 -4
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/compile_ops.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/_LAPACK.py +501 -0
- pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/__init__.py +5 -0
- pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/constructors.py +77 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/cholesky.py +5 -3
- pytensor-2.38.3/pytensor/link/numba/dispatch/slinalg.py → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/decomposition/dispatch.py +285 -275
- pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/decomposition/eigen.py +1052 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/lu.py +8 -5
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/lu_factor.py +3 -3
- pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/inverse.py +40 -0
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/cholesky.py +11 -8
- pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers/dispatch.py +188 -0
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/general.py +5 -5
- pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers/hermitian.py +145 -0
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/lu_solve.py +6 -6
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/posdef.py +11 -8
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/symmetric.py +4 -4
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/triangular.py +10 -12
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/tridiagonal.py +15 -21
- pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/summary.py +46 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/random.py +5 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/scan.py +45 -10
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/subtensor.py +104 -67
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/typed_list.py +2 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/__init__.py +1 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/basic.py +4 -4
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/elemwise.py +1 -1
- pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/__init__.py +6 -0
- pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/decomposition.py +77 -0
- pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/inverse.py +22 -0
- pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/products.py +12 -0
- pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/summary.py +20 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/subtensor.py +10 -19
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/utils.py +9 -8
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/pkl_utils.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/printing.py +861 -185
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/raise_op.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/basic.py +200 -197
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/loop.py +19 -28
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/math.py +44 -54
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/basic.py +12 -46
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/op.py +242 -213
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/rewriting.py +777 -336
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/scan_perform.pyx +26 -25
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/scan_perform_ext.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/utils.py +18 -234
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/basic.py +20 -20
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/linalg.py +4 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/math.py +12 -12
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/rewriting.py +3 -3
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/sharedvar.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/type.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/__init__.py +5 -13
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/basic.py +44 -75
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/blas.py +14 -66
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/blockwise.py +24 -24
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/einsum.py +18 -13
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/elemwise.py +61 -51
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/extra_ops.py +7 -7
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/fft.py +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/fourier.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/interpolate.py +1 -1
- pytensor-3.0.0/pytensor/tensor/linalg/__init__.py +131 -0
- pytensor-3.0.0/pytensor/tensor/linalg/constructors.py +122 -0
- pytensor-3.0.0/pytensor/tensor/linalg/decomposition/__init__.py +1 -0
- pytensor-3.0.0/pytensor/tensor/linalg/decomposition/cholesky.py +198 -0
- pytensor-3.0.0/pytensor/tensor/linalg/decomposition/eigen.py +518 -0
- pytensor-3.0.0/pytensor/tensor/linalg/decomposition/lu.py +348 -0
- pytensor-3.0.0/pytensor/tensor/linalg/decomposition/qr.py +383 -0
- pytensor-3.0.0/pytensor/tensor/linalg/decomposition/schur.py +608 -0
- pytensor-3.0.0/pytensor/tensor/linalg/decomposition/svd.py +225 -0
- pytensor-3.0.0/pytensor/tensor/linalg/dtype_utils.py +42 -0
- pytensor-3.0.0/pytensor/tensor/linalg/inverse.py +224 -0
- pytensor-3.0.0/pytensor/tensor/linalg/products.py +176 -0
- pytensor-3.0.0/pytensor/tensor/linalg/solvers/__init__.py +0 -0
- pytensor-3.0.0/pytensor/tensor/linalg/solvers/core.py +126 -0
- pytensor-3.0.0/pytensor/tensor/linalg/solvers/general.py +266 -0
- {pytensor-2.38.3/pytensor/tensor/_linalg/solve → pytensor-3.0.0/pytensor/tensor/linalg/solvers}/linear_control.py +9 -4
- pytensor-3.0.0/pytensor/tensor/linalg/solvers/lstsq.py +98 -0
- pytensor-3.0.0/pytensor/tensor/linalg/solvers/psd.py +107 -0
- pytensor-3.0.0/pytensor/tensor/linalg/solvers/triangular.py +142 -0
- pytensor-3.0.0/pytensor/tensor/linalg/summary.py +342 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/math.py +78 -40
- pytensor-3.0.0/pytensor/tensor/nlinalg.py +58 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/optimize.py +25 -10
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/__init__.py +1 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/basic.py +32 -23
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/op.py +48 -10
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/rewriting/basic.py +55 -26
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/type.py +63 -16
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/utils.py +12 -62
- pytensor-3.0.0/pytensor/tensor/random/variable.py +252 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/reshape.py +3 -5
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/__init__.py +1 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/blas_c.py +6 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/einsum.py +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/elemwise.py +31 -31
- pytensor-3.0.0/pytensor/tensor/rewriting/linalg/__init__.py +11 -0
- pytensor-3.0.0/pytensor/tensor/rewriting/linalg/decomposition.py +134 -0
- pytensor-3.0.0/pytensor/tensor/rewriting/linalg/inverse.py +163 -0
- pytensor-3.0.0/pytensor/tensor/rewriting/linalg/products.py +154 -0
- pytensor-2.38.3/pytensor/tensor/_linalg/solve/rewriting.py → pytensor-3.0.0/pytensor/tensor/rewriting/linalg/solvers.py +193 -57
- pytensor-3.0.0/pytensor/tensor/rewriting/linalg/summary.py +280 -0
- pytensor-3.0.0/pytensor/tensor/rewriting/linalg/utils.py +84 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/math.py +51 -4
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/ofg.py +1 -2
- pytensor-3.0.0/pytensor/tensor/rewriting/optimize.py +48 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/reshape.py +30 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/shape.py +62 -46
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/subtensor.py +733 -393
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/subtensor_lift.py +29 -32
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/uncanonicalize.py +34 -52
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/shape.py +20 -26
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/sharedvar.py +2 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/signal/conv.py +1 -1
- pytensor-3.0.0/pytensor/tensor/slinalg.py +65 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/sort.py +14 -14
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/special.py +12 -15
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/subtensor.py +764 -835
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/type.py +3 -9
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/type_other.py +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/utils.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/variable.py +50 -78
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/xlogx.py +2 -2
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/typed_list/basic.py +1 -3
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/typed_list/type.py +3 -4
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/__init__.py +1 -6
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/basic.py +3 -3
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/linalg.py +2 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/math.py +6 -2
- pytensor-3.0.0/pytensor/xtensor/random/__init__.py +2 -0
- pytensor-3.0.0/pytensor/xtensor/random/basic.py +254 -0
- pytensor-3.0.0/pytensor/xtensor/random/type.py +88 -0
- pytensor-3.0.0/pytensor/xtensor/random/variable.py +205 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/basic.py +25 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/indexing.py +5 -4
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/vectorization.py +14 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/type.py +30 -5
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/vectorization.py +17 -5
- {pytensor-2.38.3 → pytensor-3.0.0/pytensor.egg-info}/PKG-INFO +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/SOURCES.txt +88 -39
- {pytensor-2.38.3 → pytensor-3.0.0}/scripts/mypy-failing.txt +4 -4
- pytensor-3.0.0/tests/test_basic.py +34 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_breakpoint.py +1 -1
- {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_config.py +0 -13
- {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_gradient.py +7 -35
- {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_ifelse.py +0 -8
- pytensor-3.0.0/tests/test_printing.py +773 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_rop.py +106 -93
- pytensor-2.38.3/doc/library/tensor/nlinalg.rst +0 -22
- pytensor-2.38.3/doc/library/tensor/random/distributions.rst +0 -8
- pytensor-2.38.3/doc/library/tensor/random/index.rst +0 -90
- pytensor-2.38.3/doc/library/tensor/slinalg.rst +0 -23
- pytensor-2.38.3/doc/library/xtensor/random.md +0 -7
- pytensor-2.38.3/doc/tutorial/prng.rst +0 -736
- pytensor-2.38.3/pytensor/__init__.py +0 -176
- pytensor-2.38.3/pytensor/compile/function/__init__.py +0 -348
- pytensor-2.38.3/pytensor/compile/function/types.py +0 -1973
- pytensor-2.38.3/pytensor/link/jax/dispatch/nlinalg.py +0 -82
- pytensor-2.38.3/pytensor/link/jax/dispatch/slinalg.py +0 -211
- pytensor-2.38.3/pytensor/link/mlx/dispatch/basic.py +0 -101
- pytensor-2.38.3/pytensor/link/mlx/dispatch/elemwise.py +0 -457
- pytensor-2.38.3/pytensor/link/mlx/dispatch/nlinalg.py +0 -69
- pytensor-2.38.3/pytensor/link/numba/dispatch/nlinalg.py +0 -179
- pytensor-2.38.3/pytensor/link/pytorch/dispatch/nlinalg.py +0 -87
- pytensor-2.38.3/pytensor/link/pytorch/dispatch/slinalg.py +0 -23
- pytensor-2.38.3/pytensor/tensor/_linalg/__init__.py +0 -2
- pytensor-2.38.3/pytensor/tensor/_linalg/solve/__init__.py +0 -2
- pytensor-2.38.3/pytensor/tensor/linalg.py +0 -3
- pytensor-2.38.3/pytensor/tensor/nlinalg.py +0 -1202
- pytensor-2.38.3/pytensor/tensor/random/var.py +0 -37
- pytensor-2.38.3/pytensor/tensor/rewriting/linalg.py +0 -1147
- pytensor-2.38.3/pytensor/tensor/slinalg.py +0 -2416
- pytensor-2.38.3/pytensor/updates.py +0 -60
- pytensor-2.38.3/pytensor/xtensor/random.py +0 -292
- pytensor-2.38.3/tests/test_printing.py +0 -498
- pytensor-2.38.3/tests/test_updates.py +0 -70
- {pytensor-2.38.3 → pytensor-3.0.0}/LICENSE.txt +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/MANIFEST.in +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/README.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/.templates/PLACEHOLDER +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/.templates/layout.html +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/.templates/nb-badges.html +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/.templates/rendered_citation.html +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/LICENSE.txt +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/README.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/_drafts/benchmark_mlx_v_jax_corrected.ipynb +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/_thumbnails/autodiff/vector_jacobian_product.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/acknowledgement.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/bcast.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/bcast.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/blog.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/conf.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/core_development_guide.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/css.inc +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/dev_start_guide.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/environment.yml +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/apply.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/apply.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/apply2.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/creating_a_c_op.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/ctype.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/extending_faq.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/extending_pytensor_solution_1.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/graph_rewriting.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/graphstructures.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/index.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/inplace.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/other_ops.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/pics/symbolic_graph_opt.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/pics/symbolic_graph_unopt.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/scan.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/tips.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/type.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/unittest.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/using_params.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/faq.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/optimize/root.ipynb +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/page_footer.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/rewrites/graph_rewrites.ipynb +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/generate_dtype_tensor_table.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/glossary.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/Elman_srnn.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/PyTensor.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/PyTensor_RGB.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/PyTensor_logo.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/binder.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/blocksparse.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/colab.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/github.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/lstm.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/lstm_memorycell.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/talk2010.gif +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/talk2010.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/index.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/install.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/internal/how_to_release.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/internal/index.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/introduction.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/index.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/mode.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/opfromgraph.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/ops.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/profilemode.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/shared.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/css/d3-context-menu.css +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/css/d3viz.css +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/d3-context-menu.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/d3.v3.min.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/d3viz.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/dagre-d3.min.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/graphlib-dot.min.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp.html +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp2.html +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp2.pdf +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp2.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/ofg.html +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/ofg2.html +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index.ipynb +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index_files/index_10_0.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index_files/index_11_0.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index_files/index_24_0.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index_files/index_25_0.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/features.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/fgraph.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/graph.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/index.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/op.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/replace.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/type.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/utils.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/misc/pkl_utils.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/printing.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/scalar/index.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/sparse/index.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/sparse/sandbox.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/basic.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/basic_opt.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/bcast.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/bcast.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/elemwise.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/extra_ops.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/fft.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/functional.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/io.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/math_opt.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/optimize.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/plot_fft.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/utils.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/typed_list.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/index.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/linalg.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/math.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/module_functions.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/signal.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/type.md +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/links.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/pylintrc +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/robots.txt +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/troubleshooting.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/adding.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/adding_solution_1.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/aliasing.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/apply.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/apply.svg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/bcast.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/broadcasting.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/dlogistic.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/faq_tutorial.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/loading_and_saving.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/logistic.gp +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/logistic.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/loop_solution_1.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/multi_cores.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/nan_tutorial.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/pics/d3viz.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/pics/logreg_pydotprint_predict.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/pics/logreg_pydotprint_prediction.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/pics/logreg_pydotprint_train.png +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/profiling.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/profiling_example.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/profiling_example_out.prof +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/shape_info.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/sparse.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/symbolic_graphs.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/doc/user_guide.rst +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/bin/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/bin/pytensor_cache.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/compiledir.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/compilelock.py +0 -0
- {pytensor-2.38.3/pytensor/link/c → pytensor-3.0.0/pytensor/compile/debug}/__init__.py +0 -0
- {pytensor-2.38.3/pytensor/compile → pytensor-3.0.0/pytensor/compile/debug}/monitormode.py +0 -0
- {pytensor-2.38.3/pytensor/compile → pytensor-3.0.0/pytensor/compile/debug}/nanguardmode.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/css/d3-context-menu.css +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/css/d3viz.css +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/html/template.html +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/d3-context-menu.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/d3.v3.min.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/d3viz.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/dagre-d3.min.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/graphlib-dot.min.js +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/null_type.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/db.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/kanren.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/utils.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/traversal.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/type.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/ipython.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/__init__.py +0 -0
- {pytensor-2.38.3/pytensor/link/mlx/dispatch/signal → pytensor-3.0.0/pytensor/link/c}/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/c_code/lazylinker_c.c +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/c_code/pytensor_mod_helper.h +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/cutils.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/cvm.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/exceptions.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/interface.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/lazylinker_c.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/op.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/params_type.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/type.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/blas.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/blockwise.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/einsum.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/extra_ops.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/math.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/pad.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/random.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/scan.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/shape.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/signal/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/signal/conv.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/sort.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/sparse.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/tensor_basic.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/linker.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/blockwise.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/extra_ops.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/math.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/shape.py +0 -0
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg → pytensor-3.0.0/pytensor/link/mlx/dispatch/signal}/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/signal/conv.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/sort.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/cache.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/blockwise.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/cython_support.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/elemwise.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/extra_ops.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/qr.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/qz.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/schur.py +0 -0
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/__init__.py +0 -0
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/linear_control.py +0 -0
- {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/utils.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/utils.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/scalar.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/shape.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/signal/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/signal/conv.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sort.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sparse/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sparse/basic.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sparse/math.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sparse/variable.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/string_codegen.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/tensor_basic.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/vectorize_codegen.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/linker.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/blas.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/blockwise.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/extra_ops.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/math.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/scalar.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/shape.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/sort.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/linker.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/vm.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/check_blas.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/check_blas_many.sh +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/check_duplicate_key.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/elemwise_openmp_speedup.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/elemwise_time_test.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/frozendict.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/may_share_memory.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/ordered_set.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/npy_2_compat.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/py.typed +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/c_code/Faddeeva.cc +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/c_code/Faddeeva.hh +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/c_code/gamma.c +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/c_code/incbet.c +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/sharedvar.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/checkpoints.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/views.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/utils.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/variable.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/blas_c.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/blas_headers.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/c_code/alt_blas_common.h +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/c_code/alt_blas_template.c +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/c_code/dimshuffle.c +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/elemwise_cgen.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/exceptions.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/functional.py +0 -0
- {pytensor-2.38.3/pytensor/tensor/_linalg/solve → pytensor-3.0.0/pytensor/tensor/linalg/solvers}/tridiagonal.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/pad.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/rewriting/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/rewriting/jax.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/rewriting/numba.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/basic.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/blas.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/blockwise.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/extra_ops.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/jax.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/numba.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/special.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/signal/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/var.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/typed_list/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/typed_list/rewriting.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/utils.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/indexing.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/reduction.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/__init__.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/math.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/reduction.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/shape.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/utils.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/shape.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/signal.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/dependency_links.txt +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/entry_points.txt +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/requires.txt +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/top_level.txt +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/scripts/slowest_tests/update-slowest-times-issue.sh +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/setup.cfg +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/setup.py +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/tests/link/c/c_code/test_cenum.h +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/tests/link/c/c_code/test_quadratic_function.c +0 -0
- {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_raise_op.py +0 -0
|
@@ -484,7 +484,6 @@ Step 4: Write tests
|
|
|
484
484
|
from pytensor.configdefaults import config
|
|
485
485
|
from tests.link.jax.test_basic import compare_jax_and_py
|
|
486
486
|
from pytensor.graph import FunctionGraph
|
|
487
|
-
from pytensor.graph.op import get_test_value
|
|
488
487
|
|
|
489
488
|
def test_jax_CumOp():
|
|
490
489
|
"""Test JAX conversion of the `CumOp` `Op`."""
|
|
@@ -492,8 +491,7 @@ Step 4: Write tests
|
|
|
492
491
|
# Create a symbolic input for the first input of `CumOp`
|
|
493
492
|
a = pt.matrix("a")
|
|
494
493
|
|
|
495
|
-
|
|
496
|
-
a.tag.test_value = np.arange(9, dtype=config.floatX).reshape((3, 3))
|
|
494
|
+
test_value = np.arange(9, dtype=config.floatX).reshape((3, 3))
|
|
497
495
|
|
|
498
496
|
# Create the output variable
|
|
499
497
|
out = pt.cumsum(a, axis=0)
|
|
@@ -502,12 +500,12 @@ Step 4: Write tests
|
|
|
502
500
|
fgraph = FunctionGraph([a], [out])
|
|
503
501
|
|
|
504
502
|
# Pass the graph and inputs to the testing function
|
|
505
|
-
compare_jax_and_py(fgraph, [
|
|
503
|
+
compare_jax_and_py(fgraph, [test_value])
|
|
506
504
|
|
|
507
505
|
# For the second mode of CumOp
|
|
508
506
|
out = pt.cumprod(a, axis=1)
|
|
509
507
|
fgraph = FunctionGraph([a], [out])
|
|
510
|
-
compare_jax_and_py(fgraph, [
|
|
508
|
+
compare_jax_and_py(fgraph, [test_value])
|
|
511
509
|
|
|
512
510
|
If the variant :class:`CumprodOp` is not implemented, we can add a test for it as follows:
|
|
513
511
|
|
|
@@ -518,12 +516,12 @@ Step 4: Write tests
|
|
|
518
516
|
def test_jax_CumOp():
|
|
519
517
|
"""Test JAX conversion of the `CumOp` `Op`."""
|
|
520
518
|
a = pt.matrix("a")
|
|
521
|
-
|
|
519
|
+
test_value = np.arange(9, dtype=config.floatX).reshape((3, 3))
|
|
522
520
|
|
|
523
521
|
with pytest.raises(NotImplementedError):
|
|
524
522
|
out = pt.cumprod(a, axis=1)
|
|
525
523
|
fgraph = FunctionGraph([a], [out])
|
|
526
|
-
compare_jax_and_py(fgraph, [
|
|
524
|
+
compare_jax_and_py(fgraph, [test_value])
|
|
527
525
|
|
|
528
526
|
|
|
529
527
|
.. tab-item:: Numba
|
|
@@ -543,23 +541,23 @@ Step 4: Write tests
|
|
|
543
541
|
|
|
544
542
|
.. code:: python
|
|
545
543
|
|
|
544
|
+
import numpy as np
|
|
545
|
+
from pytensor.configdefaults import config
|
|
546
546
|
from tests.link.numba.test_basic import compare_numba_and_py
|
|
547
547
|
from pytensor.graph import FunctionGraph
|
|
548
|
-
from pytensor.compile.sharedvalue import SharedVariable
|
|
549
|
-
from pytensor.graph.basic import Constant
|
|
550
548
|
from pytensor.tensor import extra_ops
|
|
549
|
+
import pytensor.tensor as pt
|
|
550
|
+
|
|
551
|
+
def test_CumOp(axis, mode):
|
|
552
|
+
val = pt.matrix("val")
|
|
553
|
+
test_value = np.arange(9, dtype=config.floatX).reshape((3, 3))
|
|
551
554
|
|
|
552
|
-
def test_CumOp(val, axis, mode):
|
|
553
555
|
g = extra_ops.CumOp(axis=axis, mode=mode)(val)
|
|
554
556
|
g_fg = FunctionGraph(outputs=[g])
|
|
555
557
|
|
|
556
558
|
compare_numba_and_py(
|
|
557
559
|
g_fg,
|
|
558
|
-
[
|
|
559
|
-
i.tag.test_value
|
|
560
|
-
for i in g_fg.inputs
|
|
561
|
-
if not isinstance(i, SharedVariable | Constant)
|
|
562
|
-
],
|
|
560
|
+
[test_value],
|
|
563
561
|
)
|
|
564
562
|
|
|
565
563
|
|
|
@@ -601,7 +599,6 @@ Step 4: Write tests
|
|
|
601
599
|
# Create a symbolic input for the first input of `CumOp`
|
|
602
600
|
a = pt.matrix("a", dtype=dtype)
|
|
603
601
|
|
|
604
|
-
# Create test value
|
|
605
602
|
test_value = np.arange(9, dtype=dtype).reshape((3, 3))
|
|
606
603
|
|
|
607
604
|
# Create the output variable
|
|
@@ -74,20 +74,12 @@ possibilities you may encounter or need. For that refer to
|
|
|
74
74
|
def perform(self, node: Apply, inputs_storage: list[Any], output_storage: list[list[Any]]) -> None:
|
|
75
75
|
pass
|
|
76
76
|
|
|
77
|
-
# Defines the
|
|
78
|
-
|
|
79
|
-
def L_op(self, inputs: list[Variable], outputs: list[Variable], output_grads: list[Variable]) -> list[Variable]:
|
|
77
|
+
# Defines the vector-Jacobian product (pullback/reverse-mode AD). Optional.
|
|
78
|
+
def pullback(self, inputs: list[Variable], outputs: list[Variable], cotangents: list[Variable]) -> list[Variable]:
|
|
80
79
|
pass
|
|
81
80
|
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
-
def grad(self, inputs: list[Variable], output_grads: list[Variable]) -> list[Variable]:
|
|
85
|
-
# Same as self.L_op(inputs, self(inputs), output_grads)
|
|
86
|
-
pass
|
|
87
|
-
|
|
88
|
-
# Defines the symbolic expression for the R-operator based on the input variables
|
|
89
|
-
# and eval_point variables. Optional.
|
|
90
|
-
def R_op(self, inputs: list[Variable], eval_points: list[Variable | None]) -> list[Variable | None]:
|
|
81
|
+
# Defines the Jacobian-vector product (pushforward/forward-mode AD). Optional.
|
|
82
|
+
def pushforward(self, inputs: list[Variable], outputs: list[Variable], tangents: list[Variable]) -> list[Variable]:
|
|
91
83
|
pass
|
|
92
84
|
|
|
93
85
|
# Defines the symbolic expression for the output shape based on the input shapes
|
|
@@ -182,36 +174,42 @@ This could be helpful if one only needs the shape of the output instead of the
|
|
|
182
174
|
actual outputs, which can be useful, for instance, for rewriting
|
|
183
175
|
procedures.
|
|
184
176
|
|
|
185
|
-
:meth:`
|
|
186
|
-
|
|
177
|
+
:meth:`pullback`
|
|
178
|
+
^^^^^^^^^^^^^^^^^^^
|
|
187
179
|
|
|
188
|
-
The :meth:`
|
|
189
|
-
whose expression includes your :class:`Op`.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
to
|
|
180
|
+
The :meth:`pullback` method is required if you want to differentiate some cost
|
|
181
|
+
whose expression includes your :class:`Op`. It implements the vector-Jacobian
|
|
182
|
+
product (VJP) for reverse-mode automatic differentiation.
|
|
183
|
+
|
|
184
|
+
It takes three arguments ``inputs``, ``outputs`` and ``cotangents``, which are
|
|
185
|
+
all lists of :ref:`variable`\s that must be operated on using PyTensor's
|
|
186
|
+
symbolic language. The :meth:`pullback` method must return a list containing
|
|
187
|
+
one :ref:`variable` for each input. Each returned :ref:`variable` represents
|
|
188
|
+
the cotangent (gradient) with respect to that input computed based on the
|
|
189
|
+
symbolic cotangents with respect to each output.
|
|
197
190
|
|
|
198
191
|
If the output is not differentiable with respect to an input then
|
|
199
|
-
this method should
|
|
200
|
-
for that input.
|
|
201
|
-
|
|
202
|
-
:
|
|
203
|
-
|
|
192
|
+
this method should return a variable of type :class:`DisconnectedType`
|
|
193
|
+
for that input. If the gradient is not implemented or undefined for some
|
|
194
|
+
input, return a variable of type :class:`NullType` for that input
|
|
195
|
+
(see :func:`pytensor.gradient.grad_not_implemented` and
|
|
196
|
+
:func:`pytensor.gradient.grad_undefined`).
|
|
204
197
|
|
|
205
|
-
:meth:`
|
|
206
|
-
|
|
207
|
-
The :meth:`R_op` method is needed if you want :func:`pytensor.gradient.Rop` to
|
|
208
|
-
work with your :class:`Op`.
|
|
198
|
+
:meth:`pushforward`
|
|
199
|
+
^^^^^^^^^^^^^^^^^^^^^^
|
|
209
200
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
201
|
+
The :meth:`pushforward` method is needed if you want :func:`pytensor.gradient.pushforward` to
|
|
202
|
+
work with your :class:`Op` with the non-default ``use_op_pushforward=True`` argument.
|
|
203
|
+
It implements the Jacobian-vector product (JVP) for forward-mode automatic
|
|
204
|
+
differentiation.
|
|
205
|
+
|
|
206
|
+
Given a function :math:`f` with input :math:`x`, the pushforward computes
|
|
207
|
+
:math:`J \dot{x}` where :math:`J = \frac{\partial f}{\partial x}` is the
|
|
208
|
+
Jacobian and :math:`\dot{x}` are the tangent vectors. It takes ``inputs``,
|
|
209
|
+
``outputs``, and ``tangents`` as arguments. Tangent entries of type
|
|
210
|
+
:class:`DisconnectedType` indicate that the corresponding input is not being
|
|
211
|
+
differentiated. ``None`` must not be used to indicate disconnected entries;
|
|
212
|
+
use :class:`DisconnectedType` variables instead.
|
|
215
213
|
|
|
216
214
|
|
|
217
215
|
Example: :class:`Op` definition
|
|
@@ -253,22 +251,21 @@ Example: :class:`Op` definition
|
|
|
253
251
|
# The output shape is the same as the input shape
|
|
254
252
|
return input_shapes
|
|
255
253
|
|
|
256
|
-
def
|
|
257
|
-
# Symbolic expression for the
|
|
254
|
+
def pullback(self, inputs: list[TensorVariable], outputs: list[TensorVariable], cotangents: list[TensorVariable]):
|
|
255
|
+
# Symbolic expression for the vector-Jacobian product
|
|
258
256
|
# For this Op, the inputs and outputs aren't part of the expression
|
|
259
|
-
#
|
|
260
|
-
return [
|
|
261
|
-
|
|
262
|
-
def
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
#
|
|
266
|
-
# return
|
|
267
|
-
if
|
|
268
|
-
return
|
|
269
|
-
# For this Op, the
|
|
270
|
-
|
|
271
|
-
return self.L_op(inputs, outputs, eval_points)
|
|
257
|
+
# cotangents[0] is a TensorVariable!
|
|
258
|
+
return [cotangents[0] * 2]
|
|
259
|
+
|
|
260
|
+
def pushforward(self, inputs: list[TensorVariable], outputs: list[TensorVariable], tangents: list[TensorVariable]):
|
|
261
|
+
from pytensor.gradient import DisconnectedType, disconnected_type
|
|
262
|
+
|
|
263
|
+
# pushforward receives DisconnectedType for non-differentiable inputs.
|
|
264
|
+
# If this means you cannot compute some outputs, return disconnected_type() for those.
|
|
265
|
+
if isinstance(tangents[0].type, DisconnectedType):
|
|
266
|
+
return [disconnected_type()]
|
|
267
|
+
# For this Op, the Jacobian-vector product is symmetric
|
|
268
|
+
return [tangents[0] * 2]
|
|
272
269
|
|
|
273
270
|
doubleOp1 = DoubleOp1()
|
|
274
271
|
|
|
@@ -486,8 +483,8 @@ Furthermore, this :class:`Op` will work with batched dimensions, meaning we can
|
|
|
486
483
|
To achieve this behavior we cannot use `itypes` and `otypes` as those encode specific number of dimensions.
|
|
487
484
|
Instead we will have to define the `make_node` method.
|
|
488
485
|
|
|
489
|
-
We need to be careful in the :meth:`
|
|
490
|
-
If both outputs are disconnected PyTensor will not bother calling the :meth:`
|
|
486
|
+
We need to be careful in the :meth:`pullback` method, as one of output cotangents may be disconnected from the cost, in which case we should ignore its contribution.
|
|
487
|
+
If both outputs are disconnected PyTensor will not bother calling the :meth:`pullback` method, so we don't need to worry about that case.
|
|
491
488
|
|
|
492
489
|
.. testcode::
|
|
493
490
|
|
|
@@ -534,23 +531,23 @@ If both outputs are disconnected PyTensor will not bother calling the :meth:`L_o
|
|
|
534
531
|
out2_shape = y_shapes[:-1]
|
|
535
532
|
return [out1_shape, out2_shape]
|
|
536
533
|
|
|
537
|
-
def
|
|
534
|
+
def pullback(self, inputs, outputs, cotangents):
|
|
538
535
|
x, y = inputs
|
|
539
|
-
|
|
536
|
+
out1_ct, out2_ct = cotangents
|
|
540
537
|
|
|
541
|
-
if isinstance(
|
|
542
|
-
|
|
538
|
+
if isinstance(out1_ct.type, DisconnectedType):
|
|
539
|
+
x_ct = disconnected_type()
|
|
543
540
|
else:
|
|
544
|
-
# Transpose the last two dimensions of the output
|
|
545
|
-
|
|
541
|
+
# Transpose the last two dimensions of the output cotangent
|
|
542
|
+
x_ct = pt.swapaxes(out1_ct, -1, -2)
|
|
546
543
|
|
|
547
|
-
if isinstance(
|
|
548
|
-
|
|
544
|
+
if isinstance(out2_ct.type, DisconnectedType):
|
|
545
|
+
y_ct = disconnected_type()
|
|
549
546
|
else:
|
|
550
|
-
# Broadcast the output
|
|
551
|
-
|
|
547
|
+
# Broadcast the output cotangent to the same shape as y
|
|
548
|
+
y_ct = pt.broadcast_to(pt.expand_dims(out2_ct, -1), y.shape)
|
|
552
549
|
|
|
553
|
-
return [
|
|
550
|
+
return [x_ct, y_ct]
|
|
554
551
|
|
|
555
552
|
Let's test the `Op` evaluation:
|
|
556
553
|
|
|
@@ -659,8 +656,8 @@ that are added to the codebase, to be used with ``pytest``.
|
|
|
659
656
|
|
|
660
657
|
Here we mention those that can be used to test the implementation of:
|
|
661
658
|
:meth:`infer_shape`
|
|
662
|
-
:meth:`
|
|
663
|
-
:meth:`
|
|
659
|
+
:meth:`pullback`
|
|
660
|
+
:meth:`pushforward`
|
|
664
661
|
|
|
665
662
|
|
|
666
663
|
Basic Tests
|
|
@@ -763,25 +760,25 @@ If you want to see it fail, you can implement an incorrect gradient
|
|
|
763
760
|
rng = rng,
|
|
764
761
|
)
|
|
765
762
|
|
|
766
|
-
Testing the
|
|
767
|
-
|
|
763
|
+
Testing the pushforward
|
|
764
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
768
765
|
|
|
769
|
-
The class :class:`
|
|
770
|
-
:meth:`
|
|
771
|
-
These allow to test the implementation of the :meth:`
|
|
766
|
+
The class :class:`PushforwardPullbackChecker` defines the methods
|
|
767
|
+
:meth:`PushforwardPullbackChecker.check_mat_pushforward_pullback`, :meth:`PushforwardPullbackChecker.check_pushforward_pullback` and :meth:`PushforwardPullbackChecker.check_nondiff_pushforward`.
|
|
768
|
+
These allow to test the implementation of the :meth:`pushforward` method of a particular :class:`Op`.
|
|
772
769
|
|
|
773
|
-
For instance, to verify the :meth:`
|
|
770
|
+
For instance, to verify the :meth:`pushforward` method of the ``DoubleOp``, you can use this:
|
|
774
771
|
|
|
775
772
|
.. testcode:: tests
|
|
776
773
|
|
|
777
774
|
import numpy
|
|
778
775
|
import tests
|
|
779
|
-
from tests.test_rop import
|
|
776
|
+
from tests.test_rop import PushforwardPullbackChecker
|
|
780
777
|
|
|
781
|
-
class
|
|
778
|
+
class TestDoubleOpPushforward(PushforwardPullbackChecker):
|
|
782
779
|
|
|
783
|
-
def
|
|
784
|
-
self.
|
|
780
|
+
def test_double_pushforward(self):
|
|
781
|
+
self.check_pushforward_pullback(DoubleOp()(self.x), self.in_shape)
|
|
785
782
|
|
|
786
783
|
|
|
787
784
|
Running Your Tests
|
|
@@ -798,7 +795,7 @@ Modify and execute to compute: ``x * y``.
|
|
|
798
795
|
|
|
799
796
|
Modify and execute the example to return two outputs: ``x + y`` and `jx - yj`.
|
|
800
797
|
|
|
801
|
-
You can omit the :meth:`
|
|
798
|
+
You can omit the :meth:`pushforward` method. Try to implement the testing apparatus described above.
|
|
802
799
|
|
|
803
800
|
:download:`Solution<extending_pytensor_solution_1.py>`
|
|
804
801
|
|
|
@@ -830,7 +827,7 @@ It takes an optional :meth:`infer_shape` parameter that must have this signature
|
|
|
830
827
|
|
|
831
828
|
.. note::
|
|
832
829
|
|
|
833
|
-
As no
|
|
830
|
+
As no pullback is defined, this means you won't be able to
|
|
834
831
|
differentiate paths that include this :class:`Op`.
|
|
835
832
|
|
|
836
833
|
.. note::
|
|
@@ -244,21 +244,28 @@ Optional methods or attributes
|
|
|
244
244
|
If you want your :class:`Op` to work with :func:`pytensor.gradient.grad` you also
|
|
245
245
|
need to implement the functions described below.
|
|
246
246
|
|
|
247
|
-
|
|
248
|
-
|
|
247
|
+
Automatic Differentiation
|
|
248
|
+
=========================
|
|
249
249
|
|
|
250
|
-
These are the
|
|
250
|
+
These are the functions required to work with :func:`pytensor.gradient.grad`
|
|
251
|
+
and :func:`pytensor.gradient.pushforward`.
|
|
251
252
|
|
|
252
|
-
.. function::
|
|
253
|
+
.. function:: pullback(inputs, outputs, cotangents)
|
|
253
254
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
255
|
+
Implements the vector-Jacobian product (VJP) for reverse-mode automatic
|
|
256
|
+
differentiation. This is the primary method for gradient computation.
|
|
257
|
+
|
|
258
|
+
Given a function :math:`f` with inputs :math:`x` and outputs :math:`y = f(x)`,
|
|
259
|
+
the pullback computes :math:`\bar{x} = \bar{y} J` where
|
|
260
|
+
:math:`J = \frac{\partial f}{\partial x}` is the Jacobian and
|
|
261
|
+
:math:`\bar{y}` are the cotangent (row) vectors (upstream gradients).
|
|
262
|
+
|
|
263
|
+
Both ``inputs``, ``outputs``, and ``cotangents`` are lists of symbolic PyTensor
|
|
264
|
+
:class:`Variable`\s and those must be operated on using PyTensor's symbolic
|
|
265
|
+
language. The :meth:`Op.pullback` method must return a list containing one
|
|
266
|
+
:class:`Variable` for each input. Each returned :class:`Variable` represents
|
|
267
|
+
the cotangent with respect to that input computed based on the symbolic
|
|
268
|
+
cotangents with respect to each output.
|
|
262
269
|
|
|
263
270
|
If the output is not differentiable with respect to an input then
|
|
264
271
|
this method should be defined to return a variable of type :class:`NullType`
|
|
@@ -269,108 +276,50 @@ These are the function required to work with :func:`pytensor.gradient.grad`.
|
|
|
269
276
|
:func:`pytensor.gradient.grad_undefined` and
|
|
270
277
|
:func:`pytensor.gradient.grad_not_implemented`, respectively.
|
|
271
278
|
|
|
272
|
-
If an element of ``
|
|
279
|
+
If an element of ``cotangents`` is of type
|
|
273
280
|
:class:`pytensor.gradient.DisconnectedType`, it means that the cost is not a
|
|
274
281
|
function of this output. If any of the :class:`Op`'s inputs participate in
|
|
275
|
-
the computation of only disconnected outputs, then :meth:`Op.
|
|
282
|
+
the computation of only disconnected outputs, then :meth:`Op.pullback` should
|
|
276
283
|
return :class:`DisconnectedType` variables for those inputs.
|
|
277
284
|
|
|
278
|
-
If
|
|
285
|
+
If :meth:`Op.pullback` is not defined, then PyTensor assumes it has been
|
|
279
286
|
forgotten. Symbolic differentiation will fail on a graph that
|
|
280
287
|
includes this :class:`Op`.
|
|
281
288
|
|
|
282
|
-
It must be understood that the :meth:`Op.grad` method is not meant to
|
|
283
|
-
return the gradient of the :class:`Op`'s output. :func:`pytensor.grad` computes
|
|
284
|
-
gradients; :meth:`Op.grad` is a helper function that computes terms that
|
|
285
|
-
appear in gradients.
|
|
286
|
-
|
|
287
289
|
If an :class:`Op` has a single vector-valued output ``y`` and a single
|
|
288
|
-
vector-valued input ``x``, then
|
|
289
|
-
|
|
290
|
-
``x``. The
|
|
291
|
-
:func:`pytensor.grad` calls
|
|
292
|
-
gradient of the cost ``C`` with respect to ``y``. If this :class:`Op` is the only
|
|
293
|
-
that acts on ``x``, then ``dot(J
|
|
294
|
-
``x``.
|
|
295
|
-
|
|
296
|
-
:meth:`Op.
|
|
297
|
-
|
|
298
|
-
In practice, an :class:`Op`'s input and output are rarely implemented as
|
|
299
|
-
single vectors. Even if an :class:`Op`'s output consists of a list
|
|
300
|
-
containing a scalar, a sparse matrix, and a 4D tensor, you can think
|
|
301
|
-
of these objects as being formed by rearranging a vector. Likewise
|
|
302
|
-
for the input. In this view, the values computed by the :meth:`Op.grad` method
|
|
303
|
-
still represent a Jacobian-vector product.
|
|
290
|
+
vector-valued input ``x``, then :meth:`Op.pullback` will be passed ``x``,
|
|
291
|
+
``y``, and a cotangent vector ``z``. Define ``J`` to be the Jacobian of ``y``
|
|
292
|
+
with respect to ``x``. The method should return ``dot(z, J)``. When
|
|
293
|
+
:func:`pytensor.grad` calls :meth:`Op.pullback`, it will set ``z`` to be the
|
|
294
|
+
gradient of the cost ``C`` with respect to ``y``. If this :class:`Op` is the only
|
|
295
|
+
:class:`Op` that acts on ``x``, then ``dot(z, J)`` is the gradient of C with
|
|
296
|
+
respect to ``x``. If there are other :class:`Op`\s that act on ``x``,
|
|
297
|
+
:func:`pytensor.grad` will add up the terms of ``x``'s gradient contributed
|
|
298
|
+
by each :meth:`Op.pullback`.
|
|
304
299
|
|
|
305
300
|
In practice, it is probably not a good idea to explicitly construct
|
|
306
301
|
the Jacobian, which might be very large and very sparse. However,
|
|
307
|
-
the returned value should be equal to the Jacobian
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
calculus. The chain rule is the mathematical procedure that allows
|
|
316
|
-
one to calculate the total derivative :math:`\frac{d C}{d x}` of the
|
|
317
|
-
final scalar symbolic `Variable` ``C`` with respect to a primitive
|
|
318
|
-
symbolic :class:`Variable` x found in the list ``inputs``. The :meth:`Op.grad` method
|
|
319
|
-
does this using ``output_gradients`` which provides the total
|
|
320
|
-
derivative :math:`\frac{d C}{d f}` of ``C`` with respect to a symbolic
|
|
321
|
-
:class:`Variable` that is returned by the `Op` (this is provided in
|
|
322
|
-
``output_gradients``), as well as the knowledge of the total
|
|
323
|
-
derivative :math:`\frac{d f}{d x}` of the latter with respect to the
|
|
324
|
-
primitive :class:`Variable` (this has to be computed).
|
|
325
|
-
|
|
326
|
-
In mathematics, the total derivative of a scalar variable :math:`C` with
|
|
327
|
-
respect to a vector of scalar variables :math:`x`, i.e. the gradient, is
|
|
328
|
-
customarily represented as the row vector of the partial
|
|
329
|
-
derivatives, whereas the total derivative of a vector of scalar
|
|
330
|
-
variables :math:`f` with respect to another :math:`x`, is customarily
|
|
331
|
-
represented by the matrix of the partial derivatives, i.e. the
|
|
332
|
-
Jacobian matrix. In this convenient setting, the chain rule
|
|
333
|
-
says that the gradient of the final scalar variable :math:`C` with
|
|
334
|
-
respect to the primitive scalar variables in :math:`x` through those in
|
|
335
|
-
:math:`f` is simply given by the matrix product:
|
|
336
|
-
:math:`\frac{d C}{d x} = \frac{d C}{d f} * \frac{d f}{d x}`.
|
|
337
|
-
|
|
338
|
-
Here, the chain rule must be implemented in a similar but slightly
|
|
339
|
-
more complex setting: PyTensor provides in the list
|
|
340
|
-
``output_gradients`` one gradient for each of the :class:`Variable`\s returned
|
|
341
|
-
by the `Op`. Where :math:`f` is one such particular :class:`Variable`, the
|
|
342
|
-
corresponding gradient found in ``output_gradients`` and
|
|
343
|
-
representing :math:`\frac{d C}{d f}` is provided with a shape
|
|
344
|
-
similar to :math:`f` and thus not necessarily as a row vector of scalars.
|
|
345
|
-
Furthermore, for each :class:`Variable` :math:`x` of the :class:`Op`'s list of input variables
|
|
346
|
-
``inputs``, the returned gradient representing :math:`\frac{d C}{d
|
|
347
|
-
x}` must have a shape similar to that of :class:`Variable` x.
|
|
348
|
-
|
|
349
|
-
If the output list of the :class:`Op` is :math:`[f_1, ... f_n]`, then the
|
|
350
|
-
list ``output_gradients`` is :math:`[grad_{f_1}(C), grad_{f_2}(C),
|
|
351
|
-
... , grad_{f_n}(C)]`. If ``inputs`` consists of the list
|
|
352
|
-
:math:`[x_1, ..., x_m]`, then `Op.grad` should return the list
|
|
353
|
-
:math:`[grad_{x_1}(C), grad_{x_2}(C), ..., grad_{x_m}(C)]`, where
|
|
354
|
-
:math:`(grad_{y}(Z))_i = \frac{\partial Z}{\partial y_i}` (and
|
|
355
|
-
:math:`i` can stand for multiple dimensions).
|
|
356
|
-
|
|
357
|
-
In other words, :meth:`Op.grad` does not return :math:`\frac{d f_i}{d
|
|
358
|
-
x_j}`, but instead the appropriate dot product specified by the
|
|
359
|
-
chain rule: :math:`\frac{d C}{d x_j} = \frac{d C}{d f_i} \cdot
|
|
360
|
-
\frac{d f_i}{d x_j}`. Both the partial differentiation and the
|
|
361
|
-
multiplication have to be performed by :meth:`Op.grad`.
|
|
302
|
+
the returned value should be equal to the vector-Jacobian product.
|
|
303
|
+
Note that an :class:`Op`'s inputs and outputs may include scalars,
|
|
304
|
+
matrices, sparse arrays, or higher-dimensional tensors — not just vectors.
|
|
305
|
+
The VJP contract still applies: conceptually, each of these can be viewed
|
|
306
|
+
as a vector that has been reshaped into a tensor. The returned cotangent
|
|
307
|
+
for each input must have the same shape as that input, and each incoming
|
|
308
|
+
cotangent in ``cotangents`` will have the same shape as the corresponding
|
|
309
|
+
output.
|
|
362
310
|
|
|
363
311
|
PyTensor currently imposes the following constraints on the values
|
|
364
|
-
returned by the :meth:`Op.
|
|
312
|
+
returned by the :meth:`Op.pullback` method:
|
|
365
313
|
|
|
366
314
|
1) They must be :class:`Variable` instances.
|
|
367
315
|
2) When they are types that have dtypes, they must never have an integer dtype.
|
|
368
316
|
|
|
369
|
-
The output
|
|
317
|
+
The output cotangents passed *to* :meth:`Op.pullback` will also obey these
|
|
318
|
+
constraints.
|
|
370
319
|
|
|
371
320
|
Integers are a tricky subject. Integers are the main reason for
|
|
372
321
|
having :class:`DisconnectedType`, :class:`NullType` or zero gradient. When you have an
|
|
373
|
-
integer as an argument to your :meth:`Op.
|
|
322
|
+
integer as an argument to your :meth:`Op.pullback` method, recall the definition of
|
|
374
323
|
a derivative to help you decide what value to return:
|
|
375
324
|
|
|
376
325
|
:math:`\frac{d f}{d x} = \lim_{\epsilon \rightarrow 0} (f(x+\epsilon)-f(x))/\epsilon`.
|
|
@@ -410,7 +359,7 @@ These are the function required to work with :func:`pytensor.gradient.grad`.
|
|
|
410
359
|
|
|
411
360
|
1) :math:`f(x,y)` is a dot product between :math:`x` and :math:`y`. :math:`x` and :math:`y` are integers.
|
|
412
361
|
Since the output is also an integer, :math:`f` is a step function.
|
|
413
|
-
Its gradient is zero almost everywhere, so :meth:`Op.
|
|
362
|
+
Its gradient is zero almost everywhere, so :meth:`Op.pullback` should return
|
|
414
363
|
zeros in the shape of :math:`x` and :math:`y`.
|
|
415
364
|
2) :math:`f(x,y)` is a dot product between :math:`x` and :math:`y`. :math:`x`
|
|
416
365
|
is floating point and :math:`y` is an integer. In this case the output is
|
|
@@ -423,7 +372,7 @@ These are the function required to work with :func:`pytensor.gradient.grad`.
|
|
|
423
372
|
along a fractional axis? The gradient with respect to :math:`x` is 0,
|
|
424
373
|
because :math:`f(x+\epsilon, y) = f(x)` almost everywhere.
|
|
425
374
|
4) :math:`f(x,y)` is a vector with :math:`y` elements, each of which taking on
|
|
426
|
-
the value :math:`x` The :meth:`Op.
|
|
375
|
+
the value :math:`x` The :meth:`Op.pullback` method should return
|
|
427
376
|
:class:`DisconnectedType` for :math:`y`, because the elements of :math:`f`
|
|
428
377
|
don't depend on :math:`y`. Only the shape of :math:`f` depends on
|
|
429
378
|
:math:`y`. You probably also want to implement a connection_pattern method to encode this.
|
|
@@ -433,6 +382,29 @@ These are the function required to work with :func:`pytensor.gradient.grad`.
|
|
|
433
382
|
even if :math:`y` is an integer. However, the gradient with respect to :math:`x` will be
|
|
434
383
|
0, because the output of :math:`f` is integer-valued.
|
|
435
384
|
|
|
385
|
+
.. function:: pushforward(inputs, outputs, tangents)
|
|
386
|
+
|
|
387
|
+
Implements the Jacobian-vector product (JVP) for forward-mode automatic
|
|
388
|
+
differentiation.
|
|
389
|
+
|
|
390
|
+
Given a function :math:`f` with inputs :math:`x` and outputs :math:`y = f(x)`,
|
|
391
|
+
the pushforward computes :math:`\dot{y} = J \dot{x}` where
|
|
392
|
+
:math:`J = \frac{\partial f}{\partial x}` is the Jacobian and
|
|
393
|
+
:math:`\dot{x}` are the tangent vectors.
|
|
394
|
+
|
|
395
|
+
``inputs`` are the symbolic variables corresponding to the input values,
|
|
396
|
+
``outputs`` are the symbolic variables corresponding to the output values,
|
|
397
|
+
and ``tangents`` are the symbolic variables corresponding to the tangent
|
|
398
|
+
vectors to right-multiply the Jacobian with. Tangent entries of type
|
|
399
|
+
:class:`DisconnectedType` indicate that the corresponding input is not being
|
|
400
|
+
differentiated.
|
|
401
|
+
|
|
402
|
+
The method must return the same number of outputs as there are outputs of
|
|
403
|
+
the :class:`Op`. For each output, the result is the Jacobian of that output
|
|
404
|
+
with respect to the inputs, right-multiplied by the tangent vector. Return
|
|
405
|
+
a variable of type :class:`DisconnectedType` for outputs that are disconnected
|
|
406
|
+
from all inputs.
|
|
407
|
+
|
|
436
408
|
.. function:: connection_pattern(node):
|
|
437
409
|
|
|
438
410
|
Sometimes needed for proper operation of :func:`pytensor.gradient.grad`.
|
|
@@ -477,32 +449,4 @@ These are the function required to work with :func:`pytensor.gradient.grad`.
|
|
|
477
449
|
:func:`pytensor.gradient.grad` returns an expression, that expression will be
|
|
478
450
|
numerically correct.
|
|
479
451
|
|
|
480
|
-
.. function:: R_op(inputs, eval_points)
|
|
481
|
-
|
|
482
|
-
Optional, to work with :func:`pytensor.gradient.R_op`.
|
|
483
|
-
|
|
484
|
-
This function implements the application of the R-operator on the
|
|
485
|
-
function represented by your :class:`Op`. Let assume that function is :math:`f`,
|
|
486
|
-
with input :math:`x`, applying the R-operator means computing the
|
|
487
|
-
Jacobian of :math:`f` and right-multiplying it by :math:`v`, the evaluation
|
|
488
|
-
point, namely: :math:`\frac{\partial f}{\partial x} v`.
|
|
489
|
-
|
|
490
|
-
``inputs`` are the symbolic variables corresponding to the value of
|
|
491
|
-
the input where you want to evaluate the Jacobian, and ``eval_points``
|
|
492
|
-
are the symbolic variables corresponding to the value you want to
|
|
493
|
-
right multiply the Jacobian with.
|
|
494
|
-
|
|
495
|
-
Same conventions as for the :meth:`Op.grad` method hold. If your :class:`Op`
|
|
496
|
-
is not differentiable, you can return None. Note that in contrast to the
|
|
497
|
-
method :meth:`Op.grad`, for :meth:`Op.R_op` you need to return the
|
|
498
|
-
same number of outputs as there are outputs of the :class:`Op`. You can think
|
|
499
|
-
of it in the following terms. You have all your inputs concatenated
|
|
500
|
-
into a single vector :math:`x`. You do the same with the evaluation
|
|
501
|
-
points (which are as many as inputs and of the shame shape) and obtain
|
|
502
|
-
another vector :math:`v`. For each output, you reshape it into a vector,
|
|
503
|
-
compute the Jacobian of that vector with respect to :math:`x` and
|
|
504
|
-
multiply it by :math:`v`. As a last step you reshape each of these
|
|
505
|
-
vectors you obtained for each outputs (that have the same shape as
|
|
506
|
-
the outputs) back to their corresponding shapes and return them as the
|
|
507
|
-
output of the :meth:`Op.R_op` method.
|
|
508
452
|
|