from eddl.layers.base import Layer


class Conv2DTranspose(Layer):
    """Transposed convolution layer (sometimes called Deconvolution).

    The need for transposed convolutions generally arises
    from the desire to use a transformation going in the opposite direction
    of a normal convolution, i.e., from something that has the shape of the
    output of some convolution to something that has the shape of its input
    while maintaining a connectivity pattern that is compatible with
    said convolution.
    When using this layer as the first layer in a model,
    provide the keyword argument `input_shape`
    (tuple of integers, does not include the batch axis),
    e.g. `input_shape=(128, 128, 3)` for 128x128 RGB pictures
    in `data_format="channels_last"`.

    Args:
        filters: Integer, the dimensionality of the output space
            (i.e. the number of output filters in the convolution).
        kernel_size: An integer or tuple/list of 2 integers, specifying the
            height and width of the 2D convolution window.
            Can be a single integer to specify the same value for
            all spatial dimensions.
        strides: An integer or tuple/list of 2 integers,
            specifying the strides of the convolution
            along the height and width.
            Can be a single integer to specify the same value for
            all spatial dimensions.
            Specifying any stride value != 1 is incompatible with specifying
            any `dilation_rate` value != 1.
        padding: one of `"valid"` or `"same"` (case-insensitive).
        output_padding: An integer or tuple/list of 2 integers,
            specifying the amount of padding along the height and width
            of the output tensor.
            Can be a single integer to specify the same value for all
            spatial dimensions.
            The amount of output padding along a given dimension must be
            lower than the stride along that same dimension.
            If set to `None` (default), the output shape is inferred.
        data_format: A string,
            one of `"channels_last"` or `"channels_first"`.
            The ordering of the dimensions in the inputs.
            `"channels_last"` corresponds to inputs with shape
            `(batch, height, width, channels)` while `"channels_first"`
            corresponds to inputs with shape
            `(batch, channels, height, width)`.
            It defaults to the `image_data_format` value found in your
        dilation_rate: an integer or tuple/list of 2 integers, specifying
            the dilation rate to use for dilated convolution.
            Can be a single integer to specify the same value for
            all spatial dimensions.
            Currently, specifying any `dilation_rate` value != 1 is
            incompatible with specifying any stride value != 1.
        activation: Activation function to use
            If you don't specify anything, no activation is applied
            (ie. "linear" activation: `a(x) = x`).
        use_bias: Boolean, whether the layer uses a bias vector.
        kernel_initializer: Initializer for the `kernel` weights matrix
        bias_initializer: Initializer for the bias vector
        kernel_regularizer: Regularizer function applied to
            the `kernel` weights matrix
        bias_regularizer: Regularizer function applied to the bias vector
        activity_regularizer: Regularizer function applied to
            the output of the layer (its "activation").
        kernel_constraint: Constraint function applied to the kernel matrix
        bias_constraint: Constraint function applied to the bias vector

    Input shape:
        4D tensor with shape:
        `(batch, channels, rows, cols)`
        if `data_format` is `"channels_first"`
        or 4D tensor with shape:
        `(batch, rows, cols, channels)`
        if `data_format` is `"channels_last"`.

    Output shape:
        4D tensor with shape:
        `(batch, filters, new_rows, new_cols)`
        if `data_format` is `"channels_first"`
        or 4D tensor with shape:
        `(batch, new_rows, new_cols, filters)`
        if `data_format` is `"channels_last"`.
        `rows` and `cols` values might have changed due to padding.
        If `output_padding` is specified:
        ```
        new_rows = ((rows - 1) * strides[0] + kernel_size[0]
                    - 2 * padding[0] + output_padding[0])
        new_cols = ((cols - 1) * strides[1] + kernel_size[1]
                    - 2 * padding[1] + output_padding[1])
        ```

    References
        - [A guide to convolution arithmetic for deep learning](
           https://arxiv.org/abs/1603.07285v1)
        - [Deconvolutional Networks](
           https://www.matthewzeiler.com/mattzeiler/deconvolutionalnetworks.pdf)

    """

    def __init__(self, filters,
                 kernel_size,
                 strides=(1, 1),
                 padding='valid',
                 output_padding=None,
                 data_format=None,
                 dilation_rate=(1, 1),
                 activation=None,
                 use_bias=True,
                 kernel_initializer='glorot_uniform',
                 bias_initializer='zeros',
                 kernel_regularizer=None,
                 bias_regularizer=None,
                 activity_regularizer=None,
                 kernel_constraint=None,
                 bias_constraint=None,
                 **kwargs):
        super(Conv2DTranspose, self).__init__()

from eddl.layers.base import Layer


class Conv2DTranspose(Layer):
    """Transposed convolution layer (sometimes called Deconvolution).

    The need for transposed convolutions generally arises
    from the desire to use a transformation going in the opposite direction
    of a normal convolution, i.e., from something that has the shape of the
    output of some convolution to something that has the shape of its input
    while maintaining a connectivity pattern that is compatible with
    said convolution.
    When using this layer as the first layer in a model,
    provide the keyword argument `input_shape`
    (tuple of integers, does not include the batch axis),
    e.g. `input_shape=(128, 128, 3)` for 128x128 RGB pictures
    in `data_format="channels_last"`.

    Args:
        filters: Integer, the dimensionality of the output space
            (i.e. the number of output filters in the convolution).
        kernel_size: An integer or tuple/list of 2 integers, specifying the
            height and width of the 2D convolution window.
            Can be a single integer to specify the same value for
            all spatial dimensions.
        strides: An integer or tuple/list of 2 integers,
            specifying the strides of the convolution
            along the height and width.
            Can be a single integer to specify the same value for
            all spatial dimensions.
            Specifying any stride value != 1 is incompatible with specifying
            any `dilation_rate` value != 1.
        padding: one of `"valid"` or `"same"` (case-insensitive).
        output_padding: An integer or tuple/list of 2 integers,
            specifying the amount of padding along the height and width
            of the output tensor.
            Can be a single integer to specify the same value for all
            spatial dimensions.
            The amount of output padding along a given dimension must be
            lower than the stride along that same dimension.
            If set to `None` (default), the output shape is inferred.
        data_format: A string,
            one of `"channels_last"` or `"channels_first"`.
            The ordering of the dimensions in the inputs.
            `"channels_last"` corresponds to inputs with shape
            `(batch, height, width, channels)` while `"channels_first"`
            corresponds to inputs with shape
            `(batch, channels, height, width)`.
            It defaults to the `image_data_format` value found in your
        dilation_rate: an integer or tuple/list of 2 integers, specifying
            the dilation rate to use for dilated convolution.
            Can be a single integer to specify the same value for
            all spatial dimensions.
            Currently, specifying any `dilation_rate` value != 1 is
            incompatible with specifying any stride value != 1.
        activation: Activation function to use
            If you don't specify anything, no activation is applied
            (ie. "linear" activation: `a(x) = x`).
        use_bias: Boolean, whether the layer uses a bias vector.
        kernel_initializer: Initializer for the `kernel` weights matrix
        bias_initializer: Initializer for the bias vector
        kernel_regularizer: Regularizer function applied to
            the `kernel` weights matrix
        bias_regularizer: Regularizer function applied to the bias vector
        activity_regularizer: Regularizer function applied to
            the output of the layer (its "activation").
        kernel_constraint: Constraint function applied to the kernel matrix
        bias_constraint: Constraint function applied to the bias vector

    Input shape:
        4D tensor with shape:
        `(batch, channels, rows, cols)`
        if `data_format` is `"channels_first"`
        or 4D tensor with shape:
        `(batch, rows, cols, channels)`
        if `data_format` is `"channels_last"`.

    Output shape:
        4D tensor with shape:
        `(batch, filters, new_rows, new_cols)`
        if `data_format` is `"channels_first"`
        or 4D tensor with shape:
        `(batch, new_rows, new_cols, filters)`
        if `data_format` is `"channels_last"`.
        `rows` and `cols` values might have changed due to padding.
        If `output_padding` is specified:
        ```
        new_rows = ((rows - 1) * strides[0] + kernel_size[0]
                    - 2 * padding[0] + output_padding[0])
        new_cols = ((cols - 1) * strides[1] + kernel_size[1]
                    - 2 * padding[1] + output_padding[1])
        ```

    References
        - [A guide to convolution arithmetic for deep learning](
           https://arxiv.org/abs/1603.07285v1)
        - [Deconvolutional Networks](
           https://www.matthewzeiler.com/mattzeiler/deconvolutionalnetworks.pdf)

    """

    def __init__(self, filters,
                 kernel_size,
                 strides=(1, 1),
                 padding='valid',
                 output_padding=None,
                 data_format=None,
                 dilation_rate=(1, 1),
                 activation=None,
                 use_bias=True,
                 kernel_initializer='glorot_uniform',
                 bias_initializer='zeros',
                 kernel_regularizer=None,
                 bias_regularizer=None,
                 activity_regularizer=None,
                 kernel_constraint=None,
                 bias_constraint=None,
                 **kwargs):
        super(Conv2DTranspose, self).__init__()

Transposed convolution layer (sometimes called Deconvolution).      The need for transposed convolutions generally arises     from the desire to use a transformation going in the opposite direction     of a normal convolution, i.e., from something that has the shape of the     output of some convolution to something that has the shape of its input     while maintaining a connectivity pattern that is compatible with     said convolution.     When using this layer as the first layer in a model,     provide the keyword argument `input_shape`     (tuple of integers, does not include the batch axis),     e.g. `input_shape=(128, 128, 3)` for 128x128 RGB pictures     in `data_format="channels_last"`.      Args:         filters: Integer, the dimensionality of the output space             (i.e. the number of output filters in the convolution).         kernel_size: An integer or tuple/list of 2 integers, specifying the             height and width of the 2D convolution window.             Can be a single integer to specify the same value for             all spatial dimensions.         strides: An integer or tuple/list of 2 integers,             specifying the strides of the convolution             along the height and width.             Can be a single integer to specify the same value for             all spatial dimensions.             Specifying any stride value != 1 is incompatible with specifying             any `dilation_rate` value != 1.         padding: one of `"valid"` or `"same"` (case-insensitive).         output_padding: An integer or tuple/list of 2 integers,             specifying the amount of padding along the height and width             of the output tensor.             Can be a single integer to specify the same value for all             spatial dimensions.             The amount of output padding along a given dimension must be             lower than the stride along that same dimension.             If set to `None` (default), the output shape is inferred.         data_format: A string,             one of `"channels_last"` or `"channels_first"`.             The ordering of the dimensions in the inputs.             `"channels_last"` corresponds to inputs with shape             `(batch, height, width, channels)` while `"channels_first"`             corresponds to inputs with shape             `(batch, channels, height, width)`.             It defaults to the `image_data_format` value found in your         dilation_rate: an integer or tuple/list of 2 integers, specifying             the dilation rate to use for dilated convolution.             Can be a single integer to specify the same value for             all spatial dimensions.             Currently, specifying any `dilation_rate` value != 1 is             incompatible with specifying any stride value != 1.         activation: Activation function to use             If you don't specify anything, no activation is applied             (ie. "linear" activation: `a(x) = x`).         use_bias: Boolean, whether the layer uses a bias vector.         kernel_initializer: Initializer for the `kernel` weights matrix         bias_initializer: Initializer for the bias vector         kernel_regularizer: Regularizer function applied to             the `kernel` weights matrix         bias_regularizer: Regularizer function applied to the bias vector         activity_regularizer: Regularizer function applied to             the output of the layer (its "activation").         kernel_constraint: Constraint function applied to the kernel matrix         bias_constraint: Constraint function applied to the bias vector      Input shape:         4D tensor with shape:         `(batch, channels, rows, cols)`         if `data_format` is `"channels_first"`         or 4D tensor with shape:         `(batch, rows, cols, channels)`         if `data_format` is `"channels_last"`.      Output shape:         4D tensor with shape:         `(batch, filters, new_rows, new_cols)`         if `data_format` is `"channels_first"`         or 4D tensor with shape:         `(batch, new_rows, new_cols, filters)`         if `data_format` is `"channels_last"`.         `rows` and `cols` values might have changed due to padding.         If `output_padding` is specified:         ```         new_rows = ((rows - 1) * strides[0] + kernel_size[0]                     - 2 * padding[0] + output_padding[0])         new_cols = ((cols - 1) * strides[1] + kernel_size[1]                     - 2 * padding[1] + output_padding[1])         ```      References         - [A guide to convolution arithmetic for deep learning](            https://arxiv.org/abs/1603.07285v1)         - [Deconvolutional Networks](            https://www.matthewzeiler.com/mattzeiler/deconvolutionalnetworks.pdf)