# Path: hamaa/utils/np_utils.py
# def eval_numerical_gradient_array(f, x, df=None, verbose=False, h=1e-4):
#     it = np.nditer(x, flags=['multi_index'])
#     grad = np.zeros_like(x)
#     while not it.finished:
#         xi = it.multi_index
#         old_val = x[xi]
# 
#         x[xi] = old_val + h
#         y_top = f(x)
# 
#         x[xi] = old_val - h
#         y_bottom = f(x)
# 
#         if df is not None:
#             grad[xi] = np.sum((y_top - y_bottom) * df) / (2 * h)
#         else:
#             grad[xi] = np.sum(y_top - y_bottom) / (2 * h)
# 
#         if verbose:
#             print it.multi_index, grad[xi]
#         x[xi] = old_val
#         it.iternext()
# 
#     return grad
# 
# def sum_abs_err(u, v):
#     return np.sum(np.abs(u - v))


from hamaa.gates import *
from hamaa.layers import *
from hamaa.utils.np_utils import eval_numerical_gradient_array, sum_abs_err
    print np.sum(np.abs(grad_x - dx))
    print np.sum(np.abs(grad_w - dw))


def check_AddGate():
    x = np.random.randn(10, 3)
    # b = np.random.randn(1, 3)
    b = np.random.randn(1, 1)
    df = np.random.randn(10, 3)
    grad_x = eval_numerical_gradient_array(lambda t: AddGate.forward(t, b), x, df)
    grad_b = eval_numerical_gradient_array(lambda t: AddGate.forward(x, t), b, df)
    dx, db = AddGate.backward(x, b, df)
    print sum_abs_err(grad_x, dx)
    print sum_abs_err(grad_b, db)


def check_SigmoidGate():
    x = np.random.randn(10, 4)
    df = np.random.randn(10, 4)

    grad_x = eval_numerical_gradient_array(SigmoidGate.forward, x, df)
    dx = SigmoidGate.backward(x, df)

    print sum_abs_err(grad_x, dx)


def check_TanhGate():
    x = np.random.randn(10, 4)
    df = np.random.randn(10, 4)


# Path: hamaa/utils/np_utils.py
# def eval_numerical_gradient_array(f, x, df=None, verbose=False, h=1e-4):
#     it = np.nditer(x, flags=['multi_index'])
#     grad = np.zeros_like(x)
#     while not it.finished:
#         xi = it.multi_index
#         old_val = x[xi]
# 
#         x[xi] = old_val + h
#         y_top = f(x)
# 
#         x[xi] = old_val - h
#         y_bottom = f(x)
# 
#         if df is not None:
#             grad[xi] = np.sum((y_top - y_bottom) * df) / (2 * h)
#         else:
#             grad[xi] = np.sum(y_top - y_bottom) / (2 * h)
# 
#         if verbose:
#             print it.multi_index, grad[xi]
#         x[xi] = old_val
#         it.iternext()
# 
#     return grad
# 
# def sum_abs_err(u, v):
#     return np.sum(np.abs(u - v))


# Path: hamaa/tests/check_gradient.py
from hamaa.gates import *
from hamaa.layers import *
from hamaa.utils.np_utils import eval_numerical_gradient_array, sum_abs_err

    print np.sum(np.abs(grad_x - dx))
    print np.sum(np.abs(grad_w - dw))


def check_AddGate():
    x = np.random.randn(10, 3)
    # b = np.random.randn(1, 3)
    b = np.random.randn(1, 1)
    df = np.random.randn(10, 3)
    grad_x = eval_numerical_gradient_array(lambda t: AddGate.forward(t, b), x, df)
    grad_b = eval_numerical_gradient_array(lambda t: AddGate.forward(x, t), b, df)
    dx, db = AddGate.backward(x, b, df)
    print sum_abs_err(grad_x, dx)
    print sum_abs_err(grad_b, db)


def check_SigmoidGate():
    x = np.random.randn(10, 4)
    df = np.random.randn(10, 4)

    grad_x = eval_numerical_gradient_array(SigmoidGate.forward, x, df)
    dx = SigmoidGate.backward(x, df)

    print sum_abs_err(grad_x, dx)


def check_TanhGate():
    x = np.random.randn(10, 4)
    df = np.random.randn(10, 4)


    grad_x = eval_numerical_gradient_array(TanhGate.forward, x, df)