# Path: deeppy/feedforward/layers.py
# class Layer(PickleMixin):
#     bprop_to_x = True
# 
#     def setup(self, x_shape):
#         """ Setup layer with parameters that are unknown at __init__(). """
#         pass
# 
#     def fprop(self, x):
#         """ Calculate layer output for given input (forward propagation). """
#         raise NotImplementedError()
# 
#     def bprop(self, y_grad):
#         """ Calculate input gradient. """
#         raise NotImplementedError()
# 
#     def y_shape(self, x_shape):
#         """ Calculate shape of this layer's output.
#         x_shape[0] is the number of samples in the input.
#         x_shape[1:] is the shape of the feature.
#         """
#         raise NotImplementedError()
# 
# Path: deeppy/base.py
# class PhaseMixin(object):
#     _phase = None
# 
#     @property
#     def phase(self):
#         return self._phase
# 
#     @phase.setter
#     def phase(self, phase):
#         self._phase = phase


import cudarray as ca
from .layers import Layer
from ..base import PhaseMixin


class Dropout(Layer, PhaseMixin):
    def __init__(self, dropout=0.5):
        self.dropout = dropout
        self._tmp_mask = None

    def fprop(self, x):
        if self.dropout > 0.0:
            if self.phase == 'train':
                self._tmp_mask = self.dropout < ca.random.uniform(size=x.shape)
                y = x * self._tmp_mask
            elif self.phase == 'test':
                y = x * (1.0 - self.dropout)
            else:
                raise ValueError('Invalid phase: %s' % self.phase)
        return y

    def bprop(self, y_grad):
        if self.dropout > 0.0:
            return y_grad * self._tmp_mask
        else:

# Path: deeppy/feedforward/layers.py
# class Layer(PickleMixin):
#     bprop_to_x = True
# 
#     def setup(self, x_shape):
#         """ Setup layer with parameters that are unknown at __init__(). """
#         pass
# 
#     def fprop(self, x):
#         """ Calculate layer output for given input (forward propagation). """
#         raise NotImplementedError()
# 
#     def bprop(self, y_grad):
#         """ Calculate input gradient. """
#         raise NotImplementedError()
# 
#     def y_shape(self, x_shape):
#         """ Calculate shape of this layer's output.
#         x_shape[0] is the number of samples in the input.
#         x_shape[1:] is the shape of the feature.
#         """
#         raise NotImplementedError()
# 
# Path: deeppy/base.py
# class PhaseMixin(object):
#     _phase = None
# 
#     @property
#     def phase(self):
#         return self._phase
# 
#     @phase.setter
#     def phase(self, phase):
#         self._phase = phase


# Path: deeppy/feedforward/dropout_layers.py
import cudarray as ca
from .layers import Layer
from ..base import PhaseMixin



class Dropout(Layer, PhaseMixin):
    def __init__(self, dropout=0.5):
        self.dropout = dropout
        self._tmp_mask = None

    def fprop(self, x):
        if self.dropout > 0.0:
            if self.phase == 'train':
                self._tmp_mask = self.dropout < ca.random.uniform(size=x.shape)
                y = x * self._tmp_mask
            elif self.phase == 'test':
                y = x * (1.0 - self.dropout)
            else:
                raise ValueError('Invalid phase: %s' % self.phase)
        return y

    def bprop(self, y_grad):
        if self.dropout > 0.0:
            return y_grad * self._tmp_mask
        else:

            return y_grad