# Path: deeppy/base.py
# class PickleMixin(object):
#     _pickle_ignore = ['_tmp_']
# 
#     def _pickle_discard(self, attr_name):
#         for s in self._pickle_ignore:
#             if attr_name.startswith(s):
#                 return True
#         return False
# 
#     def __getstate__(self):
#         return dict((k, None) if self._pickle_discard(k) else (k, v)
#                     for k, v in self.__dict__.items())


import numpy as np
import cudarray as ca
import deeppy
from ..base import PickleMixin
    def __call__(self, lhs, rhs):
        lhs = _require_op(lhs)
        rhs = _require_op(rhs)
        self.lhs = lhs
        self.rhs = rhs
        if isinstance(lhs, Constant) and isinstance(rhs, Constant):
            # Propagate constant
            self.setup()
            self.fprop()
            return Constant(self.array)
        self.inputs = [lhs, rhs]
        return self


class Broadcast(Unary):
    def __init__(self, shape, broadcast_shape):
        self.shape = shape
        self.broadcast_shape = broadcast_shape
        # XXX: axis and keepdims are not determined correctly
        self.axis = []
        for axis, (a_dim, b_dim) in enumerate(zip(shape, broadcast_shape)):
            if a_dim != b_dim:
                self.axis.append(axis)
        self.axis = tuple(self.axis)
        self.keepdims = True

    def setup(self):
        self.array = ca.zeros(self.shape)
        self.grad_array = ca.zeros(self.broadcast_shape)


# Path: deeppy/base.py
# class PickleMixin(object):
#     _pickle_ignore = ['_tmp_']
# 
#     def _pickle_discard(self, attr_name):
#         for s in self._pickle_ignore:
#             if attr_name.startswith(s):
#                 return True
#         return False
# 
#     def __getstate__(self):
#         return dict((k, None) if self._pickle_discard(k) else (k, v)
#                     for k, v in self.__dict__.items())


# Path: deeppy/expr/base.py
import numpy as np
import cudarray as ca
import deeppy
from ..base import PickleMixin

    def __call__(self, lhs, rhs):
        lhs = _require_op(lhs)
        rhs = _require_op(rhs)
        self.lhs = lhs
        self.rhs = rhs
        if isinstance(lhs, Constant) and isinstance(rhs, Constant):
            # Propagate constant
            self.setup()
            self.fprop()
            return Constant(self.array)
        self.inputs = [lhs, rhs]
        return self


class Broadcast(Unary):
    def __init__(self, shape, broadcast_shape):
        self.shape = shape
        self.broadcast_shape = broadcast_shape
        # XXX: axis and keepdims are not determined correctly
        self.axis = []
        for axis, (a_dim, b_dim) in enumerate(zip(shape, broadcast_shape)):
            if a_dim != b_dim:
                self.axis.append(axis)
        self.axis = tuple(self.axis)
        self.keepdims = True

    def setup(self):
        self.array = ca.zeros(self.shape)
        self.grad_array = ca.zeros(self.broadcast_shape)


    def fprop(self):