import numpy as np
from sklearn import metrics

from neupy import algorithms
from base import BaseTestCase


class CMACTestCase(BaseTestCase):
    def test_cmac(self):
        X_train = np.reshape(np.linspace(0, 2 * np.pi, 100), (100, 1))
        X_train_before = X_train.copy()

        X_test = np.reshape(np.linspace(np.pi, 2 * np.pi, 50), (50, 1))

        y_train = np.sin(X_train)
        y_train_before = y_train.copy()
        y_test = np.sin(X_test)

        cmac = algorithms.CMAC(
            quantization=100,
            associative_unit_size=32,
            step=0.2,
            verbose=False,
        )
        cmac.train(X_train, y_train, epochs=100)

        predicted_test = cmac.predict(X_test)
        predicted_test = predicted_test.reshape((len(predicted_test), 1))
        error = metrics.mean_absolute_error(y_test, predicted_test)

        self.assertAlmostEqual(error, 0.0024, places=4)

        # Test that algorithm didn't modify data samples
        np.testing.assert_array_equal(X_train, X_train_before)
        np.testing.assert_array_equal(X_train, X_train_before)
        np.testing.assert_array_equal(y_train, y_train_before)

        self.assertPickledNetwork(cmac, X_train)

    def test_train_different_inputs(self):
        self.assertInvalidVectorTrain(
            network=algorithms.CMAC(),
            input_vector=np.array([1, 2, 3]),
            target=np.array([1, 2, 3])
        )

    def test_predict_different_inputs(self):
        cmac = algorithms.CMAC()

        data = np.array([[1, 2, 3]]).T
        target = np.array([[1, 2, 3]]).T

        cmac.train(data, target, epochs=100)
        self.assertInvalidVectorPred(
            network=cmac,
            input_vector=np.array([1, 2, 3]),
            target=target,
            decimal=2
        )

    def test_cmac_multi_output(self):
        X_train = np.linspace(0, 2 * np.pi, 100)
        X_train = np.vstack([X_train, X_train])

        X_test = np.linspace(0, 2 * np.pi, 100)
        X_test = np.vstack([X_test, X_test])

        y_train = np.sin(X_train)
        y_test = np.sin(X_test)

        cmac = algorithms.CMAC(
            quantization=100,
            associative_unit_size=32,
            step=0.2,
        )
        cmac.train(X_train, y_train,
                   X_test, y_test, epochs=100)
        predicted_test = cmac.predict(X_test)
        error = metrics.mean_absolute_error(y_test, predicted_test)

        self.assertAlmostEqual(error, 0, places=6)

    def test_cmac_training_exceptions(self):
        cmac = algorithms.CMAC(
            quantization=100,
            associative_unit_size=32,
            step=0.2,
        )

        with self.assertRaises(ValueError):
            cmac.train(X_train=True, y_train=True,
                       X_test=None, y_test=True)

[((15, 18, 15, 33), 'numpy.sin', 'np.sin', ({(15, 25, 15, 32): 'X_train'}, {}), '(X_train)', True, 'import numpy as np\n'), ((17, 17, 17, 31), 'numpy.sin', 'np.sin', ({(17, 24, 17, 30): 'X_test'}, {}), '(X_test)', True, 'import numpy as np\n'), ((19, 15, 24, 9), 'neupy.algorithms.CMAC', 'algorithms.CMAC', (), '', False, 'from neupy import algorithms\n'), ((29, 16, 29, 67), 'sklearn.metrics.mean_absolute_error', 'metrics.mean_absolute_error', ({(29, 44, 29, 50): 'y_test', (29, 52, 29, 66): 'predicted_test'}, {}), '(y_test, predicted_test)', False, 'from sklearn import metrics\n'), ((34, 8, 34, 62), 'numpy.testing.assert_array_equal', 'np.testing.assert_array_equal', ({(34, 38, 34, 45): 'X_train', (34, 47, 34, 61): 'X_train_before'}, {}), '(X_train, X_train_before)', True, 'import numpy as np\n'), ((35, 8, 35, 62), 'numpy.testing.assert_array_equal', 'np.testing.assert_array_equal', ({(35, 38, 35, 45): 'X_train', (35, 47, 35, 61): 'X_train_before'}, {}), '(X_train, X_train_before)', True, 'import numpy as np\n'), ((36, 8, 36, 62), 'numpy.testing.assert_array_equal', 'np.testing.assert_array_equal', ({(36, 38, 36, 45): 'y_train', (36, 47, 36, 61): 'y_train_before'}, {}), '(y_train, y_train_before)', True, 'import numpy as np\n'), ((48, 15, 48, 32), 'neupy.algorithms.CMAC', 'algorithms.CMAC', ({}, {}), '()', False, 'from neupy import algorithms\n'), ((62, 18, 62, 48), 'numpy.linspace', 'np.linspace', ({(62, 30, 62, 31): '0', (62, 33, 62, 42): '2 * np.pi', (62, 44, 62, 47): '100'}, {}), '(0, 2 * np.pi, 100)', True, 'import numpy as np\n'), ((63, 18, 63, 47), 'numpy.vstack', 'np.vstack', ({(63, 28, 63, 46): '[X_train, X_train]'}, {}), '([X_train, X_train])', True, 'import numpy as np\n'), ((65, 17, 65, 47), 'numpy.linspace', 'np.linspace', ({(65, 29, 65, 30): '0', (65, 32, 65, 41): '2 * np.pi', (65, 43, 65, 46): '100'}, {}), '(0, 2 * np.pi, 100)', True, 'import numpy as np\n'), ((66, 17, 66, 44), 'numpy.vstack', 'np.vstack', ({(66, 27, 66, 43): '[X_test, X_test]'}, {}), '([X_test, X_test])', True, 'import numpy as np\n'), ((68, 18, 68, 33), 'numpy.sin', 'np.sin', ({(68, 25, 68, 32): 'X_train'}, {}), '(X_train)', True, 'import numpy as np\n'), ((69, 17, 69, 31), 'numpy.sin', 'np.sin', ({(69, 24, 69, 30): 'X_test'}, {}), '(X_test)', True, 'import numpy as np\n'), ((71, 15, 75, 9), 'neupy.algorithms.CMAC', 'algorithms.CMAC', (), '', False, 'from neupy import algorithms\n'), ((79, 16, 79, 67), 'sklearn.metrics.mean_absolute_error', 'metrics.mean_absolute_error', ({(79, 44, 79, 50): 'y_test', (79, 52, 79, 66): 'predicted_test'}, {}), '(y_test, predicted_test)', False, 'from sklearn import metrics\n'), ((84, 15, 88, 9), 'neupy.algorithms.CMAC', 'algorithms.CMAC', (), '', False, 'from neupy import algorithms\n'), ((10, 29, 10, 59), 'numpy.linspace', 'np.linspace', ({(10, 41, 10, 42): '0', (10, 44, 10, 53): '2 * np.pi', (10, 55, 10, 58): '100'}, {}), '(0, 2 * np.pi, 100)', True, 'import numpy as np\n'), ((13, 28, 13, 61), 'numpy.linspace', 'np.linspace', ({(13, 40, 13, 45): 'np.pi', (13, 47, 13, 56): '2 * np.pi', (13, 58, 13, 60): '50'}, {}), '(np.pi, 2 * np.pi, 50)', True, 'import numpy as np\n'), ((50, 15, 50, 36), 'numpy.array', 'np.array', ({(50, 24, 50, 35): '[[1, 2, 3]]'}, {}), '([[1, 2, 3]])', True, 'import numpy as np\n'), ((51, 17, 51, 38), 'numpy.array', 'np.array', ({(51, 26, 51, 37): '[[1, 2, 3]]'}, {}), '([[1, 2, 3]])', True, 'import numpy as np\n'), ((42, 20, 42, 37), 'neupy.algorithms.CMAC', 'algorithms.CMAC', ({}, {}), '()', False, 'from neupy import algorithms\n'), ((43, 25, 43, 44), 'numpy.array', 'np.array', ({(43, 34, 43, 43): '[1, 2, 3]'}, {}), '([1, 2, 3])', True, 'import numpy as np\n'), ((44, 19, 44, 38), 'numpy.array', 'np.array', ({(44, 28, 44, 37): '[1, 2, 3]'}, {}), '([1, 2, 3])', True, 'import numpy as np\n'), ((56, 25, 56, 44), 'numpy.array', 'np.array', ({(56, 34, 56, 43): '[1, 2, 3]'}, {}), '([1, 2, 3])', True, 'import numpy as np\n')]