# --------------------------------------------------------------------------
# ⚠️ WARNING - AUTO-GENERATED CODE - DO NOT EDIT ⚠️
# ⚙️ Generated by 'python -m opgen'
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# --------------------------------------------------------------------------
# pylint: disable=W0221,W0222,R0901,W0237
# mypy: disable-error-code=override
# ruff: noqa: E741, D214, D402, D405, D411, D416
# --------------------------------------------------------------------------

from __future__ import annotations

from typing import Optional, Sequence, Tuple, TypeVar, Union

from onnx import GraphProto, SparseTensorProto, TensorProto
from onnx.defs import get_schema
from typing_extensions import TypeAlias

from onnxscript.onnx_opset._impl.opset10 import Opset10
from onnxscript.onnx_types import (
    BOOL,
    COMPLEX64,
    COMPLEX128,
    DOUBLE,
    FLOAT,
    FLOAT16,
    INT8,
    INT16,
    INT32,
    INT64,
    STRING,
    UINT8,
    UINT16,
    UINT32,
    UINT64,
)
from onnxscript.values import Op, Opset


class Opset11(Opset10):
    def __new__(cls):
        return Opset.__new__(cls, "", 11)

    T_ArgMax = TypeVar(
        "T_ArgMax",
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def ArgMax(self, data: T_ArgMax, *, axis: int = 0, keepdims: int = 1) -> INT64:
        r"""[🌐 ArgMax(11)](https://onnx.ai/onnx/operators/onnx__ArgMax.html#argmax-11 "Online Documentation")


        Computes the indices of the max elements of the input tensor's element along the
        provided axis. The resulting tensor has the same rank as the input if keepdims equals 1.
        If keepdims equal 0, then the resulting tensor has the reduced dimension pruned.
        The input tensor must not be empty.
        The type of the output tensor is integer.

        Args:
            data: An input tensor.

            axis: The axis in which to compute the arg indices. Accepted range is [-r,
                r-1] where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ArgMax", 11, "")
        op = Op(self, "ArgMax", schema)
        return op(*self._prepare_inputs(schema, data), axis=axis, keepdims=keepdims)

    T_ArgMin = TypeVar(
        "T_ArgMin",
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def ArgMin(self, data: T_ArgMin, *, axis: int = 0, keepdims: int = 1) -> INT64:
        r"""[🌐 ArgMin(11)](https://onnx.ai/onnx/operators/onnx__ArgMin.html#argmin-11 "Online Documentation")


        Computes the indices of the min elements of the input tensor's element along the
        provided axis. The resulting tensor has the same rank as the input if keepdims equals 1.
        If keepdims equal 0, then the resulting tensor has the reduced dimension pruned.
        The input tensor must not be empty.
        The type of the output tensor is integer.

        Args:
            data: An input tensor.

            axis: The axis in which to compute the arg indices. Accepted range is [-r,
                r-1] where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ArgMin", 11, "")
        op = Op(self, "ArgMin", schema)
        return op(*self._prepare_inputs(schema, data), axis=axis, keepdims=keepdims)

    T_AveragePool = TypeVar("T_AveragePool", DOUBLE, FLOAT, FLOAT16)

    def AveragePool(
        self,
        X: T_AveragePool,
        *,
        auto_pad: str = "NOTSET",
        ceil_mode: int = 0,
        count_include_pad: int = 0,
        kernel_shape: Sequence[int],
        pads: Optional[Sequence[int]] = None,
        strides: Optional[Sequence[int]] = None,
    ) -> T_AveragePool:
        r"""[🌐 AveragePool(11)](https://onnx.ai/onnx/operators/onnx__AveragePool.html#averagepool-11 "Online Documentation")


         AveragePool consumes an input tensor X and applies average pooling across
         the tensor according to kernel sizes, stride sizes, and pad lengths.
         average pooling consisting of computing the average on all values of a
         subset of the input tensor according to the kernel size and downsampling the
         data into the output tensor Y for further processing. The output spatial shape will be following:
         ```
         output_spatial_shape[i] = floor((input_spatial_shape[i] + pad_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1)) / strides_spatial_shape[i] + 1)
         ```
         or
         ```
         output_spatial_shape[i] = ceil((input_spatial_shape[i] + pad_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1)) / strides_spatial_shape[i] + 1)
         ```
         if ceil_mode is enabled

         ```
         * pad_shape[i] is sum of pads along axis i
         ```

         `auto_pad` is a DEPRECATED attribute. If you are using them currently, the output spatial shape will be following when ceil_mode is enabled:
         ```
         VALID: output_spatial_shape[i] = ceil((input_spatial_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) + 1) / strides_spatial_shape[i])
         SAME_UPPER or SAME_LOWER: output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides_spatial_shape[i])
         ```
        or when ceil_mode is disabled:
         ```
         VALID: output_spatial_shape[i] = floor((input_spatial_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) + 1) / strides_spatial_shape[i])
         SAME_UPPER or SAME_LOWER: output_spatial_shape[i] = floor(input_spatial_shape[i] / strides_spatial_shape[i])
         ```

         And pad shape will be following if `SAME_UPPER` or `SAME_LOWER`:
         ```
         pad_shape[i] = (output_spatial_shape[i] - 1) * strides_spatial_shape[i] + ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) - input_spatial_shape[i]
         ```
         The output of each pooling window is divided by the number of elements (exclude pad when attribute count_include_pad is zero).


        Args:
            X: (differentiable) Input data tensor from the previous operator; dimensions
                for image case are (N x C x H x W), where N is the batch size, C is the
                number of channels, and H and W are the height and the width of the
                data. For non image case, the dimensions are in the form of (N x C x D1
                x D2 ... Dn), where N is the batch size. Optionally, if dimension
                denotation is in effect, the operation expects the input data tensor to
                arrive with the dimension denotation of [DATA_BATCH, DATA_CHANNEL,
                DATA_FEATURE, DATA_FEATURE ...].

            auto_pad: auto_pad must be either NOTSET, SAME_UPPER, SAME_LOWER or VALID.
                Where default value is NOTSET, which means explicit padding is used.
                SAME_UPPER or SAME_LOWER mean pad the input so that `output_shape[i] =
                ceil(input_shape[i] / strides[i])` for each axis `i`. The padding is
                split between the two sides equally or almost equally (depending on
                whether it is even or odd). In case the padding is an odd number, the
                extra padding is added at the end for SAME_UPPER and at the beginning
                for SAME_LOWER.

            ceil_mode: Whether to use ceil or floor (default) to compute the output
                shape.

            count_include_pad: Whether include pad pixels when calculating values for
                the edges. Default is 0, doesn't count include pad.

            kernel_shape: The size of the kernel along each axis.

            pads: Padding for the beginning and ending along each spatial axis, it can
                take any value greater than or equal to 0. The value represent the
                number of pixels added to the beginning and end part of the
                corresponding axis. `pads` format should be as follow [x1_begin,
                x2_begin...x1_end, x2_end,...], where xi_begin the number of pixels
                added at the beginning of axis `i` and xi_end, the number of pixels
                added at the end of axis `i`. This attribute cannot be used
                simultaneously with auto_pad attribute. If not present, the padding
                defaults to 0 along start and end of each spatial axis.

            strides: Stride along each spatial axis. If not present, the stride defaults
                to 1 along each spatial axis.
        """

        schema = get_schema("AveragePool", 11, "")
        op = Op(self, "AveragePool", schema)
        return op(
            *self._prepare_inputs(schema, X),
            auto_pad=auto_pad,
            ceil_mode=ceil_mode,
            count_include_pad=count_include_pad,
            kernel_shape=kernel_shape,
            pads=pads,
            strides=strides,
        )

    T_BitShift = TypeVar("T_BitShift", UINT16, UINT32, UINT64, UINT8)

    def BitShift(self, X: T_BitShift, Y: T_BitShift, *, direction: str) -> T_BitShift:
        r"""[🌐 BitShift(11)](https://onnx.ai/onnx/operators/onnx__BitShift.html#bitshift-11 "Online Documentation")


        Bitwise shift operator performs element-wise operation. For each input element, if the
        attribute "direction" is "RIGHT", this operator moves its binary representation toward
        the right side so that the input value is effectively decreased. If the attribute "direction"
        is "LEFT", bits of binary representation moves toward the left side, which results the
        increase of its actual value. The input X is the tensor to be shifted and another input
        Y specifies the amounts of shifting. For example, if "direction" is "Right", X is [1, 4],
        and S is [1, 1], the corresponding output Z would be [0, 2]. If "direction" is "LEFT" with
        X=[1, 2] and S=[1, 2], the corresponding output Y would be [2, 8].

        Because this operator supports Numpy-style broadcasting, X's and Y's shapes are
        not necessarily identical.
        This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check `Broadcasting in ONNX <https://github.com/onnx/onnx/blob/master/docs/Broadcasting.md>`_.

        Args:
            X: (non-differentiable) First operand, input to be shifted.

            Y: (non-differentiable) Second operand, amounts of shift.

            direction: Direction of moving bits. It can be either "RIGHT" (for right
                shift) or "LEFT" (for left shift).
        """

        schema = get_schema("BitShift", 11, "")
        op = Op(self, "BitShift", schema)
        return op(*self._prepare_inputs(schema, X, Y), direction=direction)

    T_Clip = TypeVar("T_Clip", DOUBLE, FLOAT, FLOAT16)

    def Clip(
        self, input: T_Clip, min: Optional[T_Clip] = None, max: Optional[T_Clip] = None
    ) -> T_Clip:
        r"""[🌐 Clip(11)](https://onnx.ai/onnx/operators/onnx__Clip.html#clip-11 "Online Documentation")


        Clip operator limits the given input within an interval. The interval is
        specified by the inputs 'min' and 'max'. They default to
        numeric_limits::lowest() and numeric_limits::max(), respectively.


        Args:
            input: Input tensor whose elements to be clipped

            min: (optional) Minimum value, under which element is replaced by min. It
                must be a scalar(tensor of empty shape).

            max: (optional) Maximum value, above which element is replaced by max. It
                must be a scalar(tensor of empty shape).
        """

        schema = get_schema("Clip", 11, "")
        op = Op(self, "Clip", schema)
        return op(*self._prepare_inputs(schema, input, min, max))

    T_Compress = TypeVar(
        "T_Compress",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    T1_Compress: TypeAlias = BOOL

    def Compress(
        self, input: T_Compress, condition: T1_Compress, *, axis: Optional[int] = None
    ) -> T_Compress:
        r"""[🌐 Compress(11)](https://onnx.ai/onnx/operators/onnx__Compress.html#compress-11 "Online Documentation")


            Selects slices from an input tensor along a given axis where condition evaluates to True for each axis index.
            In case axis is not provided, input is flattened before elements are selected.
            Compress behaves like numpy.compress: https://docs.scipy.org/doc/numpy/reference/generated/numpy.compress.html


        Args:
            input: (differentiable) Tensor of rank r >= 1.

            condition: (non-differentiable) Rank 1 tensor of booleans to indicate which
                slices or data elements to be selected. Its length can be less than the
                input length along the axis or the flattened input size if axis is not
                specified. In such cases data slices or elements exceeding the condition
                length are discarded.

            axis: (Optional) Axis along which to take slices. If not specified, input is
                flattened before elements being selected. Negative value means counting
                dimensions from the back. Accepted range is [-r, r-1] where r =
                rank(input).
        """

        schema = get_schema("Compress", 11, "")
        op = Op(self, "Compress", schema)
        return op(*self._prepare_inputs(schema, input, condition), axis=axis)

    T_Concat = TypeVar(
        "T_Concat",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Concat(self, *inputs: T_Concat, axis: int) -> T_Concat:
        r"""[🌐 Concat(11)](https://onnx.ai/onnx/operators/onnx__Concat.html#concat-11 "Online Documentation")

        Concatenate a list of tensors into a single tensor. All input tensors must have the same shape, except for the dimension size of the axis to concatenate on.

        Args:
            inputs: (variadic) List of tensors for concatenation

            axis: Which axis to concat on. A negative value means counting dimensions
                from the back. Accepted range is [-r, r-1] where r = rank(inputs)..
        """

        schema = get_schema("Concat", 11, "")
        op = Op(self, "Concat", schema)
        return op(*self._prepare_inputs(schema, *inputs), axis=axis)

    S_ConcatFromSequence = TypeVar(
        "S_ConcatFromSequence",
        Sequence[BOOL],
        Sequence[COMPLEX128],
        Sequence[COMPLEX64],
        Sequence[DOUBLE],
        Sequence[FLOAT],
        Sequence[FLOAT16],
        Sequence[INT16],
        Sequence[INT32],
        Sequence[INT64],
        Sequence[INT8],
        Sequence[STRING],
        Sequence[UINT16],
        Sequence[UINT32],
        Sequence[UINT64],
        Sequence[UINT8],
    )

    T_ConcatFromSequence: TypeAlias = Union[
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    ]

    def ConcatFromSequence(
        self, input_sequence: S_ConcatFromSequence, *, axis: int, new_axis: int = 0
    ) -> T_ConcatFromSequence:
        r"""[🌐 ConcatFromSequence(11)](https://onnx.ai/onnx/operators/onnx__ConcatFromSequence.html#concatfromsequence-11 "Online Documentation")


        Concatenate a sequence of tensors into a single tensor.
        All input tensors must have the same shape, except for the dimension size of the axis to concatenate on.
        By default 'new_axis' is 0, the behavior is similar to numpy.concatenate.
        When 'new_axis' is 1, the behavior is similar to numpy.stack.


        Args:
            input_sequence: Sequence of tensors for concatenation

            axis: Which axis to concat on. Accepted range in `[-r, r - 1]`, where `r` is
                the rank of input tensors. When `new_axis` is 1, accepted range is `[-r
                - 1, r]`.

            new_axis: Insert and concatenate on a new axis or not, default 0 means do
                not insert new axis.
        """

        schema = get_schema("ConcatFromSequence", 11, "")
        op = Op(self, "ConcatFromSequence", schema)
        return op(*self._prepare_inputs(schema, input_sequence), axis=axis, new_axis=new_axis)

    T_Constant: TypeAlias = Union[
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    ]

    def Constant(
        self,
        *,
        sparse_value: Optional[SparseTensorProto] = None,
        value: Optional[TensorProto] = None,
    ) -> T_Constant:
        r"""[🌐 Constant(11)](https://onnx.ai/onnx/operators/onnx__Constant.html#constant-11 "Online Documentation")


        A constant tensor. Exactly one of the two attributes, either value or sparse_value,
        must be specified.


        Args:
            sparse_value: The value for the elements of the output tensor in sparse
                format.

            value: The value for the elements of the output tensor.
        """

        schema = get_schema("Constant", 11, "")
        op = Op(self, "Constant", schema)
        return op(sparse_value=sparse_value, value=value)

    T_Conv = TypeVar("T_Conv", DOUBLE, FLOAT, FLOAT16)

    def Conv(
        self,
        X: T_Conv,
        W: T_Conv,
        B: Optional[T_Conv] = None,
        *,
        auto_pad: str = "NOTSET",
        dilations: Optional[Sequence[int]] = None,
        group: int = 1,
        kernel_shape: Optional[Sequence[int]] = None,
        pads: Optional[Sequence[int]] = None,
        strides: Optional[Sequence[int]] = None,
    ) -> T_Conv:
        r"""[🌐 Conv(11)](https://onnx.ai/onnx/operators/onnx__Conv.html#conv-11 "Online Documentation")


        The convolution operator consumes an input tensor and a filter, and
        computes the output.

        Args:
            X: (differentiable) Input data tensor from previous layer; has size (N x C x
                H x W), where N is the batch size, C is the number of channels, and H
                and W are the height and width. Note that this is for the 2D image.
                Otherwise the size is (N x C x D1 x D2 ... x Dn). Optionally, if
                dimension denotation is in effect, the operation expects input data
                tensor to arrive with the dimension denotation of [DATA_BATCH,
                DATA_CHANNEL, DATA_FEATURE, DATA_FEATURE ...].

            W: (differentiable) The weight tensor that will be used in the convolutions;
                has size (M x C/group x kH x kW), where C is the number of channels, and
                kH and kW are the height and width of the kernel, and M is the number of
                feature maps. For more than 2 dimensions, the kernel shape will be (M x
                C/group x k1 x k2 x ... x kn), where (k1 x k2 x ... kn) is the dimension
                of the kernel. Optionally, if dimension denotation is in effect, the
                operation expects the weight tensor to arrive with the dimension
                denotation of [FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, FILTER_SPATIAL,
                FILTER_SPATIAL ...]. Assuming zero based indices for the shape array,
                X.shape[1] == (W.shape[1] * group) == C and W.shape[0] mod G == 0. Or in
                other words FILTER_IN_CHANNEL multiplied by the number of groups should
                be equal to DATA_CHANNEL and the number of feature maps M should be a
                multiple of the number of groups G.

            B: (optional, differentiable) Optional 1D bias to be added to the
                convolution, has size of M.

            auto_pad: auto_pad must be either NOTSET, SAME_UPPER, SAME_LOWER or VALID.
                Where default value is NOTSET, which means explicit padding is used.
                SAME_UPPER or SAME_LOWER mean pad the input so that `output_shape[i] =
                ceil(input_shape[i] / strides[i])` for each axis `i`. The padding is
                split between the two sides equally or almost equally (depending on
                whether it is even or odd). In case the padding is an odd number, the
                extra padding is added at the end for SAME_UPPER and at the beginning
                for SAME_LOWER.

            dilations: dilation value along each spatial axis of the filter. If not
                present, the dilation defaults is 1 along each spatial axis.

            group: number of groups input channels and output channels are divided into.

            kernel_shape: The shape of the convolution kernel. If not present, should be
                inferred from input W.

            pads: Padding for the beginning and ending along each spatial axis, it can
                take any value greater than or equal to 0. The value represent the
                number of pixels added to the beginning and end part of the
                corresponding axis. `pads` format should be as follow [x1_begin,
                x2_begin...x1_end, x2_end,...], where xi_begin the number of pixels
                added at the beginning of axis `i` and xi_end, the number of pixels
                added at the end of axis `i`. This attribute cannot be used
                simultaneously with auto_pad attribute. If not present, the padding
                defaults to 0 along start and end of each spatial axis.

            strides: Stride along each spatial axis. If not present, the stride defaults
                is 1 along each spatial axis.
        """

        schema = get_schema("Conv", 11, "")
        op = Op(self, "Conv", schema)
        return op(
            *self._prepare_inputs(schema, X, W, B),
            auto_pad=auto_pad,
            dilations=dilations,
            group=group,
            kernel_shape=kernel_shape,
            pads=pads,
            strides=strides,
        )

    T_ConvTranspose = TypeVar("T_ConvTranspose", DOUBLE, FLOAT, FLOAT16)

    def ConvTranspose(
        self,
        X: T_ConvTranspose,
        W: T_ConvTranspose,
        B: Optional[T_ConvTranspose] = None,
        *,
        auto_pad: str = "NOTSET",
        dilations: Optional[Sequence[int]] = None,
        group: int = 1,
        kernel_shape: Optional[Sequence[int]] = None,
        output_padding: Optional[Sequence[int]] = None,
        output_shape: Optional[Sequence[int]] = None,
        pads: Optional[Sequence[int]] = None,
        strides: Optional[Sequence[int]] = None,
    ) -> T_ConvTranspose:
        r"""[🌐 ConvTranspose(11)](https://onnx.ai/onnx/operators/onnx__ConvTranspose.html#convtranspose-11 "Online Documentation")


        The convolution transpose operator consumes an input tensor and a filter,
        and computes the output.

        If the pads parameter is provided the shape of the output is calculated via the following equation:

          output_shape[i] = stride[i] * (input_size[i] - 1) + output_padding[i] + ((kernel_shape[i] - 1) * dilations[i] + 1) - pads[start_i] - pads[end_i]

        output_shape can also be explicitly specified in which case pads values are auto generated using these equations:

          total_padding[i] = stride[i] * (input_size[i] - 1) + output_padding[i] + ((kernel_shape[i] - 1) * dilations[i] + 1) - output_shape[i]
          If (auto_pads == SAME_UPPER): pads[start_i] = total_padding[i]/2; pads[end_i] = total_padding[i] - (total_padding[i]/2)
          Else: pads[start_i] = total_padding[i] - (total_padding[i]/2); pads[end_i] = (total_padding[i]/2).



        Args:
            X: (differentiable) Input data tensor from previous layer; has size (N x C x
                H x W), where N is the batch size, C is the number of channels, and H
                and W are the height and width. Note that this is for the 2D image.
                Otherwise the size is (N x C x D1 x D2 ... x Dn)

            W: (differentiable) The weight tensor that will be used in the convolutions;
                has size (C x M/group x kH x kW), where C is the number of channels, and
                kH and kW are the height and width of the kernel, and M is the number of
                feature maps. For more than 2 dimensions, the weight shape will be (C x
                M/group x k1 x k2 x ... x kn), where (k1 x k2 x ... x kn) is the
                dimension of the kernel. The number of channels in the output should be
                equal to W.shape[1] * group (assuming zero based indices of the shape
                array)

            B: (optional, differentiable) Optional 1D bias to be added to the
                convolution, has size of M.

            auto_pad: auto_pad must be either NOTSET, SAME_UPPER, SAME_LOWER or VALID.
                Where default value is NOTSET, which means explicit padding is used.
                SAME_UPPER or SAME_LOWER mean pad the input so that `output_shape[i] =
                input_shape[i] * strides[i]` for each axis `i`. The padding is split
                between the two sides equally or almost equally (depending on whether it
                is even or odd). In case the padding is an odd number, the extra padding
                is added at the end for SAME_UPPER and at the beginning for SAME_LOWER.

            dilations: dilation value along each spatial axis of the filter. If not
                present, the dilation defaults to 1 along each spatial axis.

            group: number of groups input channels and output channels are divided into.

            kernel_shape: The shape of the convolution kernel. If not present, should be
                inferred from input W.

            output_padding: Additional elements added to the side with higher coordinate
                indices in the output. Each padding value in "output_padding" must be
                less than the corresponding stride/dilation dimension. By default, this
                attribute is a zero vector. Note that this attribute doesn't directly
                affect the computed output values. It only controls the selection of the
                computed values, so changing this attribute only adds or removes output
                elements. If "output_shape" is explicitly provided, "output_padding"
                does not contribute additional size to "output_shape" but participates
                in the computation of the needed padding amount. This is also called
                adjs or adjustment in some frameworks.

            output_shape: The shape of the output can be explicitly set which will cause
                pads values to be auto generated. If output_shape is specified pads
                values are ignored. See doc for details for equations to generate pads.
                Note that the output_shape attribute value should not include dimensions
                for batch size and channels, which are automatically inferred.

            pads: Padding for the beginning and ending along each spatial axis, it can
                take any value greater than or equal to 0. The value represent the
                number of pixels added to the beginning and end part of the
                corresponding axis. `pads` format should be as follow [x1_begin,
                x2_begin...x1_end, x2_end,...], where xi_begin the number of pixels
                added at the beginning of axis `i` and xi_end, the number of pixels
                added at the end of axis `i`. This attribute cannot be used
                simultaneously with auto_pad attribute. If not present, the padding
                defaults to 0 along start and end of each spatial axis.

            strides: Stride along each spatial axis. If not present, the stride defaults
                to 1 along each spatial axis.
        """

        schema = get_schema("ConvTranspose", 11, "")
        op = Op(self, "ConvTranspose", schema)
        return op(
            *self._prepare_inputs(schema, X, W, B),
            auto_pad=auto_pad,
            dilations=dilations,
            group=group,
            kernel_shape=kernel_shape,
            output_padding=output_padding,
            output_shape=output_shape,
            pads=pads,
            strides=strides,
        )

    T_CumSum = TypeVar("T_CumSum", DOUBLE, FLOAT, INT32, INT64, UINT32, UINT64)

    T2_CumSum = TypeVar("T2_CumSum", INT32, INT64)

    def CumSum(
        self, x: T_CumSum, axis: T2_CumSum, *, exclusive: int = 0, reverse: int = 0
    ) -> T_CumSum:
        r"""[🌐 CumSum(11)](https://onnx.ai/onnx/operators/onnx__CumSum.html#cumsum-11 "Online Documentation")


        Performs cumulative sum of the input elements along the given axis.
        By default, it will do the sum inclusively meaning the first element is copied as is.
        Through an `exclusive` attribute, this behavior can change to exclude the first element.
        It can also perform summation in the opposite direction of the axis. For that, set `reverse` attribute to 1.

        Example:
        ::

            input_x = [1, 2, 3]
            axis=0
            output = [1, 3, 6]
            exclusive=1
            output = [0, 1, 3]
            exclusive=0
            reverse=1
            output = [6, 5, 3]
            exclusive=1
            reverse=1
            output = [5, 3, 0]




        Args:
            x: (differentiable) An input tensor that is to be processed.

            axis: (non-differentiable) A 0-D tensor. Must be in the range [-rank(x),
                rank(x)-1]. Negative value means counting dimensions from the back.

            exclusive: If set to 1 will return exclusive sum in which the top element is
                not included. In other terms, if set to 1, the j-th output element would
                be the sum of the first (j-1) elements. Otherwise, it would be the sum
                of the first j elements.

            reverse: If set to 1 will perform the sums in reverse direction.
        """

        schema = get_schema("CumSum", 11, "")
        op = Op(self, "CumSum", schema)
        return op(*self._prepare_inputs(schema, x, axis), exclusive=exclusive, reverse=reverse)

    T_DepthToSpace = TypeVar(
        "T_DepthToSpace",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def DepthToSpace(
        self, input: T_DepthToSpace, *, blocksize: int, mode: str = "DCR"
    ) -> T_DepthToSpace:
        r"""[🌐 DepthToSpace(11)](https://onnx.ai/onnx/operators/onnx__DepthToSpace.html#depthtospace-11 "Online Documentation")

        DepthToSpace rearranges (permutes) data from depth into blocks of spatial data.
        This is the reverse transformation of SpaceToDepth. More specifically, this op outputs a copy of
        the input tensor where values from the depth dimension are moved in spatial blocks to the height
        and width dimensions. By default, `mode` = `DCR`.
        In the DCR mode, elements along the depth dimension from the input tensor are rearranged in the
        following order: depth, column, and then row. The output y is computed from the input x as below:

        b, c, h, w = x.shape

        tmp = np.reshape(x, [b, blocksize, blocksize, c // (blocksize**2), h, w])

        tmp = np.transpose(tmp, [0, 3, 4, 1, 5, 2])

        y = np.reshape(tmp, [b, c // (blocksize**2), h * blocksize, w * blocksize])


        In the CRD mode, elements along the depth dimension from the input tensor are rearranged in the
        following order: column, row, and the depth. The output y is computed from the input x as below:

        b, c, h, w = x.shape

        tmp = np.reshape(x, [b, c // (blocksize ** 2), blocksize, blocksize, h, w])

        tmp = np.transpose(tmp, [0, 1, 4, 2, 5, 3])

        y = np.reshape(tmp, [b, c // (blocksize ** 2), h * blocksize, w * blocksize])



        Args:
            input: Input tensor of [N,C,H,W], where N is the batch axis, C is the
                channel or depth, H is the height and W is the width.

            blocksize: Blocks of [blocksize, blocksize] are moved.

            mode: DCR (default) for depth-column-row order re-arrangement. Use CRD for
                column-row-depth order.
        """

        schema = get_schema("DepthToSpace", 11, "")
        op = Op(self, "DepthToSpace", schema)
        return op(*self._prepare_inputs(schema, input), blocksize=blocksize, mode=mode)

    T_Det = TypeVar("T_Det", DOUBLE, FLOAT, FLOAT16)

    def Det(self, X: T_Det) -> T_Det:
        r"""[🌐 Det(11)](https://onnx.ai/onnx/operators/onnx__Det.html#det-11 "Online Documentation")


        Det calculates determinant of a square matrix or batches of square matrices.
        Det takes one input tensor of shape `[*, M, M]`, where `*` is zero or more batch dimensions,
        and the inner-most 2 dimensions form square matrices.
        The output is a tensor of shape `[*]`, containing the determinants of all input submatrices.
        e.g., When the input is 2-D, the output is a scalar(shape is empty: `[]`).


        Args:
            X: (differentiable) Input tensor
        """

        schema = get_schema("Det", 11, "")
        op = Op(self, "Det", schema)
        return op(*self._prepare_inputs(schema, X))

    T1_DynamicQuantizeLinear: TypeAlias = FLOAT

    T2_DynamicQuantizeLinear: TypeAlias = UINT8

    def DynamicQuantizeLinear(
        self, x: T1_DynamicQuantizeLinear
    ) -> Tuple[T2_DynamicQuantizeLinear, FLOAT, T2_DynamicQuantizeLinear]:
        r"""[🌐 DynamicQuantizeLinear(11)](https://onnx.ai/onnx/operators/onnx__DynamicQuantizeLinear.html#dynamicquantizelinear-11 "Online Documentation")


        A Function to fuse calculation for Scale, Zero Point and FP32->8Bit conversion of FP32 Input data.
        Outputs Scale, ZeroPoint and Quantized Input for a given FP32 Input.
        Scale is calculated as:
        ::

            y_scale = (maximum(0, max(x)) - minimum(0, min(x))) / (qmax - qmin)



        * where qmax and qmin are max and min values for quantization range i.e. [0, 255] in case of uint8
        * data range is adjusted to include 0.

        Zero point is calculated as:
        ::

            intermediate_zero_point = qmin - min(x)/y_scale
            y_zero_point = cast(round(saturate(itermediate_zero_point)))



        * where qmax and qmin are max and min values for quantization range .i.e [0, 255] in case of uint8
        * for saturation, it saturates to [0, 255] if it's uint8, or [-127, 127] if it's int8. Right now only uint8 is supported.
        * rounding to nearest ties to even.

        Data quantization formula is:
        ::

            y = saturate (round (x / y_scale) + y_zero_point)



        * for saturation, it saturates to [0, 255] if it's uint8, or [-127, 127] if it's int8. Right now only uint8 is supported.
        * rounding to nearest ties to even.


        Args:
            x: Input tensor
        """

        schema = get_schema("DynamicQuantizeLinear", 11, "")
        op = Op(self, "DynamicQuantizeLinear", schema)
        return op(*self._prepare_inputs(schema, x))

    T_Equal = TypeVar(
        "T_Equal",
        BOOL,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    T1_Equal: TypeAlias = BOOL

    def Equal(self, A: T_Equal, B: T_Equal) -> T1_Equal:
        r"""[🌐 Equal(11)](https://onnx.ai/onnx/operators/onnx__Equal.html#equal-11 "Online Documentation")


        Returns the tensor resulted from performing the `equal` logical operation
        elementwise on the input tensors `A` and `B` (with Numpy-style broadcasting support).

        This operator supports **multidirectional (i.e., Numpy-style) broadcasting**; for more details please check `Broadcasting in ONNX <https://github.com/onnx/onnx/blob/master/docs/Broadcasting.md>`_.


        Args:
            A: First input operand for the logical operator.

            B: Second input operand for the logical operator.
        """

        schema = get_schema("Equal", 11, "")
        op = Op(self, "Equal", schema)
        return op(*self._prepare_inputs(schema, A, B))

    T_Flatten = TypeVar(
        "T_Flatten",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Flatten(self, input: T_Flatten, *, axis: int = 1) -> T_Flatten:
        r"""[🌐 Flatten(11)](https://onnx.ai/onnx/operators/onnx__Flatten.html#flatten-11 "Online Documentation")


        Flattens the input tensor into a 2D matrix. If input tensor has shape
        (d_0, d_1, ... d_n) then the output will have shape
        (d_0 X d_1 ... d_(axis-1), d_axis X d_(axis+1) ... X dn).


        Args:
            input: A tensor of rank >= axis.

            axis: Indicate up to which input dimensions (exclusive) should be flattened
                to the outer dimension of the output. The value for axis must be in the
                range [-r, r], where r is the rank of the input tensor. Negative value
                means counting dimensions from the back. When axis = 0, the shape of the
                output tensor is (1, (d_0 X d_1 ... d_n), where the shape of the input
                tensor is (d_0, d_1, ... d_n).
        """

        schema = get_schema("Flatten", 11, "")
        op = Op(self, "Flatten", schema)
        return op(*self._prepare_inputs(schema, input), axis=axis)

    T_Gather = TypeVar(
        "T_Gather",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    Tind_Gather = TypeVar("Tind_Gather", INT32, INT64)

    def Gather(self, data: T_Gather, indices: Tind_Gather, *, axis: int = 0) -> T_Gather:
        r"""[🌐 Gather(11)](https://onnx.ai/onnx/operators/onnx__Gather.html#gather-11 "Online Documentation")


        Given `data` tensor of rank r >= 1, and `indices` tensor of rank q, gather
        entries of the axis dimension of `data` (by default outer-most one as axis=0) indexed by `indices`, and concatenates
        them in an output tensor of rank q + (r - 1).

        axis = 0 :

        Let
        k = indices[i_{0}, ..., i_{q-1}]
        Then
        output[i_{0}, ..., i_{q-1}, j_{0}, ..., j_{r-2}] = input[k , j_{0}, ..., j_{r-2}]

        ::

              data = [
                  [1.0, 1.2],
                  [2.3, 3.4],
                  [4.5, 5.7],
              ]
              indices = [
                  [0, 1],
                  [1, 2],
              ]
              output = [
                  [
                      [1.0, 1.2],
                      [2.3, 3.4],
                  ],
                  [
                      [2.3, 3.4],
                      [4.5, 5.7],
                  ],
              ]


        axis = 1 :

        Let
        k = indices[i_{0}, ..., i_{q-1}]
        Then
        output[j_{0}, i_{0}, ..., i_{q-1}, j_{1}, ..., j_{r-2}] = input[j_{0}, k, j_{1}, ..., j_{r-2}]

        ::

              data = [
                  [1.0, 1.2, 1.9],
                  [2.3, 3.4, 3.9],
                  [4.5, 5.7, 5.9],
              ]
              indices = [
                  [0, 2],
              ]
              axis = 1,
              output = [
                  [[1.0, 1.9]],
                  [[2.3, 3.9]],
                  [[4.5, 5.9]],
              ]




        Args:
            data: Tensor of rank r >= 1.

            indices: Tensor of int32/int64 indices, of any rank q. All index values are
                expected to be within bounds [-s, s-1] along axis of size s. It is an
                error if any of the index values are out of bounds.

            axis: Which axis to gather on. Negative value means counting dimensions from
                the back. Accepted range is [-r, r-1] where r = rank(data).
        """

        schema = get_schema("Gather", 11, "")
        op = Op(self, "Gather", schema)
        return op(*self._prepare_inputs(schema, data, indices), axis=axis)

    T_GatherElements = TypeVar(
        "T_GatherElements",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    Tind_GatherElements = TypeVar("Tind_GatherElements", INT32, INT64)

    def GatherElements(
        self, data: T_GatherElements, indices: Tind_GatherElements, *, axis: int = 0
    ) -> T_GatherElements:
        r"""[🌐 GatherElements(11)](https://onnx.ai/onnx/operators/onnx__GatherElements.html#gatherelements-11 "Online Documentation")



        GatherElements takes two inputs `data` and `indices` of the same rank r >= 1
        and an optional attribute `axis` that identifies an axis of `data`
        (by default, the outer-most axis, that is axis 0). It is an indexing operation
        that produces its output by indexing into the input data tensor at index
        positions determined by elements of the `indices` tensor.
        Its output shape is the same as the shape of `indices` and consists of one value
        (gathered from the `data`) for each element in `indices`.

        For instance, in the 3-D case (r = 3), the output produced is determined
        by the following equations:
        ::

              out[i][j][k] = input[index[i][j][k]][j][k] if axis = 0,
              out[i][j][k] = input[i][index[i][j][k]][k] if axis = 1,
              out[i][j][k] = input[i][j][index[i][j][k]] if axis = 2,



        This operator is also the inverse of ScatterElements. It is similar to Torch's gather operation.

        Example 1:
        ::

              data = [
                  [1, 2],
                  [3, 4],
              ]
              indices = [
                  [0, 0],
                  [1, 0],
              ]
              axis = 1
              output = [
                  [
                    [1, 1],
                    [4, 3],
                  ],
              ]


        Example 2:
        ::

              data = [
                  [1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9],
              ]
              indices = [
                  [1, 2, 0],
                  [2, 0, 0],
              ]
              axis = 0
              output = [
                  [
                    [4, 8, 3],
                    [7, 2, 3],
                  ],
              ]




        Args:
            data: Tensor of rank r >= 1.

            indices: Tensor of int32/int64 indices, with the same rank r as the input.
                All index values are expected to be within bounds [-s, s-1] along axis
                of size s. It is an error if any of the index values are out of bounds.

            axis: Which axis to gather on. Negative value means counting dimensions from
                the back. Accepted range is [-r, r-1] where r = rank(data).
        """

        schema = get_schema("GatherElements", 11, "")
        op = Op(self, "GatherElements", schema)
        return op(*self._prepare_inputs(schema, data, indices), axis=axis)

    T_GatherND = TypeVar(
        "T_GatherND",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def GatherND(self, data: T_GatherND, indices: INT64) -> T_GatherND:
        r"""[🌐 GatherND(11)](https://onnx.ai/onnx/operators/onnx__GatherND.html#gathernd-11 "Online Documentation")


        Given `data` tensor of rank `r` >= 1, and `indices` tensor of rank `q` >= 1, this operator gathers
        slices of `data` into an output tensor of rank `q + r - indices_shape[-1] - 1`.

        `indices` is an q-dimensional integer tensor, best thought of as a `(q-1)`-dimensional tensor of index-tuples into `data`,
        where each element defines a slice of `data`

        Some salient points about the inputs' rank and shape:

        1) r >= 1 and q >= 1 are to be honored. There is no dependency condition to be met between ranks `r` and `q`

        2) The `indices_shape[-1]` should have a value between 1 (inclusive) and rank `r` (inclusive)

        3) All values in `indices` are expected to be within bounds [-s, s-1] along axis of size `s` (i.e.) `-data_shape[i] <= indices[...,i] <= data_shape[i] - 1`.
           It is an error if any of the index values are out of bounds.

        The output is computed as follows:

        The output tensor is obtained by mapping each index-tuple in the `indices` tensor to the corresponding slice of the input `data`.

        1) If `indices_shape[-1] > r` => error condition

        2) If `indices_shape[-1] == r`, since the rank of `indices` is `q`, `indices` can be thought of as a `(q-1)`-dimensional tensor
           containing 1-D tensors of dimension `r`. Let us think of each such `r` ranked tensor as `indices_slice`.
           Each *scalar value* corresponding to `data[indices_slice]` is filled into the corresponding location of the `(q-1)`-dimensional tensor
           to form the `output` tensor (Example 1 below)

        3) If `indices_shape[-1] < r`, since the rank of `indices` is `q`, `indices` can be thought of as a `(q-1)`-dimensional tensor
           containing 1-D tensors of dimension `< r`. Let us think of each such tensors as `indices_slice`.
           Each *tensor slice* corresponding to `data[indices_slice , :]` is filled into the corresponding location of the `(q-1)`-dimensional tensor
           to form the `output` tensor (Examples 2, 3, and 4 below)

        This operator is the inverse of `ScatterND`.

        `Example 1`

          data    = [[0,1],[2,3]]   # data_shape = [2, 2]

          indices = [[0,0],[1,1]]   # indices_shape = [2, 2]

          output  = [0,3]           # output_shape = [2]

        `Example 2`

          data    = [[0,1],[2,3]]  # data_shape = [2, 2]

          indices = [[1],[0]]      # indices_shape = [2, 1]

          output  = [[2,3],[0,1]]  # output_shape = [2, 2]

        `Example 3`

          data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape = [2, 2, 2]

          indices = [[0,1],[1,0]]                 # indices_shape = [2, 2]

          output  = [[2,3],[4,5]]                 # output_shape = [2, 2]

        `Example 4`

          data    = [[[0,1],[2,3]],[[4,5],[6,7]]] # data_shape = [2, 2, 2]

          indices = [[[0,1]],[[1,0]]]             # indices_shape = [2, 1, 2]

          output  = [[[2,3]],[[4,5]]]             # output_shape = [2, 1, 2]



        Args:
            data: Tensor of rank r >= 1.

            indices: Tensor of rank q >= 1. All index values are expected to be within
                bounds [-s, s-1] along axis of size s. It is an error if any of the
                index values are out of bounds.
        """

        schema = get_schema("GatherND", 11, "")
        op = Op(self, "GatherND", schema)
        return op(*self._prepare_inputs(schema, data, indices))

    T_Gemm = TypeVar("T_Gemm", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64)

    def Gemm(
        self,
        A: T_Gemm,
        B: T_Gemm,
        C: Optional[T_Gemm] = None,
        *,
        alpha: float = 1.0,
        beta: float = 1.0,
        transA: int = 0,
        transB: int = 0,
    ) -> T_Gemm:
        r"""[🌐 Gemm(11)](https://onnx.ai/onnx/operators/onnx__Gemm.html#gemm-11 "Online Documentation")

        General Matrix multiplication:
        https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms#Level_3

        A' = transpose(A) if transA else A

        B' = transpose(B) if transB else B

        Compute Y = alpha * A' * B' + beta * C, where input tensor A has shape (M, K) or (K, M),
        input tensor B has shape (K, N) or (N, K), input tensor C is broadcastable to shape (M, N),
        and output tensor Y has shape (M, N). A will be transposed before doing the
        computation if attribute transA is non-zero, same for B and transB.
        This operator supports **unidirectional broadcasting** (tensor C should be unidirectional broadcastable to tensor A * B); for more details please check `Broadcasting in ONNX <https://github.com/onnx/onnx/blob/master/docs/Broadcasting.md>`_.
        This operator has **optional** inputs/outputs. See `ONNX <https://github.com/onnx/onnx/blob/master/docs/IR.md>`_ for more details about the representation of optional arguments. An empty string may be used in the place of an actual argument's name to indicate a missing argument. Trailing optional arguments (those not followed by an argument that is present) may also be simply omitted.


        Args:
            A: Input tensor A. The shape of A should be (M, K) if transA is 0, or (K, M)
                if transA is non-zero.

            B: Input tensor B. The shape of B should be (K, N) if transB is 0, or (N, K)
                if transB is non-zero.

            C: (optional) Optional input tensor C. If not specified, the computation is
                done as if C is a scalar 0. The shape of C should be unidirectional
                broadcastable to (M, N).

            alpha: Scalar multiplier for the product of input tensors A * B.

            beta: Scalar multiplier for input tensor C.

            transA: Whether A should be transposed

            transB: Whether B should be transposed
        """

        schema = get_schema("Gemm", 11, "")
        op = Op(self, "Gemm", schema)
        return op(
            *self._prepare_inputs(schema, A, B, C),
            alpha=alpha,
            beta=beta,
            transA=transA,
            transB=transB,
        )

    T_Hardmax = TypeVar("T_Hardmax", DOUBLE, FLOAT, FLOAT16)

    def Hardmax(self, input: T_Hardmax, *, axis: int = 1) -> T_Hardmax:
        r"""[🌐 Hardmax(11)](https://onnx.ai/onnx/operators/onnx__Hardmax.html#hardmax-11 "Online Documentation")


        The operator computes the hardmax (1 for the first maximum value, and 0 for all others) values for each layer in the batch
         of the given input.

        The input does not need to explicitly be a 2D vector; rather, it will be
        coerced into one. For an arbitrary n-dimensional tensor
        input \in [a_0, a_1, ..., a_{k-1}, a_k, ..., a_{n-1}] and k is
        the axis provided, then input will be coerced into a 2-dimensional tensor with
        dimensions [a_0 * ... * a_{k-1}, a_k * ... * a_{n-1}]. For the default
        case where axis=1, this means the input tensor will be coerced into a 2D tensor
        of dimensions [a_0, a_1 * ... * a_{n-1}], where a_0 is often the batch size.
        In this situation, we must have a_0 = N and a_1 * ... * a_{n-1} = D.
        Each of these dimensions must be matched correctly, or else the operator
        will throw errors. The output tensor has the same shape
        and contains the hardmax values of the corresponding input.


        Args:
            input: The input tensor that's coerced into a 2D matrix of size (NxD) as
                described above.

            axis: Describes the axis of the inputs when coerced to 2D; defaults to one
                because the 0th axis most likely describes the batch_size. Negative
                value means counting dimensions from the back. Accepted range is [-r,
                r-1] where r = rank(input).
        """

        schema = get_schema("Hardmax", 11, "")
        op = Op(self, "Hardmax", schema)
        return op(*self._prepare_inputs(schema, input), axis=axis)

    B_If: TypeAlias = BOOL

    V_If: TypeAlias = Union[
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    ]

    def If(self, cond: B_If, *, else_branch: GraphProto, then_branch: GraphProto) -> V_If:
        r"""[🌐 If(11)](https://onnx.ai/onnx/operators/onnx__If.html#if-11 "Online Documentation")

        If conditional

        Args:
            cond: Condition for the if. The tensor must contain a single element.

            else_branch: Graph to run if condition is false. Has N outputs: values you
                wish to be live-out to the enclosing scope. The number of outputs must
                match the number of outputs in the then_branch.

            then_branch: Graph to run if condition is true. Has N outputs: values you
                wish to be live-out to the enclosing scope. The number of outputs must
                match the number of outputs in the else_branch.
        """

        schema = get_schema("If", 11, "")
        op = Op(self, "If", schema)
        return op(
            *self._prepare_inputs(schema, cond),
            else_branch=else_branch,
            then_branch=then_branch,
        )

    T_LogSoftmax = TypeVar("T_LogSoftmax", DOUBLE, FLOAT, FLOAT16)

    def LogSoftmax(self, input: T_LogSoftmax, *, axis: int = 1) -> T_LogSoftmax:
        r"""[🌐 LogSoftmax(11)](https://onnx.ai/onnx/operators/onnx__LogSoftmax.html#logsoftmax-11 "Online Documentation")


        The operator computes the logsoftmax (log of softmax) values for each layer in the batch
         of the given input.

        The input does not need to explicitly be a 2D vector; rather, it will be
        coerced into one. For an arbitrary n-dimensional tensor
        input \in [a_0, a_1, ..., a_{k-1}, a_k, ..., a_{n-1}] and k is
        the axis provided, then input will be coerced into a 2-dimensional tensor with
        dimensions [a_0 * ... * a_{k-1}, a_k * ... * a_{n-1}]. For the default
        case where axis=1, this means the input tensor will be coerced into a 2D tensor
        of dimensions [a_0, a_1 * ... * a_{n-1}], where a_0 is often the batch size.
        In this situation, we must have a_0 = N and a_1 * ... * a_{n-1} = D.
        Each of these dimensions must be matched correctly, or else the operator
        will throw errors. The output tensor has the same shape
        and contains the logsoftmax values of the corresponding input.


        Args:
            input: The input tensor that's coerced into a 2D matrix of size (NxD) as
                described above.

            axis: Describes the axis of the inputs when coerced to 2D; defaults to one
                because the 0th axis most likely describes the batch_size. Negative
                value means counting dimensions from the back. Accepted range is [-r,
                r-1] where r = rank(input).
        """

        schema = get_schema("LogSoftmax", 11, "")
        op = Op(self, "LogSoftmax", schema)
        return op(*self._prepare_inputs(schema, input), axis=axis)

    I_Loop: TypeAlias = INT64

    B_Loop: TypeAlias = BOOL

    V_Loop = TypeVar(
        "V_Loop",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Loop(
        self,
        M: Optional[I_Loop],
        cond: Optional[B_Loop],
        *v_initial: V_Loop,
        body: GraphProto,
    ) -> V_Loop:
        r"""[🌐 Loop(11)](https://onnx.ai/onnx/operators/onnx__Loop.html#loop-11 "Online Documentation")


        Generic Looping construct. This loop has multiple termination conditions:

        1) Trip count. Iteration count specified at runtime. Set by
           specifying the input M. Optional. Set to empty string to omit.
           Note that a static trip count (specified at graph construction time) can be
           specified by passing in a constant node for input M.
        2) Loop termination condition. This is an input to the op that determines
           whether to run the first iteration and also a loop-carried dependency for
           the body graph. The body graph must yield a value for the condition variable,
           whether this input is provided or not.

        This table summarizes the operating modes of this operator with equivalent
        C-style code:

        Operator inputs defined as (max_trip_count, condition_var).

            input ("", ""):
                for (int i=0; ; ++i) {
                  cond = ... // Note this value is ignored, but is required in the body
                }

            input ("", cond) // Note this is analogous to a while loop
                bool cond = ...;
                for (int i=0; cond; ++i) {
                  cond = ...;
                }

            input ("", 1) // Note this is analogous to a do-while loop
                bool cond = true
                for (int i=0; cond; ++i) {
                  cond = ...;
                }

            input (trip_count, "") // Note this is analogous to a for loop
                int trip_count = ...
                for (int i=0; i < trip_count; ++i) {
                  cond = ...; // ignored
                }

            input (trip_count, cond)
                int trip_count = ...;
                bool cond = ...;
                for (int i=0; i < trip_count && cond; ++i) {
                  cond = ...;
                }


        *Sample usage - cond as well as trip count*

            graph predict-net {
              %a = Constant[value = <Scalar Tensor [3]>]()
              %b = Constant[value = <Scalar Tensor [6]>]()
              %keepgoing = Constant[value = <Scalar Tensor [1]>]()
              %max_trip_count = Constant[value = <Scalar Tensor [10]>]()
              %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)
              return
            }

            graph body-net (
              %i[INT32, scalar]           // iteration number
              %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
              %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b
            ) {
              %my_local = Add(%a, %b_in)
              %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
              %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
              %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
              return %keepgoing_out, %b_out, %user_defined_val
            }

        *Sample equivalent C code*

            {
              /* User-defined code (enclosing scope) */
              int a = 3, b = 6;
              bool keepgoing = true; // Analogous to input cond
              /* End user-defined code */

              /* Implicitly-defined code */
              const int max_trip_count = 10; // Analogous to input M
              int user_defined_vals[]; // Imagine this is resizable
              /* End implicitly-defined code */
              /* initialize loop-carried variables and scan-output variables */
              bool keepgoing_out = keepgoing
              int b_out = b

              for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
                /* Implicitly-defined code: bind actual parameter values
                   to formal parameter variables of loop-body */
                bool keepgoing_in = keepgoing_out;
                bool b_in = b_out;

                /* User-defined code (loop body) */
                int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
                b_out = a - b_in;
                keepgoing_out = my_local > b_out;
                user_defined_val = b_in + b_in; // b_in and b_out are different variables
                /* End user-defined code */

                /* Implicitly defined-code */
                user_defined_vals[i] = user_defined_val // accumulate scan-output values
              }
              // int t = my_local; // Can't do this. my_local is not accessible here.

              // The values below are bound to the output variables of the loop and therefore accessible
              // b_out; user_defined_vals; keepgoing_out;
            }

        There are several things of note in this code snippet:

        1) Values from the enclosing scope (i.e. variable "a" here) are in scope and can
           be referenced in the inputs of the loop.
        2) Any values computed in the loop body that needs to be used in a subsequent
           iteration or after the loop are modelled using a pair of variables in the loop-body,
           consisting of an input variable (eg., b_in) and an output variable (eg., b_out).
           These are referred to as loop-carried dependences. The loop operation node
           supplies the input value of the input variable for the first iteration, and
           returns the output value of the output variable produced by the final
           iteration.
        3) Scan_output variables are used to implicitly concatenate values computed across
           all the iterations. In the above example, the value of user_defined_val computed
           over all iterations are concatenated and returned as the value of user_defined_vals
           after the loop.
        4) Values created in the body cannot be accessed in the enclosing scope,
           except using the mechanism described above.

        Note that the semantics of this op support "diagonal" or "wavefront" execution.
        (See Step 3 here for an example:
        https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/).
        Frontends should emit multi-layer RNNs as a series of While operators (with
        time being the inner looping dimension), with each successive layer consuming
        the scan_outputs from the previous layer, possibly going through several
        point-wise operators (e.g. dropout, residual connections, linear layer).


        Args:
            M: (optional) A maximum trip-count for the loop specified at runtime.
                Optional. Pass empty string to skip.

            cond: (optional) A boolean termination condition. Optional. Pass empty
                string to skip.

            v_initial: (variadic, heterogeneous) The initial values of any loop-carried
                dependencies (values that change across loop iterations)

            body: The graph run each iteration. It has 2+N inputs: (iteration_num,
                condition, loop carried dependencies...). It has 1+N+K outputs:
                (condition, loop carried dependencies..., scan_outputs...). Each
                scan_output is created by concatenating the value of the specified
                output value at the end of each iteration of the loop. It is an error if
                the dimensions or data type of these scan_outputs change across loop
                iterations.
        """

        schema = get_schema("Loop", 11, "")
        op = Op(self, "Loop", schema)
        return op(*self._prepare_inputs(schema, M, cond, *v_initial), body=body)

    T_LpPool = TypeVar("T_LpPool", DOUBLE, FLOAT, FLOAT16)

    def LpPool(
        self,
        X: T_LpPool,
        *,
        auto_pad: str = "NOTSET",
        kernel_shape: Sequence[int],
        p: int = 2,
        pads: Optional[Sequence[int]] = None,
        strides: Optional[Sequence[int]] = None,
    ) -> T_LpPool:
        r"""[🌐 LpPool(11)](https://onnx.ai/onnx/operators/onnx__LpPool.html#lppool-11 "Online Documentation")


         LpPool consumes an input tensor X and applies Lp pooling across
         the tensor according to kernel sizes, stride sizes, and pad lengths.
         Lp pooling consisting of computing the Lp norm on all values of a subset
         of the input tensor according to the kernel size and downsampling the
         data into the output tensor Y for further processing.

        Args:
            X: (differentiable) Input data tensor from the previous operator; dimensions
                for image case are (N x C x H x W), where N is the batch size, C is the
                number of channels, and H and W are the height and the width of the
                data. For non image case, the dimensions are in the form of (N x C x D1
                x D2 ... Dn), where N is the batch size.

            auto_pad: auto_pad must be either NOTSET, SAME_UPPER, SAME_LOWER or VALID.
                Where default value is NOTSET, which means explicit padding is used.
                SAME_UPPER or SAME_LOWER mean pad the input so that `output_shape[i] =
                ceil(input_shape[i] / strides[i])` for each axis `i`. The padding is
                split between the two sides equally or almost equally (depending on
                whether it is even or odd). In case the padding is an odd number, the
                extra padding is added at the end for SAME_UPPER and at the beginning
                for SAME_LOWER.

            kernel_shape: The size of the kernel along each axis.

            p: p value of the Lp norm used to pool over the input data.

            pads: Padding for the beginning and ending along each spatial axis, it can
                take any value greater than or equal to 0. The value represent the
                number of pixels added to the beginning and end part of the
                corresponding axis. `pads` format should be as follow [x1_begin,
                x2_begin...x1_end, x2_end,...], where xi_begin the number of pixels
                added at the beginning of axis `i` and xi_end, the number of pixels
                added at the end of axis `i`. This attribute cannot be used
                simultaneously with auto_pad attribute. If not present, the padding
                defaults to 0 along start and end of each spatial axis.

            strides: Stride along each spatial axis. If not present, the stride defaults
                to 1 along each spatial axis.
        """

        schema = get_schema("LpPool", 11, "")
        op = Op(self, "LpPool", schema)
        return op(
            *self._prepare_inputs(schema, X),
            auto_pad=auto_pad,
            kernel_shape=kernel_shape,
            p=p,
            pads=pads,
            strides=strides,
        )

    T_MaxPool = TypeVar("T_MaxPool", DOUBLE, FLOAT, FLOAT16)

    I_MaxPool: TypeAlias = INT64

    def MaxPool(
        self,
        X: T_MaxPool,
        *,
        auto_pad: str = "NOTSET",
        ceil_mode: int = 0,
        dilations: Optional[Sequence[int]] = None,
        kernel_shape: Sequence[int],
        pads: Optional[Sequence[int]] = None,
        storage_order: int = 0,
        strides: Optional[Sequence[int]] = None,
    ) -> Tuple[T_MaxPool, I_MaxPool]:
        r"""[🌐 MaxPool(11)](https://onnx.ai/onnx/operators/onnx__MaxPool.html#maxpool-11 "Online Documentation")


         MaxPool consumes an input tensor X and applies max pooling across
         the tensor according to kernel sizes, stride sizes, and pad lengths.
         max pooling consisting of computing the max on all values of a
         subset of the input tensor according to the kernel size and downsampling the
         data into the output tensor Y for further processing. The output spatial shape will be following:
         ```
         output_spatial_shape[i] = floor((input_spatial_shape[i] + pad_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1)) / strides_spatial_shape[i] + 1)
         ```
         or
         ```
         output_spatial_shape[i] = ceil((input_spatial_shape[i] + pad_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1)) / strides_spatial_shape[i] + 1)
         ```
         if ceil_mode is enabled

         ```
         * pad_shape[i] is sum of pads along axis i
         ```

         `auto_pad` is a DEPRECATED attribute. If you are using them currently, the output spatial shape will be following:
         ```
         VALID: output_spatial_shape[i] = ceil((input_spatial_shape[i] - ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) + 1) / strides_spatial_shape[i])
         SAME_UPPER or SAME_LOWER: output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides_spatial_shape[i])
         ```
         And pad shape will be following if `SAME_UPPER` or `SAME_LOWER`:
         ```
         pad_shape[i] = (output_spatial_shape[i] - 1) * strides_spatial_shape[i] + ((kernel_spatial_shape[i] - 1) * dilations[i] + 1) - input_spatial_shape[i]
         ```
         The output of each pooling window is maximum number of elements exclude pad.


        Args:
            X: Input data tensor from the previous operator; dimensions for image case
                are (N x C x H x W), where N is the batch size, C is the number of
                channels, and H and W are the height and the width of the data. For non
                image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn),
                where N is the batch size. Optionally, if dimension denotation is in
                effect, the operation expects the input data tensor to arrive with the
                dimension denotation of [DATA_BATCH, DATA_CHANNEL, DATA_FEATURE,
                DATA_FEATURE ...].

            auto_pad: auto_pad must be either NOTSET, SAME_UPPER, SAME_LOWER or VALID.
                Where default value is NOTSET, which means explicit padding is used.
                SAME_UPPER or SAME_LOWER mean pad the input so that the output spatial
                size match the input.In case of odd number add the extra padding at the
                end for SAME_UPPER and at the beginning for SAME_LOWER. VALID mean no
                padding.

            ceil_mode: Whether to use ceil or floor (default) to compute the output
                shape.

            dilations: Dilation value along each spatial axis of filter. If not present,
                the dilation defaults to 1 along each spatial axis.

            kernel_shape: The size of the kernel along each axis.

            pads: Padding for the beginning and ending along each spatial axis, it can
                take any value greater than or equal to 0. The value represent the
                number of pixels added to the beginning and end part of the
                corresponding axis. `pads` format should be as follow [x1_begin,
                x2_begin...x1_end, x2_end,...], where xi_begin the number of pixels
                added at the beginning of axis `i` and xi_end, the number of pixels
                added at the end of axis `i`. This attribute cannot be used
                simultaneously with auto_pad attribute. If not present, the padding
                defaults to 0 along start and end of each spatial axis.

            storage_order: The storage order of the tensor. 0 is row major, and 1 is
                column major.

            strides: Stride along each spatial axis. If not present, the stride defaults
                to 1 along each spatial axis.
        """

        schema = get_schema("MaxPool", 11, "")
        op = Op(self, "MaxPool", schema)
        return op(
            *self._prepare_inputs(schema, X),
            auto_pad=auto_pad,
            ceil_mode=ceil_mode,
            dilations=dilations,
            kernel_shape=kernel_shape,
            pads=pads,
            storage_order=storage_order,
            strides=strides,
        )

    T1_MaxUnpool = TypeVar("T1_MaxUnpool", DOUBLE, FLOAT, FLOAT16)

    T2_MaxUnpool: TypeAlias = INT64

    def MaxUnpool(
        self,
        X: T1_MaxUnpool,
        I: T2_MaxUnpool,
        output_shape: Optional[T2_MaxUnpool] = None,
        *,
        kernel_shape: Sequence[int],
        pads: Optional[Sequence[int]] = None,
        strides: Optional[Sequence[int]] = None,
    ) -> T1_MaxUnpool:
        r"""[🌐 MaxUnpool(11)](https://onnx.ai/onnx/operators/onnx__MaxUnpool.html#maxunpool-11 "Online Documentation")


        MaxUnpool essentially computes the partial inverse of the MaxPool op.
         The input information to this op is typically the output information from a MaxPool op. The first
         input tensor X is the tensor that needs to be unpooled, which is typically the pooled tensor (first output)
         from MaxPool. The second input tensor, I, contains the indices to the (locally maximal) elements corresponding
         to the elements in the first input tensor X. Input tensor I is typically the second output of the MaxPool op.
         The third (optional) input is a tensor that specifies the output size of the unpooling operation.

        MaxUnpool is intended to do 'partial' inverse of the MaxPool op. 'Partial' because all the non-maximal
         values from the original input to MaxPool are set to zero in the output of the MaxUnpool op. Pooling
         the result of an unpooling operation should give back the original input to the unpooling op.

        MaxUnpool can produce the same output size for several input sizes, which makes unpooling op ambiguous.
         The third input argument, output_size, is meant to disambiguate the op and produce output tensor of
         known/predictable size.

        In addition to the inputs, MaxUnpool takes three attributes, namely kernel_shape, strides, and pads,
         which define the exact unpooling op. The attributes typically have the same values as the corresponding
         pooling op that the unpooling op is trying to invert.


        Args:
            X: (differentiable) Input data tensor that has to be unpooled. This tensor
                is typically the first output of the MaxPool op.Dimensions for image
                case are (N x C x H x W), where N is the batch size, C is the number of
                channels, and H and W are the height and the width of the data. For
                non-image case, the dimensions are in the form of (N x C x D1 x D2 ...
                Dn), where N is the batch size. Optionally, if dimension denotation is
                in effect, the operation expects the input data tensor to arrive with
                the dimension denotation of [DATA_BATCH, DATA_CHANNEL, DATA_FEATURE,
                DATA_FEATURE ...].

            I: (non-differentiable) Input data tensor containing the indices
                corresponding to elements in the first input tensor X.This tensor is
                typically the second output of the MaxPool op.Dimensions must be the
                same as input tensor X. The indices are linear, i.e. computed
                considering the tensor as flattened 1-D tensor, assuming row-major
                storage. Also, the linear indices should not consider padding. So the
                values in indices are in the range [0, N x C x D1 x ... x Dn).

            output_shape: (optional, non-differentiable) The shape of the output can be
                explicitly set which will cause pads values to be auto generated. If
                'output_shape' is specified, 'pads' values are ignored.

            kernel_shape: The size of the kernel along each axis.

            pads: Padding for the beginning and ending along each spatial axis, it can
                take any value greater than or equal to 0. The value represent the
                number of pixels added to the beginning and end part of the
                corresponding axis. `pads` format should be as follow [x1_begin,
                x2_begin...x1_end, x2_end,...], where xi_begin the number of pixels
                added at the beginning of axis `i` and xi_end, the number of pixels
                added at the end of axis `i`. This attribute cannot be used
                simultaneously with auto_pad attribute. If not present, the padding
                defaults to 0 along start and end of each spatial axis.

            strides: Stride along each spatial axis. If not present, the stride defaults
                to 1 along each spatial axis.
        """

        schema = get_schema("MaxUnpool", 11, "")
        op = Op(self, "MaxUnpool", schema)
        return op(
            *self._prepare_inputs(schema, X, I, output_shape),
            kernel_shape=kernel_shape,
            pads=pads,
            strides=strides,
        )

    def NonMaxSuppression(
        self,
        boxes: FLOAT,
        scores: FLOAT,
        max_output_boxes_per_class: Optional[INT64] = None,
        iou_threshold: Optional[FLOAT] = None,
        score_threshold: Optional[FLOAT] = None,
        *,
        center_point_box: int = 0,
    ) -> INT64:
        r"""[🌐 NonMaxSuppression(11)](https://onnx.ai/onnx/operators/onnx__NonMaxSuppression.html#nonmaxsuppression-11 "Online Documentation")


        Filter out boxes that have high intersection-over-union (IOU) overlap with previously selected boxes.
        Bounding boxes with score less than score_threshold are removed. Bounding box format is indicated by attribute center_point_box.
        Note that this algorithm is agnostic to where the origin is in the coordinate system and more generally is invariant to
        orthogonal transformations and translations of the coordinate system; thus translating or reflections of the coordinate system
        result in the same boxes being selected by the algorithm.
        The selected_indices output is a set of integers indexing into the input collection of bounding boxes representing the selected boxes.
        The bounding box coordinates corresponding to the selected indices can then be obtained using the Gather or GatherND operation.


        Args:
            boxes: An input tensor with shape [num_batches, spatial_dimension, 4]. The
                single box data format is indicated by center_point_box.

            scores: An input tensor with shape [num_batches, num_classes,
                spatial_dimension]

            max_output_boxes_per_class: (optional) Integer representing the maximum
                number of boxes to be selected per batch per class. It is a scalar.
                Default to 0, which means no output.

            iou_threshold: (optional) Float representing the threshold for deciding
                whether boxes overlap too much with respect to IOU. It is scalar. Value
                range [0, 1]. Default to 0.

            score_threshold: (optional) Float representing the threshold for deciding
                when to remove boxes based on score. It is a scalar.

            center_point_box: Integer indicate the format of the box data. The default
                is 0. 0 - the box data is supplied as [y1, x1, y2, x2] where (y1, x1)
                and (y2, x2) are the coordinates of any diagonal pair of box corners and
                the coordinates can be provided as normalized (i.e., lying in the
                interval [0, 1]) or absolute. Mostly used for TF models. 1 - the box
                data is supplied as [x_center, y_center, width, height]. Mostly used for
                Pytorch models.
        """

        schema = get_schema("NonMaxSuppression", 11, "")
        op = Op(self, "NonMaxSuppression", schema)
        return op(
            *self._prepare_inputs(
                schema,
                boxes,
                scores,
                max_output_boxes_per_class,
                iou_threshold,
                score_threshold,
            ),
            center_point_box=center_point_box,
        )

    T1_OneHot = TypeVar(
        "T1_OneHot",
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    T2_OneHot = TypeVar(
        "T2_OneHot",
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    T3_OneHot = TypeVar(
        "T3_OneHot",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def OneHot(
        self, indices: T1_OneHot, depth: T2_OneHot, values: T3_OneHot, *, axis: int = -1
    ) -> T3_OneHot:
        r"""[🌐 OneHot(11)](https://onnx.ai/onnx/operators/onnx__OneHot.html#onehot-11 "Online Documentation")


            Produces a one-hot tensor based on inputs.
            The locations represented by the index values in the 'indices' input tensor will have 'on_value'
            and the other locations will have 'off_value' in the output tensor, where 'on_value' and 'off_value'
            are specified as part of required input argument 'values', which is a two-element tensor of format
            [off_value, on_value]. The rank of the output tensor will be one greater than the rank of the
            input tensor. The additional dimension is for one-hot representation. The additional dimension will
            be inserted at the position specified by 'axis'. If 'axis' is not specified then then additional
            dimension will be inserted as the innermost dimension, i.e. axis=-1. The size of the additional
            dimension is specified by required scalar input 'depth'. The type of the output tensor is the same
            as the type of the 'values' input. Any entries in the 'indices' input tensor with values outside
            the range [-depth, depth-1] will result in one-hot representation with all 'off_value' values in the
            output tensor.

            when axis = 0:
            output[input[i, j, k], i, j, k] = 1 for all i, j, k and 0 otherwise.

            when axis = -1:
            output[i, j, k, input[i, j, k]] = 1 for all i, j, k and 0 otherwise.



        Args:
            indices: (non-differentiable) Input tensor containing indices. Any entries
                in the 'indices' input tensor with values outside the range [-depth,
                depth-1] will result in one-hot representation with all 'off_value'
                values in the output tensor.In case 'indices' is of non-integer type,
                the values will be casted to int64 before use.

            depth: (non-differentiable) Scalar or Rank 1 tensor containing exactly one
                element, specifying the number of classes in one-hot tensor. This is
                also the size of the one-hot dimension (specified by 'axis' attribute)
                added on in the output tensor. The values in the 'indices' input tensor
                are expected to be in the range [-depth, depth-1]. In case 'depth' is of
                non-integer type, it will be casted to int64 before use.

            values: (non-differentiable) Rank 1 tensor containing exactly two elements,
                in the format [off_value, on_value], where 'on_value' is the value used
                for filling locations specified in 'indices' input tensor, and
                'off_value' is the value used for filling locations other than those
                specified in 'indices' input tensor.

            axis: (Optional) Axis along which one-hot representation in added. Default:
                axis=-1. axis=-1 means that the additional dimension will be inserted as
                the innermost/last dimension in the output tensor. Negative value means
                counting dimensions from the back. Accepted range is [-r-1, r] where r =
                rank(indices).
        """

        schema = get_schema("OneHot", 11, "")
        op = Op(self, "OneHot", schema)
        return op(*self._prepare_inputs(schema, indices, depth, values), axis=axis)

    T_Pad = TypeVar(
        "T_Pad",
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Pad(
        self,
        data: T_Pad,
        pads: INT64,
        constant_value: Optional[T_Pad] = None,
        *,
        mode: str = "constant",
    ) -> T_Pad:
        r"""[🌐 Pad(11)](https://onnx.ai/onnx/operators/onnx__Pad.html#pad-11 "Online Documentation")


        Given a tensor containing the data to be padded (`data`), a tensor containing the number of start and end pad values for axis (`pads`), (optionally) a `mode`, and (optionally) `constant_value`,
        a padded tensor (`output`) is generated.

        The three supported `modes` are (similar to corresponding modes supported by `numpy.pad`):

        1) `constant`(default) - pads with a given constant value as specified by `constant_value` (which defaults to 0)

        2) `reflect` - pads with the reflection of the vector mirrored on the first and last values of the vector along each axis

        3) `edge` - pads with the edge values of array


        Example 1 (`constant` mode):
          Insert 0 pads to the beginning of the second dimension.

          data =
          [
              [1.0, 1.2],
              [2.3, 3.4],
              [4.5, 5.7],
          ]

          pads = [0, 2, 0, 0]

          mode = 'constant'

          constant_value = 0.0

          output =
          [
              [0.0, 0.0, 1.0, 1.2],
              [0.0, 0.0, 2.3, 3.4],
              [0.0, 0.0, 4.5, 5.7],
          ]


        Example 2 (`reflect` mode):
          data =
          [
              [1.0, 1.2],
              [2.3, 3.4],
              [4.5, 5.7],
          ]

          pads = [0, 2, 0, 0]

          mode = 'reflect'

          output =
          [
              [1.0, 1.2, 1.0, 1.2],
              [2.3, 3.4, 2.3, 3.4],
              [4.5, 5.7, 4.5, 5.7],
          ]


        Example 3 (`edge` mode):
          data =
          [
              [1.0, 1.2],
              [2.3, 3.4],
              [4.5, 5.7],
          ]

          pads = [0, 2, 0, 0]

          mode = 'edge'

          output =
          [
              [1.0, 1.0, 1.0, 1.2],
              [2.3, 2.3, 2.3, 3.4],
              [4.5, 4.5, 4.5, 5.7],
          ]



        Args:
            data: Input tensor.

            pads: Tensor of integers indicating the number of padding elements to add or
                remove (if negative) at the beginning and end of each axis. For 2D input
                tensor, it is the number of pixels. `pads` should be a 1D tensor of
                shape [2 * input_rank]. `pads` format should be: [x1_begin,
                x2_begin,...,x1_end, x2_end,...], where xi_begin is the number of pad
                values added at the beginning of axis `i` and xi_end, the number of pad
                values added at the end of axis `i`.

            constant_value: (optional) (Optional) A scalar value to be used if the mode
                chosen is `constant` (by default it is 0).

            mode: Supported modes: `constant`(default), `reflect`, `edge`
        """

        schema = get_schema("Pad", 11, "")
        op = Op(self, "Pad", schema)
        return op(*self._prepare_inputs(schema, data, pads, constant_value), mode=mode)

    T_Range = TypeVar("T_Range", DOUBLE, FLOAT, INT16, INT32, INT64)

    def Range(self, start: T_Range, limit: T_Range, delta: T_Range) -> T_Range:
        r"""[🌐 Range(11)](https://onnx.ai/onnx/operators/onnx__Range.html#range-11 "Online Documentation")


        Generate a tensor containing a sequence of numbers that begin at `start` and extends by increments of `delta`
        up to `limit` (exclusive).

        The number of elements in the output of range is computed as below:

        ::

            number_of_elements = max( ceil( (limit - start) / delta ) , 0 )



        The pseudocode determining the contents of the output is shown below:

        ::

            for(int i=0; i<number_of_elements; ++i) {
              output[i] =  start + (i * delta);
            }



        Example 1

        ::

            Inputs: start = 3, limit = 9, delta = 3
            Output: [3, 6]



        Example 2

        ::

            Inputs: start = 10, limit = 4, delta = -2
            Output: [10, 8, 6]




        Args:
            start: Scalar. First entry for the range of output values.

            limit: Scalar. Exclusive upper limit for the range of output values.

            delta: Scalar. Value to step by.
        """

        schema = get_schema("Range", 11, "")
        op = Op(self, "Range", schema)
        return op(*self._prepare_inputs(schema, start, limit, delta))

    T_ReduceL1 = TypeVar("T_ReduceL1", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64)

    def ReduceL1(
        self,
        data: T_ReduceL1,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceL1:
        r"""[🌐 ReduceL1(11)](https://onnx.ai/onnx/operators/onnx__ReduceL1.html#reducel1-11 "Online Documentation")


        Computes the L1 norm of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceL1", 11, "")
        op = Op(self, "ReduceL1", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceL2 = TypeVar("T_ReduceL2", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64)

    def ReduceL2(
        self,
        data: T_ReduceL2,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceL2:
        r"""[🌐 ReduceL2(11)](https://onnx.ai/onnx/operators/onnx__ReduceL2.html#reducel2-11 "Online Documentation")


        Computes the L2 norm of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceL2", 11, "")
        op = Op(self, "ReduceL2", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceLogSum = TypeVar(
        "T_ReduceLogSum", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64
    )

    def ReduceLogSum(
        self,
        data: T_ReduceLogSum,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceLogSum:
        r"""[🌐 ReduceLogSum(11)](https://onnx.ai/onnx/operators/onnx__ReduceLogSum.html#reducelogsum-11 "Online Documentation")


        Computes the log sum of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceLogSum", 11, "")
        op = Op(self, "ReduceLogSum", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceLogSumExp = TypeVar(
        "T_ReduceLogSumExp", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64
    )

    def ReduceLogSumExp(
        self,
        data: T_ReduceLogSumExp,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceLogSumExp:
        r"""[🌐 ReduceLogSumExp(11)](https://onnx.ai/onnx/operators/onnx__ReduceLogSumExp.html#reducelogsumexp-11 "Online Documentation")


        Computes the log sum exponent of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceLogSumExp", 11, "")
        op = Op(self, "ReduceLogSumExp", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceMax = TypeVar("T_ReduceMax", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64)

    def ReduceMax(
        self,
        data: T_ReduceMax,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceMax:
        r"""[🌐 ReduceMax(11)](https://onnx.ai/onnx/operators/onnx__ReduceMax.html#reducemax-11 "Online Documentation")


        Computes the max of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned. Input tensors of rank zero are
        valid. Reduction over an empty set of values yields minus infinity (if supported by the datatype) or the minimum value of the data type otherwise.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceMax", 11, "")
        op = Op(self, "ReduceMax", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceMean = TypeVar(
        "T_ReduceMean", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64
    )

    def ReduceMean(
        self,
        data: T_ReduceMean,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceMean:
        r"""[🌐 ReduceMean(11)](https://onnx.ai/onnx/operators/onnx__ReduceMean.html#reducemean-11 "Online Documentation")


        Computes the mean of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceMean", 11, "")
        op = Op(self, "ReduceMean", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceMin = TypeVar("T_ReduceMin", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64)

    def ReduceMin(
        self,
        data: T_ReduceMin,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceMin:
        r"""[🌐 ReduceMin(11)](https://onnx.ai/onnx/operators/onnx__ReduceMin.html#reducemin-11 "Online Documentation")


        Computes the min of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned. Input tensors of rank zero are
        valid. Reduction over an empty set of values yields plus infinity (if supported by the datatype) or the maximum value of the data type otherwise.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceMin", 11, "")
        op = Op(self, "ReduceMin", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceProd = TypeVar(
        "T_ReduceProd", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64
    )

    def ReduceProd(
        self,
        data: T_ReduceProd,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceProd:
        r"""[🌐 ReduceProd(11)](https://onnx.ai/onnx/operators/onnx__ReduceProd.html#reduceprod-11 "Online Documentation")


        Computes the product of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceProd", 11, "")
        op = Op(self, "ReduceProd", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceSum = TypeVar("T_ReduceSum", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64)

    def ReduceSum(
        self,
        data: T_ReduceSum,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceSum:
        r"""[🌐 ReduceSum(11)](https://onnx.ai/onnx/operators/onnx__ReduceSum.html#reducesum-11 "Online Documentation")


        Computes the sum of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceSum", 11, "")
        op = Op(self, "ReduceSum", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T_ReduceSumSquare = TypeVar(
        "T_ReduceSumSquare", DOUBLE, FLOAT, FLOAT16, INT32, INT64, UINT32, UINT64
    )

    def ReduceSumSquare(
        self,
        data: T_ReduceSumSquare,
        *,
        axes: Optional[Sequence[int]] = None,
        keepdims: int = 1,
    ) -> T_ReduceSumSquare:
        r"""[🌐 ReduceSumSquare(11)](https://onnx.ai/onnx/operators/onnx__ReduceSumSquare.html#reducesumsquare-11 "Online Documentation")


        Computes the sum square of the input tensor's element along the provided axes. The resulting
        tensor has the same rank as the input if keepdims equals 1. If keepdims equal 0, then
        the resulted tensor have the reduced dimension pruned.

        The above behavior is similar to numpy, with the exception that numpy defaults keepdims to
        False instead of True.

        Args:
            data: An input tensor.

            axes: A list of integers, along which to reduce. The default is to reduce
                over all the dimensions of the input tensor. Accepted range is [-r, r-1]
                where r = rank(data).

            keepdims: Keep the reduced dimension or not, default 1 means keep reduced
                dimension.
        """

        schema = get_schema("ReduceSumSquare", 11, "")
        op = Op(self, "ReduceSumSquare", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes, keepdims=keepdims)

    T1_Resize = TypeVar(
        "T1_Resize",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    T2_Resize = TypeVar("T2_Resize", DOUBLE, FLOAT, FLOAT16)

    def Resize(
        self,
        X: T1_Resize,
        roi: T2_Resize,
        scales: FLOAT,
        sizes: Optional[INT64] = None,
        *,
        coordinate_transformation_mode: str = "half_pixel",
        cubic_coeff_a: float = -0.75,
        exclude_outside: int = 0,
        extrapolation_value: float = 0.0,
        mode: str = "nearest",
        nearest_mode: str = "round_prefer_floor",
    ) -> T1_Resize:
        r"""[🌐 Resize(11)](https://onnx.ai/onnx/operators/onnx__Resize.html#resize-11 "Online Documentation")


        Resize the input tensor. In general, it calculates every value in the output tensor as a weighted average of neighborhood (a.k.a. sampling locations) in the input tensor.
        Each dimension value of the output tensor is:
          output_dimension = floor(input_dimension * (roi_end - roi_start) * scale) if input \"sizes\" is not specified.


        Args:
            X: N-D tensor

            roi: 1-D tensor given as [start1, ..., startN, end1, ..., endN], where N is
                the rank of X. The RoIs' coordinates are normalized in the coordinate
                system of the input image. It only takes effect when
                coordinate_transformation_mode is "tf_crop_and_resize"

            scales: The scale array along each dimension. It takes value greater than 0.
                If it's less than 1, it's sampling down, otherwise, it's upsampling. The
                number of elements of 'scales' should be the same as the rank of input
                'X'. If 'size' is needed, the user must set 'scales' to an empty tensor.

            sizes: (optional) The size of the output tensor. The number of elements of
                'sizes' should be the same as the rank of input 'X'. May only be set if
                'scales' is set to an empty tensor.

            coordinate_transformation_mode:
        This attribute describes how to transform
                the coordinate in the resized tensor to the coordinate in the original
                tensor. <br/>

        The coordinate of each dimension is transformed
                individually. Let's describe a case using axis x as an example.
        Denote
                x_resized as the coordinate of axis x in the resized tensor, x_original
                as the coordinate of axis x in the original tensor, length_original as
                the length of the original tensor in axis x, length_resized as the
                length of the resized tensor in axis x, roi_x = (start_x, end_x) of the
                axis x in input "roi", scale = length_resized / length_original, <br/>
                if coordinate_transformation_mode is "half_pixel", <br/>
        x_original =
                (x_resized + 0.5) / scale - 0.5, <br/>

        if
                coordinate_transformation_mode is "pytorch_half_pixel", <br/>
        x_original
                = length_resized > 1 ? (x_resized + 0.5) / scale - 0.5 : 0, <br/>

        if
                coordinate_transformation_mode is "align_corners", <br/>
        x_original =
                x_resized * (length_original - 1) / (length_resized - 1), <br/>

        if
                coordinate_transformation_mode is "asymmetric", <br/>
        x_original =
                x_resized / scale, <br/>

        if coordinate_transformation_mode is
                "tf_half_pixel_for_nn", <br/>
        x_original = (x_resized + 0.5) / scale,
                <br/>

        if coordinate_transformation_mode is "tf_crop_and_resize", <br/>
                x_original = length_resized > 1 ? start_x * (length_original - 1) +
                x_resized * (end_x - start_x) * (length_original - 1) / (length_resized
                - 1) : 0.5 * (start_x + end_x) * (length_original - 1).

            cubic_coeff_a: The coefficient 'a' used in cubic interpolation. Two common
                choice are -0.5 (in some cases of TensorFlow) and -0.75 (in PyTorch).
                Check out Equation (4) in https://ieeexplore.ieee.org/document/1163711
                for the details. This attribute is valid only if "mode" is "cubic".

            exclude_outside: If set to 1, the weight of sampling locations outside the
                tensor will be set to 0 and the weight will be renormalized so that
                their sum is 1.0. The default value is 0.

            extrapolation_value: When coordinate_transformation_mode is
                "tf_crop_and_resize" and x_original is outside the range [0,
                length_original - 1], this value is used as the corresponding output
                value. Default is 0.0f.

            mode: Three interpolation modes: nearest (default), linear and cubic. The
                "linear" mode includes linear interpolation for 1D tensor and N-linear
                interpolation for N-D tensor (for example, bilinear interpolation for 2D
                tensor). The "cubic" mode includes cubic interpolation for 1D tensor and
                N-cubic interpolation for N-D tensor (for example, bicubic interpolation
                for 2D tensor).

            nearest_mode: Four modes: round_prefer_floor (default, as known as round
                half down), round_prefer_ceil (as known as round half up), floor, ceil.
                Only used by nearest interpolation. It indicates how to get "nearest"
                pixel in input tensor from x_original, so this attribute is valid only
                if "mode" is "nearest".
        """

        schema = get_schema("Resize", 11, "")
        op = Op(self, "Resize", schema)
        return op(
            *self._prepare_inputs(schema, X, roi, scales, sizes),
            coordinate_transformation_mode=coordinate_transformation_mode,
            cubic_coeff_a=cubic_coeff_a,
            exclude_outside=exclude_outside,
            extrapolation_value=extrapolation_value,
            mode=mode,
            nearest_mode=nearest_mode,
        )

    T_Round = TypeVar("T_Round", DOUBLE, FLOAT, FLOAT16)

    def Round(self, X: T_Round) -> T_Round:
        r"""[🌐 Round(11)](https://onnx.ai/onnx/operators/onnx__Round.html#round-11 "Online Documentation")


        Round takes one input Tensor and rounds the values, element-wise, meaning
        it finds the nearest integer for each value.
        In case of halves, the rule is to round them to the nearest even integer.
        If input x is integral, +0, -0, NaN,  or infinite, x itself is returned.
        The output tensor has the same shape and type as the input.

        Examples:
        ::

            round([0.9]) = [1.0]
            round([2.5]) = [2.0]
            round([2.3]) = [2.0]
            round([1.5]) = [2.0]
            round([-4.5]) = [-4.0]




        Args:
            X: (non-differentiable) Input tensor
        """

        schema = get_schema("Round", 11, "")
        op = Op(self, "Round", schema)
        return op(*self._prepare_inputs(schema, X))

    V_Scan = TypeVar(
        "V_Scan",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Scan(
        self,
        *initial_state_and_scan_inputs: V_Scan,
        body: GraphProto,
        num_scan_inputs: int,
        scan_input_axes: Optional[Sequence[int]] = None,
        scan_input_directions: Optional[Sequence[int]] = None,
        scan_output_axes: Optional[Sequence[int]] = None,
        scan_output_directions: Optional[Sequence[int]] = None,
    ) -> V_Scan:
        r"""[🌐 Scan(11)](https://onnx.ai/onnx/operators/onnx__Scan.html#scan-11 "Online Documentation")


        Scan can be used to iterate over one or more scan_input tensors,
        constructing zero or more scan_output tensors. It combines ideas from general recurrences,
        functional programming constructs such as scan, fold, map, and zip, and is intended to enable
        generalizations of RNN-like constructs for sequence-to-sequence processing.
        Other tensors (referred to as state_variables here) can be used to carry a state
        when iterating from one element to another (similar to hidden-state in RNNs, also referred
        to as loop-carried dependences in the context of loops).
        Many common usages involve a single scan_input tensor (where functionality
        similar to scan, fold and map can be obtained). When more than one scan_input is used,
        a behavior similar to zip is obtained.

        The attribute body must be a graph, specifying the computation to be performed in
        every iteration. It takes as input the current values of the state_variables and
        the current iterated element of the scan_inputs. It must return the (updated) values
        of the state_variables and zero or more scan_output_element tensors. The values of the
        scan_output_element tensors are concatenated over all the iterations to produce the
        scan_output values of the scan construct (similar to the concatenated intermediate
        hidden-state values of RNN-like constructs). All the output tensors (state_variables as
        well as scan_output_element tensors) are required to have the same shape in each iteration
        of the loop (a restriction imposed to enable efficient memory allocation).

        Note that the iterated element passed to the body subgraph does not have a sequence
        axis. It will have a rank one less than the rank of the corresponding scan_input.

        The scan operation returns the final values of the state_variables as well as the
        scan_outputs.

        The optional attribute scan_input_directions specifies the direction (forward or backward)
        for each scan input. If this attribute is omitted, all sequences are scanned in the forward
        direction. A bidirectional scan may be performed by specifying the same tensor input twice
        in the scan_inputs, once with a forward direction, and once with a backward direction.

        The scan_output of the operation is produced by concatenating the scan_output_element
        values produced by the body in each iteration.  The optional attribute scan_output_directions
        specifies the direction in which scan_output is constructed (by appending or prepending the
        scan_output_element to scan_output in each iteration) for each scan_output. If this attribute
        is omitted, the scan_output_element is appended to the scan_output in each iteration.

        The optional attribute scan_input_axes specifies the axis to be scanned for each scan_input.
        If omitted, every scan_input will be scanned in axis 0. For example, if axis 0 is the
        batch axis and axis 1 is the time axis (to be scanned), specify an axis value of 1.
        Note that scanning a non-zero axis may be less efficient than scanning axis zero.

        The optional attribute scan_output_axes specifies the axis along which the scan_outputs
        are accumulated for each scan_output. For example, if axis 1 is the time axis (to be
        scanned) for both inputs and outputs, specify a scan_input axis and scan_output axis
        value of 1.

        Note that because of the ONNX restriction that only the last parameter of an operator can
        be variadic, the initial-states and scan-inputs are listed together as one input parameter.
        Similarly, the final-states and scan-outputs are listed together as one output parameter.
        The attribute num_scan_inputs indicates the number M of scan-inputs.

        The behavior of

            Scan <
                num_scan_inputs = m,
                body = loop-body,
                scan_input_axes = [axis_1, ..., axis_m]
            > (init_1, ..., init_n, scan_1, ..., scan_m)

        is equivalent to the following pseudo-code:

            // scan_i.shape[axis_i] denotes the (max) sequence-length of scan_i
            // scan_i.shape[axis_i] is required to be equal to scan_j.shape[axis_j] for all i,j.
            sequence_length = scan_1.shape[axis_1];

            // initialize state-variables
            st_1 = init_1; ... st_n = init_n;
            // initialize scan-output variables: [] denotes an empty tensor
            scan_out_1 = []; ...; scan_out_k = [];
            // identify number of iterations:

            // execute loop
            for (int t = 0; t < sequence_length; ++t) {
                // generate the scan-input elements: the notation T<axis=k>[t] indicates the sub-tensor
                // of rank one less than T obtained by indexing T at position t along axis k.
                si_1 = scan_1<axis=axis_1>[t];
                ... ;
                si_m = scan_m<axis=axis_m>[t];
                // execute loop-body
                st_1, ..., st_n, so_1, ..., so_k = loop-body(st_1, ..., st_n, si_1, ..., si_m)
                // accumulate the scan-output elements
                scan_out_1 = Concat<axis=0>(scan_out_1, so_1); ... ; scan_out_k = Concat<axis=0>(scan_out_k, so_k);
            }

            return st_1, ..., st_n, scan_out_1, ..., scan_out_k;

        *Sample usage: Encoding RNN using a Scan*

        The following example shows how a simple RNN over an input tensor %X, with weight tensor %Wi,
        recurrence weight tensor %Ri, bias tensors %Wbi and %Rbi, and initial hidden-state %H_0 can
        be encoded as a ScanLoop. Note that the loop-body is a nested graph, and it directly computes
        %Wi, %Ri, %Wbi, and %Rbi (typically constants or initializers in the body graph). If these
        values are computed in the outer graph, they need to be passed in as extra state_variables.

            graph rnn-encoding {
              %H_0 = ...
              %X = ...
              %Y_h, %Y = Scan[body = <graph rnn-cell-1>, num_scan_inputs=1](%H_0, %X)
              return %Y, %Y_h
            }

            graph rnn-cell-1 (
              %H_tminus1[FLOAT, tensor]
              %X_t[FLOAT, tensor]
            ) {
              %Wi = ...
              %Ri = ...
              %Wbi = ...
              %Rbi = ...
              %t1 = X_t * (Wi^T)
              %t2 = H_tminus1*(Ri^T)
              %t3 = Add(%t1, %t2)
              %t4 = Add(%t3, %Wbi)
              %t5 = Add(%t4, %Rbi)
              %Ht = Tanh(%t5)
              %Accumulate = Identity(%Ht)
              return %Ht, %Accumulate
            }



        Args:
            initial_state_and_scan_inputs: (variadic, heterogeneous) Initial values of
                the loop's N state variables followed by M scan_inputs

            body: The graph run each iteration. It has N+M inputs: (loop state
                variables..., scan_input_elts...). It has N+K outputs: (loop state
                variables..., scan_output_elts...). Each scan_output is created by
                concatenating the value of the specified scan_output_elt value at the
                end of each iteration of the loop. It is an error if the dimensions of
                these values change across loop iterations.

            num_scan_inputs: An attribute specifying the number of scan_inputs M.

            scan_input_axes: An optional list of M flags. The i-th element of the list
                specifies the axis to be scanned (the sequence axis) for the i-th
                scan_input. If omitted, 0 will be used as the scan axis for every
                scan_input. Negative value for an axis means counting dimensions from
                the back. Accepted range is [-r, r-1] where r = rank(input).

            scan_input_directions: An optional list of M flags. The i-th element of the
                list specifies the direction to be scanned for the i-th scan_input
                tensor: 0 indicates forward direction and 1 indicates reverse direction.
                If omitted, all scan_input tensors will be scanned in the forward
                direction.

            scan_output_axes: An optional list of K flags. The i-th element of the list
                specifies the axis for the i-th scan_output. The scan outputs are
                accumulated along the specified axis. If omitted, 0 will be used as the
                scan axis for every scan_output. Negative value for an axis means
                counting dimensions from the back. Accepted range is [-r, r-1].

            scan_output_directions: An optional list of K flags, one for each
                scan_output. The i-th element of the list specifies whether the i-th
                scan_output should be constructed by appending or prepending a new value
                in each iteration: 0 indicates appending and 1 indicates prepending. If
                omitted, all scan_output tensors will be produced by appending a value
                in each iteration.
        """

        schema = get_schema("Scan", 11, "")
        op = Op(self, "Scan", schema)
        return op(
            *self._prepare_inputs(schema, *initial_state_and_scan_inputs),
            body=body,
            num_scan_inputs=num_scan_inputs,
            scan_input_axes=scan_input_axes,
            scan_input_directions=scan_input_directions,
            scan_output_axes=scan_output_axes,
            scan_output_directions=scan_output_directions,
        )

    T_ScatterElements = TypeVar(
        "T_ScatterElements",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    Tind_ScatterElements = TypeVar("Tind_ScatterElements", INT32, INT64)

    def ScatterElements(
        self,
        data: T_ScatterElements,
        indices: Tind_ScatterElements,
        updates: T_ScatterElements,
        *,
        axis: int = 0,
    ) -> T_ScatterElements:
        r"""[🌐 ScatterElements(11)](https://onnx.ai/onnx/operators/onnx__ScatterElements.html#scatterelements-11 "Online Documentation")


        ScatterElements takes three inputs `data`, `updates`, and `indices` of the same
        rank r >= 1 and an optional attribute axis that identifies an axis of `data`
        (by default, the outer-most axis, that is axis 0). The output of the operation
        is produced by creating a copy of the input `data`, and then updating its value
        to values specified by `updates` at specific index positions specified by
        `indices`. Its output shape is the same as the shape of `data`.

        For each entry in `updates`, the target index in `data` is obtained by combining
        the corresponding entry in `indices` with the index of the entry itself: the
        index-value for dimension = axis is obtained from the value of the corresponding
        entry in `indices` and the index-value for dimension != axis is obtained from the
        index of the entry itself.

        For instance, in a 2-D tensor case, the update corresponding to the [i][j] entry
        is performed as below:
        ::

              output[indices[i][j]][j] = updates[i][j] if axis = 0,
              output[i][indices[i][j]] = updates[i][j] if axis = 1,



        This operator is the inverse of GatherElements. It is similar to Torch's Scatter operation.

        Example 1:
        ::

              data = [
                  [0.0, 0.0, 0.0],
                  [0.0, 0.0, 0.0],
                  [0.0, 0.0, 0.0],
              ]
              indices = [
                  [1, 0, 2],
                  [0, 2, 1],
              ]
              updates = [
                  [1.0, 1.1, 1.2],
                  [2.0, 2.1, 2.2],
              ]
              output = [
                  [2.0, 1.1, 0.0]
                  [1.0, 0.0, 2.2]
                  [0.0, 2.1, 1.2]
              ]


        Example 2:
        ::

              data = [[1.0, 2.0, 3.0, 4.0, 5.0]]
              indices = [[1, 3]]
              updates = [[1.1, 2.1]]
              axis = 1
              output = [[1.0, 1.1, 3.0, 2.1, 5.0]]




        Args:
            data: Tensor of rank r >= 1.

            indices: Tensor of int32/int64 indices, of r >= 1 (same rank as input). All
                index values are expected to be within bounds [-s, s-1] along axis of
                size s. It is an error if any of the index values are out of bounds.

            updates: Tensor of rank r >=1 (same rank and shape as indices)

            axis: Which axis to scatter on. Negative value means counting dimensions
                from the back. Accepted range is [-r, r-1] where r = rank(data).
        """

        schema = get_schema("ScatterElements", 11, "")
        op = Op(self, "ScatterElements", schema)
        return op(*self._prepare_inputs(schema, data, indices, updates), axis=axis)

    T_ScatterND = TypeVar(
        "T_ScatterND",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def ScatterND(
        self, data: T_ScatterND, indices: INT64, updates: T_ScatterND
    ) -> T_ScatterND:
        r"""[🌐 ScatterND(11)](https://onnx.ai/onnx/operators/onnx__ScatterND.html#scatternd-11 "Online Documentation")


        ScatterND takes three inputs `data` tensor of rank r >= 1, `indices` tensor of rank q >= 1,
        and `updates` tensor of rank q + r - indices.shape[-1] - 1. The output of the operation
        is produced by creating a copy of the input `data`, and then updating its value to values
        specified by `updates` at specific index positions specified by `indices`. Its output shape
        is the same as the shape of `data`. Note that `indices` should not have duplicate entries.
        That is, two or more `updates` for the same index-location is not supported.

        `indices` is an integer tensor. Let k denote indices.shape[-1], the last dimension in the shape of `indices`.
         `indices` is treated as a (q-1)-dimensional tensor of k-tuples, where each k-tuple is a partial-index into `data`.
        Hence, k can be a value at most the rank of `data`. When k equals rank(data), each update entry specifies an
        update to a single element of the tensor. When k is less than rank(data) each update entry specifies an
        update to a slice of the tensor. Index values are allowed to be negative, as per the usual
        convention for counting backwards from the end, but are expected in the valid range.

        `updates` is treated as a (q-1)-dimensional tensor of replacement-slice-values. Thus, the
        first (q-1) dimensions of updates.shape must match the first (q-1) dimensions of indices.shape.
        The remaining dimensions of `updates` correspond to the dimensions of the
        replacement-slice-values. Each replacement-slice-value is a (r-k) dimensional tensor,
        corresponding to the trailing (r-k) dimensions of `data`.  Thus, the shape of `updates`
        must equal indices.shape[0:q-1] ++ data.shape[k:r-1], where ++ denotes the concatenation
        of shapes.

        The `output` is calculated via the following equation:

            output = np.copy(data)
            update_indices = indices.shape[:-1]
            for idx in np.ndindex(update_indices):
                output[indices[idx]] = updates[idx]

        The order of iteration in the above loop is not specified.
        In particular, indices should not have duplicate entries: that is, if idx1 != idx2, then indices[idx1] != indices[idx2].
        This ensures that the output value does not depend on the iteration order.

        This operator is the inverse of GatherND.

        Example 1:
        ::

              data    = [1, 2, 3, 4, 5, 6, 7, 8]
              indices = [[4], [3], [1], [7]]
              updates = [9, 10, 11, 12]
              output  = [1, 11, 3, 10, 9, 6, 7, 12]



        Example 2:
        ::

              data    = [[[1, 2, 3, 4], [5, 6, 7, 8], [8, 7, 6, 5], [4, 3, 2, 1]],
                         [[1, 2, 3, 4], [5, 6, 7, 8], [8, 7, 6, 5], [4, 3, 2, 1]],
                         [[8, 7, 6, 5], [4, 3, 2, 1], [1, 2, 3, 4], [5, 6, 7, 8]],
                         [[8, 7, 6, 5], [4, 3, 2, 1], [1, 2, 3, 4], [5, 6, 7, 8]]]
              indices = [[0], [2]]
              updates = [[[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]],
                         [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]]
              output  = [[[5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7], [8, 8, 8, 8]],
                         [[1, 2, 3, 4], [5, 6, 7, 8], [8, 7, 6, 5], [4, 3, 2, 1]],
                         [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]],
                         [[8, 7, 6, 5], [4, 3, 2, 1], [1, 2, 3, 4], [5, 6, 7, 8]]]




        Args:
            data: Tensor of rank r >= 1.

            indices: Tensor of rank q >= 1.

            updates: Tensor of rank q + r - indices_shape[-1] - 1.
        """

        schema = get_schema("ScatterND", 11, "")
        op = Op(self, "ScatterND", schema)
        return op(*self._prepare_inputs(schema, data, indices, updates))

    S_SequenceAt = TypeVar(
        "S_SequenceAt",
        Sequence[BOOL],
        Sequence[COMPLEX128],
        Sequence[COMPLEX64],
        Sequence[DOUBLE],
        Sequence[FLOAT],
        Sequence[FLOAT16],
        Sequence[INT16],
        Sequence[INT32],
        Sequence[INT64],
        Sequence[INT8],
        Sequence[STRING],
        Sequence[UINT16],
        Sequence[UINT32],
        Sequence[UINT64],
        Sequence[UINT8],
    )

    I_SequenceAt = TypeVar("I_SequenceAt", INT32, INT64)

    T_SequenceAt: TypeAlias = Union[
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    ]

    def SequenceAt(self, input_sequence: S_SequenceAt, position: I_SequenceAt) -> T_SequenceAt:
        r"""[🌐 SequenceAt(11)](https://onnx.ai/onnx/operators/onnx__SequenceAt.html#sequenceat-11 "Online Documentation")


        Outputs a tensor copy from the tensor at 'position' in 'input_sequence'.
        Accepted range for 'position' is in `[-n, n - 1]`, where `n` is the number of tensors in 'input_sequence'.
        Negative value means counting positions from the back.


        Args:
            input_sequence: Input sequence.

            position: Position of the tensor in the sequence. Negative value means
                counting positions from the back. Accepted range in `[-n, n - 1]`, where
                `n` is the number of tensors in 'input_sequence'. It is an error if any
                of the index values are out of bounds. It must be a scalar(tensor of
                empty shape).
        """

        schema = get_schema("SequenceAt", 11, "")
        op = Op(self, "SequenceAt", schema)
        return op(*self._prepare_inputs(schema, input_sequence, position))

    T_SequenceConstruct = TypeVar(
        "T_SequenceConstruct",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    S_SequenceConstruct: TypeAlias = Union[
        Sequence[BOOL],
        Sequence[COMPLEX128],
        Sequence[COMPLEX64],
        Sequence[DOUBLE],
        Sequence[FLOAT],
        Sequence[FLOAT16],
        Sequence[INT16],
        Sequence[INT32],
        Sequence[INT64],
        Sequence[INT8],
        Sequence[STRING],
        Sequence[UINT16],
        Sequence[UINT32],
        Sequence[UINT64],
        Sequence[UINT8],
    ]

    def SequenceConstruct(self, *inputs: T_SequenceConstruct) -> S_SequenceConstruct:
        r"""[🌐 SequenceConstruct(11)](https://onnx.ai/onnx/operators/onnx__SequenceConstruct.html#sequenceconstruct-11 "Online Documentation")


        Construct a tensor sequence containing 'inputs' tensors.
        All tensors in 'inputs' must have the same data type.


        Args:
            inputs: (variadic) Tensors.
        """

        schema = get_schema("SequenceConstruct", 11, "")
        op = Op(self, "SequenceConstruct", schema)
        return op(*self._prepare_inputs(schema, *inputs))

    S_SequenceEmpty: TypeAlias = Union[
        Sequence[BOOL],
        Sequence[COMPLEX128],
        Sequence[COMPLEX64],
        Sequence[DOUBLE],
        Sequence[FLOAT],
        Sequence[FLOAT16],
        Sequence[INT16],
        Sequence[INT32],
        Sequence[INT64],
        Sequence[INT8],
        Sequence[STRING],
        Sequence[UINT16],
        Sequence[UINT32],
        Sequence[UINT64],
        Sequence[UINT8],
    ]

    def SequenceEmpty(self, *, dtype: Optional[int] = None) -> S_SequenceEmpty:
        r"""[🌐 SequenceEmpty(11)](https://onnx.ai/onnx/operators/onnx__SequenceEmpty.html#sequenceempty-11 "Online Documentation")


        Construct an empty tensor sequence, with given data type.


        Args:
            dtype: (Optional) The data type of the tensors in the output sequence. The
                default type is 'float'.
        """

        schema = get_schema("SequenceEmpty", 11, "")
        op = Op(self, "SequenceEmpty", schema)
        return op(dtype=dtype)

    S_SequenceErase = TypeVar(
        "S_SequenceErase",
        Sequence[BOOL],
        Sequence[COMPLEX128],
        Sequence[COMPLEX64],
        Sequence[DOUBLE],
        Sequence[FLOAT],
        Sequence[FLOAT16],
        Sequence[INT16],
        Sequence[INT32],
        Sequence[INT64],
        Sequence[INT8],
        Sequence[STRING],
        Sequence[UINT16],
        Sequence[UINT32],
        Sequence[UINT64],
        Sequence[UINT8],
    )

    I_SequenceErase = TypeVar("I_SequenceErase", INT32, INT64)

    def SequenceErase(
        self,
        input_sequence: S_SequenceErase,
        position: Optional[I_SequenceErase] = None,
    ) -> S_SequenceErase:
        r"""[🌐 SequenceErase(11)](https://onnx.ai/onnx/operators/onnx__SequenceErase.html#sequenceerase-11 "Online Documentation")


        Outputs a tensor sequence that removes the tensor at 'position' from 'input_sequence'.
        Accepted range for 'position' is in `[-n, n - 1]`, where `n` is the number of tensors in 'input_sequence'.
        Negative value means counting positions from the back.
        'position' is optional, by default it erases the last tensor from 'input_sequence'.


        Args:
            input_sequence: Input sequence.

            position: (optional) Position of the tensor in the sequence. Negative value
                means counting positions from the back. Accepted range in `[-n, n - 1]`,
                where `n` is the number of tensors in 'input_sequence'. It is an error
                if any of the index values are out of bounds. It must be a scalar(tensor
                of empty shape).
        """

        schema = get_schema("SequenceErase", 11, "")
        op = Op(self, "SequenceErase", schema)
        return op(*self._prepare_inputs(schema, input_sequence, position))

    S_SequenceInsert = TypeVar(
        "S_SequenceInsert",
        Sequence[BOOL],
        Sequence[COMPLEX128],
        Sequence[COMPLEX64],
        Sequence[DOUBLE],
        Sequence[FLOAT],
        Sequence[FLOAT16],
        Sequence[INT16],
        Sequence[INT32],
        Sequence[INT64],
        Sequence[INT8],
        Sequence[STRING],
        Sequence[UINT16],
        Sequence[UINT32],
        Sequence[UINT64],
        Sequence[UINT8],
    )

    T_SequenceInsert = TypeVar(
        "T_SequenceInsert",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    I_SequenceInsert = TypeVar("I_SequenceInsert", INT32, INT64)

    def SequenceInsert(
        self,
        input_sequence: S_SequenceInsert,
        tensor: T_SequenceInsert,
        position: Optional[I_SequenceInsert] = None,
    ) -> S_SequenceInsert:
        r"""[🌐 SequenceInsert(11)](https://onnx.ai/onnx/operators/onnx__SequenceInsert.html#sequenceinsert-11 "Online Documentation")


        Outputs a tensor sequence that inserts 'tensor' into 'input_sequence' at 'position'.
        'tensor' must have the same data type as 'input_sequence'.
        Accepted range for 'position' is in `[-n, n]`, where `n` is the number of tensors in 'input_sequence'.
        Negative value means counting positions from the back.
        'position' is optional, by default it inserts 'tensor' to the back of 'input_sequence'.


        Args:
            input_sequence: Input sequence.

            tensor: Input tensor to be inserted into the input sequence.

            position: (optional) Position in the sequence where the new tensor is
                inserted. It is optional and default is to insert to the back of the
                sequence. Negative value means counting positions from the back.
                Accepted range in `[-n, n]`, where `n` is the number of tensors in
                'input_sequence'. It is an error if any of the index values are out of
                bounds. It must be a scalar(tensor of empty shape).
        """

        schema = get_schema("SequenceInsert", 11, "")
        op = Op(self, "SequenceInsert", schema)
        return op(*self._prepare_inputs(schema, input_sequence, tensor, position))

    S_SequenceLength = TypeVar(
        "S_SequenceLength",
        Sequence[BOOL],
        Sequence[COMPLEX128],
        Sequence[COMPLEX64],
        Sequence[DOUBLE],
        Sequence[FLOAT],
        Sequence[FLOAT16],
        Sequence[INT16],
        Sequence[INT32],
        Sequence[INT64],
        Sequence[INT8],
        Sequence[STRING],
        Sequence[UINT16],
        Sequence[UINT32],
        Sequence[UINT64],
        Sequence[UINT8],
    )

    I_SequenceLength: TypeAlias = INT64

    def SequenceLength(self, input_sequence: S_SequenceLength) -> I_SequenceLength:
        r"""[🌐 SequenceLength(11)](https://onnx.ai/onnx/operators/onnx__SequenceLength.html#sequencelength-11 "Online Documentation")


        Produces a scalar(tensor of empty shape) containing the number of tensors in 'input_sequence'.


        Args:
            input_sequence: Input sequence.
        """

        schema = get_schema("SequenceLength", 11, "")
        op = Op(self, "SequenceLength", schema)
        return op(*self._prepare_inputs(schema, input_sequence))

    T_Slice = TypeVar(
        "T_Slice",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    Tind_Slice = TypeVar("Tind_Slice", INT32, INT64)

    def Slice(
        self,
        data: T_Slice,
        starts: Tind_Slice,
        ends: Tind_Slice,
        axes: Optional[Tind_Slice] = None,
        steps: Optional[Tind_Slice] = None,
    ) -> T_Slice:
        r"""[🌐 Slice(11)](https://onnx.ai/onnx/operators/onnx__Slice.html#slice-11 "Online Documentation")


        Produces a slice of the input tensor along multiple axes. Similar to numpy:
        https://numpy.org/doc/stable/reference/routines.indexing.html
        Slices uses `starts`, `ends`, `axes` and `steps` inputs to specify the start and end
        dimension and step for each axis in the list of axes, it uses this information to
        slice the input `data` tensor. If a negative value is passed for any of the
        start or end indices, it represents number of elements before the end of that
        dimension. If the value passed to start or end is larger than the `n` (the
        number of elements in this dimension), it represents `n`. For slicing to the
        end of a dimension with unknown size, it is recommended to pass in `INT_MAX`
        when slicing forward and 'INT_MIN' when slicing backward.
        If a negative value is passed for step, it represents slicing backward.
        However step value cannot be 0.
        If `axes` are omitted, they are set to `[0, ..., ndim-1]`.
        If `steps` are omitted, they are set to `[1, ..., 1]` of length `len(starts)`
        Example 1:
          data = [
              [1, 2, 3, 4],
              [5, 6, 7, 8],
          ]
          axes = [0, 1]
          starts = [1, 0]
          ends = [2, 3]
          steps = [1, 2]
          result = [
              [5, 7],
          ]
        Example 2:
          data = [
              [1, 2, 3, 4],
              [5, 6, 7, 8],
          ]
          starts = [0, 1]
          ends = [-1, 1000]
          result = [
              [2, 3, 4],
          ]


        Args:
            data: Tensor of data to extract slices from.

            starts: 1-D tensor of starting indices of corresponding axis in `axes`

            ends: 1-D tensor of ending indices (exclusive) of corresponding axis in
                `axes`

            axes: (optional) 1-D tensor of axes that `starts` and `ends` apply to.
                Negative value means counting dimensions from the back. Accepted range
                is [-r, r-1] where r = rank(data).

            steps: (optional) 1-D tensor of slice step of corresponding axis in `axes`.
                Negative value means slicing backward. 'steps' cannot be 0. Defaults to
                1.
        """

        schema = get_schema("Slice", 11, "")
        op = Op(self, "Slice", schema)
        return op(*self._prepare_inputs(schema, data, starts, ends, axes, steps))

    T_Softmax = TypeVar("T_Softmax", DOUBLE, FLOAT, FLOAT16)

    def Softmax(self, input: T_Softmax, *, axis: int = 1) -> T_Softmax:
        r"""[🌐 Softmax(11)](https://onnx.ai/onnx/operators/onnx__Softmax.html#softmax-11 "Online Documentation")


        The operator computes the softmax (normalized exponential) values for each layer in the batch
         of the given input.

        The input does not need to explicitly be a 2D vector; rather, it will be
        coerced into one. For an arbitrary n-dimensional tensor
        input \in [a_0, a_1, ..., a_{k-1}, a_k, ..., a_{n-1}] and k is
        the axis provided, then input will be coerced into a 2-dimensional tensor with
        dimensions [a_0 * ... * a_{k-1}, a_k * ... * a_{n-1}]. For the default
        case where axis=1, this means the input tensor will be coerced into a 2D tensor
        of dimensions [a_0, a_1 * ... * a_{n-1}], where a_0 is often the batch size.
        In this situation, we must have a_0 = N and a_1 * ... * a_{n-1} = D.
        Each of these dimensions must be matched correctly, or else the operator
        will throw errors. The output tensor has the same shape
        and contains the softmax values of the corresponding input.


        Args:
            input: The input tensor that's coerced into a 2D matrix of size (NxD) as
                described above.

            axis: Describes the axis of the inputs when coerced to 2D; defaults to one
                because the 0th axis most likely describes the batch_size. Negative
                value means counting dimensions from the back. Accepted range is [-r,
                r-1] where r = rank(input).
        """

        schema = get_schema("Softmax", 11, "")
        op = Op(self, "Softmax", schema)
        return op(*self._prepare_inputs(schema, input), axis=axis)

    T_Split = TypeVar(
        "T_Split",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Split(
        self, input: T_Split, *, axis: int = 0, split: Optional[Sequence[int]] = None
    ) -> T_Split:
        r"""[🌐 Split(11)](https://onnx.ai/onnx/operators/onnx__Split.html#split-11 "Online Documentation")

        Split a tensor into a list of tensors, along the specified
        'axis'. Lengths of the parts can be specified using argument 'split'.
        Otherwise, the tensor is split to equal sized parts.


        Args:
            input: The tensor to split

            axis: Which axis to split on. A negative value means counting dimensions
                from the back. Accepted range is [-rank, rank-1] where r = rank(input).

            split: length of each output. Values should be >= 0.
        """

        schema = get_schema("Split", 11, "")
        op = Op(self, "Split", schema)
        return op(*self._prepare_inputs(schema, input), axis=axis, split=split)

    T_SplitToSequence = TypeVar(
        "T_SplitToSequence",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    I_SplitToSequence = TypeVar("I_SplitToSequence", INT32, INT64)

    S_SplitToSequence: TypeAlias = Union[
        Sequence[BOOL],
        Sequence[COMPLEX128],
        Sequence[COMPLEX64],
        Sequence[DOUBLE],
        Sequence[FLOAT],
        Sequence[FLOAT16],
        Sequence[INT16],
        Sequence[INT32],
        Sequence[INT64],
        Sequence[INT8],
        Sequence[STRING],
        Sequence[UINT16],
        Sequence[UINT32],
        Sequence[UINT64],
        Sequence[UINT8],
    ]

    def SplitToSequence(
        self,
        input: T_SplitToSequence,
        split: Optional[I_SplitToSequence] = None,
        *,
        axis: int = 0,
        keepdims: int = 1,
    ) -> S_SplitToSequence:
        r"""[🌐 SplitToSequence(11)](https://onnx.ai/onnx/operators/onnx__SplitToSequence.html#splittosequence-11 "Online Documentation")


        Split a tensor into a sequence of tensors, along the specified 'axis'.
        Lengths of the parts can be specified using the optional argument 'split'.
        If the argument `split' is not specified, a default scalar value of 1
        is used as the value of `split'.
        'split' must contain only positive numbers.
        'split' is either a scalar (tensor of empty shape), or a 1-D tensor.
        If 'split' is a scalar, then 'input' will be split into chunks all of size 'split'
        if possible. The last chunk alone may be smaller than 'split' if the 'input' size
        along the given axis 'axis' is not divisible by 'split'.
        If 'split' is a 1-dimensional tensor, the input tensor is split into 'size(split)' chunks,
        with lengths of the parts on 'axis' specified in 'split'. In this scenario, the sum of entries
        in 'split' must be equal to the dimension size of input tensor on 'axis'.


        Args:
            input: The tensor to split

            split: (optional) Length of each output. It can be either a scalar(tensor of
                empty shape), or a 1-D tensor. All values must be >= 0.

            axis: Which axis to split on. A negative value means counting dimensions
                from the back. Accepted range is [-rank, rank-1].

            keepdims: Keep the split dimension or not. Default 1, which means we keep
                split dimension. If input 'split' is specified, this attribute is
                ignored.
        """

        schema = get_schema("SplitToSequence", 11, "")
        op = Op(self, "SplitToSequence", schema)
        return op(*self._prepare_inputs(schema, input, split), axis=axis, keepdims=keepdims)

    T_Squeeze = TypeVar(
        "T_Squeeze",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Squeeze(self, data: T_Squeeze, *, axes: Optional[Sequence[int]] = None) -> T_Squeeze:
        r"""[🌐 Squeeze(11)](https://onnx.ai/onnx/operators/onnx__Squeeze.html#squeeze-11 "Online Documentation")


        Remove single-dimensional entries from the shape of a tensor.
        Takes a  parameter `axes` with a list of axes to squeeze.
        If `axes` is not provided, all the single dimensions will be removed from
        the shape. If an axis is selected with shape entry not equal to one, an error is raised.


        Args:
            data: Tensors with at least max(dims) dimensions.

            axes: List of integers indicating the dimensions to squeeze. Negative value
                means counting dimensions from the back. Accepted range is [-r, r-1]
                where r = rank(data).
        """

        schema = get_schema("Squeeze", 11, "")
        op = Op(self, "Squeeze", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes)

    T_TopK = TypeVar(
        "T_TopK",
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    I_TopK: TypeAlias = INT64

    def TopK(
        self, X: T_TopK, K: INT64, *, axis: int = -1, largest: int = 1, sorted: int = 1
    ) -> Tuple[T_TopK, I_TopK]:
        r"""[🌐 TopK(11)](https://onnx.ai/onnx/operators/onnx__TopK.html#topk-11 "Online Documentation")


        Retrieve the top-K largest or smallest elements along a specified axis. Given an input tensor of
        shape [a_0, a_1, ..., a_{n-1}] and integer argument k, return two outputs:

        * Value tensor of shape [a_0, a_1, ..., a_{axis-1}, k, a_{axis+1}, ... a_{n-1}]
          which contains the values of the top k elements along the specified axis
        * Index tensor of shape [a_0, a_1, ..., a_{axis-1}, k, a_{axis+1}, ... a_{n-1}] which
          contains the indices of the top k elements (original indices from the input
          tensor).

        * If "largest" is 1 (the default value) then the k largest elements are returned.
        * If "sorted" is 1 (the default value) then the resulting k elements will be sorted.
        * If "sorted" is 0, order of returned 'Values' and 'Indices' are undefined.

        Given two equivalent values, this operator uses the indices along the axis as
        a tiebreaker. That is, the element with the lower index will appear first.


        Args:
            X: (differentiable) Tensor of shape [a_0, a_1, ..., a_{n-1}]

            K: (non-differentiable) A 1-D tensor containing a single positive value
                corresponding to the number of top elements to retrieve

            axis: Dimension on which to do the sort. Negative value means counting
                dimensions from the back. Accepted range is [-r, r-1] where r =
                rank(input).

            largest: Whether to return the top-K largest or smallest elements.

            sorted: Whether to return the elements in sorted order.
        """

        schema = get_schema("TopK", 11, "")
        op = Op(self, "TopK", schema)
        return op(
            *self._prepare_inputs(schema, X, K),
            axis=axis,
            largest=largest,
            sorted=sorted,
        )

    T_Unique = TypeVar(
        "T_Unique",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Unique(
        self, X: T_Unique, *, axis: Optional[int] = None, sorted: int = 1
    ) -> Tuple[T_Unique, INT64, INT64, INT64]:
        r"""[🌐 Unique(11)](https://onnx.ai/onnx/operators/onnx__Unique.html#unique-11 "Online Documentation")


        Find the unique elements of a tensor. When an optional attribute 'axis' is provided, unique subtensors sliced along the 'axis' are returned.
        Otherwise the input tensor is flattened and unique values of the flattened tensor are returned.

        This operator returns the unique values or sliced unique subtensors of the input tensor and three optional outputs.
        The first output tensor 'Y' contains all unique values or subtensors of the input.
        The second optional output tensor 'indices' contains indices of 'Y' elements' first occurrence in 'X'.
        The third optional output tensor 'inverse_indices' contains, for elements of 'X', its corresponding indices in 'Y'.
        The fourth optional output tensor 'counts' contains the count of each element of 'Y' in the input.

        Outputs are either sorted in ascending order or optionally in the order of the first occurrence of the values in the input.

        https://docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html

        Example 1:
        ::

            input_X = [2, 1, 1, 3, 4, 3]
            attribute_sorted = 0
            attribute_axis = None
            output_Y = [2, 1, 3, 4]
            output_indices = [0, 1, 3, 4]
            output_inverse_indices = [0, 1, 1, 2, 3, 2]
            output_counts = [1, 2, 2, 1]



        Example 2:
        ::

            input_X = [[1, 3], [2, 3]]
            attribute_sorted = 1
            attribute_axis = None
            output_Y = [1, 2, 3]
            output_indices = [0, 2, 1]
            output_inverse_indices = [0, 2, 1, 2]
            output_counts = [1, 1, 2]



        Example 3:
        ::

            input_X = [[1, 0, 0], [1, 0, 0], [2, 3, 4]]
            attribute_sorted = 1
            attribute_axis = 0
            output_Y = [[1, 0, 0], [2, 3, 4]]
            output_indices = [0, 2]
            output_inverse_indices = [0, 0, 1]
            output_counts = [2, 1]



        Example 4:
        ::

            input_x = [[[1., 1.], [0., 1.], [2., 1.], [0., 1.]],
                        [[1., 1.], [0., 1.], [2., 1.], [0., 1.]]]
            attribute_sorted = 1
            attribute_axis = 1



        intermediate data are presented below for better understanding:
        there are 4 subtensors sliced along axis 1 of input_x (shape = (2, 4, 2)):
        ::

            A: [[1, 1], [1, 1]],
               [[0, 1], [0, 1]],
               [[2, 1], [2, 1]],
               [[0, 1], [0, 1]].



        there are 3 unique subtensors:
        ::

            [[1, 1], [1, 1]],
            [[0, 1], [0, 1]],
            [[2, 1], [2, 1]].



        sorted unique subtensors:
        ::

            B: [[0, 1], [0, 1]],
               [[1, 1], [1, 1]],
               [[2, 1], [2, 1]].



        output_Y is constructed from B:
        ::

            [[[0. 1.], [1. 1.], [2. 1.]],
             [[0. 1.], [1. 1.], [2. 1.]]]



        output_indices is to map from B to A:
        ::

            [1, 0, 2]



        output_inverse_indices is to map from A to B:
        ::

            [1, 0, 2, 0]



        output_counts:
        ::

            [2, 1, 1]




        Args:
            X: (non-differentiable) A N-D input tensor that is to be processed.

            axis: (Optional) The dimension to apply unique. If not specified, the unique
                elements of the flattened input are returned. Negative value means
                counting dimensions from the back. Accepted range is [-r, r-1] where r =
                rank(input).

            sorted: (Optional) Whether to sort the unique elements in ascending order
                before returning as output. Must be one of 0, or 1 (default).
        """

        schema = get_schema("Unique", 11, "")
        op = Op(self, "Unique", schema)
        return op(*self._prepare_inputs(schema, X), axis=axis, sorted=sorted)

    T_Unsqueeze = TypeVar(
        "T_Unsqueeze",
        BOOL,
        COMPLEX128,
        COMPLEX64,
        DOUBLE,
        FLOAT,
        FLOAT16,
        INT16,
        INT32,
        INT64,
        INT8,
        STRING,
        UINT16,
        UINT32,
        UINT64,
        UINT8,
    )

    def Unsqueeze(self, data: T_Unsqueeze, *, axes: Sequence[int]) -> T_Unsqueeze:
        r"""[🌐 Unsqueeze(11)](https://onnx.ai/onnx/operators/onnx__Unsqueeze.html#unsqueeze-11 "Online Documentation")


        Insert single-dimensional entries to the shape of an input tensor (`data`).
        Takes one required argument `axes` - which contains a list of dimension indices and this operator will insert a dimension of value `1` into the corresponding index of the output tensor (`expanded`).

        For example:
          Given an input tensor (`data`) of shape [3, 4, 5], then
          Unsqueeze(data, axes=[0, 4]) outputs a tensor (`expanded`) containing same data as `data` but with shape [1, 3, 4, 5, 1].

        The attribute `axes` should not contain any duplicate entries. It is an error if it contains duplicates.
        The rank of the output tensor (`output_rank`) is the rank of the input tensor (`data`) plus the number of values in `axes`.
        Each value in `axes` should be within the (inclusive) range [-output_rank , output_rank - 1].
        The order of values in `axes` does not matter and can come in any order.



        Args:
            data: Original tensor

            axes: List of integers indicating the dimensions to be inserted. Negative
                value means counting dimensions from the back. Accepted range is [-r,
                r-1] where r = rank(expanded).
        """

        schema = get_schema("Unsqueeze", 11, "")
        op = Op(self, "Unsqueeze", schema)
        return op(*self._prepare_inputs(schema, data), axes=axes)
