pytensor 2.31.4__tar.gz → 2.31.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytensor-2.31.4/pytensor.egg-info → pytensor-2.31.5}/PKG-INFO +1 -1
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/gradients.rst +34 -7
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/_version.py +3 -3
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/gradient.py +68 -50
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/replace.py +2 -2
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/basic.py +4 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/op.py +7 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/linalg.py +46 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/math.py +31 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/__init__.py +1 -1
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/math.py +1 -1
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/random.py +14 -3
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/rewriting/utils.py +11 -1
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/rewriting/vectorization.py +1 -1
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/shape.py +20 -14
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/type.py +10 -4
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/vectorization.py +13 -0
- {pytensor-2.31.4 → pytensor-2.31.5/pytensor.egg-info}/PKG-INFO +1 -1
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/test_gradient.py +201 -150
- {pytensor-2.31.4 → pytensor-2.31.5}/LICENSE.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/MANIFEST.in +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/README.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/.templates/PLACEHOLDER +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/.templates/layout.html +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/.templates/nb-badges.html +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/.templates/rendered_citation.html +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/LICENSE.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/README.md +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/acknowledgement.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/bcast.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/bcast.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/blog.md +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/conf.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/core_development_guide.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/css.inc +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/dev_start_guide.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/environment.yml +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/apply.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/apply.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/apply2.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/creating_a_c_op.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/creating_a_numba_jax_op.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/creating_an_op.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/ctype.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/extending_faq.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/extending_pytensor_solution_1.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/graph_rewriting.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/graphstructures.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/inplace.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/op.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/other_ops.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/pics/symbolic_graph_opt.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/pics/symbolic_graph_unopt.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/pipeline.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/scan.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/tips.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/type.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/unittest.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/extending/using_params.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/faq.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/gallery/optimize/root.ipynb +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/gallery/page_footer.md +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/gallery/rewrites/graph_rewrites.ipynb +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/gallery/scan/scan_tutorial.ipynb +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/generate_dtype_tensor_table.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/glossary.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/Elman_srnn.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/PyTensor.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/PyTensor_RGB.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/PyTensor_logo.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/binder.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/blocksparse.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/colab.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/github.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/lstm.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/lstm_memorycell.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/talk2010.gif +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/images/talk2010.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/install.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/internal/how_to_release.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/internal/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/internal/metadocumentation.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/introduction.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/debugmode.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/function.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/io.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/mode.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/nanguardmode.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/opfromgraph.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/ops.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/profilemode.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/compile/shared.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/config.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/d3viz/css/d3-context-menu.css +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/d3viz/css/d3viz.css +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/d3viz/js/d3-context-menu.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/d3viz/js/d3.v3.min.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/d3viz/js/d3viz.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/d3viz/js/dagre-d3.min.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/d3viz/js/graphlib-dot.min.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/mlp.html +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/mlp.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/mlp2.html +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/mlp2.pdf +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/mlp2.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/ofg.html +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/examples/ofg2.html +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/index.ipynb +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/index_files/index_10_0.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/index_files/index_11_0.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/index_files/index_24_0.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/d3viz/index_files/index_25_0.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/graph/features.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/graph/fgraph.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/graph/graph.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/graph/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/graph/op.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/graph/replace.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/graph/type.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/graph/utils.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/misc/pkl_utils.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/printing.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/scalar/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/scan.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/sparse/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/sparse/sandbox.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/basic.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/basic_opt.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/bcast.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/bcast.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/conv.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/elemwise.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/extra_ops.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/fft.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/functional.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/io.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/math_opt.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/nlinalg.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/optimize.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/plot_fft.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/random/distributions.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/random/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/slinalg.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/tensor/utils.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/library/typed_list.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/links.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/optimizations.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/pylintrc +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/robots.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/troubleshooting.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/adding.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/adding_solution_1.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/aliasing.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/apply.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/apply.svg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/bcast.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/broadcasting.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/conditions.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/debug_faq.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/dlogistic.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/examples.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/faq_tutorial.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/index.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/loading_and_saving.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/logistic.gp +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/logistic.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/loop.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/loop_solution_1.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/modes.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/modes_solution_1.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/multi_cores.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/nan_tutorial.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/pics/d3viz.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/pics/logreg_pydotprint_predict.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/pics/logreg_pydotprint_prediction.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/pics/logreg_pydotprint_train.png +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/printing_drawing.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/prng.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/profiling.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/profiling_example.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/profiling_example_out.prof +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/shape_info.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/sparse.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/tutorial/symbolic_graphs.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/doc/user_guide.rst +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pyproject.toml +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/bin/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/bin/pytensor_cache.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/breakpoint.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/builders.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/compiledir.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/compilelock.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/debugmode.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/function/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/function/pfunc.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/function/types.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/io.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/mode.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/monitormode.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/nanguardmode.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/ops.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/profiling.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/compile/sharedvalue.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/configdefaults.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/configparser.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/css/d3-context-menu.css +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/css/d3viz.css +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/d3viz.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/formatting.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/html/template.html +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/js/d3-context-menu.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/js/d3.v3.min.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/js/d3viz.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/js/dagre-d3.min.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/d3viz/js/graphlib-dot.min.js +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/destroyhandler.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/features.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/fg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/null_type.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/op.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/rewriting/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/rewriting/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/rewriting/db.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/rewriting/kanren.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/rewriting/unify.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/rewriting/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/type.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/graph/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/ifelse.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/ipython.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/c_code/lazylinker_c.c +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/c_code/pytensor_mod_helper.h +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/cmodule.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/cutils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/cvm.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/exceptions.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/interface.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/lazylinker_c.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/op.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/params_type.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/c/type.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/blas.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/blockwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/einsum.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/elemwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/extra_ops.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/math.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/nlinalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/pad.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/random.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/scalar.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/scan.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/shape.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/signal/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/signal/conv.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/slinalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/sort.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/sparse.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/subtensor.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/dispatch/tensor_basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/jax/linker.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/blockwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/cython_support.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/elemwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/extra_ops.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/_LAPACK.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/decomposition/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/decomposition/cholesky.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/decomposition/lu.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/decomposition/lu_factor.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/cholesky.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/general.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/lu_solve.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/norm.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/posdef.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/symmetric.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/triangular.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/tridiagonal.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/solve/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/linalg/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/nlinalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/random.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/scalar.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/scan.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/signal/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/signal/conv.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/slinalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/sparse.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/subtensor.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/tensor_basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/dispatch/vectorize_codegen.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/numba/linker.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/blas.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/blockwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/elemwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/extra_ops.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/math.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/nlinalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/scalar.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/shape.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/sort.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/dispatch/subtensor.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/pytorch/linker.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/link/vm.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/check_blas.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/check_blas_many.sh +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/check_duplicate_key.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/elemwise_openmp_speedup.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/elemwise_time_test.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/frozendict.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/may_share_memory.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/ordered_set.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/misc/pkl_utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/npy_2_compat.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/printing.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/py.typed +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/raise_op.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/c_code/Faddeeva.cc +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/c_code/Faddeeva.hh +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/c_code/gamma.c +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/c_code/incbet.c +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/loop.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/math.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scalar/sharedvar.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/checkpoints.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/op.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/rewriting.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/scan_perform.pyx +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/scan_perform_ext.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/scan/views.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/rewriting.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/sandbox/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/sandbox/sp.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/sandbox/sp2.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/sharedvar.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/type.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/sparse/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/_linalg/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/_linalg/solve/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/_linalg/solve/rewriting.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/_linalg/solve/tridiagonal.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/blas.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/blas_c.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/blas_headers.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/blas_scipy.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/blockwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/c_code/alt_blas_common.h +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/c_code/alt_blas_template.c +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/c_code/dimshuffle.c +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/conv/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/conv/abstract_conv.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/einsum.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/elemwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/elemwise_cgen.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/exceptions.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/extra_ops.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/fft.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/fourier.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/functional.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/inplace.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/interpolate.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/io.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/linalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/math.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/nlinalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/optimize.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/pad.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/rewriting/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/rewriting/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/rewriting/jax.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/rewriting/numba.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/type.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/random/var.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/blas.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/blas_c.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/blas_scipy.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/blockwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/conv.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/einsum.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/elemwise.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/extra_ops.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/jax.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/numba.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/ofg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/shape.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/special.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/subtensor.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/subtensor_lift.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/rewriting/uncanonicalize.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/shape.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/sharedvar.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/signal/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/signal/conv.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/slinalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/sort.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/special.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/subtensor.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/type.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/type_other.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/var.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/variable.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/tensor/xlogx.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/typed_list/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/typed_list/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/typed_list/rewriting.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/typed_list/type.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/updates.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/utils.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/indexing.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/linalg.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/reduction.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/rewriting/__init__.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/rewriting/basic.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/rewriting/indexing.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/rewriting/math.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/rewriting/reduction.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor/xtensor/rewriting/shape.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor.egg-info/SOURCES.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor.egg-info/dependency_links.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor.egg-info/entry_points.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor.egg-info/requires.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/pytensor.egg-info/top_level.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/scripts/mypy-failing.txt +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/scripts/slowest_tests/update-slowest-times-issue.sh +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/setup.cfg +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/setup.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/link/c/c_code/test_cenum.h +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/link/c/c_code/test_quadratic_function.c +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/tensor/conv/c_code/corr3d_gemm.c +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/tensor/conv/c_code/corr_gemm.c +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/test_breakpoint.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/test_config.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/test_ifelse.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/test_printing.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/test_raise_op.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/test_rop.py +0 -0
- {pytensor-2.31.4 → pytensor-2.31.5}/tests/test_updates.py +0 -0
|
@@ -101,9 +101,12 @@ PyTensor implements the :func:`pytensor.gradient.jacobian` macro that does all
|
|
|
101
101
|
that is needed to compute the Jacobian. The following text explains how
|
|
102
102
|
to do it manually.
|
|
103
103
|
|
|
104
|
+
Using Scan
|
|
105
|
+
----------
|
|
106
|
+
|
|
104
107
|
In order to manually compute the Jacobian of some function ``y`` with
|
|
105
|
-
respect to some parameter ``x`` we
|
|
106
|
-
|
|
108
|
+
respect to some parameter ``x`` we can use `scan`.
|
|
109
|
+
In this case, we loop over the entries in ``y`` and compute the gradient of
|
|
107
110
|
``y[i]`` with respect to ``x``.
|
|
108
111
|
|
|
109
112
|
.. note::
|
|
@@ -111,8 +114,7 @@ do is to loop over the entries in ``y`` and compute the gradient of
|
|
|
111
114
|
`scan` is a generic op in PyTensor that allows writing in a symbolic
|
|
112
115
|
manner all kinds of recurrent equations. While creating
|
|
113
116
|
symbolic loops (and optimizing them for performance) is a hard task,
|
|
114
|
-
|
|
115
|
-
shall return to :ref:`scan<tutloop>` later in this tutorial.
|
|
117
|
+
efforts are being made to improving the performance of `scan`.
|
|
116
118
|
|
|
117
119
|
>>> import pytensor
|
|
118
120
|
>>> import pytensor.tensor as pt
|
|
@@ -124,9 +126,9 @@ do is to loop over the entries in ``y`` and compute the gradient of
|
|
|
124
126
|
array([[ 8., 0.],
|
|
125
127
|
[ 0., 8.]])
|
|
126
128
|
|
|
127
|
-
|
|
128
|
-
``y.shape[0]`` using `pt.arange`. Then
|
|
129
|
-
at each step,
|
|
129
|
+
This code generates a sequence of integers from ``0`` to
|
|
130
|
+
``y.shape[0]`` using `pt.arange`. Then it loops through this sequence, and
|
|
131
|
+
at each step, computes the gradient of element ``y[i]`` with respect to
|
|
130
132
|
``x``. `scan` automatically concatenates all these rows, generating a
|
|
131
133
|
matrix which corresponds to the Jacobian.
|
|
132
134
|
|
|
@@ -139,6 +141,31 @@ matrix which corresponds to the Jacobian.
|
|
|
139
141
|
``x`` anymore, while ``y[i]`` still is.
|
|
140
142
|
|
|
141
143
|
|
|
144
|
+
Using automatic vectorization
|
|
145
|
+
-----------------------------
|
|
146
|
+
An alternative way to build the Jacobian is to vectorize the graph that computes a single row or colum of the jacobian
|
|
147
|
+
We can use `Lop` or `Rop` (more about it below) to obtain the row or column of the jacobian and `vectorize_graph`
|
|
148
|
+
to vectorize it to the full jacobian matrix.
|
|
149
|
+
|
|
150
|
+
>>> import pytensor
|
|
151
|
+
>>> import pytensor.tensor as pt
|
|
152
|
+
>>> from pytensor.gradient import Lop
|
|
153
|
+
>>> from pytensor.graph import vectorize_graph
|
|
154
|
+
>>> x = pt.dvector('x')
|
|
155
|
+
>>> y = x ** 2
|
|
156
|
+
>>> row_cotangent = pt.dvector("row_cotangent") # Helper variable, it will be replaced during vectorization
|
|
157
|
+
>>> J_row = Lop(y, x, row_cotangent)
|
|
158
|
+
>>> J = vectorize_graph(J_row, replace={row_cotangent: pt.eye(x.size)})
|
|
159
|
+
>>> f = pytensor.function([x], J)
|
|
160
|
+
>>> f([4, 4])
|
|
161
|
+
array([[ 8., 0.],
|
|
162
|
+
[ 0., 8.]])
|
|
163
|
+
|
|
164
|
+
This avoids the overhead of scan, at the cost of higher memory usage if the jacobian expression has large intermediate operations.
|
|
165
|
+
Also, not all graphs are safely vectorizable (e.g., if different rows require intermediate operations of different sizes).
|
|
166
|
+
For these reasons `jacobian` uses scan by default. The behavior can be changed by setting `vectorize=True`.
|
|
167
|
+
|
|
168
|
+
|
|
142
169
|
Computing the Hessian
|
|
143
170
|
=====================
|
|
144
171
|
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2025-06-
|
|
11
|
+
"date": "2025-06-30T17:01:33+0200",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "2.31.
|
|
14
|
+
"full-revisionid": "2ab60b39e4622b1d9d677ab3e598d752bd25b17e",
|
|
15
|
+
"version": "2.31.5"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -11,7 +11,7 @@ import numpy as np
|
|
|
11
11
|
import pytensor
|
|
12
12
|
from pytensor.compile.ops import ViewOp
|
|
13
13
|
from pytensor.configdefaults import config
|
|
14
|
-
from pytensor.graph import utils
|
|
14
|
+
from pytensor.graph import utils, vectorize_graph
|
|
15
15
|
from pytensor.graph.basic import Apply, NominalVariable, Variable
|
|
16
16
|
from pytensor.graph.null_type import NullType, null_type
|
|
17
17
|
from pytensor.graph.op import get_test_values
|
|
@@ -703,15 +703,15 @@ def grad(
|
|
|
703
703
|
grad_dict[var] = g_var
|
|
704
704
|
|
|
705
705
|
def handle_disconnected(var):
|
|
706
|
-
message = (
|
|
707
|
-
"grad method was asked to compute the gradient "
|
|
708
|
-
"with respect to a variable that is not part of "
|
|
709
|
-
"the computational graph of the cost, or is used "
|
|
710
|
-
f"only by a non-differentiable operator: {var}"
|
|
711
|
-
)
|
|
712
706
|
if disconnected_inputs == "ignore":
|
|
713
|
-
|
|
707
|
+
return
|
|
714
708
|
elif disconnected_inputs == "warn":
|
|
709
|
+
message = (
|
|
710
|
+
"grad method was asked to compute the gradient "
|
|
711
|
+
"with respect to a variable that is not part of "
|
|
712
|
+
"the computational graph of the cost, or is used "
|
|
713
|
+
f"only by a non-differentiable operator: {var}"
|
|
714
|
+
)
|
|
715
715
|
warnings.warn(message, stacklevel=2)
|
|
716
716
|
elif disconnected_inputs == "raise":
|
|
717
717
|
message = utils.get_variable_trace_string(var)
|
|
@@ -2021,13 +2021,19 @@ GradientError: numeric gradient and analytic gradient exceed tolerance:
|
|
|
2021
2021
|
Exception args: {args_msg}"""
|
|
2022
2022
|
|
|
2023
2023
|
|
|
2024
|
-
def jacobian(
|
|
2024
|
+
def jacobian(
|
|
2025
|
+
expression,
|
|
2026
|
+
wrt,
|
|
2027
|
+
consider_constant=None,
|
|
2028
|
+
disconnected_inputs="raise",
|
|
2029
|
+
vectorize=False,
|
|
2030
|
+
):
|
|
2025
2031
|
"""
|
|
2026
2032
|
Compute the full Jacobian, row by row.
|
|
2027
2033
|
|
|
2028
2034
|
Parameters
|
|
2029
2035
|
----------
|
|
2030
|
-
expression :
|
|
2036
|
+
expression :class:`~pytensor.graph.basic.Variable`
|
|
2031
2037
|
Values that we are differentiating (that we want the Jacobian of)
|
|
2032
2038
|
wrt : :class:`~pytensor.graph.basic.Variable` or list of Variables
|
|
2033
2039
|
Term[s] with respect to which we compute the Jacobian
|
|
@@ -2051,18 +2057,18 @@ def jacobian(expression, wrt, consider_constant=None, disconnected_inputs="raise
|
|
|
2051
2057
|
output, then a zero variable is returned. The return value is
|
|
2052
2058
|
of same type as `wrt`: a list/tuple or TensorVariable in all cases.
|
|
2053
2059
|
"""
|
|
2060
|
+
from pytensor.tensor.basic import eye
|
|
2061
|
+
from pytensor.tensor.extra_ops import broadcast_to
|
|
2054
2062
|
|
|
2055
2063
|
if not isinstance(expression, Variable):
|
|
2056
2064
|
raise TypeError("jacobian expects a Variable as `expression`")
|
|
2057
2065
|
|
|
2058
|
-
if expression.ndim > 1:
|
|
2059
|
-
raise ValueError(
|
|
2060
|
-
"jacobian expects a 1 dimensional variable as `expression`."
|
|
2061
|
-
" If not use flatten to make it a vector"
|
|
2062
|
-
)
|
|
2063
|
-
|
|
2064
2066
|
using_list = isinstance(wrt, list)
|
|
2065
2067
|
using_tuple = isinstance(wrt, tuple)
|
|
2068
|
+
grad_kwargs = {
|
|
2069
|
+
"consider_constant": consider_constant,
|
|
2070
|
+
"disconnected_inputs": disconnected_inputs,
|
|
2071
|
+
}
|
|
2066
2072
|
|
|
2067
2073
|
if isinstance(wrt, list | tuple):
|
|
2068
2074
|
wrt = list(wrt)
|
|
@@ -2070,43 +2076,55 @@ def jacobian(expression, wrt, consider_constant=None, disconnected_inputs="raise
|
|
|
2070
2076
|
wrt = [wrt]
|
|
2071
2077
|
|
|
2072
2078
|
if all(expression.type.broadcastable):
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2079
|
+
jacobian_matrices = grad(expression.squeeze(), wrt, **grad_kwargs)
|
|
2080
|
+
|
|
2081
|
+
elif vectorize:
|
|
2082
|
+
expression_flat = expression.ravel()
|
|
2083
|
+
row_tangent = _float_ones_like(expression_flat).type("row_tangent")
|
|
2084
|
+
jacobian_single_rows = Lop(expression.ravel(), wrt, row_tangent, **grad_kwargs)
|
|
2085
|
+
|
|
2086
|
+
n_rows = expression_flat.size
|
|
2087
|
+
jacobian_matrices = vectorize_graph(
|
|
2088
|
+
jacobian_single_rows,
|
|
2089
|
+
replace={row_tangent: eye(n_rows, dtype=row_tangent.dtype)},
|
|
2083
2090
|
)
|
|
2091
|
+
if disconnected_inputs != "raise":
|
|
2092
|
+
# If the input is disconnected from the cost, `vectorize_graph` has no effect on the respective jacobian
|
|
2093
|
+
# We have to broadcast the zeros explicitly here
|
|
2094
|
+
for i, (jacobian_single_row, jacobian_matrix) in enumerate(
|
|
2095
|
+
zip(jacobian_single_rows, jacobian_matrices, strict=True)
|
|
2096
|
+
):
|
|
2097
|
+
if jacobian_single_row.ndim == jacobian_matrix.ndim:
|
|
2098
|
+
jacobian_matrices[i] = broadcast_to(
|
|
2099
|
+
jacobian_matrix, shape=(n_rows, *jacobian_matrix.shape)
|
|
2100
|
+
)
|
|
2084
2101
|
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2102
|
+
else:
|
|
2103
|
+
|
|
2104
|
+
def inner_function(*args):
|
|
2105
|
+
idx, expr, *wrt = args
|
|
2106
|
+
return grad(expr[idx], wrt, **grad_kwargs)
|
|
2107
|
+
|
|
2108
|
+
jacobian_matrices, updates = pytensor.scan(
|
|
2109
|
+
inner_function,
|
|
2110
|
+
sequences=pytensor.tensor.arange(expression.size),
|
|
2111
|
+
non_sequences=[expression.ravel(), *wrt],
|
|
2112
|
+
return_list=True,
|
|
2113
|
+
)
|
|
2114
|
+
if updates:
|
|
2115
|
+
raise ValueError(
|
|
2116
|
+
"The scan used to build the jacobian matrices returned a list of updates"
|
|
2095
2117
|
)
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
non_sequences=[expression, *wrt],
|
|
2107
|
-
)
|
|
2108
|
-
assert not updates, "Scan has returned a list of updates; this should not happen."
|
|
2109
|
-
return as_list_or_tuple(using_list, using_tuple, jacobs)
|
|
2118
|
+
|
|
2119
|
+
if jacobian_matrices[0].ndim < (expression.ndim + wrt[0].ndim):
|
|
2120
|
+
# There was some raveling or squeezing done prior to getting the jacobians
|
|
2121
|
+
# Reshape into original shapes
|
|
2122
|
+
jacobian_matrices = [
|
|
2123
|
+
jac_matrix.reshape((*expression.shape, *w.shape))
|
|
2124
|
+
for jac_matrix, w in zip(jacobian_matrices, wrt, strict=True)
|
|
2125
|
+
]
|
|
2126
|
+
|
|
2127
|
+
return as_list_or_tuple(using_list, using_tuple, jacobian_matrices)
|
|
2110
2128
|
|
|
2111
2129
|
|
|
2112
2130
|
def hessian(cost, wrt, consider_constant=None, disconnected_inputs="raise"):
|
|
@@ -232,13 +232,13 @@ def vectorize_graph(
|
|
|
232
232
|
def vectorize_graph(
|
|
233
233
|
outputs: Sequence[Variable],
|
|
234
234
|
replace: Mapping[Variable, Variable],
|
|
235
|
-
) ->
|
|
235
|
+
) -> list[Variable]: ...
|
|
236
236
|
|
|
237
237
|
|
|
238
238
|
def vectorize_graph(
|
|
239
239
|
outputs: Variable | Sequence[Variable],
|
|
240
240
|
replace: Mapping[Variable, Variable],
|
|
241
|
-
) -> Variable |
|
|
241
|
+
) -> Variable | list[Variable]:
|
|
242
242
|
"""Vectorize outputs graph given mapping from old variables to expanded counterparts version.
|
|
243
243
|
|
|
244
244
|
Expanded dimensions must be on the left. Behavior is similar to the functional `numpy.vectorize`.
|
|
@@ -3081,6 +3081,10 @@ def flatten(x, ndim=1):
|
|
|
3081
3081
|
else:
|
|
3082
3082
|
dims = (-1,)
|
|
3083
3083
|
|
|
3084
|
+
if len(dims) == _x.ndim:
|
|
3085
|
+
# Nothing to ravel
|
|
3086
|
+
return _x
|
|
3087
|
+
|
|
3084
3088
|
x_reshaped = _x.reshape(dims)
|
|
3085
3089
|
shape_kept_dims = _x.type.shape[: ndim - 1]
|
|
3086
3090
|
bcast_new_dim = builtins.all(s == 1 for s in _x.type.shape[ndim - 1 :])
|
|
@@ -392,6 +392,13 @@ class RandomVariable(RNGConsumerOp):
|
|
|
392
392
|
out_type = TensorType(dtype=self.dtype, shape=static_shape)
|
|
393
393
|
outputs = (rng.type(), out_type())
|
|
394
394
|
|
|
395
|
+
if self.dtype == "floatX":
|
|
396
|
+
# Commit to a specific float type if the Op is still using "floatX"
|
|
397
|
+
dtype = config.floatX
|
|
398
|
+
props = self._props_dict()
|
|
399
|
+
props["dtype"] = dtype
|
|
400
|
+
self = type(self)(**props)
|
|
401
|
+
|
|
395
402
|
return Apply(self, inputs, outputs)
|
|
396
403
|
|
|
397
404
|
def batch_ndim(self, node: Apply) -> int:
|
|
@@ -47,8 +47,10 @@ from pytensor.tensor.rewriting.basic import (
|
|
|
47
47
|
from pytensor.tensor.slinalg import (
|
|
48
48
|
BlockDiagonal,
|
|
49
49
|
Cholesky,
|
|
50
|
+
CholeskySolve,
|
|
50
51
|
Solve,
|
|
51
52
|
SolveBase,
|
|
53
|
+
SolveTriangular,
|
|
52
54
|
_bilinear_solve_discrete_lyapunov,
|
|
53
55
|
block_diag,
|
|
54
56
|
cholesky,
|
|
@@ -908,6 +910,11 @@ def rewrite_cholesky_diag_to_sqrt_diag(fgraph, node):
|
|
|
908
910
|
return None
|
|
909
911
|
|
|
910
912
|
[input] = node.inputs
|
|
913
|
+
|
|
914
|
+
# Check if input is a (1, 1) matrix
|
|
915
|
+
if all(input.type.broadcastable[-2:]):
|
|
916
|
+
return [pt.sqrt(input)]
|
|
917
|
+
|
|
911
918
|
# Check for use of pt.diag first
|
|
912
919
|
if (
|
|
913
920
|
input.owner
|
|
@@ -1020,3 +1027,42 @@ def slogdet_specialization(fgraph, node):
|
|
|
1020
1027
|
k: slogdet_specialization_map[v] for k, v in dummy_replacements.items()
|
|
1021
1028
|
}
|
|
1022
1029
|
return replacements
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
@register_stabilize
|
|
1033
|
+
@register_canonicalize
|
|
1034
|
+
@node_rewriter([Blockwise])
|
|
1035
|
+
def scalar_solve_to_division(fgraph, node):
|
|
1036
|
+
"""
|
|
1037
|
+
Replace solve(a, b) with b / a if a is a (1, 1) matrix
|
|
1038
|
+
"""
|
|
1039
|
+
|
|
1040
|
+
core_op = node.op.core_op
|
|
1041
|
+
if not isinstance(core_op, SolveBase):
|
|
1042
|
+
return None
|
|
1043
|
+
|
|
1044
|
+
a, b = node.inputs
|
|
1045
|
+
old_out = node.outputs[0]
|
|
1046
|
+
if not all(a.broadcastable[-2:]):
|
|
1047
|
+
return None
|
|
1048
|
+
|
|
1049
|
+
# Special handling for different types of solve
|
|
1050
|
+
match core_op:
|
|
1051
|
+
case SolveTriangular():
|
|
1052
|
+
# Corner case: if user asked for a triangular solve with a unit diagonal, a is taken to be 1
|
|
1053
|
+
new_out = b / a if not core_op.unit_diagonal else b
|
|
1054
|
+
case CholeskySolve():
|
|
1055
|
+
new_out = b / a**2
|
|
1056
|
+
case Solve():
|
|
1057
|
+
new_out = b / a
|
|
1058
|
+
case _:
|
|
1059
|
+
raise NotImplementedError(
|
|
1060
|
+
f"Unsupported core_op type: {type(core_op)} in scalar_solve_to_divison"
|
|
1061
|
+
)
|
|
1062
|
+
|
|
1063
|
+
if core_op.b_ndim == 1:
|
|
1064
|
+
new_out = new_out.squeeze(-1)
|
|
1065
|
+
|
|
1066
|
+
copy_stack_trace(old_out, new_out)
|
|
1067
|
+
|
|
1068
|
+
return [new_out]
|
|
@@ -400,6 +400,37 @@ def local_exp_log(fgraph, node):
|
|
|
400
400
|
return [exp(x)]
|
|
401
401
|
|
|
402
402
|
|
|
403
|
+
@register_canonicalize
|
|
404
|
+
@register_specialize
|
|
405
|
+
@node_rewriter([sqrt, sqr])
|
|
406
|
+
def local_sqrt_sqr(fgraph, node):
|
|
407
|
+
x = node.inputs[0]
|
|
408
|
+
|
|
409
|
+
if not (x.owner and isinstance(x.owner.op, Elemwise)):
|
|
410
|
+
return
|
|
411
|
+
|
|
412
|
+
prev_op = x.owner.op.scalar_op
|
|
413
|
+
node_op = node.op.scalar_op
|
|
414
|
+
|
|
415
|
+
# Case for sqrt(sqr(x)) -> |x|
|
|
416
|
+
if isinstance(prev_op, ps.Sqrt) and isinstance(node_op, ps.Sqr):
|
|
417
|
+
new_out = pt_abs(x.owner.inputs[0])
|
|
418
|
+
old_out = node.outputs[0]
|
|
419
|
+
|
|
420
|
+
# Handle potential integer to float cast by sqr
|
|
421
|
+
if new_out.dtype != old_out.dtype:
|
|
422
|
+
new_out = cast(new_out, old_out.dtype)
|
|
423
|
+
return [new_out]
|
|
424
|
+
|
|
425
|
+
# Case for sqr(sqrt(x)) -> x
|
|
426
|
+
if isinstance(prev_op, ps.Sqr) and isinstance(node_op, ps.Sqrt):
|
|
427
|
+
x = x.owner.inputs[0]
|
|
428
|
+
old_out = node.outputs[0]
|
|
429
|
+
new_out = switch(ge(x, 0), x, np.asarray(np.nan, old_out.dtype))
|
|
430
|
+
|
|
431
|
+
return [new_out]
|
|
432
|
+
|
|
433
|
+
|
|
403
434
|
@register_specialize
|
|
404
435
|
@node_rewriter([exp, expm1])
|
|
405
436
|
def local_exp_log_nan_switch(fgraph, node):
|
|
@@ -101,7 +101,7 @@ round = _as_xelemwise(ps.round_half_to_even)
|
|
|
101
101
|
maximum = _as_xelemwise(ps.scalar_maximum)
|
|
102
102
|
minimum = _as_xelemwise(ps.scalar_minimum)
|
|
103
103
|
second = _as_xelemwise(ps.second)
|
|
104
|
-
sigmoid = _as_xelemwise(ps.sigmoid)
|
|
104
|
+
sigmoid = expit = _as_xelemwise(ps.sigmoid)
|
|
105
105
|
sign = _as_xelemwise(ps.sign)
|
|
106
106
|
sin = _as_xelemwise(ps.sin)
|
|
107
107
|
sinh = _as_xelemwise(ps.sinh)
|
|
@@ -5,8 +5,8 @@ from typing import Literal
|
|
|
5
5
|
import pytensor.tensor.random.basic as ptr
|
|
6
6
|
from pytensor.graph.basic import Variable
|
|
7
7
|
from pytensor.tensor.random.op import RandomVariable
|
|
8
|
-
from pytensor.xtensor import as_xtensor
|
|
9
8
|
from pytensor.xtensor.math import sqrt
|
|
9
|
+
from pytensor.xtensor.type import as_xtensor
|
|
10
10
|
from pytensor.xtensor.vectorization import XRV
|
|
11
11
|
|
|
12
12
|
|
|
@@ -14,6 +14,7 @@ def _as_xrv(
|
|
|
14
14
|
core_op: RandomVariable,
|
|
15
15
|
core_inps_dims_map: Sequence[Sequence[int]] | None = None,
|
|
16
16
|
core_out_dims_map: Sequence[int] | None = None,
|
|
17
|
+
name: str | None = None,
|
|
17
18
|
):
|
|
18
19
|
"""Helper function to define an XRV constructor.
|
|
19
20
|
|
|
@@ -41,7 +42,14 @@ def _as_xrv(
|
|
|
41
42
|
core_out_dims_map = tuple(range(core_op.ndim_supp))
|
|
42
43
|
|
|
43
44
|
core_dims_needed = max(
|
|
44
|
-
(
|
|
45
|
+
max(
|
|
46
|
+
(
|
|
47
|
+
max((entry + 1 for entry in dims_map), default=0)
|
|
48
|
+
for dims_map in core_inps_dims_map
|
|
49
|
+
),
|
|
50
|
+
default=0,
|
|
51
|
+
),
|
|
52
|
+
max((entry + 1 for entry in core_out_dims_map), default=0),
|
|
45
53
|
)
|
|
46
54
|
|
|
47
55
|
@wraps(core_op)
|
|
@@ -76,7 +84,10 @@ def _as_xrv(
|
|
|
76
84
|
extra_dims = {}
|
|
77
85
|
|
|
78
86
|
return XRV(
|
|
79
|
-
core_op,
|
|
87
|
+
core_op,
|
|
88
|
+
core_dims=full_core_dims,
|
|
89
|
+
extra_dims=tuple(extra_dims.keys()),
|
|
90
|
+
name=name,
|
|
80
91
|
)(rng, *extra_dims.values(), *params)
|
|
81
92
|
|
|
82
93
|
return xrv_constructor
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from pytensor.compile import optdb
|
|
2
|
-
from pytensor.graph.rewriting.basic import NodeRewriter
|
|
2
|
+
from pytensor.graph.rewriting.basic import NodeRewriter, in2out
|
|
3
3
|
from pytensor.graph.rewriting.db import EquilibriumDB, RewriteDatabase
|
|
4
|
+
from pytensor.tensor.rewriting.ofg import inline_ofg_expansion
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
lower_xtensor_db = EquilibriumDB(ignore_newtrees=False)
|
|
@@ -14,6 +15,15 @@ optdb.register(
|
|
|
14
15
|
position=0.1,
|
|
15
16
|
)
|
|
16
17
|
|
|
18
|
+
# Register OFG inline again after lowering xtensor
|
|
19
|
+
optdb.register(
|
|
20
|
+
"inline_ofg_expansion_xtensor",
|
|
21
|
+
in2out(inline_ofg_expansion),
|
|
22
|
+
"fast_run",
|
|
23
|
+
"fast_compile",
|
|
24
|
+
position=0.11,
|
|
25
|
+
)
|
|
26
|
+
|
|
17
27
|
|
|
18
28
|
def register_lower_xtensor(
|
|
19
29
|
node_rewriter: RewriteDatabase | NodeRewriter | str, *tags: str, **kwargs
|
|
@@ -116,7 +116,7 @@ def lower_rv(fgraph, node):
|
|
|
116
116
|
size = [*extra_dim_lengths, *param_batch_shape]
|
|
117
117
|
|
|
118
118
|
# RVs are their own core Op
|
|
119
|
-
new_next_rng, tensor_out = core_op(
|
|
119
|
+
new_next_rng, tensor_out = core_op.make_node(rng, size, *tensor_params).outputs
|
|
120
120
|
|
|
121
121
|
# Convert output Tensors to XTensors
|
|
122
122
|
new_out = xtensor_from_tensor(tensor_out, dims=old_out.type.dims)
|
|
@@ -189,7 +189,7 @@ class Transpose(XOp):
|
|
|
189
189
|
|
|
190
190
|
def transpose(
|
|
191
191
|
x,
|
|
192
|
-
*
|
|
192
|
+
*dim: str | EllipsisType,
|
|
193
193
|
missing_dims: Literal["raise", "warn", "ignore"] = "raise",
|
|
194
194
|
):
|
|
195
195
|
"""Transpose dimensions of the tensor.
|
|
@@ -198,7 +198,7 @@ def transpose(
|
|
|
198
198
|
----------
|
|
199
199
|
x : XTensorVariable
|
|
200
200
|
Input tensor to transpose.
|
|
201
|
-
*
|
|
201
|
+
*dim : str
|
|
202
202
|
Dimensions to transpose to. Can include ellipsis (...) to represent
|
|
203
203
|
remaining dimensions in their original order.
|
|
204
204
|
missing_dims : {"raise", "warn", "ignore"}, optional
|
|
@@ -220,7 +220,7 @@ def transpose(
|
|
|
220
220
|
# Validate dimensions
|
|
221
221
|
x = as_xtensor(x)
|
|
222
222
|
x_dims = x.type.dims
|
|
223
|
-
invalid_dims = set(
|
|
223
|
+
invalid_dims = set(dim) - {..., *x_dims}
|
|
224
224
|
if invalid_dims:
|
|
225
225
|
if missing_dims != "ignore":
|
|
226
226
|
msg = f"Dimensions {invalid_dims} do not exist. Expected one or more of: {x_dims}"
|
|
@@ -229,21 +229,27 @@ def transpose(
|
|
|
229
229
|
else:
|
|
230
230
|
warnings.warn(msg)
|
|
231
231
|
# Handle missing dimensions if not raising
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if
|
|
235
|
-
|
|
236
|
-
elif
|
|
237
|
-
|
|
232
|
+
dim = tuple(d for d in dim if d in x_dims or d is ...)
|
|
233
|
+
|
|
234
|
+
if dim == ():
|
|
235
|
+
dim = tuple(reversed(x_dims))
|
|
236
|
+
elif dim == (...,):
|
|
237
|
+
dim = x_dims
|
|
238
|
+
elif ... in dim:
|
|
239
|
+
if dim.count(...) > 1:
|
|
238
240
|
raise ValueError("Ellipsis (...) can only appear once in the dimensions")
|
|
239
241
|
# Handle ellipsis expansion
|
|
240
|
-
ellipsis_idx =
|
|
241
|
-
pre =
|
|
242
|
-
post =
|
|
242
|
+
ellipsis_idx = dim.index(...)
|
|
243
|
+
pre = dim[:ellipsis_idx]
|
|
244
|
+
post = dim[ellipsis_idx + 1 :]
|
|
243
245
|
middle = [d for d in x_dims if d not in pre + post]
|
|
244
|
-
|
|
246
|
+
dim = (*pre, *middle, *post)
|
|
247
|
+
|
|
248
|
+
if dim == x_dims:
|
|
249
|
+
# No-op transpose
|
|
250
|
+
return x
|
|
245
251
|
|
|
246
|
-
return Transpose(typing.cast(tuple[str],
|
|
252
|
+
return Transpose(dims=typing.cast(tuple[str], dim))(x)
|
|
247
253
|
|
|
248
254
|
|
|
249
255
|
class Concat(XOp):
|
|
@@ -71,6 +71,8 @@ class XTensorType(Type, HasDataType, HasShape):
|
|
|
71
71
|
self.name = name
|
|
72
72
|
self.numpy_dtype = np.dtype(self.dtype)
|
|
73
73
|
self.filter_checks_isfinite = False
|
|
74
|
+
# broadcastable is here just for code that would work fine with XTensorType but checks for it
|
|
75
|
+
self.broadcastable = (False,) * self.ndim
|
|
74
76
|
|
|
75
77
|
def clone(
|
|
76
78
|
self,
|
|
@@ -93,6 +95,10 @@ class XTensorType(Type, HasDataType, HasShape):
|
|
|
93
95
|
self, value, strict=strict, allow_downcast=allow_downcast
|
|
94
96
|
)
|
|
95
97
|
|
|
98
|
+
@staticmethod
|
|
99
|
+
def may_share_memory(a, b):
|
|
100
|
+
return TensorType.may_share_memory(a, b)
|
|
101
|
+
|
|
96
102
|
def filter_variable(self, other, allow_convert=True):
|
|
97
103
|
if not isinstance(other, Variable):
|
|
98
104
|
# The value is not a Variable: we cast it into
|
|
@@ -160,7 +166,7 @@ class XTensorType(Type, HasDataType, HasShape):
|
|
|
160
166
|
return None
|
|
161
167
|
|
|
162
168
|
def __repr__(self):
|
|
163
|
-
return f"XTensorType({self.dtype}, {self.
|
|
169
|
+
return f"XTensorType({self.dtype}, shape={self.shape}, dims={self.dims})"
|
|
164
170
|
|
|
165
171
|
def __hash__(self):
|
|
166
172
|
return hash((type(self), self.dtype, self.shape, self.dims))
|
|
@@ -691,14 +697,14 @@ class XTensorVariable(Variable[_XTensorTypeType, OptionalApplyType]):
|
|
|
691
697
|
# https://docs.xarray.dev/en/latest/api.html#id8
|
|
692
698
|
def transpose(
|
|
693
699
|
self,
|
|
694
|
-
*
|
|
700
|
+
*dim: str | EllipsisType,
|
|
695
701
|
missing_dims: Literal["raise", "warn", "ignore"] = "raise",
|
|
696
702
|
):
|
|
697
703
|
"""Transpose dimensions of the tensor.
|
|
698
704
|
|
|
699
705
|
Parameters
|
|
700
706
|
----------
|
|
701
|
-
*
|
|
707
|
+
*dim : str | Ellipsis
|
|
702
708
|
Dimensions to transpose. If empty, performs a full transpose.
|
|
703
709
|
Can use ellipsis (...) to represent remaining dimensions.
|
|
704
710
|
missing_dims : {"raise", "warn", "ignore"}, default="raise"
|
|
@@ -718,7 +724,7 @@ class XTensorVariable(Variable[_XTensorTypeType, OptionalApplyType]):
|
|
|
718
724
|
If missing_dims="raise" and any dimensions don't exist.
|
|
719
725
|
If multiple ellipsis are provided.
|
|
720
726
|
"""
|
|
721
|
-
return px.shape.transpose(self, *
|
|
727
|
+
return px.shape.transpose(self, *dim, missing_dims=missing_dims)
|
|
722
728
|
|
|
723
729
|
def stack(self, dim, **dims):
|
|
724
730
|
return px.shape.stack(self, dim, **dims)
|
|
@@ -142,8 +142,12 @@ class XRV(XOp, RNGConsumerOp):
|
|
|
142
142
|
core_op,
|
|
143
143
|
core_dims: tuple[tuple[tuple[str, ...], ...], tuple[str, ...]],
|
|
144
144
|
extra_dims: tuple[str, ...],
|
|
145
|
+
name: str | None = None,
|
|
145
146
|
):
|
|
146
147
|
super().__init__()
|
|
148
|
+
if name is None:
|
|
149
|
+
name = getattr(core_op, "name", None)
|
|
150
|
+
self.name = name
|
|
147
151
|
self.core_op = core_op
|
|
148
152
|
inps_core_dims, out_core_dims = core_dims
|
|
149
153
|
for operand_dims in (*inps_core_dims, out_core_dims):
|
|
@@ -154,6 +158,15 @@ class XRV(XOp, RNGConsumerOp):
|
|
|
154
158
|
raise ValueError("size_dims must be unique")
|
|
155
159
|
self.extra_dims = tuple(extra_dims)
|
|
156
160
|
|
|
161
|
+
def __str__(self):
|
|
162
|
+
if self.name is not None:
|
|
163
|
+
name = self.name
|
|
164
|
+
attrs = f"(core_dims={self.core_dims}, extra_dims={self.extra_dims})"
|
|
165
|
+
else:
|
|
166
|
+
name = self.__class__.__name__
|
|
167
|
+
attrs = f"(core_op={self.core_op}, core_dims={self.core_dims}, extra_dims={self.extra_dims})"
|
|
168
|
+
return f"{name}({attrs})"
|
|
169
|
+
|
|
157
170
|
def update(self, node):
|
|
158
171
|
# RNG input and update are the first input and output respectively
|
|
159
172
|
return {node.inputs[0]: node.outputs[0]}
|