pytensor 2.17.4__tar.gz → 2.18.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 (413) hide show
  1. {pytensor-2.17.4 → pytensor-2.18.0}/PKG-INFO +1 -1
  2. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/random/basic.rst +0 -3
  3. {pytensor-2.17.4 → pytensor-2.18.0}/pyproject.toml +1 -1
  4. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/_version.py +3 -3
  5. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/gradient.py +1 -1
  6. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/__init__.py +1 -1
  7. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/replace.py +14 -4
  8. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/cmodule.py +12 -0
  9. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/scalar.py +70 -40
  10. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/random.py +0 -1
  11. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scalar/math.py +53 -4
  12. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/__init__.py +1 -0
  13. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/blockwise.py +23 -57
  14. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/elemwise.py +2 -3
  15. pytensor-2.18.0/pytensor/tensor/functional.py +125 -0
  16. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/math.py +6 -0
  17. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/basic.py +16 -35
  18. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/rewriting/jax.py +0 -13
  19. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/math.py +22 -2
  20. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/shape.py +59 -1
  21. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/utils.py +38 -0
  22. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/variable.py +36 -0
  23. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor.egg-info/PKG-INFO +1 -1
  24. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor.egg-info/SOURCES.txt +1 -0
  25. {pytensor-2.17.4 → pytensor-2.18.0}/LICENSE.txt +0 -0
  26. {pytensor-2.17.4 → pytensor-2.18.0}/MANIFEST.in +0 -0
  27. {pytensor-2.17.4 → pytensor-2.18.0}/README.rst +0 -0
  28. {pytensor-2.17.4 → pytensor-2.18.0}/bin/__init__.py +0 -0
  29. {pytensor-2.17.4 → pytensor-2.18.0}/bin/pytensor-cache +0 -0
  30. {pytensor-2.17.4 → pytensor-2.18.0}/bin/pytensor_cache.py +0 -0
  31. {pytensor-2.17.4 → pytensor-2.18.0}/doc/.templates/PLACEHOLDER +0 -0
  32. {pytensor-2.17.4 → pytensor-2.18.0}/doc/.templates/layout.html +0 -0
  33. {pytensor-2.17.4 → pytensor-2.18.0}/doc/LICENSE.txt +0 -0
  34. {pytensor-2.17.4 → pytensor-2.18.0}/doc/README.md +0 -0
  35. {pytensor-2.17.4 → pytensor-2.18.0}/doc/acknowledgement.rst +0 -0
  36. {pytensor-2.17.4 → pytensor-2.18.0}/doc/bcast.png +0 -0
  37. {pytensor-2.17.4 → pytensor-2.18.0}/doc/bcast.svg +0 -0
  38. {pytensor-2.17.4 → pytensor-2.18.0}/doc/conf.py +0 -0
  39. {pytensor-2.17.4 → pytensor-2.18.0}/doc/core_development_guide.rst +0 -0
  40. {pytensor-2.17.4 → pytensor-2.18.0}/doc/css.inc +0 -0
  41. {pytensor-2.17.4 → pytensor-2.18.0}/doc/dev_start_guide.rst +0 -0
  42. {pytensor-2.17.4 → pytensor-2.18.0}/doc/environment.yml +0 -0
  43. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/apply.png +0 -0
  44. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/apply.svg +0 -0
  45. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/apply2.svg +0 -0
  46. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/creating_a_c_op.rst +0 -0
  47. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/creating_a_numba_jax_op.rst +0 -0
  48. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/creating_an_op.rst +0 -0
  49. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/ctype.rst +0 -0
  50. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/extending_faq.rst +0 -0
  51. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/extending_pytensor_solution_1.py +0 -0
  52. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/graph_rewriting.rst +0 -0
  53. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/graphstructures.rst +0 -0
  54. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/index.rst +0 -0
  55. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/inplace.rst +0 -0
  56. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/op.rst +0 -0
  57. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/other_ops.rst +0 -0
  58. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/pics/symbolic_graph_opt.png +0 -0
  59. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/pics/symbolic_graph_unopt.png +0 -0
  60. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/pipeline.rst +0 -0
  61. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/scan.rst +0 -0
  62. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/tips.rst +0 -0
  63. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/type.rst +0 -0
  64. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/unittest.rst +0 -0
  65. {pytensor-2.17.4 → pytensor-2.18.0}/doc/extending/using_params.rst +0 -0
  66. {pytensor-2.17.4 → pytensor-2.18.0}/doc/faq.rst +0 -0
  67. {pytensor-2.17.4 → pytensor-2.18.0}/doc/generate_dtype_tensor_table.py +0 -0
  68. {pytensor-2.17.4 → pytensor-2.18.0}/doc/glossary.rst +0 -0
  69. {pytensor-2.17.4 → pytensor-2.18.0}/doc/images/Elman_srnn.png +0 -0
  70. {pytensor-2.17.4 → pytensor-2.18.0}/doc/images/PyTensor_RGB.svg +0 -0
  71. {pytensor-2.17.4 → pytensor-2.18.0}/doc/images/blocksparse.png +0 -0
  72. {pytensor-2.17.4 → pytensor-2.18.0}/doc/images/lstm.png +0 -0
  73. {pytensor-2.17.4 → pytensor-2.18.0}/doc/images/lstm_memorycell.png +0 -0
  74. {pytensor-2.17.4 → pytensor-2.18.0}/doc/images/talk2010.gif +0 -0
  75. {pytensor-2.17.4 → pytensor-2.18.0}/doc/images/talk2010.png +0 -0
  76. {pytensor-2.17.4 → pytensor-2.18.0}/doc/index.rst +0 -0
  77. {pytensor-2.17.4 → pytensor-2.18.0}/doc/install.rst +0 -0
  78. {pytensor-2.17.4 → pytensor-2.18.0}/doc/internal/how_to_release.rst +0 -0
  79. {pytensor-2.17.4 → pytensor-2.18.0}/doc/internal/index.rst +0 -0
  80. {pytensor-2.17.4 → pytensor-2.18.0}/doc/internal/metadocumentation.rst +0 -0
  81. {pytensor-2.17.4 → pytensor-2.18.0}/doc/introduction.rst +0 -0
  82. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/debugmode.rst +0 -0
  83. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/function.rst +0 -0
  84. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/index.rst +0 -0
  85. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/io.rst +0 -0
  86. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/mode.rst +0 -0
  87. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/nanguardmode.rst +0 -0
  88. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/opfromgraph.rst +0 -0
  89. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/ops.rst +0 -0
  90. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/profilemode.rst +0 -0
  91. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/compile/shared.rst +0 -0
  92. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/config.rst +0 -0
  93. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/d3viz/css/d3-context-menu.css +0 -0
  94. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/d3viz/css/d3viz.css +0 -0
  95. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/d3viz/js/d3-context-menu.js +0 -0
  96. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/d3viz/js/d3.v3.min.js +0 -0
  97. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/d3viz/js/d3viz.js +0 -0
  98. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/d3viz/js/dagre-d3.min.js +0 -0
  99. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/d3viz/js/graphlib-dot.min.js +0 -0
  100. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/mlp.html +0 -0
  101. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/mlp.png +0 -0
  102. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/mlp2.html +0 -0
  103. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/mlp2.pdf +0 -0
  104. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/mlp2.png +0 -0
  105. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/ofg.html +0 -0
  106. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/examples/ofg2.html +0 -0
  107. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/index.ipynb +0 -0
  108. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/index.rst +0 -0
  109. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/index_files/index_10_0.png +0 -0
  110. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/index_files/index_11_0.png +0 -0
  111. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/index_files/index_24_0.png +0 -0
  112. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/d3viz/index_files/index_25_0.png +0 -0
  113. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/gradient.rst +0 -0
  114. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/graph/features.rst +0 -0
  115. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/graph/fgraph.rst +0 -0
  116. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/graph/graph.rst +0 -0
  117. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/graph/index.rst +0 -0
  118. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/graph/op.rst +0 -0
  119. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/graph/type.rst +0 -0
  120. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/graph/utils.rst +0 -0
  121. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/index.rst +0 -0
  122. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/misc/pkl_utils.rst +0 -0
  123. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/printing.rst +0 -0
  124. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/sandbox/index.rst +0 -0
  125. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/sandbox/linalg.rst +0 -0
  126. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/scalar/index.rst +0 -0
  127. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/scan.rst +0 -0
  128. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/sparse/index.rst +0 -0
  129. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/sparse/sandbox.rst +0 -0
  130. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/basic.rst +0 -0
  131. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/basic_opt.rst +0 -0
  132. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/bcast.png +0 -0
  133. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/bcast.svg +0 -0
  134. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/conv.rst +0 -0
  135. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/elemwise.rst +0 -0
  136. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/extra_ops.rst +0 -0
  137. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/fft.rst +0 -0
  138. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/index.rst +0 -0
  139. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/io.rst +0 -0
  140. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/math_opt.rst +0 -0
  141. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/nlinalg.rst +0 -0
  142. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/plot_fft.png +0 -0
  143. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/random/index.rst +0 -0
  144. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/random/utils.rst +0 -0
  145. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/slinalg.rst +0 -0
  146. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/tensor/utils.rst +0 -0
  147. {pytensor-2.17.4 → pytensor-2.18.0}/doc/library/typed_list.rst +0 -0
  148. {pytensor-2.17.4 → pytensor-2.18.0}/doc/links.rst +0 -0
  149. {pytensor-2.17.4 → pytensor-2.18.0}/doc/optimizations.rst +0 -0
  150. {pytensor-2.17.4 → pytensor-2.18.0}/doc/pylintrc +0 -0
  151. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/ccodegen.rst +0 -0
  152. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/compilation.rst +0 -0
  153. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/debugging_with_stepmode.rst +0 -0
  154. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/elemwise_compiler.rst +0 -0
  155. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/function.rst +0 -0
  156. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/functional.rst +0 -0
  157. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/how_to_make_ops.rst +0 -0
  158. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/index.rst +0 -0
  159. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/index2.rst +0 -0
  160. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/interactive_debugger.rst +0 -0
  161. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/logistic_regression_example.rst +0 -0
  162. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/performance.rst +0 -0
  163. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/randomnumbers.rst +0 -0
  164. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/rethinkccodegen.rst +0 -0
  165. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/sandbox.rst +0 -0
  166. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/software.rst +0 -0
  167. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/sparse.rst +0 -0
  168. {pytensor-2.17.4 → pytensor-2.18.0}/doc/sandbox/tensoroptools.rst +0 -0
  169. {pytensor-2.17.4 → pytensor-2.18.0}/doc/scripts/docgen.py +0 -0
  170. {pytensor-2.17.4 → pytensor-2.18.0}/doc/troubleshooting.rst +0 -0
  171. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/adding.rst +0 -0
  172. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/adding_solution_1.py +0 -0
  173. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/aliasing.rst +0 -0
  174. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/apply.png +0 -0
  175. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/apply.svg +0 -0
  176. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/bcast.png +0 -0
  177. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/broadcasting.rst +0 -0
  178. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/conditions.rst +0 -0
  179. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/debug_faq.rst +0 -0
  180. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/dlogistic.png +0 -0
  181. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/examples.rst +0 -0
  182. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/faq_tutorial.rst +0 -0
  183. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/gradients.rst +0 -0
  184. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/index.rst +0 -0
  185. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/loading_and_saving.rst +0 -0
  186. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/logistic.gp +0 -0
  187. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/logistic.png +0 -0
  188. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/loop.rst +0 -0
  189. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/loop_solution_1.py +0 -0
  190. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/modes.rst +0 -0
  191. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/modes_solution_1.py +0 -0
  192. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/multi_cores.rst +0 -0
  193. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/nan_tutorial.rst +0 -0
  194. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/pics/d3viz.png +0 -0
  195. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/pics/logreg_pydotprint_predict.png +0 -0
  196. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/pics/logreg_pydotprint_prediction.png +0 -0
  197. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/pics/logreg_pydotprint_train.png +0 -0
  198. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/printing_drawing.rst +0 -0
  199. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/profiling.rst +0 -0
  200. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/profiling_example.py +0 -0
  201. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/profiling_example_out.prof +0 -0
  202. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/shape_info.rst +0 -0
  203. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/sparse.rst +0 -0
  204. {pytensor-2.17.4 → pytensor-2.18.0}/doc/tutorial/symbolic_graphs.rst +0 -0
  205. {pytensor-2.17.4 → pytensor-2.18.0}/doc/user_guide.rst +0 -0
  206. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/__init__.py +0 -0
  207. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/bin/__init__.py +0 -0
  208. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/bin/pytensor_cache.py +0 -0
  209. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/breakpoint.py +0 -0
  210. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/__init__.py +0 -0
  211. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/builders.py +0 -0
  212. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/compiledir.py +0 -0
  213. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/compilelock.py +0 -0
  214. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/debugmode.py +0 -0
  215. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/function/__init__.py +0 -0
  216. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/function/pfunc.py +0 -0
  217. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/function/types.py +0 -0
  218. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/io.py +0 -0
  219. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/mode.py +0 -0
  220. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/monitormode.py +0 -0
  221. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/nanguardmode.py +0 -0
  222. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/ops.py +0 -0
  223. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/profiling.py +0 -0
  224. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/compile/sharedvalue.py +0 -0
  225. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/configdefaults.py +0 -0
  226. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/configparser.py +0 -0
  227. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/__init__.py +0 -0
  228. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/css/d3-context-menu.css +0 -0
  229. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/css/d3viz.css +0 -0
  230. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/d3viz.py +0 -0
  231. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/formatting.py +0 -0
  232. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/js/d3-context-menu.js +0 -0
  233. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/js/d3.v3.min.js +0 -0
  234. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/js/d3viz.js +0 -0
  235. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/js/dagre-d3.min.js +0 -0
  236. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/d3viz/js/graphlib-dot.min.js +0 -0
  237. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/basic.py +0 -0
  238. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/destroyhandler.py +0 -0
  239. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/features.py +0 -0
  240. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/fg.py +0 -0
  241. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/null_type.py +0 -0
  242. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/op.py +0 -0
  243. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/rewriting/__init__.py +0 -0
  244. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/rewriting/basic.py +0 -0
  245. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/rewriting/db.py +0 -0
  246. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/rewriting/kanren.py +0 -0
  247. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/rewriting/unify.py +0 -0
  248. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/rewriting/utils.py +0 -0
  249. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/type.py +0 -0
  250. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/graph/utils.py +0 -0
  251. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/ifelse.py +0 -0
  252. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/__init__.py +0 -0
  253. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/basic.py +0 -0
  254. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/__init__.py +0 -0
  255. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/basic.py +0 -0
  256. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/c_code/lazylinker_c.c +0 -0
  257. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/c_code/pytensor_mod_helper.h +0 -0
  258. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/cutils.py +0 -0
  259. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/cvm.py +0 -0
  260. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/exceptions.py +0 -0
  261. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/interface.py +0 -0
  262. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/lazylinker_c.py +0 -0
  263. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/op.py +0 -0
  264. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/params_type.py +0 -0
  265. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/c/type.py +0 -0
  266. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/__init__.py +0 -0
  267. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/__init__.py +0 -0
  268. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/basic.py +0 -0
  269. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/blockwise.py +0 -0
  270. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/elemwise.py +0 -0
  271. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/extra_ops.py +0 -0
  272. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/nlinalg.py +0 -0
  273. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/random.py +0 -0
  274. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/scan.py +0 -0
  275. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/shape.py +0 -0
  276. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/slinalg.py +0 -0
  277. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/sparse.py +0 -0
  278. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/subtensor.py +0 -0
  279. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/dispatch/tensor_basic.py +0 -0
  280. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/jax/linker.py +0 -0
  281. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/__init__.py +0 -0
  282. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/__init__.py +0 -0
  283. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/basic.py +0 -0
  284. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/cython_support.py +0 -0
  285. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/elemwise.py +0 -0
  286. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/elemwise_codegen.py +0 -0
  287. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/extra_ops.py +0 -0
  288. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/nlinalg.py +0 -0
  289. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/scalar.py +0 -0
  290. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/scan.py +0 -0
  291. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/slinalg.py +0 -0
  292. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/sparse.py +0 -0
  293. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/dispatch/tensor_basic.py +0 -0
  294. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/numba/linker.py +0 -0
  295. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/utils.py +0 -0
  296. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/link/vm.py +0 -0
  297. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/__init__.py +0 -0
  298. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/check_blas.py +0 -0
  299. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/check_blas_many.sh +0 -0
  300. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/check_duplicate_key.py +0 -0
  301. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/elemwise_openmp_speedup.py +0 -0
  302. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/elemwise_time_test.py +0 -0
  303. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/frozendict.py +0 -0
  304. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/may_share_memory.py +0 -0
  305. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/ordered_set.py +0 -0
  306. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/pkl_utils.py +0 -0
  307. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/misc/safe_asarray.py +0 -0
  308. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/printing.py +0 -0
  309. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/py.typed +0 -0
  310. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/raise_op.py +0 -0
  311. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scalar/__init__.py +0 -0
  312. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scalar/basic.py +0 -0
  313. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scalar/c_code/Faddeeva.cc +0 -0
  314. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scalar/c_code/Faddeeva.hh +0 -0
  315. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scalar/c_code/gamma.c +0 -0
  316. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scalar/loop.py +0 -0
  317. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scalar/sharedvar.py +0 -0
  318. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/__init__.py +0 -0
  319. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/basic.py +0 -0
  320. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/checkpoints.py +0 -0
  321. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/op.py +0 -0
  322. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/rewriting.py +0 -0
  323. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/scan_perform.pyx +0 -0
  324. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/scan_perform_ext.py +0 -0
  325. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/utils.py +0 -0
  326. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/scan/views.py +0 -0
  327. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/__init__.py +0 -0
  328. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/basic.py +0 -0
  329. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/rewriting.py +0 -0
  330. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/sandbox/__init__.py +0 -0
  331. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/sandbox/sp.py +0 -0
  332. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/sandbox/sp2.py +0 -0
  333. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/sharedvar.py +0 -0
  334. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/type.py +0 -0
  335. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/sparse/utils.py +0 -0
  336. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/basic.py +0 -0
  337. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/blas.py +0 -0
  338. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/blas_c.py +0 -0
  339. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/blas_headers.py +0 -0
  340. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/blas_scipy.py +0 -0
  341. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/c_code/alt_blas_common.h +0 -0
  342. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/c_code/alt_blas_template.c +0 -0
  343. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/c_code/dimshuffle.c +0 -0
  344. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/conv/__init__.py +0 -0
  345. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/conv/abstract_conv.py +0 -0
  346. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/elemwise_cgen.py +0 -0
  347. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/exceptions.py +0 -0
  348. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/extra_ops.py +0 -0
  349. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/fft.py +0 -0
  350. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/fourier.py +0 -0
  351. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/inplace.py +0 -0
  352. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/io.py +0 -0
  353. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/linalg.py +0 -0
  354. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/nlinalg.py +0 -0
  355. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/__init__.py +0 -0
  356. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/op.py +0 -0
  357. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/rewriting/__init__.py +0 -0
  358. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/rewriting/basic.py +0 -0
  359. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/type.py +0 -0
  360. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/utils.py +0 -0
  361. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/random/var.py +0 -0
  362. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/__init__.py +0 -0
  363. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/basic.py +0 -0
  364. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/blas.py +0 -0
  365. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/blas_c.py +0 -0
  366. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/blas_scipy.py +0 -0
  367. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/blockwise.py +0 -0
  368. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/elemwise.py +0 -0
  369. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/extra_ops.py +0 -0
  370. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/jax.py +0 -0
  371. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/linalg.py +0 -0
  372. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/shape.py +0 -0
  373. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/special.py +0 -0
  374. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/subtensor.py +0 -0
  375. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/rewriting/uncanonicalize.py +0 -0
  376. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/sharedvar.py +0 -0
  377. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/slinalg.py +0 -0
  378. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/sort.py +0 -0
  379. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/special.py +0 -0
  380. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/subtensor.py +0 -0
  381. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/type.py +0 -0
  382. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/type_other.py +0 -0
  383. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/var.py +0 -0
  384. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/tensor/xlogx.py +0 -0
  385. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/typed_list/__init__.py +0 -0
  386. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/typed_list/basic.py +0 -0
  387. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/typed_list/rewriting.py +0 -0
  388. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/typed_list/type.py +0 -0
  389. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/updates.py +0 -0
  390. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/utils.py +0 -0
  391. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor/version.py +0 -0
  392. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor.egg-info/dependency_links.txt +0 -0
  393. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor.egg-info/entry_points.txt +0 -0
  394. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor.egg-info/requires.txt +0 -0
  395. {pytensor-2.17.4 → pytensor-2.18.0}/pytensor.egg-info/top_level.txt +0 -0
  396. {pytensor-2.17.4 → pytensor-2.18.0}/scripts/downstream_pr.sh +0 -0
  397. {pytensor-2.17.4 → pytensor-2.18.0}/scripts/mypy-failing.txt +0 -0
  398. {pytensor-2.17.4 → pytensor-2.18.0}/scripts/upstream_pr.sh +0 -0
  399. {pytensor-2.17.4 → pytensor-2.18.0}/setup.cfg +0 -0
  400. {pytensor-2.17.4 → pytensor-2.18.0}/setup.py +0 -0
  401. {pytensor-2.17.4 → pytensor-2.18.0}/tests/link/c/c_code/test_cenum.h +0 -0
  402. {pytensor-2.17.4 → pytensor-2.18.0}/tests/link/c/c_code/test_quadratic_function.c +0 -0
  403. {pytensor-2.17.4 → pytensor-2.18.0}/tests/tensor/conv/c_code/corr3d_gemm.c +0 -0
  404. {pytensor-2.17.4 → pytensor-2.18.0}/tests/tensor/conv/c_code/corr_gemm.c +0 -0
  405. {pytensor-2.17.4 → pytensor-2.18.0}/tests/test_breakpoint.py +0 -0
  406. {pytensor-2.17.4 → pytensor-2.18.0}/tests/test_config.py +0 -0
  407. {pytensor-2.17.4 → pytensor-2.18.0}/tests/test_gradient.py +0 -0
  408. {pytensor-2.17.4 → pytensor-2.18.0}/tests/test_ifelse.py +0 -0
  409. {pytensor-2.17.4 → pytensor-2.18.0}/tests/test_printing.py +0 -0
  410. {pytensor-2.17.4 → pytensor-2.18.0}/tests/test_raise_op.py +0 -0
  411. {pytensor-2.17.4 → pytensor-2.18.0}/tests/test_rop.py +0 -0
  412. {pytensor-2.17.4 → pytensor-2.18.0}/tests/test_updates.py +0 -0
  413. {pytensor-2.17.4 → pytensor-2.18.0}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytensor
3
- Version: 2.17.4
3
+ Version: 2.18.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: .. _license:
@@ -82,9 +82,6 @@ PyTensor can produce :class:`RandomVariable`\s that draw samples from many diffe
82
82
  .. autoclass:: pytensor.tensor.random.basic.CategoricalRV
83
83
  :members: __call__
84
84
 
85
- .. autoclass:: pytensor.tensor.random.basic.ChiSquareRV
86
- :members: __call__
87
-
88
85
  .. autoclass:: pytensor.tensor.random.basic.DirichletRV
89
86
  :members: __call__
90
87
 
@@ -2,7 +2,7 @@
2
2
  requires = [
3
3
  "setuptools>=48.0.0",
4
4
  "cython",
5
- "numpy>=1.17.0,<1.26",
5
+ "numpy>=1.17.0",
6
6
  "versioneer[toml]==0.28",
7
7
  ]
8
8
  build-backend = "setuptools.build_meta"
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2023-11-11T07:10:07+0000",
11
+ "date": "2023-11-20T14:04:50+0100",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "0f802ab2ddb5f960218f88d1e984417cdbe94bc8",
15
- "version": "2.17.4"
14
+ "full-revisionid": "eb552eef7a8381e47a38ce0694244700693cb978",
15
+ "version": "2.18.0"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -101,7 +101,7 @@ def grad_undefined(op, x_pos, x, comment=""):
101
101
  return (
102
102
  NullType(
103
103
  "This variable is Null because the grad method for "
104
- f"input {x_pos} ({x}) of the {op} op is not implemented. {comment}"
104
+ f"input {x_pos} ({x}) of the {op} op is undefined. {comment}"
105
105
  )
106
106
  )()
107
107
 
@@ -9,7 +9,7 @@ from pytensor.graph.basic import (
9
9
  clone,
10
10
  ancestors,
11
11
  )
12
- from pytensor.graph.replace import clone_replace, graph_replace, vectorize
12
+ from pytensor.graph.replace import clone_replace, graph_replace, vectorize_graph
13
13
  from pytensor.graph.op import Op
14
14
  from pytensor.graph.type import Type
15
15
  from pytensor.graph.fg import FunctionGraph
@@ -1,3 +1,4 @@
1
+ import warnings
1
2
  from collections.abc import Iterable, Mapping, Sequence
2
3
  from functools import partial, singledispatch
3
4
  from typing import Optional, Union, cast, overload
@@ -203,7 +204,7 @@ def graph_replace(
203
204
 
204
205
 
205
206
  @singledispatch
206
- def _vectorize_node(op: Op, node: Apply, *bached_inputs) -> Apply:
207
+ def _vectorize_node(op: Op, node: Apply, *batched_inputs) -> Apply:
207
208
  # Default implementation is provided in pytensor.tensor.blockwise
208
209
  raise NotImplementedError
209
210
 
@@ -214,8 +215,12 @@ def vectorize_node(node: Apply, *batched_inputs) -> Apply:
214
215
  return _vectorize_node(op, node, *batched_inputs)
215
216
 
216
217
 
218
+ def _vectorize_not_needed(op, node, *batched_inputs):
219
+ return op.make_node(*batched_inputs)
220
+
221
+
217
222
  @overload
218
- def vectorize(
223
+ def vectorize_graph(
219
224
  outputs: Variable,
220
225
  replace: Mapping[Variable, Variable],
221
226
  ) -> Variable:
@@ -223,14 +228,14 @@ def vectorize(
223
228
 
224
229
 
225
230
  @overload
226
- def vectorize(
231
+ def vectorize_graph(
227
232
  outputs: Sequence[Variable],
228
233
  replace: Mapping[Variable, Variable],
229
234
  ) -> Sequence[Variable]:
230
235
  ...
231
236
 
232
237
 
233
- def vectorize(
238
+ def vectorize_graph(
234
239
  outputs: Union[Variable, Sequence[Variable]],
235
240
  replace: Mapping[Variable, Variable],
236
241
  ) -> Union[Variable, Sequence[Variable]]:
@@ -309,3 +314,8 @@ def vectorize(
309
314
  else:
310
315
  [vect_output] = seq_vect_outputs
311
316
  return vect_output
317
+
318
+
319
+ def vectorize(*args, **kwargs):
320
+ warnings.warn("vectorize was renamed to vectorize_graph", UserWarning)
321
+ return vectorize_graph(*args, **kwargs)
@@ -2731,6 +2731,15 @@ def default_blas_ldflags():
2731
2731
  shell=True,
2732
2732
  )
2733
2733
  (stdout, stderr) = p.communicate(input=b"")
2734
+ if p.returncode != 0:
2735
+ warnings.warn(
2736
+ "Pytensor cxx failed to communicate its search dirs. As a consequence, "
2737
+ "it might not be possible to automatically determine the blas link flags to use.\n"
2738
+ f"Command that was run: {config.cxx} -print-search-dirs\n"
2739
+ f"Output printed to stderr: {stderr.decode(sys.stderr.encoding)}"
2740
+ )
2741
+ return []
2742
+
2734
2743
  maybe_lib_dirs = [
2735
2744
  [pathlib.Path(p).resolve() for p in line[len("libraries: =") :].split(":")]
2736
2745
  for line in stdout.decode(sys.stdout.encoding).splitlines()
@@ -2773,6 +2782,9 @@ def default_blas_ldflags():
2773
2782
  else:
2774
2783
  raise RuntimeError(f"Supplied flags {flags} failed to compile")
2775
2784
 
2785
+ # If no compiler is available we default to empty ldflags
2786
+ if not config.cxx:
2787
+ return ""
2776
2788
  _std_lib_dirs = std_lib_dirs()
2777
2789
  if len(_std_lib_dirs) > 0:
2778
2790
  rpath = _std_lib_dirs[0]
@@ -20,7 +20,17 @@ from pytensor.scalar.basic import (
20
20
  Second,
21
21
  Sub,
22
22
  )
23
- from pytensor.scalar.math import Erf, Erfc, Erfcinv, Erfcx, Erfinv, Iv, Log1mexp, Psi
23
+ from pytensor.scalar.math import (
24
+ Erf,
25
+ Erfc,
26
+ Erfcinv,
27
+ Erfcx,
28
+ Erfinv,
29
+ Iv,
30
+ Log1mexp,
31
+ Psi,
32
+ TriGamma,
33
+ )
24
34
 
25
35
 
26
36
  def try_import_tfp_jax_op(op: ScalarOp, jax_op_name: Optional[str] = None) -> Callable:
@@ -37,7 +47,7 @@ def try_import_tfp_jax_op(op: ScalarOp, jax_op_name: Optional[str] = None) -> Ca
37
47
  return typing.cast(Callable, getattr(tfp_jax_math, jax_op_name))
38
48
 
39
49
 
40
- def check_if_inputs_scalars(node):
50
+ def all_inputs_are_scalar(node):
41
51
  """Check whether all the inputs of an `Elemwise` are scalar values.
42
52
 
43
53
  `jax.lax` or `jax.numpy` functions systematically return `TracedArrays`,
@@ -62,56 +72,68 @@ def check_if_inputs_scalars(node):
62
72
 
63
73
  @jax_funcify.register(ScalarOp)
64
74
  def jax_funcify_ScalarOp(op, node, **kwargs):
65
- func_name = op.nfunc_spec[0]
75
+ """Return JAX function that implements the same computation as the Scalar Op.
76
+
77
+ This dispatch is expected to return a JAX function that works on Array inputs as Elemwise does,
78
+ even though it's dispatched on the Scalar Op.
79
+ """
66
80
 
67
81
  # We dispatch some PyTensor operators to Python operators
68
82
  # whenever the inputs are all scalars.
69
- are_inputs_scalars = check_if_inputs_scalars(node)
70
- if are_inputs_scalars:
71
- elemwise = elemwise_scalar(op)
72
- if elemwise is not None:
73
- return elemwise
83
+ if all_inputs_are_scalar(node):
84
+ jax_func = jax_funcify_scalar_op_via_py_operators(op)
85
+ if jax_func is not None:
86
+ return jax_func
87
+
88
+ nfunc_spec = getattr(op, "nfunc_spec", None)
89
+ if nfunc_spec is None:
90
+ raise NotImplementedError(f"Dispatch not implemented for Scalar Op {op}")
74
91
 
92
+ func_name = nfunc_spec[0]
75
93
  if "." in func_name:
76
- jnp_func = functools.reduce(getattr, [jax] + func_name.split("."))
94
+ jax_func = functools.reduce(getattr, [jax] + func_name.split("."))
77
95
  else:
78
- jnp_func = getattr(jnp, func_name)
79
-
80
- if hasattr(op, "nfunc_variadic"):
81
- # These are special cases that handle invalid arities due to the broken
82
- # PyTensor `Op` type contract (e.g. binary `Op`s that also function as
83
- # their own variadic counterparts--even when those counterparts already
84
- # exist as independent `Op`s).
85
- jax_variadic_func = getattr(jnp, op.nfunc_variadic)
86
-
87
- def elemwise(*args):
88
- if len(args) > op.nfunc_spec[1]:
89
- return jax_variadic_func(
90
- jnp.stack(jnp.broadcast_arrays(*args), axis=0), axis=0
91
- )
92
- else:
93
- return jnp_func(*args)
94
-
95
- return elemwise
96
- else:
97
- return jnp_func
96
+ jax_func = getattr(jnp, func_name)
97
+
98
+ if len(node.inputs) > op.nfunc_spec[1]:
99
+ # Some Scalar Ops accept multiple number of inputs, behaving as a variadic function,
100
+ # even though the base Op from `func_name` is specified as a binary Op.
101
+ # This happens with `Add`, which can work as a `Sum` for multiple scalars.
102
+ jax_variadic_func = getattr(jnp, op.nfunc_variadic, None)
103
+ if not jax_variadic_func:
104
+ raise NotImplementedError(
105
+ f"Dispatch not implemented for Scalar Op {op} with {len(node.inputs)} inputs"
106
+ )
107
+
108
+ def jax_func(*args):
109
+ return jax_variadic_func(
110
+ jnp.stack(jnp.broadcast_arrays(*args), axis=0), axis=0
111
+ )
112
+
113
+ return jax_func
98
114
 
99
115
 
100
116
  @functools.singledispatch
101
- def elemwise_scalar(op):
117
+ def jax_funcify_scalar_op_via_py_operators(op):
118
+ """Specialized JAX dispatch for Elemwise operations where all inputs are Scalar arrays.
119
+
120
+ Scalar (constant) arrays in the JAX backend get lowered to the native types (int, floats),
121
+ which can perform better with Python operators, and more importantly, avoid upcasting to array types
122
+ not supported by some JAX functions.
123
+ """
102
124
  return None
103
125
 
104
126
 
105
- @elemwise_scalar.register(Add)
106
- def elemwise_scalar_add(op):
127
+ @jax_funcify_scalar_op_via_py_operators.register(Add)
128
+ def jax_funcify_scalar_Add(op):
107
129
  def elemwise(*inputs):
108
130
  return sum(inputs)
109
131
 
110
132
  return elemwise
111
133
 
112
134
 
113
- @elemwise_scalar.register(Mul)
114
- def elemwise_scalar_mul(op):
135
+ @jax_funcify_scalar_op_via_py_operators.register(Mul)
136
+ def jax_funcify_scalar_Mul(op):
115
137
  import operator
116
138
  from functools import reduce
117
139
 
@@ -121,24 +143,24 @@ def elemwise_scalar_mul(op):
121
143
  return elemwise
122
144
 
123
145
 
124
- @elemwise_scalar.register(Sub)
125
- def elemwise_scalar_sub(op):
146
+ @jax_funcify_scalar_op_via_py_operators.register(Sub)
147
+ def jax_funcify_scalar_Sub(op):
126
148
  def elemwise(x, y):
127
149
  return x - y
128
150
 
129
151
  return elemwise
130
152
 
131
153
 
132
- @elemwise_scalar.register(IntDiv)
133
- def elemwise_scalar_intdiv(op):
154
+ @jax_funcify_scalar_op_via_py_operators.register(IntDiv)
155
+ def jax_funcify_scalar_IntDiv(op):
134
156
  def elemwise(x, y):
135
157
  return x // y
136
158
 
137
159
  return elemwise
138
160
 
139
161
 
140
- @elemwise_scalar.register(Mod)
141
- def elemwise_scalar_mod(op):
162
+ @jax_funcify_scalar_op_via_py_operators.register(Mod)
163
+ def jax_funcify_scalar_Mod(op):
142
164
  def elemwise(x, y):
143
165
  return x % y
144
166
 
@@ -263,6 +285,14 @@ def jax_funcify_Psi(op, node, **kwargs):
263
285
  return psi
264
286
 
265
287
 
288
+ @jax_funcify.register(TriGamma)
289
+ def jax_funcify_TriGamma(op, node, **kwargs):
290
+ def tri_gamma(x):
291
+ return jax.scipy.special.polygamma(1, x)
292
+
293
+ return tri_gamma
294
+
295
+
266
296
  @jax_funcify.register(Softplus)
267
297
  def jax_funcify_Softplus(op, **kwargs):
268
298
  def softplus(x):
@@ -195,7 +195,6 @@ def {sized_fn_name}({random_fn_input_names}):
195
195
  @numba_funcify.register(aer.NormalRV)
196
196
  @numba_funcify.register(aer.LogNormalRV)
197
197
  @numba_funcify.register(aer.GammaRV)
198
- @numba_funcify.register(aer.ChiSquareRV)
199
198
  @numba_funcify.register(aer.ParetoRV)
200
199
  @numba_funcify.register(aer.GumbelRV)
201
200
  @numba_funcify.register(aer.ExponentialRV)
@@ -13,7 +13,7 @@ import scipy.special
13
13
  import scipy.stats
14
14
 
15
15
  from pytensor.configdefaults import config
16
- from pytensor.gradient import grad_not_implemented
16
+ from pytensor.gradient import grad_not_implemented, grad_undefined
17
17
  from pytensor.scalar.basic import BinaryScalarOp, ScalarOp, UnaryScalarOp
18
18
  from pytensor.scalar.basic import abs as scalar_abs
19
19
  from pytensor.scalar.basic import (
@@ -473,8 +473,12 @@ class TriGamma(UnaryScalarOp):
473
473
  def impl(self, x):
474
474
  return TriGamma.st_impl(x)
475
475
 
476
- def grad(self, inputs, outputs_gradients):
477
- raise NotImplementedError()
476
+ def L_op(self, inputs, outputs, outputs_gradients):
477
+ (x,) = inputs
478
+ (g_out,) = outputs_gradients
479
+ if x in complex_types:
480
+ raise NotImplementedError("gradient not implemented for complex types")
481
+ return [g_out * polygamma(2, x)]
478
482
 
479
483
  def c_support_code(self, **kwargs):
480
484
  # The implementation has been copied from
@@ -541,7 +545,52 @@ class TriGamma(UnaryScalarOp):
541
545
  raise NotImplementedError("only floating point is implemented")
542
546
 
543
547
 
544
- tri_gamma = TriGamma(upgrade_to_float, name="tri_gamma")
548
+ # Scipy polygamma does not support complex inputs: https://github.com/scipy/scipy/issues/7410
549
+ tri_gamma = TriGamma(upgrade_to_float_no_complex, name="tri_gamma")
550
+
551
+
552
+ class PolyGamma(BinaryScalarOp):
553
+ """Polygamma function of order n evaluated at x.
554
+
555
+ It corresponds to the (n+1)th derivative of the log gamma function.
556
+
557
+ TODO: Because the first input is discrete and the output is continuous,
558
+ the default elemwise inplace won't work, as it always tries to store the results in the first input.
559
+ """
560
+
561
+ nfunc_spec = ("scipy.special.polygamma", 2, 1)
562
+
563
+ @staticmethod
564
+ def output_types_preference(n_type, x_type):
565
+ if n_type not in discrete_types:
566
+ raise TypeError(
567
+ f"Polygamma order parameter must be discrete, got {n_type} dtype"
568
+ )
569
+ # Scipy doesn't support it
570
+ return upgrade_to_float_no_complex(x_type)
571
+
572
+ @staticmethod
573
+ def st_impl(n, x):
574
+ return scipy.special.polygamma(n, x)
575
+
576
+ def impl(self, n, x):
577
+ return PolyGamma.st_impl(n, x)
578
+
579
+ def L_op(self, inputs, outputs, output_gradients):
580
+ (n, x) = inputs
581
+ (g_out,) = output_gradients
582
+ if x in complex_types:
583
+ raise NotImplementedError("gradient not implemented for complex types")
584
+ return [
585
+ grad_undefined(self, 0, n),
586
+ g_out * self(n + 1, x),
587
+ ]
588
+
589
+ def c_code(self, *args, **kwargs):
590
+ raise NotImplementedError()
591
+
592
+
593
+ polygamma = PolyGamma(name="polygamma")
545
594
 
546
595
 
547
596
  class Chi2SF(BinaryScalarOp):
@@ -148,6 +148,7 @@ from pytensor.tensor.subtensor import * # noqa
148
148
  from pytensor.tensor.type import * # noqa
149
149
  from pytensor.tensor.type_other import * # noqa
150
150
  from pytensor.tensor.variable import TensorConstant, TensorVariable # noqa
151
+ from pytensor.tensor.functional import vectorize # noqa
151
152
 
152
153
  # Allow accessing numpy constants from pytensor.tensor
153
154
  from numpy import e, euler_gamma, inf, infty, nan, newaxis, pi # noqa
@@ -1,4 +1,3 @@
1
- import re
2
1
  from collections.abc import Sequence
3
2
  from typing import Any, Optional, cast
4
3
 
@@ -9,53 +8,22 @@ from pytensor.gradient import DisconnectedType
9
8
  from pytensor.graph.basic import Apply, Constant, Variable
10
9
  from pytensor.graph.null_type import NullType
11
10
  from pytensor.graph.op import Op
12
- from pytensor.graph.replace import _vectorize_node, vectorize
11
+ from pytensor.graph.replace import (
12
+ _vectorize_node,
13
+ _vectorize_not_needed,
14
+ vectorize_graph,
15
+ )
13
16
  from pytensor.tensor import as_tensor_variable
14
17
  from pytensor.tensor.shape import shape_padleft
15
18
  from pytensor.tensor.type import continuous_dtypes, discrete_dtypes, tensor
16
- from pytensor.tensor.utils import broadcast_static_dim_lengths, import_func_from_string
19
+ from pytensor.tensor.utils import (
20
+ _parse_gufunc_signature,
21
+ broadcast_static_dim_lengths,
22
+ import_func_from_string,
23
+ )
17
24
  from pytensor.tensor.variable import TensorVariable
18
25
 
19
26
 
20
- # TODO: Implement vectorize helper to batch whole graphs (similar to what Blockwise does for the grad)
21
-
22
- # Copied verbatim from numpy.lib.function_base
23
- # https://github.com/numpy/numpy/blob/f2db090eb95b87d48a3318c9a3f9d38b67b0543c/numpy/lib/function_base.py#L1999-L2029
24
- _DIMENSION_NAME = r"\w+"
25
- _CORE_DIMENSION_LIST = "(?:{0:}(?:,{0:})*)?".format(_DIMENSION_NAME)
26
- _ARGUMENT = rf"\({_CORE_DIMENSION_LIST}\)"
27
- _ARGUMENT_LIST = "{0:}(?:,{0:})*".format(_ARGUMENT)
28
- _SIGNATURE = "^{0:}->{0:}$".format(_ARGUMENT_LIST)
29
-
30
-
31
- def _parse_gufunc_signature(signature):
32
- """
33
- Parse string signatures for a generalized universal function.
34
-
35
- Arguments
36
- ---------
37
- signature : string
38
- Generalized universal function signature, e.g., ``(m,n),(n,p)->(m,p)``
39
- for ``np.matmul``.
40
-
41
- Returns
42
- -------
43
- Tuple of input and output core dimensions parsed from the signature, each
44
- of the form List[Tuple[str, ...]].
45
- """
46
- signature = re.sub(r"\s+", "", signature)
47
-
48
- if not re.match(_SIGNATURE, signature):
49
- raise ValueError(f"not a valid gufunc signature: {signature}")
50
- return tuple(
51
- [
52
- tuple(re.findall(_DIMENSION_NAME, arg))
53
- for arg in re.findall(_ARGUMENT, arg_list)
54
- ]
55
- for arg_list in signature.split("->")
56
- )
57
-
58
-
59
27
  def safe_signature(
60
28
  core_inputs: Sequence[Variable],
61
29
  core_outputs: Sequence[Variable],
@@ -73,17 +41,6 @@ def safe_signature(
73
41
  return f"{inputs_sig}->{outputs_sig}"
74
42
 
75
43
 
76
- @_vectorize_node.register(Op)
77
- def vectorize_node_fallback(op: Op, node: Apply, *bached_inputs) -> Apply:
78
- if hasattr(op, "gufunc_signature"):
79
- signature = op.gufunc_signature
80
- else:
81
- # TODO: This is pretty bad for shape inference and merge optimization!
82
- # Should get better as we add signatures to our Ops
83
- signature = safe_signature(node.inputs, node.outputs)
84
- return cast(Apply, Blockwise(op, signature=signature).make_node(*bached_inputs))
85
-
86
-
87
44
  class Blockwise(Op):
88
45
  """Generalizes a core `Op` to work with batched dimensions.
89
46
 
@@ -274,7 +231,7 @@ class Blockwise(Op):
274
231
 
275
232
  core_igrads = self.core_op.L_op(core_inputs, core_outputs, core_ograds)
276
233
 
277
- igrads = vectorize(
234
+ igrads = vectorize_graph(
278
235
  [core_igrad for core_igrad in core_igrads if core_igrad is not None],
279
236
  replace=dict(
280
237
  zip(core_inputs + core_outputs + core_ograds, inputs + outputs + ograds)
@@ -397,6 +354,15 @@ class Blockwise(Op):
397
354
  return self.name
398
355
 
399
356
 
400
- @_vectorize_node.register(Blockwise)
401
- def vectorize_not_needed(op, node, *batch_inputs):
402
- return op.make_node(*batch_inputs)
357
+ @_vectorize_node.register(Op)
358
+ def vectorize_node_fallback(op: Op, node: Apply, *bached_inputs) -> Apply:
359
+ if hasattr(op, "gufunc_signature"):
360
+ signature = op.gufunc_signature
361
+ else:
362
+ # TODO: This is pretty bad for shape inference and merge optimization!
363
+ # Should get better as we add signatures to our Ops
364
+ signature = safe_signature(node.inputs, node.outputs)
365
+ return cast(Apply, Blockwise(op, signature=signature).make_node(*bached_inputs))
366
+
367
+
368
+ _vectorize_node.register(Blockwise, _vectorize_not_needed)
@@ -7,7 +7,7 @@ from pytensor.configdefaults import config
7
7
  from pytensor.gradient import DisconnectedType
8
8
  from pytensor.graph.basic import Apply
9
9
  from pytensor.graph.null_type import NullType
10
- from pytensor.graph.replace import _vectorize_node
10
+ from pytensor.graph.replace import _vectorize_node, _vectorize_not_needed
11
11
  from pytensor.graph.utils import MethodNotDefined
12
12
  from pytensor.link.c.basic import failure_code
13
13
  from pytensor.link.c.op import COp, ExternalCOp, OpenMPOp
@@ -22,7 +22,6 @@ from pytensor.scalar.basic import transfer_type, upcast
22
22
  from pytensor.tensor import elemwise_cgen as cgen
23
23
  from pytensor.tensor import get_vector_length
24
24
  from pytensor.tensor.basic import _get_vector_length, as_tensor_variable
25
- from pytensor.tensor.blockwise import vectorize_not_needed
26
25
  from pytensor.tensor.type import (
27
26
  TensorType,
28
27
  continuous_dtypes,
@@ -1741,7 +1740,7 @@ def _get_vector_length_Elemwise(op, var):
1741
1740
  raise ValueError(f"Length of {var} cannot be determined")
1742
1741
 
1743
1742
 
1744
- _vectorize_node.register(Elemwise, vectorize_not_needed)
1743
+ _vectorize_node.register(Elemwise, _vectorize_not_needed)
1745
1744
 
1746
1745
 
1747
1746
  @_vectorize_node.register(DimShuffle)
@@ -0,0 +1,125 @@
1
+ from typing import Callable, Optional
2
+
3
+ from pytensor.graph import vectorize_graph
4
+ from pytensor.tensor import TensorVariable
5
+ from pytensor.tensor.utils import _parse_gufunc_signature
6
+
7
+
8
+ def vectorize(func: Callable, signature: Optional[str] = None) -> Callable:
9
+ """Create a vectorized version of a python function that takes TensorVariables as inputs and outputs.
10
+
11
+ Similar to numpy.vectorize. See respective docstrings for more details.
12
+
13
+ Parameters
14
+ ----------
15
+ func: Callable
16
+ Function that creates the desired outputs from TensorVariable inputs with the core dimensions.
17
+ signature: str, optional
18
+ Generalized universal function signature, e.g., (m,n),(n)->(m) for vectorized matrix-vector multiplication.
19
+ If not provided, it is assumed all inputs have scalar core dimensions. Unlike numpy, the outputs
20
+ can have arbitrary shapes when the signature is not provided.
21
+
22
+ Returns
23
+ -------
24
+ vectorized_func: Callable
25
+ Callable that takes TensorVariables with arbitrarily batched dimensions on the left
26
+ and returns variables whose graphs correspond to the vectorized expressions of func.
27
+
28
+ Notes
29
+ -----
30
+ Unlike numpy.vectorize, the equality of core dimensions implied by the signature is not explicitly asserted.
31
+
32
+ To vectorize an existing graph, use `pytensor.graph.replace.vectorize_graph` instead.
33
+
34
+
35
+ Examples
36
+ --------
37
+ .. code-block:: python
38
+
39
+ import pytensor
40
+ import pytensor.tensor as pt
41
+
42
+ def func(x):
43
+ return pt.exp(x) / pt.sum(pt.exp(x))
44
+
45
+ vec_func = pt.vectorize(func, signature="(a)->(a)")
46
+
47
+ x = pt.matrix("x")
48
+ y = vec_func(x)
49
+
50
+ fn = pytensor.function([x], y)
51
+ fn([[0, 1, 2], [2, 1, 0]])
52
+ # array([[0.09003057, 0.24472847, 0.66524096],
53
+ # [0.66524096, 0.24472847, 0.09003057]])
54
+
55
+
56
+ .. code-block:: python
57
+
58
+ import pytensor
59
+ import pytensor.tensor as pt
60
+
61
+ def func(x):
62
+ return x[0], x[-1]
63
+
64
+ vec_func = pt.vectorize(func, signature="(a)->(),()")
65
+
66
+ x = pt.matrix("x")
67
+ y1, y2 = vec_func(x)
68
+
69
+ fn = pytensor.function([x], [y1, y2])
70
+ fn([[-10, 0, 10], [-11, 0, 11]])
71
+ # [array([-10., -11.]), array([10., 11.])]
72
+
73
+ """
74
+
75
+ def inner(*inputs):
76
+ if signature is None:
77
+ # Assume all inputs are scalar
78
+ inputs_sig = [()] * len(inputs)
79
+ else:
80
+ inputs_sig, outputs_sig = _parse_gufunc_signature(signature)
81
+ if len(inputs) != len(inputs_sig):
82
+ raise ValueError(
83
+ f"Number of inputs does not match signature: {signature}"
84
+ )
85
+
86
+ # Create dummy core inputs by stripping the batched dimensions of inputs
87
+ core_inputs = []
88
+ for input, input_sig in zip(inputs, inputs_sig):
89
+ if not isinstance(input, TensorVariable):
90
+ raise TypeError(
91
+ f"Inputs to vectorize function must be TensorVariable, got {type(input)}"
92
+ )
93
+
94
+ if input.ndim < len(input_sig):
95
+ raise ValueError(
96
+ f"Input {input} has less dimensions than signature {input_sig}"
97
+ )
98
+ if len(input_sig):
99
+ core_shape = input.type.shape[-len(input_sig) :]
100
+ else:
101
+ core_shape = ()
102
+
103
+ core_input = input.type.clone(shape=core_shape)(name=input.name)
104
+ core_inputs.append(core_input)
105
+
106
+ # Call function on dummy core inputs
107
+ core_outputs = func(*core_inputs)
108
+ if core_outputs is None:
109
+ raise ValueError("vectorize function returned no outputs")
110
+
111
+ if signature is not None:
112
+ if isinstance(core_outputs, (list, tuple)):
113
+ n_core_outputs = len(core_outputs)
114
+ else:
115
+ n_core_outputs = 1
116
+ if n_core_outputs != len(outputs_sig):
117
+ raise ValueError(
118
+ f"Number of outputs does not match signature: {signature}"
119
+ )
120
+
121
+ # Vectorize graph by replacing dummy core inputs by original inputs
122
+ outputs = vectorize_graph(core_outputs, replace=dict(zip(core_inputs, inputs)))
123
+ return outputs
124
+
125
+ return inner