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.
Files changed (593) hide show
  1. {pytensor-2.38.3/pytensor.egg-info → pytensor-3.0.0}/PKG-INFO +1 -1
  2. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/creating_a_numba_jax_op.rst +13 -16
  3. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/creating_an_op.rst +76 -79
  4. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/op.rst +68 -124
  5. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/pipeline.rst +49 -46
  6. {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/applications/normalizing_flows_in_pytensor.ipynb +2 -2
  7. {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/autodiff/vector_jacobian_product.ipynb +13 -13
  8. {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/introduction/pytensor_intro.ipynb +5 -4
  9. {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/scan/scan_tutorial.ipynb +156 -146
  10. {pytensor-2.38.3 → pytensor-3.0.0}/doc/internal/metadocumentation.rst +2 -2
  11. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/debugmode.rst +2 -2
  12. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/function.rst +5 -5
  13. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/io.rst +23 -162
  14. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/nanguardmode.rst +3 -3
  15. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/config.rst +0 -36
  16. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/index.rst +1 -1
  17. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/scan.rst +57 -38
  18. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/index.rst +2 -1
  19. pytensor-3.0.0/doc/library/tensor/linalg.rst +72 -0
  20. pytensor-3.0.0/doc/library/tensor/nlinalg.rst +16 -0
  21. pytensor-3.0.0/doc/library/tensor/random.rst +119 -0
  22. pytensor-3.0.0/doc/library/tensor/slinalg.rst +16 -0
  23. pytensor-3.0.0/doc/library/xtensor/random.md +22 -0
  24. {pytensor-2.38.3 → pytensor-3.0.0}/doc/optimizations.rst +1 -1
  25. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/conditions.rst +0 -8
  26. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/debug_faq.rst +2 -169
  27. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/examples.rst +44 -87
  28. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/gradients.rst +26 -26
  29. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/index.rst +1 -1
  30. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/loop.rst +16 -15
  31. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/modes.rst +0 -3
  32. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/modes_solution_1.py +0 -2
  33. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/printing_drawing.rst +0 -2
  34. pytensor-3.0.0/doc/tutorial/prng.rst +603 -0
  35. {pytensor-2.38.3 → pytensor-3.0.0}/pyproject.toml +1 -1
  36. pytensor-3.0.0/pytensor/__init__.py +41 -0
  37. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/_version.py +3 -3
  38. pytensor-3.0.0/pytensor/basic.py +42 -0
  39. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/breakpoint.py +1 -1
  40. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/__init__.py +15 -13
  41. pytensor-3.0.0/pytensor/compile/aliasing.py +260 -0
  42. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/builders.py +260 -200
  43. {pytensor-2.38.3/pytensor/compile → pytensor-3.0.0/pytensor/compile/debug}/debugmode.py +35 -71
  44. pytensor-3.0.0/pytensor/compile/debug/dump.py +75 -0
  45. {pytensor-2.38.3/pytensor/compile → pytensor-3.0.0/pytensor/compile/debug}/profiling.py +1 -1
  46. pytensor-3.0.0/pytensor/compile/executor.py +871 -0
  47. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/io.py +7 -3
  48. pytensor-3.0.0/pytensor/compile/maker.py +741 -0
  49. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/mode.py +15 -32
  50. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/ops.py +5 -31
  51. pytensor-2.38.3/pytensor/compile/function/pfunc.py → pytensor-3.0.0/pytensor/compile/rebuild.py +63 -211
  52. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/sharedvalue.py +4 -3
  53. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/configdefaults.py +162 -256
  54. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/configparser.py +1 -32
  55. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/d3viz.py +2 -2
  56. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/formatting.py +3 -2
  57. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/gradient.py +177 -189
  58. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/__init__.py +1 -1
  59. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/basic.py +126 -79
  60. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/destroyhandler.py +48 -64
  61. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/features.py +166 -134
  62. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/fg.py +230 -60
  63. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/op.py +139 -204
  64. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/replace.py +11 -6
  65. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/basic.py +3 -3
  66. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/unify.py +2 -2
  67. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/utils.py +0 -20
  68. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/ifelse.py +21 -16
  69. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/basic.py +8 -2
  70. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/basic.py +4 -2
  71. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/cmodule.py +2 -10
  72. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/__init__.py +1 -2
  73. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/basic.py +3 -3
  74. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/elemwise.py +1 -1
  75. pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/__init__.py +8 -0
  76. pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/constructors.py +12 -0
  77. pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/decomposition.py +140 -0
  78. pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/inverse.py +20 -0
  79. pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/products.py +21 -0
  80. pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/solvers.py +89 -0
  81. pytensor-3.0.0/pytensor/link/jax/dispatch/linalg/summary.py +20 -0
  82. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/scalar.py +0 -11
  83. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/subtensor.py +3 -33
  84. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/ops.py +2 -2
  85. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/__init__.py +6 -3
  86. pytensor-3.0.0/pytensor/link/mlx/dispatch/basic.py +210 -0
  87. pytensor-3.0.0/pytensor/link/mlx/dispatch/blas.py +14 -0
  88. pytensor-3.0.0/pytensor/link/mlx/dispatch/einsum.py +14 -0
  89. pytensor-3.0.0/pytensor/link/mlx/dispatch/elemwise.py +132 -0
  90. pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/__init__.py +7 -0
  91. pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/decomposition.py +176 -0
  92. pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/inverse.py +24 -0
  93. pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/products.py +22 -0
  94. pytensor-2.38.3/pytensor/link/mlx/dispatch/slinalg.py → pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/solvers.py +3 -41
  95. pytensor-3.0.0/pytensor/link/mlx/dispatch/linalg/summary.py +46 -0
  96. pytensor-3.0.0/pytensor/link/mlx/dispatch/pad.py +37 -0
  97. pytensor-3.0.0/pytensor/link/mlx/dispatch/scalar.py +180 -0
  98. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/subtensor.py +5 -18
  99. pytensor-2.38.3/pytensor/link/mlx/dispatch/core.py → pytensor-3.0.0/pytensor/link/mlx/dispatch/tensor_basic.py +30 -81
  100. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/linker.py +2 -1
  101. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/__init__.py +1 -2
  102. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/basic.py +4 -4
  103. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/compile_ops.py +1 -1
  104. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/_LAPACK.py +501 -0
  105. pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/__init__.py +5 -0
  106. pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/constructors.py +77 -0
  107. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/cholesky.py +5 -3
  108. pytensor-2.38.3/pytensor/link/numba/dispatch/slinalg.py → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/decomposition/dispatch.py +285 -275
  109. pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/decomposition/eigen.py +1052 -0
  110. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/lu.py +8 -5
  111. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/lu_factor.py +3 -3
  112. pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/inverse.py +40 -0
  113. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/cholesky.py +11 -8
  114. pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers/dispatch.py +188 -0
  115. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/general.py +5 -5
  116. pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers/hermitian.py +145 -0
  117. {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
  118. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/posdef.py +11 -8
  119. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/symmetric.py +4 -4
  120. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/triangular.py +10 -12
  121. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/tridiagonal.py +15 -21
  122. pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/summary.py +46 -0
  123. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/random.py +5 -2
  124. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/scan.py +45 -10
  125. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/subtensor.py +104 -67
  126. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/typed_list.py +2 -0
  127. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/__init__.py +1 -2
  128. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/basic.py +4 -4
  129. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/elemwise.py +1 -1
  130. pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/__init__.py +6 -0
  131. pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/decomposition.py +77 -0
  132. pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/inverse.py +22 -0
  133. pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/products.py +12 -0
  134. pytensor-3.0.0/pytensor/link/pytorch/dispatch/linalg/summary.py +20 -0
  135. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/subtensor.py +10 -19
  136. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/utils.py +9 -8
  137. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/pkl_utils.py +1 -1
  138. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/printing.py +861 -185
  139. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/raise_op.py +1 -1
  140. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/basic.py +200 -197
  141. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/loop.py +19 -28
  142. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/math.py +44 -54
  143. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/basic.py +12 -46
  144. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/op.py +242 -213
  145. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/rewriting.py +777 -336
  146. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/scan_perform.pyx +26 -25
  147. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/scan_perform_ext.py +1 -1
  148. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/utils.py +18 -234
  149. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/basic.py +20 -20
  150. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/linalg.py +4 -1
  151. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/math.py +12 -12
  152. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/rewriting.py +3 -3
  153. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/sharedvar.py +1 -1
  154. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/type.py +1 -1
  155. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/__init__.py +5 -13
  156. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/basic.py +44 -75
  157. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/blas.py +14 -66
  158. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/blockwise.py +24 -24
  159. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/einsum.py +18 -13
  160. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/elemwise.py +61 -51
  161. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/extra_ops.py +7 -7
  162. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/fft.py +2 -2
  163. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/fourier.py +1 -1
  164. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/interpolate.py +1 -1
  165. pytensor-3.0.0/pytensor/tensor/linalg/__init__.py +131 -0
  166. pytensor-3.0.0/pytensor/tensor/linalg/constructors.py +122 -0
  167. pytensor-3.0.0/pytensor/tensor/linalg/decomposition/__init__.py +1 -0
  168. pytensor-3.0.0/pytensor/tensor/linalg/decomposition/cholesky.py +198 -0
  169. pytensor-3.0.0/pytensor/tensor/linalg/decomposition/eigen.py +518 -0
  170. pytensor-3.0.0/pytensor/tensor/linalg/decomposition/lu.py +348 -0
  171. pytensor-3.0.0/pytensor/tensor/linalg/decomposition/qr.py +383 -0
  172. pytensor-3.0.0/pytensor/tensor/linalg/decomposition/schur.py +608 -0
  173. pytensor-3.0.0/pytensor/tensor/linalg/decomposition/svd.py +225 -0
  174. pytensor-3.0.0/pytensor/tensor/linalg/dtype_utils.py +42 -0
  175. pytensor-3.0.0/pytensor/tensor/linalg/inverse.py +224 -0
  176. pytensor-3.0.0/pytensor/tensor/linalg/products.py +176 -0
  177. pytensor-3.0.0/pytensor/tensor/linalg/solvers/__init__.py +0 -0
  178. pytensor-3.0.0/pytensor/tensor/linalg/solvers/core.py +126 -0
  179. pytensor-3.0.0/pytensor/tensor/linalg/solvers/general.py +266 -0
  180. {pytensor-2.38.3/pytensor/tensor/_linalg/solve → pytensor-3.0.0/pytensor/tensor/linalg/solvers}/linear_control.py +9 -4
  181. pytensor-3.0.0/pytensor/tensor/linalg/solvers/lstsq.py +98 -0
  182. pytensor-3.0.0/pytensor/tensor/linalg/solvers/psd.py +107 -0
  183. pytensor-3.0.0/pytensor/tensor/linalg/solvers/triangular.py +142 -0
  184. pytensor-3.0.0/pytensor/tensor/linalg/summary.py +342 -0
  185. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/math.py +78 -40
  186. pytensor-3.0.0/pytensor/tensor/nlinalg.py +58 -0
  187. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/optimize.py +25 -10
  188. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/__init__.py +1 -0
  189. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/basic.py +32 -23
  190. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/op.py +48 -10
  191. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/rewriting/basic.py +55 -26
  192. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/type.py +63 -16
  193. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/utils.py +12 -62
  194. pytensor-3.0.0/pytensor/tensor/random/variable.py +252 -0
  195. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/reshape.py +3 -5
  196. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/__init__.py +1 -0
  197. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/blas_c.py +6 -1
  198. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/einsum.py +2 -2
  199. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/elemwise.py +31 -31
  200. pytensor-3.0.0/pytensor/tensor/rewriting/linalg/__init__.py +11 -0
  201. pytensor-3.0.0/pytensor/tensor/rewriting/linalg/decomposition.py +134 -0
  202. pytensor-3.0.0/pytensor/tensor/rewriting/linalg/inverse.py +163 -0
  203. pytensor-3.0.0/pytensor/tensor/rewriting/linalg/products.py +154 -0
  204. pytensor-2.38.3/pytensor/tensor/_linalg/solve/rewriting.py → pytensor-3.0.0/pytensor/tensor/rewriting/linalg/solvers.py +193 -57
  205. pytensor-3.0.0/pytensor/tensor/rewriting/linalg/summary.py +280 -0
  206. pytensor-3.0.0/pytensor/tensor/rewriting/linalg/utils.py +84 -0
  207. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/math.py +51 -4
  208. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/ofg.py +1 -2
  209. pytensor-3.0.0/pytensor/tensor/rewriting/optimize.py +48 -0
  210. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/reshape.py +30 -2
  211. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/shape.py +62 -46
  212. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/subtensor.py +733 -393
  213. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/subtensor_lift.py +29 -32
  214. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/uncanonicalize.py +34 -52
  215. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/shape.py +20 -26
  216. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/sharedvar.py +2 -1
  217. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/signal/conv.py +1 -1
  218. pytensor-3.0.0/pytensor/tensor/slinalg.py +65 -0
  219. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/sort.py +14 -14
  220. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/special.py +12 -15
  221. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/subtensor.py +764 -835
  222. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/type.py +3 -9
  223. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/type_other.py +2 -2
  224. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/utils.py +1 -1
  225. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/variable.py +50 -78
  226. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/xlogx.py +2 -2
  227. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/typed_list/basic.py +1 -3
  228. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/typed_list/type.py +3 -4
  229. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/__init__.py +1 -6
  230. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/basic.py +3 -3
  231. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/linalg.py +2 -1
  232. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/math.py +6 -2
  233. pytensor-3.0.0/pytensor/xtensor/random/__init__.py +2 -0
  234. pytensor-3.0.0/pytensor/xtensor/random/basic.py +254 -0
  235. pytensor-3.0.0/pytensor/xtensor/random/type.py +88 -0
  236. pytensor-3.0.0/pytensor/xtensor/random/variable.py +205 -0
  237. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/basic.py +25 -0
  238. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/indexing.py +5 -4
  239. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/vectorization.py +14 -1
  240. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/type.py +30 -5
  241. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/vectorization.py +17 -5
  242. {pytensor-2.38.3 → pytensor-3.0.0/pytensor.egg-info}/PKG-INFO +1 -1
  243. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/SOURCES.txt +88 -39
  244. {pytensor-2.38.3 → pytensor-3.0.0}/scripts/mypy-failing.txt +4 -4
  245. pytensor-3.0.0/tests/test_basic.py +34 -0
  246. {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_breakpoint.py +1 -1
  247. {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_config.py +0 -13
  248. {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_gradient.py +7 -35
  249. {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_ifelse.py +0 -8
  250. pytensor-3.0.0/tests/test_printing.py +773 -0
  251. {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_rop.py +106 -93
  252. pytensor-2.38.3/doc/library/tensor/nlinalg.rst +0 -22
  253. pytensor-2.38.3/doc/library/tensor/random/distributions.rst +0 -8
  254. pytensor-2.38.3/doc/library/tensor/random/index.rst +0 -90
  255. pytensor-2.38.3/doc/library/tensor/slinalg.rst +0 -23
  256. pytensor-2.38.3/doc/library/xtensor/random.md +0 -7
  257. pytensor-2.38.3/doc/tutorial/prng.rst +0 -736
  258. pytensor-2.38.3/pytensor/__init__.py +0 -176
  259. pytensor-2.38.3/pytensor/compile/function/__init__.py +0 -348
  260. pytensor-2.38.3/pytensor/compile/function/types.py +0 -1973
  261. pytensor-2.38.3/pytensor/link/jax/dispatch/nlinalg.py +0 -82
  262. pytensor-2.38.3/pytensor/link/jax/dispatch/slinalg.py +0 -211
  263. pytensor-2.38.3/pytensor/link/mlx/dispatch/basic.py +0 -101
  264. pytensor-2.38.3/pytensor/link/mlx/dispatch/elemwise.py +0 -457
  265. pytensor-2.38.3/pytensor/link/mlx/dispatch/nlinalg.py +0 -69
  266. pytensor-2.38.3/pytensor/link/numba/dispatch/nlinalg.py +0 -179
  267. pytensor-2.38.3/pytensor/link/pytorch/dispatch/nlinalg.py +0 -87
  268. pytensor-2.38.3/pytensor/link/pytorch/dispatch/slinalg.py +0 -23
  269. pytensor-2.38.3/pytensor/tensor/_linalg/__init__.py +0 -2
  270. pytensor-2.38.3/pytensor/tensor/_linalg/solve/__init__.py +0 -2
  271. pytensor-2.38.3/pytensor/tensor/linalg.py +0 -3
  272. pytensor-2.38.3/pytensor/tensor/nlinalg.py +0 -1202
  273. pytensor-2.38.3/pytensor/tensor/random/var.py +0 -37
  274. pytensor-2.38.3/pytensor/tensor/rewriting/linalg.py +0 -1147
  275. pytensor-2.38.3/pytensor/tensor/slinalg.py +0 -2416
  276. pytensor-2.38.3/pytensor/updates.py +0 -60
  277. pytensor-2.38.3/pytensor/xtensor/random.py +0 -292
  278. pytensor-2.38.3/tests/test_printing.py +0 -498
  279. pytensor-2.38.3/tests/test_updates.py +0 -70
  280. {pytensor-2.38.3 → pytensor-3.0.0}/LICENSE.txt +0 -0
  281. {pytensor-2.38.3 → pytensor-3.0.0}/MANIFEST.in +0 -0
  282. {pytensor-2.38.3 → pytensor-3.0.0}/README.rst +0 -0
  283. {pytensor-2.38.3 → pytensor-3.0.0}/doc/.templates/PLACEHOLDER +0 -0
  284. {pytensor-2.38.3 → pytensor-3.0.0}/doc/.templates/layout.html +0 -0
  285. {pytensor-2.38.3 → pytensor-3.0.0}/doc/.templates/nb-badges.html +0 -0
  286. {pytensor-2.38.3 → pytensor-3.0.0}/doc/.templates/rendered_citation.html +0 -0
  287. {pytensor-2.38.3 → pytensor-3.0.0}/doc/LICENSE.txt +0 -0
  288. {pytensor-2.38.3 → pytensor-3.0.0}/doc/README.md +0 -0
  289. {pytensor-2.38.3 → pytensor-3.0.0}/doc/_drafts/benchmark_mlx_v_jax_corrected.ipynb +0 -0
  290. {pytensor-2.38.3 → pytensor-3.0.0}/doc/_thumbnails/autodiff/vector_jacobian_product.png +0 -0
  291. {pytensor-2.38.3 → pytensor-3.0.0}/doc/acknowledgement.rst +0 -0
  292. {pytensor-2.38.3 → pytensor-3.0.0}/doc/bcast.png +0 -0
  293. {pytensor-2.38.3 → pytensor-3.0.0}/doc/bcast.svg +0 -0
  294. {pytensor-2.38.3 → pytensor-3.0.0}/doc/blog.md +0 -0
  295. {pytensor-2.38.3 → pytensor-3.0.0}/doc/conf.py +0 -0
  296. {pytensor-2.38.3 → pytensor-3.0.0}/doc/core_development_guide.rst +0 -0
  297. {pytensor-2.38.3 → pytensor-3.0.0}/doc/css.inc +0 -0
  298. {pytensor-2.38.3 → pytensor-3.0.0}/doc/dev_start_guide.rst +0 -0
  299. {pytensor-2.38.3 → pytensor-3.0.0}/doc/environment.yml +0 -0
  300. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/apply.png +0 -0
  301. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/apply.svg +0 -0
  302. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/apply2.svg +0 -0
  303. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/creating_a_c_op.rst +0 -0
  304. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/ctype.rst +0 -0
  305. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/extending_faq.rst +0 -0
  306. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/extending_pytensor_solution_1.py +0 -0
  307. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/graph_rewriting.rst +0 -0
  308. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/graphstructures.rst +0 -0
  309. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/index.rst +0 -0
  310. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/inplace.rst +0 -0
  311. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/other_ops.rst +0 -0
  312. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/pics/symbolic_graph_opt.png +0 -0
  313. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/pics/symbolic_graph_unopt.png +0 -0
  314. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/scan.rst +0 -0
  315. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/tips.rst +0 -0
  316. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/type.rst +0 -0
  317. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/unittest.rst +0 -0
  318. {pytensor-2.38.3 → pytensor-3.0.0}/doc/extending/using_params.rst +0 -0
  319. {pytensor-2.38.3 → pytensor-3.0.0}/doc/faq.rst +0 -0
  320. {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/optimize/root.ipynb +0 -0
  321. {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/page_footer.md +0 -0
  322. {pytensor-2.38.3 → pytensor-3.0.0}/doc/gallery/rewrites/graph_rewrites.ipynb +0 -0
  323. {pytensor-2.38.3 → pytensor-3.0.0}/doc/generate_dtype_tensor_table.py +0 -0
  324. {pytensor-2.38.3 → pytensor-3.0.0}/doc/glossary.rst +0 -0
  325. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/Elman_srnn.png +0 -0
  326. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/PyTensor.png +0 -0
  327. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/PyTensor_RGB.svg +0 -0
  328. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/PyTensor_logo.png +0 -0
  329. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/binder.svg +0 -0
  330. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/blocksparse.png +0 -0
  331. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/colab.svg +0 -0
  332. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/github.svg +0 -0
  333. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/lstm.png +0 -0
  334. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/lstm_memorycell.png +0 -0
  335. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/talk2010.gif +0 -0
  336. {pytensor-2.38.3 → pytensor-3.0.0}/doc/images/talk2010.png +0 -0
  337. {pytensor-2.38.3 → pytensor-3.0.0}/doc/index.rst +0 -0
  338. {pytensor-2.38.3 → pytensor-3.0.0}/doc/install.rst +0 -0
  339. {pytensor-2.38.3 → pytensor-3.0.0}/doc/internal/how_to_release.rst +0 -0
  340. {pytensor-2.38.3 → pytensor-3.0.0}/doc/internal/index.rst +0 -0
  341. {pytensor-2.38.3 → pytensor-3.0.0}/doc/introduction.rst +0 -0
  342. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/index.rst +0 -0
  343. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/mode.rst +0 -0
  344. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/opfromgraph.rst +0 -0
  345. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/ops.rst +0 -0
  346. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/profilemode.rst +0 -0
  347. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/compile/shared.rst +0 -0
  348. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/css/d3-context-menu.css +0 -0
  349. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/css/d3viz.css +0 -0
  350. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/d3-context-menu.js +0 -0
  351. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/d3.v3.min.js +0 -0
  352. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/d3viz.js +0 -0
  353. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/dagre-d3.min.js +0 -0
  354. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/d3viz/js/graphlib-dot.min.js +0 -0
  355. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp.html +0 -0
  356. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp.png +0 -0
  357. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp2.html +0 -0
  358. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp2.pdf +0 -0
  359. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/mlp2.png +0 -0
  360. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/ofg.html +0 -0
  361. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/examples/ofg2.html +0 -0
  362. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index.ipynb +0 -0
  363. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index.rst +0 -0
  364. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index_files/index_10_0.png +0 -0
  365. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index_files/index_11_0.png +0 -0
  366. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index_files/index_24_0.png +0 -0
  367. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/d3viz/index_files/index_25_0.png +0 -0
  368. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/features.rst +0 -0
  369. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/fgraph.rst +0 -0
  370. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/graph.rst +0 -0
  371. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/index.rst +0 -0
  372. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/op.rst +0 -0
  373. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/replace.rst +0 -0
  374. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/type.rst +0 -0
  375. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/graph/utils.rst +0 -0
  376. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/misc/pkl_utils.rst +0 -0
  377. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/printing.rst +0 -0
  378. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/scalar/index.rst +0 -0
  379. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/sparse/index.rst +0 -0
  380. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/sparse/sandbox.rst +0 -0
  381. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/basic.rst +0 -0
  382. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/basic_opt.rst +0 -0
  383. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/bcast.png +0 -0
  384. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/bcast.svg +0 -0
  385. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/elemwise.rst +0 -0
  386. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/extra_ops.rst +0 -0
  387. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/fft.rst +0 -0
  388. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/functional.rst +0 -0
  389. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/io.rst +0 -0
  390. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/math_opt.rst +0 -0
  391. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/optimize.rst +0 -0
  392. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/plot_fft.png +0 -0
  393. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/tensor/utils.rst +0 -0
  394. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/typed_list.rst +0 -0
  395. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/index.md +0 -0
  396. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/linalg.md +0 -0
  397. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/math.md +0 -0
  398. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/module_functions.md +0 -0
  399. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/signal.md +0 -0
  400. {pytensor-2.38.3 → pytensor-3.0.0}/doc/library/xtensor/type.md +0 -0
  401. {pytensor-2.38.3 → pytensor-3.0.0}/doc/links.rst +0 -0
  402. {pytensor-2.38.3 → pytensor-3.0.0}/doc/pylintrc +0 -0
  403. {pytensor-2.38.3 → pytensor-3.0.0}/doc/robots.txt +0 -0
  404. {pytensor-2.38.3 → pytensor-3.0.0}/doc/troubleshooting.rst +0 -0
  405. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/adding.rst +0 -0
  406. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/adding_solution_1.py +0 -0
  407. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/aliasing.rst +0 -0
  408. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/apply.png +0 -0
  409. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/apply.svg +0 -0
  410. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/bcast.png +0 -0
  411. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/broadcasting.rst +0 -0
  412. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/dlogistic.png +0 -0
  413. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/faq_tutorial.rst +0 -0
  414. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/loading_and_saving.rst +0 -0
  415. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/logistic.gp +0 -0
  416. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/logistic.png +0 -0
  417. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/loop_solution_1.py +0 -0
  418. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/multi_cores.rst +0 -0
  419. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/nan_tutorial.rst +0 -0
  420. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/pics/d3viz.png +0 -0
  421. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/pics/logreg_pydotprint_predict.png +0 -0
  422. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/pics/logreg_pydotprint_prediction.png +0 -0
  423. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/pics/logreg_pydotprint_train.png +0 -0
  424. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/profiling.rst +0 -0
  425. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/profiling_example.py +0 -0
  426. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/profiling_example_out.prof +0 -0
  427. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/shape_info.rst +0 -0
  428. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/sparse.rst +0 -0
  429. {pytensor-2.38.3 → pytensor-3.0.0}/doc/tutorial/symbolic_graphs.rst +0 -0
  430. {pytensor-2.38.3 → pytensor-3.0.0}/doc/user_guide.rst +0 -0
  431. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/bin/__init__.py +0 -0
  432. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/bin/pytensor_cache.py +0 -0
  433. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/compiledir.py +0 -0
  434. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/compile/compilelock.py +0 -0
  435. {pytensor-2.38.3/pytensor/link/c → pytensor-3.0.0/pytensor/compile/debug}/__init__.py +0 -0
  436. {pytensor-2.38.3/pytensor/compile → pytensor-3.0.0/pytensor/compile/debug}/monitormode.py +0 -0
  437. {pytensor-2.38.3/pytensor/compile → pytensor-3.0.0/pytensor/compile/debug}/nanguardmode.py +0 -0
  438. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/__init__.py +0 -0
  439. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/css/d3-context-menu.css +0 -0
  440. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/css/d3viz.css +0 -0
  441. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/html/template.html +0 -0
  442. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/d3-context-menu.js +0 -0
  443. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/d3.v3.min.js +0 -0
  444. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/d3viz.js +0 -0
  445. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/dagre-d3.min.js +0 -0
  446. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/d3viz/js/graphlib-dot.min.js +0 -0
  447. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/null_type.py +0 -0
  448. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/__init__.py +0 -0
  449. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/db.py +0 -0
  450. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/kanren.py +0 -0
  451. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/rewriting/utils.py +0 -0
  452. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/traversal.py +0 -0
  453. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/graph/type.py +0 -0
  454. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/ipython.py +0 -0
  455. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/__init__.py +0 -0
  456. {pytensor-2.38.3/pytensor/link/mlx/dispatch/signal → pytensor-3.0.0/pytensor/link/c}/__init__.py +0 -0
  457. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/c_code/lazylinker_c.c +0 -0
  458. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/c_code/pytensor_mod_helper.h +0 -0
  459. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/cutils.py +0 -0
  460. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/cvm.py +0 -0
  461. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/exceptions.py +0 -0
  462. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/interface.py +0 -0
  463. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/lazylinker_c.py +0 -0
  464. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/op.py +0 -0
  465. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/params_type.py +0 -0
  466. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/c/type.py +0 -0
  467. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/__init__.py +0 -0
  468. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/blas.py +0 -0
  469. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/blockwise.py +0 -0
  470. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/einsum.py +0 -0
  471. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/extra_ops.py +0 -0
  472. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/math.py +0 -0
  473. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/pad.py +0 -0
  474. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/random.py +0 -0
  475. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/scan.py +0 -0
  476. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/shape.py +0 -0
  477. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/signal/__init__.py +0 -0
  478. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/signal/conv.py +0 -0
  479. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/sort.py +0 -0
  480. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/sparse.py +0 -0
  481. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/dispatch/tensor_basic.py +0 -0
  482. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/jax/linker.py +0 -0
  483. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/__init__.py +0 -0
  484. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/blockwise.py +0 -0
  485. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/extra_ops.py +0 -0
  486. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/math.py +0 -0
  487. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/shape.py +0 -0
  488. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg → pytensor-3.0.0/pytensor/link/mlx/dispatch/signal}/__init__.py +0 -0
  489. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/signal/conv.py +0 -0
  490. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/mlx/dispatch/sort.py +0 -0
  491. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/__init__.py +0 -0
  492. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/cache.py +0 -0
  493. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/blockwise.py +0 -0
  494. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/cython_support.py +0 -0
  495. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/elemwise.py +0 -0
  496. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/extra_ops.py +0 -0
  497. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/__init__.py +0 -0
  498. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/qr.py +0 -0
  499. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/qz.py +0 -0
  500. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/decomposition/schur.py +0 -0
  501. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/__init__.py +0 -0
  502. {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
  503. {pytensor-2.38.3/pytensor/link/numba/dispatch/linalg/solve → pytensor-3.0.0/pytensor/link/numba/dispatch/linalg/solvers}/utils.py +0 -0
  504. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/linalg/utils.py +0 -0
  505. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/scalar.py +0 -0
  506. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/shape.py +0 -0
  507. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/signal/__init__.py +0 -0
  508. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/signal/conv.py +0 -0
  509. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sort.py +0 -0
  510. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sparse/__init__.py +0 -0
  511. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sparse/basic.py +0 -0
  512. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sparse/math.py +0 -0
  513. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/sparse/variable.py +0 -0
  514. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/string_codegen.py +0 -0
  515. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/tensor_basic.py +0 -0
  516. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/dispatch/vectorize_codegen.py +0 -0
  517. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/numba/linker.py +0 -0
  518. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/blas.py +0 -0
  519. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/blockwise.py +0 -0
  520. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/extra_ops.py +0 -0
  521. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/math.py +0 -0
  522. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/scalar.py +0 -0
  523. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/shape.py +0 -0
  524. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/dispatch/sort.py +0 -0
  525. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/pytorch/linker.py +0 -0
  526. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/link/vm.py +0 -0
  527. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/__init__.py +0 -0
  528. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/check_blas.py +0 -0
  529. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/check_blas_many.sh +0 -0
  530. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/check_duplicate_key.py +0 -0
  531. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/elemwise_openmp_speedup.py +0 -0
  532. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/elemwise_time_test.py +0 -0
  533. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/frozendict.py +0 -0
  534. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/may_share_memory.py +0 -0
  535. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/misc/ordered_set.py +0 -0
  536. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/npy_2_compat.py +0 -0
  537. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/py.typed +0 -0
  538. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/__init__.py +0 -0
  539. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/c_code/Faddeeva.cc +0 -0
  540. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/c_code/Faddeeva.hh +0 -0
  541. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/c_code/gamma.c +0 -0
  542. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/c_code/incbet.c +0 -0
  543. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scalar/sharedvar.py +0 -0
  544. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/__init__.py +0 -0
  545. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/checkpoints.py +0 -0
  546. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/scan/views.py +0 -0
  547. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/__init__.py +0 -0
  548. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/utils.py +0 -0
  549. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/sparse/variable.py +0 -0
  550. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/blas_c.py +0 -0
  551. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/blas_headers.py +0 -0
  552. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/c_code/alt_blas_common.h +0 -0
  553. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/c_code/alt_blas_template.c +0 -0
  554. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/c_code/dimshuffle.c +0 -0
  555. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/elemwise_cgen.py +0 -0
  556. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/exceptions.py +0 -0
  557. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/functional.py +0 -0
  558. {pytensor-2.38.3/pytensor/tensor/_linalg/solve → pytensor-3.0.0/pytensor/tensor/linalg/solvers}/tridiagonal.py +0 -0
  559. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/pad.py +0 -0
  560. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/rewriting/__init__.py +0 -0
  561. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/rewriting/jax.py +0 -0
  562. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/random/rewriting/numba.py +0 -0
  563. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/basic.py +0 -0
  564. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/blas.py +0 -0
  565. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/blockwise.py +0 -0
  566. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/extra_ops.py +0 -0
  567. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/jax.py +0 -0
  568. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/numba.py +0 -0
  569. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/rewriting/special.py +0 -0
  570. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/signal/__init__.py +0 -0
  571. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/tensor/var.py +0 -0
  572. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/typed_list/__init__.py +0 -0
  573. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/typed_list/rewriting.py +0 -0
  574. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/utils.py +0 -0
  575. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/indexing.py +0 -0
  576. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/reduction.py +0 -0
  577. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/__init__.py +0 -0
  578. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/math.py +0 -0
  579. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/reduction.py +0 -0
  580. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/shape.py +0 -0
  581. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/rewriting/utils.py +0 -0
  582. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/shape.py +0 -0
  583. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor/xtensor/signal.py +0 -0
  584. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/dependency_links.txt +0 -0
  585. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/entry_points.txt +0 -0
  586. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/requires.txt +0 -0
  587. {pytensor-2.38.3 → pytensor-3.0.0}/pytensor.egg-info/top_level.txt +0 -0
  588. {pytensor-2.38.3 → pytensor-3.0.0}/scripts/slowest_tests/update-slowest-times-issue.sh +0 -0
  589. {pytensor-2.38.3 → pytensor-3.0.0}/setup.cfg +0 -0
  590. {pytensor-2.38.3 → pytensor-3.0.0}/setup.py +0 -0
  591. {pytensor-2.38.3 → pytensor-3.0.0}/tests/link/c/c_code/test_cenum.h +0 -0
  592. {pytensor-2.38.3 → pytensor-3.0.0}/tests/link/c/c_code/test_quadratic_function.c +0 -0
  593. {pytensor-2.38.3 → pytensor-3.0.0}/tests/test_raise_op.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytensor
3
- Version: 2.38.3
3
+ Version: 3.0.0
4
4
  Summary: Optimizing compiler for evaluating mathematical expressions on CPUs and GPUs.
5
5
  Author-email: pymc-devs <pymc.devs@gmail.com>
6
6
  License-Expression: BSD-3-Clause
@@ -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
- # Create test value tag for a
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, [get_test_value(i) for i in fgraph.inputs])
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, [get_test_value(i) for i in fgraph.inputs])
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
- a.tag.test_value = np.arange(9, dtype=config.floatX).reshape((3, 3))
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, [get_test_value(i) for i in fgraph.inputs])
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 symbolic expression for the L-operator based on the input and output variables
78
- # and the output gradient variables. Optional.
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
- # Equivalent to L_op, but with a "technically"-bad name and without outputs provided.
83
- # It exists for historical reasons. Optional.
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:`L_op`
186
- ^^^^^^^^^^^^^^^
177
+ :meth:`pullback`
178
+ ^^^^^^^^^^^^^^^^^^^
187
179
 
188
- The :meth:`L_op` method is required if you want to differentiate some cost
189
- whose expression includes your :class:`Op`. The gradient is
190
- specified symbolically in this method. It takes three arguments ``inputs``, ``outputs`` and
191
- ``output_gradients``, which are both lists of :ref:`variable`\s, and
192
- those must be operated on using PyTensor's symbolic language. The :meth:`L_op`
193
- method must return a list containing one :ref:`variable` for each
194
- input. Each returned :ref:`variable` represents the gradient with respect
195
- to that input computed based on the symbolic gradients with respect
196
- to each output.
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 be defined to return a variable of type :class:`NullType`
200
- for that input. Likewise, if you have not implemented the gradient
201
- computation for some input, you may return a variable of type
202
- :class:`NullType` for that input. Please refer to :meth:`L_op` for a more detailed
203
- view.
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:`R_op`
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
- This function implements the application of the R-operator on the
211
- function represented by your :class:`Op`. Let's assume that function is :math:`f`,
212
- with input :math:`x`, applying the R-operator means computing the
213
- Jacobian of :math:`f` and right-multiplying it by :math:`v`, the evaluation
214
- point, namely: :math:`\frac{\partial f}{\partial x} v`.
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 L_op(self, inputs: list[TensorVariable], outputs: list[TensorVariable], output_grads: list[TensorVariable]):
257
- # Symbolic expression for the gradient
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
- # output_grads[0] is a TensorVariable!
260
- return [output_grads[0] * 2]
261
-
262
- def R_op(self, inputs: list[TensorVariable], eval_points: list[TensorVariable | None]) -> list[TensorVariable] | None:
263
- # R_op can receive None as eval_points.
264
- # That means there is no differentiable path through that input
265
- # If this imply that you cannot compute some outputs,
266
- # return None for those.
267
- if eval_points[0] is None:
268
- return None
269
- # For this Op, the R_op is the same as the L_op
270
- outputs = self(inputs)
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:`L_op` method, as one of output gradients may be disconnected from the cost, in which case we should ignore its contribution.
490
- If both outputs are disconnected PyTensor will not bother calling the :meth:`L_op` method, so we don't need to worry about that case.
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 L_op(self, inputs, outputs, output_grads):
534
+ def pullback(self, inputs, outputs, cotangents):
538
535
  x, y = inputs
539
- out1_grad, out2_grad = output_grads
536
+ out1_ct, out2_ct = cotangents
540
537
 
541
- if isinstance(out1_grad.type, DisconnectedType):
542
- x_grad = disconnected_type()
538
+ if isinstance(out1_ct.type, DisconnectedType):
539
+ x_ct = disconnected_type()
543
540
  else:
544
- # Transpose the last two dimensions of the output gradient
545
- x_grad = pt.swapaxes(out1_grad, -1, -2)
541
+ # Transpose the last two dimensions of the output cotangent
542
+ x_ct = pt.swapaxes(out1_ct, -1, -2)
546
543
 
547
- if isinstance(out2_grad.type, DisconnectedType):
548
- y_grad = disconnected_type()
544
+ if isinstance(out2_ct.type, DisconnectedType):
545
+ y_ct = disconnected_type()
549
546
  else:
550
- # Broadcast the output gradient to the same shape as y
551
- y_grad = pt.broadcast_to(pt.expand_dims(out2_grad, -1), y.shape)
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 [x_grad, y_grad]
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:`L_op`
663
- :meth:`R_op`
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 Rop
767
- ^^^^^^^^^^^^^^^
763
+ Testing the pushforward
764
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
768
765
 
769
- The class :class:`RopLopChecker` defines the methods
770
- :meth:`RopLopChecker.check_mat_rop_lop`, :meth:`RopLopChecker.check_rop_lop` and :meth:`RopLopChecker.check_nondiff_rop`.
771
- These allow to test the implementation of the :meth:`R_op` method of a particular :class:`Op`.
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:`R_op` method of the ``DoubleOp``, you can use this:
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 RopLopChecker
776
+ from tests.test_rop import PushforwardPullbackChecker
780
777
 
781
- class TestDoubleOpRop(RopLopChecker):
778
+ class TestDoubleOpPushforward(PushforwardPullbackChecker):
782
779
 
783
- def test_double_rop(self):
784
- self.check_rop_lop(DoubleOp()(self.x), self.in_shape)
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:`Rop` functions. Try to implement the testing apparatus described above.
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 L_op is defined, this means you won't be able to
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
- Gradient
248
- ========
247
+ Automatic Differentiation
248
+ =========================
249
249
 
250
- These are the function required to work with :func:`pytensor.gradient.grad`.
250
+ These are the functions required to work with :func:`pytensor.gradient.grad`
251
+ and :func:`pytensor.gradient.pushforward`.
251
252
 
252
- .. function:: grad(inputs, output_gradients)
253
+ .. function:: pullback(inputs, outputs, cotangents)
253
254
 
254
- If the :class:`Op` being defined is differentiable, its gradient may be
255
- specified symbolically in this method. Both ``inputs`` and
256
- ``output_gradients`` are lists of symbolic PyTensor :class:`Variable`\s and
257
- those must be operated on using PyTensor's symbolic language. The :meth:`Op.grad`
258
- method must return a list containing one :class:`Variable` for each
259
- input. Each returned :class:`Variable` represents the gradient with respect
260
- to that input computed based on the symbolic gradients with respect
261
- to each output.
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 ``output_gradient`` is of type
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.grad` should
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 the :meth:`Op.grad` method is not defined, then PyTensor assumes it has been
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 the :meth:`Op.grad` method will be passed ``x`` and a
289
- second vector ``z``. Define ``J`` to be the Jacobian of ``y`` with respect to
290
- ``x``. The :meth:`Op.grad` method should return ``dot(J.T,z)``. When
291
- :func:`pytensor.grad` calls the :meth:`Op.grad` method, it will set ``z`` to be the
292
- gradient of the cost ``C`` with respect to ``y``. If this :class:`Op` is the only :class:`Op`
293
- that acts on ``x``, then ``dot(J.T,z)`` is the gradient of C with respect to
294
- ``x``. If there are other :class:`Op`\s that act on ``x``, :func:`pytensor.grad` will
295
- have to add up the terms of ``x``'s gradient contributed by the other
296
- :meth:`Op.grad` method.
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-vector product.
308
-
309
- So long as you implement this product correctly, you need not
310
- understand what :func:`pytensor.gradient.grad` is doing, but for the curious the
311
- mathematical justification is as follows:
312
-
313
- In essence, the :meth:`Op.grad` method must simply implement through symbolic
314
- :class:`Variable`\s and operations the chain rule of differential
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.grad` method:
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 gradients passed *to* :meth:`Op.grad` will also obey these constraints.
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.grad` method, recall the definition of
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.grad` should return
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.grad` method should return
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