import pytest
import numpy as np
from numpy.testing import assert_allclose

from keras import backend as K
from keras import activations


def get_standard_values():
    '''
    These are just a set of floats used for testing the activation
    functions, and are useful in multiple tests.
    '''
    return np.array([[0, 0.1, 0.5, 0.9, 1.0]], dtype=K.floatx())


def test_softmax():
    '''
    Test using a reference implementation of softmax
    '''
    def softmax(values):
        m = np.max(values)
        e = np.exp(values - m)
        return e / np.sum(e)

    x = K.placeholder(ndim=2)
    f = K.function([x], [activations.softmax(x)])
    test_values = get_standard_values()

    result = f([test_values])[0]
    expected = softmax(test_values)
    assert_allclose(result, expected, rtol=1e-05)


def test_time_distributed_softmax():
    x = K.placeholder(shape=(1, 1, 5))
    f = K.function([x], [activations.softmax(x)])
    test_values = get_standard_values()
    test_values = np.reshape(test_values, (1, 1, np.size(test_values)))
    f([test_values])[0]


def test_softplus():
    '''
    Test using a reference softplus implementation
    '''
    def softplus(x):
        return np.log(np.ones_like(x) + np.exp(x))

    x = K.placeholder(ndim=2)
    f = K.function([x], [activations.softplus(x)])
    test_values = get_standard_values()

    result = f([test_values])[0]
    expected = softplus(test_values)
    assert_allclose(result, expected, rtol=1e-05)


def test_softsign():
    '''
    Test using a reference softsign implementation
    '''
    def softsign(x):
        return np.divide(x, np.ones_like(x) + np.absolute(x))

    x = K.placeholder(ndim=2)
    f = K.function([x], [activations.softsign(x)])
    test_values = get_standard_values()

    result = f([test_values])[0]
    expected = softsign(test_values)
    assert_allclose(result, expected, rtol=1e-05)


def test_sigmoid():
    '''
    Test using a numerically stable reference sigmoid implementation
    '''
    def ref_sigmoid(x):
        if x >= 0:
            return 1 / (1 + np.exp(-x))
        else:
            z = np.exp(x)
            return z / (1 + z)
    sigmoid = np.vectorize(ref_sigmoid)

    x = K.placeholder(ndim=2)
    f = K.function([x], [activations.sigmoid(x)])
    test_values = get_standard_values()

    result = f([test_values])[0]
    expected = sigmoid(test_values)
    assert_allclose(result, expected, rtol=1e-05)


def test_hard_sigmoid():
    '''
    Test using a reference hard sigmoid implementation
    '''
    def ref_hard_sigmoid(x):
        '''
        Reference hard sigmoid with slope and shift values from theano, see
        https://github.com/Theano/Theano/blob/master/theano/tensor/nnet/sigm.py
        '''
        x = (x * 0.2) + 0.5
        z = 0.0 if x <= 0 else (1.0 if x >= 1 else x)
        return z
    hard_sigmoid = np.vectorize(ref_hard_sigmoid)

    x = K.placeholder(ndim=2)
    f = K.function([x], [activations.hard_sigmoid(x)])
    test_values = get_standard_values()

    result = f([test_values])[0]
    expected = hard_sigmoid(test_values)
    assert_allclose(result, expected, rtol=1e-05)


def test_relu():
    '''
    Relu implementation doesn't depend on the value being
    a theano variable. Testing ints, floats and theano tensors.
    '''
    x = K.placeholder(ndim=2)
    f = K.function([x], [activations.relu(x)])

    test_values = get_standard_values()
    result = f([test_values])[0]

    # because no negatives in test values
    assert_allclose(result, test_values, rtol=1e-05)


def test_elu():
    x = K.placeholder(ndim=2)
    f = K.function([x], [activations.elu(x, 0.5)])

    test_values = get_standard_values()
    result = f([test_values])[0]

    # because no negatives in test values
    assert_allclose(result, test_values, rtol=1e-05)

    negative_values = np.array([[-1, -2]], dtype=K.floatx())
    result = f([negative_values])[0]
    true_result = (np.exp(negative_values) - 1) / 2

    assert_allclose(result, true_result)


def test_tanh():
    test_values = get_standard_values()

    x = K.placeholder(ndim=2)
    exp = activations.tanh(x)
    f = K.function([x], [exp])

    result = f([test_values])[0]
    expected = np.tanh(test_values)
    assert_allclose(result, expected, rtol=1e-05)


def test_linear():
    '''
    This function does no input validation, it just returns the thing
    that was passed in.
    '''
    xs = [1, 5, True, None, 'foo']
    for x in xs:
        assert(x == activations.linear(x))


if __name__ == '__main__':
    pytest.main([__file__])

[((26, 8, 26, 29), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((32, 4, 32, 49), 'numpy.testing.assert_allclose', 'assert_allclose', (), '', False, 'from numpy.testing import assert_allclose\n'), ((36, 8, 36, 38), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((50, 8, 50, 29), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((56, 4, 56, 49), 'numpy.testing.assert_allclose', 'assert_allclose', (), '', False, 'from numpy.testing import assert_allclose\n'), ((66, 8, 66, 29), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((72, 4, 72, 49), 'numpy.testing.assert_allclose', 'assert_allclose', (), '', False, 'from numpy.testing import assert_allclose\n'), ((85, 14, 85, 39), 'numpy.vectorize', 'np.vectorize', ({(85, 27, 85, 38): 'ref_sigmoid'}, {}), '(ref_sigmoid)', True, 'import numpy as np\n'), ((87, 8, 87, 29), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((93, 4, 93, 49), 'numpy.testing.assert_allclose', 'assert_allclose', (), '', False, 'from numpy.testing import assert_allclose\n'), ((108, 19, 108, 49), 'numpy.vectorize', 'np.vectorize', ({(108, 32, 108, 48): 'ref_hard_sigmoid'}, {}), '(ref_hard_sigmoid)', True, 'import numpy as np\n'), ((110, 8, 110, 29), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((116, 4, 116, 49), 'numpy.testing.assert_allclose', 'assert_allclose', (), '', False, 'from numpy.testing import assert_allclose\n'), ((124, 8, 124, 29), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((131, 4, 131, 52), 'numpy.testing.assert_allclose', 'assert_allclose', (), '', False, 'from numpy.testing import assert_allclose\n'), ((135, 8, 135, 29), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((142, 4, 142, 52), 'numpy.testing.assert_allclose', 'assert_allclose', (), '', False, 'from numpy.testing import assert_allclose\n'), ((148, 4, 148, 40), 'numpy.testing.assert_allclose', 'assert_allclose', ({(148, 20, 148, 26): 'result', (148, 28, 148, 39): 'true_result'}, {}), '(result, true_result)', False, 'from numpy.testing import assert_allclose\n'), ((154, 8, 154, 29), 'keras.backend.placeholder', 'K.placeholder', (), '', True, 'from keras import backend as K\n'), ((155, 10, 155, 29), 'keras.activations.tanh', 'activations.tanh', ({(155, 27, 155, 28): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((156, 8, 156, 30), 'keras.backend.function', 'K.function', ({(156, 19, 156, 22): '[x]', (156, 24, 156, 29): '[exp]'}, {}), '([x], [exp])', True, 'from keras import backend as K\n'), ((159, 15, 159, 35), 'numpy.tanh', 'np.tanh', ({(159, 23, 159, 34): 'test_values'}, {}), '(test_values)', True, 'import numpy as np\n'), ((160, 4, 160, 49), 'numpy.testing.assert_allclose', 'assert_allclose', (), '', False, 'from numpy.testing import assert_allclose\n'), ((174, 4, 174, 27), 'pytest.main', 'pytest.main', ({(174, 16, 174, 26): '[__file__]'}, {}), '([__file__])', False, 'import pytest\n'), ((22, 12, 22, 26), 'numpy.max', 'np.max', ({(22, 19, 22, 25): 'values'}, {}), '(values)', True, 'import numpy as np\n'), ((23, 12, 23, 30), 'numpy.exp', 'np.exp', ({(23, 19, 23, 29): 'values - m'}, {}), '(values - m)', True, 'import numpy as np\n'), ((14, 53, 14, 63), 'keras.backend.floatx', 'K.floatx', ({}, {}), '()', True, 'from keras import backend as K\n'), ((24, 19, 24, 28), 'numpy.sum', 'np.sum', ({(24, 26, 24, 27): 'e'}, {}), '(e)', True, 'import numpy as np\n'), ((27, 25, 27, 47), 'keras.activations.softmax', 'activations.softmax', ({(27, 45, 27, 46): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((37, 25, 37, 47), 'keras.activations.softmax', 'activations.softmax', ({(37, 45, 37, 46): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((39, 49, 39, 69), 'numpy.size', 'np.size', ({(39, 57, 39, 68): 'test_values'}, {}), '(test_values)', True, 'import numpy as np\n'), ((51, 25, 51, 48), 'keras.activations.softplus', 'activations.softplus', ({(51, 46, 51, 47): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((67, 25, 67, 48), 'keras.activations.softsign', 'activations.softsign', ({(67, 46, 67, 47): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((83, 16, 83, 25), 'numpy.exp', 'np.exp', ({(83, 23, 83, 24): 'x'}, {}), '(x)', True, 'import numpy as np\n'), ((88, 25, 88, 47), 'keras.activations.sigmoid', 'activations.sigmoid', ({(88, 45, 88, 46): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((111, 25, 111, 52), 'keras.activations.hard_sigmoid', 'activations.hard_sigmoid', ({(111, 50, 111, 51): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((125, 25, 125, 44), 'keras.activations.relu', 'activations.relu', ({(125, 42, 125, 43): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((136, 25, 136, 48), 'keras.activations.elu', 'activations.elu', ({(136, 41, 136, 42): 'x', (136, 44, 136, 47): '0.5'}, {}), '(x, 0.5)', False, 'from keras import activations\n'), ((144, 49, 144, 59), 'keras.backend.floatx', 'K.floatx', ({}, {}), '()', True, 'from keras import backend as K\n'), ((146, 19, 146, 42), 'numpy.exp', 'np.exp', ({(146, 26, 146, 41): 'negative_values'}, {}), '(negative_values)', True, 'import numpy as np\n'), ((170, 20, 170, 41), 'keras.activations.linear', 'activations.linear', ({(170, 39, 170, 40): 'x'}, {}), '(x)', False, 'from keras import activations\n'), ((48, 22, 48, 37), 'numpy.ones_like', 'np.ones_like', ({(48, 35, 48, 36): 'x'}, {}), '(x)', True, 'import numpy as np\n'), ((48, 40, 48, 49), 'numpy.exp', 'np.exp', ({(48, 47, 48, 48): 'x'}, {}), '(x)', True, 'import numpy as np\n'), ((64, 28, 64, 43), 'numpy.ones_like', 'np.ones_like', ({(64, 41, 64, 42): 'x'}, {}), '(x)', True, 'import numpy as np\n'), ((64, 46, 64, 60), 'numpy.absolute', 'np.absolute', ({(64, 58, 64, 59): 'x'}, {}), '(x)', True, 'import numpy as np\n'), ((81, 28, 81, 38), 'numpy.exp', 'np.exp', ({(81, 35, 81, 37): '(-x)'}, {}), '(-x)', True, 'import numpy as np\n')]