def test_squared_euclidean_cost(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C_XY = squared_euclidean_cost(X, Y)
        C = np.zeros_like(C_XY)

        for i in range(len(X)):
            for j in range(len(Y)):
                C[i, j] = 0.5 * np.sum((X[i] - Y[j])**2)

        assert_array_almost_equal(C_XY, C)

        C_XX = squared_euclidean_cost(X, X)
        C_YY = squared_euclidean_cost(Y, Y)
        C_XY2, C_XX2, C_YY2 = squared_euclidean_cost(X, Y, return_all=True)
        assert_array_almost_equal(C_XY, C_XY2)
        assert_array_almost_equal(C_XX, C_XX2)
        assert_array_almost_equal(C_YY, C_YY2)
    def test_squared_euclidean_cost_log_vjp(self):
        def f(X, Y):
            C = squared_euclidean_cost(X, Y, log=True)
            return sdtw_C(C)

        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y, log=True)
        val, grad_C = sdtw_value_and_grad_C(C)
        grad_X = squared_euclidean_cost_vjp(X, Y, grad_C, log=True)
        grad_num = _num_gradient(functools.partial(f, Y=Y), X)
        assert_array_almost_equal(grad_X, grad_num)
    def test_squared_euclidean_cost_vjp(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        vjp = squared_euclidean_cost_vjp(X, Y, C)
        vjp2 = np.zeros_like(vjp)
        for i in range(len(X)):
            for j in range(len(Y)):
                for k in range(X.shape[1]):
                    vjp2[i, k] += C[i, j] * (X[i, k] - Y[j, k])
        assert_array_almost_equal(vjp, vjp2)
    def test_sdtw(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        assert_almost_equal(sdtw_C(C), _sdtw_brute_force(C))
        assert_almost_equal(sdtw_C(C), sdtw_value_and_grad_C(C)[0])
        assert_almost_equal(sdtw_C(C), sdtw(X, Y))

        assert_almost_equal(sdtw_C(C, gamma=0.1),
                            _sdtw_brute_force(C, gamma=0.1))
        assert_almost_equal(sdtw_C(C, gamma=0.1),
                            sdtw_value_and_grad_C(C, gamma=0.1)[0])
    def test_sharp_sdtw_grad(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        for gamma in (0.1, 1.0):
            G = sharp_sdtw_value_and_grad_C(C, gamma=gamma)[1]
            f = functools.partial(sharp_sdtw_C, gamma=gamma)
            G_num = _num_gradient(f, C)
            assert_array_almost_equal(G, G_num)

            G = sharp_sdtw_value_and_grad(X, Y, gamma=gamma)[1]
            f = functools.partial(sharp_sdtw, Y=Y, gamma=gamma)
            G_num = _num_gradient(f, X)
            assert_array_almost_equal(G, G_num)
    def test_sdtw_entropy(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        gamma = 1.0
        eps = 1e-6
        p = _probas(C, gamma=gamma)
        H1 = -np.dot(p, np.log(p))
        H2 = sdtw_entropy_C(C, gamma=gamma)
        H3 = -(sdtw_C(C, gamma + eps) - sdtw_C(C, gamma - eps)) / (2 * eps)
        H4 = sdtw_entropy(X, Y, gamma=gamma)
        assert_almost_equal(H1, H2)
        assert_almost_equal(H1, H3)
        assert_almost_equal(H1, H4)
    def test_sharp_sdtw(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        for gamma in (0.1, 1.0):
            E = sdtw_value_and_grad_C(C, gamma=gamma)[1]
            val1 = np.vdot(E, C)
            val2 = sharp_sdtw_C(C, gamma=gamma)
            val3 = sharp_sdtw_value_and_grad_C(C, gamma=gamma)[0]
            val4 = sharp_sdtw_value_and_grad(X, Y, gamma=gamma)[0]
            val5 = sharp_sdtw(X, Y, gamma=gamma)
            assert_almost_equal(val1, val2)
            assert_almost_equal(val1, val3)
            assert_almost_equal(val1, val4)
            assert_almost_equal(val1, val5)
    def test_mean_cost_grad(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        A_sum = np.zeros_like(C)
        n = 0
        for A in alignment_matrices(*C.shape):
            A_sum += A
            n += 1
        A_mean1 = A_sum / n
        A_mean2 = mean_cost_value_and_grad_C(C)[1]

        assert_array_almost_equal(A_mean1, A_mean2)

        G = _num_gradient(mean_cost_C, A_sum)  # Any matrix can be used.
        assert_array_almost_equal(A_mean1, G)
    def test_mean_cost(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        scores = []
        for A in alignment_matrices(*C.shape):
            scores.append(np.vdot(A, C))
        val1 = np.mean(scores)
        val2 = mean_cost_C(C)
        val3 = mean_cost_value_and_grad_C(C)[0]
        val4 = mean_cost(X, Y)
        val5 = mean_cost_value_and_grad(X, Y)[0]
        assert_almost_equal(val1, val2)
        assert_almost_equal(val1, val3)
        assert_almost_equal(val1, val4)
        assert_almost_equal(val1, val5)
    def test_sdtw_grad_C(self):
        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        V, P = sdtw_C(C, return_all=True)
        G = sdtw_grad_C(P)
        G_num = _num_gradient(sdtw_C, C)
        G_bf = _expectation_brute_force(C)
        assert_array_almost_equal(G, G_num)
        assert_array_almost_equal(G, G_bf)

        # Check value_and_grad.
        for gamma in (0.1, 1.0):
            G = sdtw_value_and_grad_C(C, gamma=gamma)[1]
            G_bf = _expectation_brute_force(C, gamma=gamma)
            assert_array_almost_equal(G, G_bf)
    def test_sdtw_hessian_product(self):
        def f(C, M):
            V, P = sdtw_C(C, return_all=True)
            return sdtw_directional_derivative_C(P, M)

        X, Y = _make_time_series(size_X=3, size_Y=4, num_dim=2)
        C = squared_euclidean_cost(X, Y)

        V, P = sdtw_C(C, return_all=True)
        E = sdtw_grad_C(P, return_all=True)
        V_dot = sdtw_directional_derivative_C(P, C, return_all=True)
        hvp = sdtw_hessian_product_C(P, E, V_dot)
        hvp_num = _num_gradient(functools.partial(f, M=C), C)
        # The Hessian product is equal to the gradient of the directional derivative.
        assert_array_almost_equal(hvp, hvp_num)

        # Check that wrong inputs raise an exception.
        assert_raises(ValueError, sdtw_hessian_product_C, P, E, X)
        assert_raises(ValueError, sdtw_hessian_product_C, P, X, V_dot)
 def f(X, Y):
     C = squared_euclidean_cost(X, Y, log=True)
     return sdtw_C(C)