@@ -2842,66 +2842,55 @@ def matmul(x1: "ArrayLike", x2: "ArrayLike", dtype: Optional["DTypeLike"] = None
2842
2842
2843
2843
2844
2844
def vecdot (
2845
- x1 : "ArrayLike" ,
2846
- x2 : "ArrayLike" ,
2847
- axis : int = - 1 ,
2845
+ x1 : "TensorLike" ,
2846
+ x2 : "TensorLike" ,
2848
2847
dtype : Optional ["DTypeLike" ] = None ,
2849
- ):
2850
- """Compute the dot product of two vectors along specified dimensions .
2848
+ ) -> "TensorVariable" :
2849
+ """Compute the vector dot product of two arrays .
2851
2850
2852
2851
Parameters
2853
2852
----------
2854
2853
x1, x2
2855
- Input arrays, scalars not allowed.
2856
- axis
2857
- The axis along which to compute the dot product. By default, the last
2858
- axes of the inputs are used.
2854
+ Input arrays with the same shape.
2859
2855
dtype
2860
- The desired data-type for the array . If not given, then the type will
2856
+ The desired data-type for the result . If not given, then the type will
2861
2857
be determined as the minimum type required to hold the objects in the
2862
2858
sequence.
2863
2859
2864
2860
Returns
2865
2861
-------
2866
- out : ndarray
2867
- The vector dot product of the inputs computed along the specified axes .
2862
+ TensorVariable
2863
+ The vector dot product of the inputs.
2868
2864
2869
2865
Notes
2870
2866
-----
2871
- This is similar to `dot` but with broadcasting. It computes the dot product
2872
- along the specified axes, treating these as vectors, and broadcasts across
2873
- the remaining axes.
2867
+ This is similar to `np.vecdot` and computes the dot product of
2868
+ vectors along the last axis of both inputs. Broadcasting is supported
2869
+ across all other dimensions.
2870
+
2871
+ Examples
2872
+ --------
2873
+ >>> import pytensor.tensor as pt
2874
+ >>> x = pt.matrix("x")
2875
+ >>> y = pt.matrix("y")
2876
+ >>> z = pt.vecdot(x, y)
2877
+ >>> # Equivalent to np.sum(x * y, axis=-1)
2874
2878
"""
2875
2879
x1 = as_tensor_variable (x1 )
2876
2880
x2 = as_tensor_variable (x2 )
2877
2881
2878
- # Handle negative axis
2879
- if axis < 0 :
2880
- x1_axis = axis % x1 .type .ndim
2881
- x2_axis = axis % x2 .type .ndim
2882
- else :
2883
- x1_axis = axis
2884
- x2_axis = axis
2885
-
2886
- # Move the axes to the end for dot product calculation
2887
- x1_perm = list (range (x1 .type .ndim ))
2888
- x1_perm .append (x1_perm .pop (x1_axis ))
2889
- x1_transposed = x1 .transpose (x1_perm )
2890
-
2891
- x2_perm = list (range (x2 .type .ndim ))
2892
- x2_perm .append (x2_perm .pop (x2_axis ))
2893
- x2_transposed = x2 .transpose (x2_perm )
2894
-
2895
- # Use the inner product operation
2896
- out = _inner_prod (x1_transposed , x2_transposed )
2882
+ # Use the inner product operation along the last axis
2883
+ out = _inner_prod (x1 , x2 )
2897
2884
2898
2885
if dtype is not None :
2899
2886
out = out .astype (dtype )
2900
2887
2901
2888
return out
2902
2889
2903
2890
2904
- def matvec (x1 : "ArrayLike" , x2 : "ArrayLike" , dtype : Optional ["DTypeLike" ] = None ):
2891
+ def matvec (
2892
+ x1 : "TensorLike" , x2 : "TensorLike" , dtype : Optional ["DTypeLike" ] = None
2893
+ ) -> "TensorVariable" :
2905
2894
"""Compute the matrix-vector product.
2906
2895
2907
2896
Parameters
@@ -2911,20 +2900,35 @@ def matvec(x1: "ArrayLike", x2: "ArrayLike", dtype: Optional["DTypeLike"] = None
2911
2900
x2
2912
2901
Input array for the vector with shape (..., K).
2913
2902
dtype
2914
- The desired data-type for the array . If not given, then the type will
2903
+ The desired data-type for the result . If not given, then the type will
2915
2904
be determined as the minimum type required to hold the objects in the
2916
2905
sequence.
2917
2906
2918
2907
Returns
2919
2908
-------
2920
- out : ndarray
2909
+ TensorVariable
2921
2910
The matrix-vector product with shape (..., M).
2922
2911
2923
2912
Notes
2924
2913
-----
2925
- This is similar to `matmul` where the second argument is a vector,
2926
- but with different broadcasting rules. Broadcasting happens over all but
2927
- the last dimension of x1 and all dimensions of x2 except the last.
2914
+ This is equivalent to `numpy.matmul` where the second argument is a vector,
2915
+ but with more intuitive broadcasting rules. Broadcasting happens over all but
2916
+ the last two dimensions of x1 and all dimensions of x2 except the last.
2917
+
2918
+ Examples
2919
+ --------
2920
+ >>> import pytensor.tensor as pt
2921
+ >>> import numpy as np
2922
+ >>> # Matrix-vector product
2923
+ >>> A = pt.matrix("A") # shape (M, K)
2924
+ >>> v = pt.vector("v") # shape (K,)
2925
+ >>> result = pt.matvec(A, v) # shape (M,)
2926
+ >>> # Equivalent to np.matmul(A, v)
2927
+ >>>
2928
+ >>> # Batched matrix-vector product
2929
+ >>> batched_A = pt.tensor3("A") # shape (B, M, K)
2930
+ >>> batched_v = pt.matrix("v") # shape (B, K)
2931
+ >>> result = pt.matvec(batched_A, batched_v) # shape (B, M)
2928
2932
"""
2929
2933
x1 = as_tensor_variable (x1 )
2930
2934
x2 = as_tensor_variable (x2 )
@@ -2937,7 +2941,9 @@ def matvec(x1: "ArrayLike", x2: "ArrayLike", dtype: Optional["DTypeLike"] = None
2937
2941
return out
2938
2942
2939
2943
2940
- def vecmat (x1 : "ArrayLike" , x2 : "ArrayLike" , dtype : Optional ["DTypeLike" ] = None ):
2944
+ def vecmat (
2945
+ x1 : "TensorLike" , x2 : "TensorLike" , dtype : Optional ["DTypeLike" ] = None
2946
+ ) -> "TensorVariable" :
2941
2947
"""Compute the vector-matrix product.
2942
2948
2943
2949
Parameters
@@ -2947,20 +2953,35 @@ def vecmat(x1: "ArrayLike", x2: "ArrayLike", dtype: Optional["DTypeLike"] = None
2947
2953
x2
2948
2954
Input array for the matrix with shape (..., K, N).
2949
2955
dtype
2950
- The desired data-type for the array . If not given, then the type will
2956
+ The desired data-type for the result . If not given, then the type will
2951
2957
be determined as the minimum type required to hold the objects in the
2952
2958
sequence.
2953
2959
2954
2960
Returns
2955
2961
-------
2956
- out : ndarray
2962
+ TensorVariable
2957
2963
The vector-matrix product with shape (..., N).
2958
2964
2959
2965
Notes
2960
2966
-----
2961
- This is similar to `matmul` where the first argument is a vector,
2962
- but with different broadcasting rules. Broadcasting happens over all but
2967
+ This is equivalent to `numpy. matmul` where the first argument is a vector,
2968
+ but with more intuitive broadcasting rules. Broadcasting happens over all but
2963
2969
the last dimension of x1 and all but the last two dimensions of x2.
2970
+
2971
+ Examples
2972
+ --------
2973
+ >>> import pytensor.tensor as pt
2974
+ >>> import numpy as np
2975
+ >>> # Vector-matrix product
2976
+ >>> v = pt.vector("v") # shape (K,)
2977
+ >>> A = pt.matrix("A") # shape (K, N)
2978
+ >>> result = pt.vecmat(v, A) # shape (N,)
2979
+ >>> # Equivalent to np.matmul(v, A)
2980
+ >>>
2981
+ >>> # Batched vector-matrix product
2982
+ >>> batched_v = pt.matrix("v") # shape (B, K)
2983
+ >>> batched_A = pt.tensor3("A") # shape (B, K, N)
2984
+ >>> result = pt.vecmat(batched_v, batched_A) # shape (B, N)
2964
2985
"""
2965
2986
x1 = as_tensor_variable (x1 )
2966
2987
x2 = as_tensor_variable (x2 )
0 commit comments