def test_loglikelihood_dcm(self):
        """
        a = np.array([[0, 1, 1],
                      [1, 0, 1],
                      [0, 1, 0]])
        """
        n, seed = (3, 42)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        g = sample.DirectedGraph(a)
        g.degree_reduction()
        g.initial_guess = "uniform"
        g.regularise = "eigenvalues"
        g._initialize_problem("dcm", "quasinewton")
        x0 = np.concatenate((g.r_x, g.r_y))

        # call loglikelihood function
        f_sample = -g.step_fun(x0)
        f_correct = 4 * np.log(1 / 2) - 3 * np.log(5 / 4)
        # debug
        # print(x0)
        # print(f_sample)
        # print(f_correct)

        # test result
        self.assertTrue(round(f_sample, 3) == round(f_correct, 3))
    def test_iterative_3(self):

        n, seed = (40, 22)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)
        a[0, :] = 0

        k_out = np.sum(a, 1)
        k_in = np.sum(a, 0)

        g = sample.DirectedGraph(a)
        g._solve_problem(
            model="dcm_exp",
            method="fixed-point",
            max_steps=3000,
            verbose=False,
            initial_guess="uniform",
            linsearch="False",
        )

        g._solution_error()
        err = g.error
        # debug
        # print('\ntest 1: error = {}'.format(err))

        # test result
        self.assertTrue(err < 1)
    def test_cm_2(self):
        """classes with cardinality more than 1 and zero degrees"""
        # test Matrix 1
        n, seed = (100, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=True, seed=seed)

        g = sample.UndirectedGraph(A)

        g._solve_problem(
            model="cm",
            method="newton",
            max_steps=300,
            verbose=False,
            linsearch="True",
            initial_guess='random'
        )

        g._solution_error()
        # print('degseq = ', np.concatenate((g.dseq_out, g.dseq_in)))
        # print('expected degseq = ',g.expected_dseq)
        # debug
        # print(g.r_dseq_out)
        # print(g.r_dseq_in)
        # print(g.rnz_dseq_out)
        # print(g.rnz_dseq_in)
        # print('\ntest 9: error = {}'.format(g.error))

        # test result
        self.assertTrue(g.error < 1e-1)
Exemple #4
0
    def test_fixedpoint_cm_6(self):
        """classes with cardinality > 1, no zero degree"""
        n, seed = (20, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=True, seed=seed)

        g = sample.UndirectedGraph(A)

        g._solve_problem(
            model="cm_exp",
            method="fixed-point",
            initial_guess="random",
            max_steps=300,
            verbose=False,
            linsearch="True",
        )

        g._solution_error()
        # print('degseq = ', np.concatenate((g.dseq_out, g.dseq_in)))
        # print('expected degseq = ',g.expected_dseq)
        # debug
        # print(g.r_dseq_out)
        # print(g.r_dseq_in)
        # print(g.rnz_dseq_out)
        # print(g.rnz_dseq_in)
        # print('\ntest 6: error = {}'.format(g.error))

        # test result
        self.assertTrue(g.error < 1e-1)
Exemple #5
0
    def test_loglikelihood_hessian_dcm_exp_simmetry(self):

        n, seed = (3, 42)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        g = sample.DirectedGraph(a)
        g.degree_reduction()
        g.initial_guess = "uniform"
        g.regularise = "identity"
        g._initialize_problem("dcm", "newton")
        theta = np.random.rand(2 * n)
        x0 = np.exp(-theta)

        k_out = g.args[0]
        k_in = g.args[1]
        nz_index_out = g.args[2]
        nz_index_in = g.args[3]

        f = loglikelihood_hessian_dcm_exp(theta, g.args)
        f_t = f.T

        # debug
        # print(a)
        # print(theta, x0)
        # print(g.args)
        # print(f-f_t)

        # test result
        self.assertTrue(np.allclose(f - f_t, np.zeros((2 * n, 2 * n))))
    def test_fixedpoint_2(self):
        """classes with cardinality 1 and zero degrees"""
        # test Matrix 1
        n, seed = (40, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)
        A[0, :] = 0

        g = sample.DirectedGraph(A)

        g._solve_problem(
            model="dcm",
            method="fixed-point",
            max_steps=300,
            verbose=False,
            initial_guess="uniform",
            linsearch="False",
        )

        g._solution_error()
        # print('degseq = ', np.concatenate((g.dseq_out, g.dseq_in)))
        # print('expected degseq = ',g.expected_dseq)
        # debug
        # print(g.r_dseq_out)
        # print(g.r_dseq_in)
        # print(g.rnz_dseq_out)
        # print(g.rnz_dseq_in)
        # print('\ntest 7: error = {}'.format(g.error))

        # test result
        self.assertTrue(g.error < 1e-1)
Exemple #7
0
    def test_loglikelihood_hessian_diag_dcm_exp(self):

        n, seed = (3, 42)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        g = sample.DirectedGraph(a)
        g.degree_reduction()
        g.initial_guess = "uniform"
        g.regularise = "identity"
        g._initialize_problem("dcm", "newton")
        theta = np.random.rand(n * 2)
        x0 = np.exp(-theta)

        k_out = g.args[0]
        k_in = g.args[1]
        nz_index_out = g.args[2]
        nz_index_in = g.args[3]

        f_sample = np.zeros(2 * n)
        for i in range(2 * n):
            f = lambda x: loglikelihood_prime_dcm_exp(x, g.args)[i]
            f_sample[i] = approx_fprime(theta, f, epsilon=1e-6)[i]
        g.last_model = "dcm"
        f_exp = loglikelihood_hessian_diag_dcm_exp(theta, g.args)

        # debug
        # print(a)
        # print(theta, x0)
        # print(g.args)
        # print(f_sample)
        # print(f_exp)

        # test result
        self.assertTrue(np.allclose(f_sample, f_exp))
    def test_emi(self):

        n, seed = (50, 1)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        k_out = np.sum(a, 1)
        k_in = np.sum(a, 0)

        g = sample.DirectedGraph(a)
        g._solve_problem(
            model="dcm",
            method="quasinewton",
            max_steps=3000,
            verbose=False,
            initial_guess="uniform",
            linsearch="False",
        )

        g._solution_error()
        err = g.error
        # debug
        print("\ntest emi: error = {}".format(err))

        # test result
        self.assertTrue(err < 1)
    def test_3(self):
        # test Matrix 1
        n, seed = (40, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)
        A[0, :] = 0

        g = sample.DirectedGraph(A)

        g._solve_problem(
            model="dcm",
            method="quasinewton",
            max_steps=100,
            verbose=False,
            initial_guess="uniform",
        )

        g._solution_error()
        # debug
        # print(g.r_dseq_out)
        # print(g.r_dseq_in)
        # print(g.rnz_dseq_out)
        # print(g.rnz_dseq_in)
        # print('\ntest 3: error = {}'.format(g.error))

        # test result
        self.assertTrue(g.error < 1e-2)
    def test_iterative_dcm(self):

        n, seed = (3, 42)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        # rd
        g = sample.DirectedGraph(a)
        g.degree_reduction()
        g.initial_guess = "uniform"
        g.regularise = "eigenvalues"
        g._initialize_problem("dcm", "fixed-point")
        x0 = 0.5 * np.ones(4)

        f_sample = -g.fun(x0)
        g.last_model = "dcm"
        g._set_solved_problem(f_sample)
        f_full = np.concatenate((g.x, g.y))
        f_correct = -np.array([2.5, 2.5, 0, 0, 1, 1.25])

        # debug
        # print(a)
        # print(x0, x)
        # print(f_full)

        # test result
        self.assertTrue(np.allclose(f_full, f_correct))
    def test_cm_uniform(self):
        n, seed = (4, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=True, seed=seed)

        g = sample_u.UndirectedGraph(A)
        g.initial_guess = 'uniform'
        g.last_model = "cm"
        g._set_initial_guess('cm')

        self.assertTrue(g.x0.all() == np.array([0.5, 0.5]).all())
    def test_dcm_exp(self):
        n, seed = (4, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        x0 = np.random.rand(2 * n)
        g = sample.DirectedGraph(A)
        g.initial_guess = x0
        g._set_initial_guess('dcm_exp')
        g._set_solved_problem_dcm(x0)
        self.assertTrue(np.concatenate((g.x, g.y)).all() == x0.all())
    def test_dcm_uniform(self):
        n, seed = (4, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        g = sample.DirectedGraph(A)
        g.initial_guess = 'uniform'
        g._set_initial_guess('dcm')
        self.assertTrue(
            np.concatenate((
                g.r_x,
                g.r_y)).all() == np.array([0., 0.5, 0.5, 0.5, 0., 0.5]).all())
    def test_cm(self):
        n, seed = (4, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=True, seed=seed)

        x0 = np.random.rand(n)
        g = sample_u.UndirectedGraph(A)
        g.initial_guess = x0
        g._set_initial_guess_cm()
        g.full_return = False
        g.last_model = "cm"
        g._set_solved_problem_cm(g.x0)
        self.assertTrue(g.x.all() == x0.all())
    def test_0(self):
        n, seed = (4, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        g = sample.DirectedGraph(A)

        g._solve_problem(
            model="dcm",
            method="quasinewton",
            max_steps=400,
            verbose=False,
            initial_guess="uniform",
        )

        g._solution_error()
        # debug
        # print('\ntest 0: error = {}'.format(g.error))

        # test result
        self.assertTrue(g.error < 1e-1)
    def test_loglikelihood_prime_dcm(self):
        """
        a = np.array([[0, 1, 1],
                      [1, 0, 1],
                      [0, 1, 0]])
        """
        n, seed = (30, 42)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        # rd
        g = sample.DirectedGraph(a)
        g.degree_reduction()
        g.initial_guess = "uniform"
        g.regularise = "eigenvalues"
        g._initialize_problem("dcm", "newton")

        k_out = g.args[0]
        k_in = g.args[1]
        nz_index_out = g.args[2]
        nz_index_in = g.args[3]

        n_rd = len(k_out)
        theta = np.random.rand(2 * n_rd)
        f_sample = np.zeros(n_rd * 2)
        f = lambda x: mof.loglikelihood_dcm(x, g.args)
        f_sample = approx_fprime(theta, f, epsilon=1e-6)
        f_new = mof.loglikelihood_prime_dcm(theta, g.args)

        # debug
        # print(a)
        # print(x0, x)
        # print(f_sample)
        # print(f_new)
        # for i in range(2*n_rd):
        #         if not np.allclose(f_new[i], f_sample[i],atol=1e-1):
        #             print(i)

        # test result
        self.assertTrue(np.allclose(f_sample, f_new, atol=1e-1))
Exemple #17
0
    def test_iterative_dcm_exp(self):

        n, seed = (3, 42)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        # rd
        g = sample.DirectedGraph(a)
        g.degree_reduction()
        g.initial_guess = "uniform"
        g.regularise = "identity"
        g._initialize_problem("dcm", "fixed-point")
        # theta = np.random.rand(6)
        theta = np.array([np.infty, 0.5, 0.5, 0.5, np.infty, 0.5])
        x0 = np.exp(-theta)

        f_sample = g.fun(x0)
        g.last_model = "dcm"
        g._set_solved_problem(f_sample)
        f_full = np.concatenate((g.x, g.y))
        f_full = -np.log(f_full)
        f_exp = iterative_dcm_exp(theta, g.args)
        g._set_solved_problem_dcm(f_exp)
        f_exp_full = np.concatenate((g.x, g.y))

        # f_exp_bis = iterative_dcm_exp_bis(theta, g.args)
        # print('normale ',f_exp)
        # print('bis',f_exp_bis)

        # debug
        # print(a)
        # print(theta, x0)
        # print(g.args)
        # print(f_full)
        # print(f_exp)
        # print(f_exp_full)

        # test result
        self.assertTrue(np.allclose(f_full, f_exp_full))
    def test_2(self):
        n, seed = (40, 22)
        A = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        g = sample.DirectedGraph(A)

        g._solve_problem(
            model="dcm",
            method="newton",
            max_steps=300,
            verbose=False,
            initial_guess="uniform",
        )

        g._solution_error()
        # print('degseq = ', np.concatenate((g.dseq_out, g.dseq_in)))
        # print('expected degseq = ',g.expected_dseq)
        # print(np.concatenate((g.dseq_out, g.dseq_in)) - g.expected_dseq)
        # debug
        print("\ntest 2, n={}: error = {}".format(n, g.error))

        # test result
        self.assertTrue(g.error < 1)
    def test_0(self):
        """test with 3 classes of cardinality 1
        and no zero degrees
        """
        """
        A = np.array(
            [
                [0, 1, 1, 0],
                [1, 0, 0, 1],
                [1, 0, 0, 0],
                [0, 1, 0, 0],
            ]
        )
        e = [(0,1), (0,2), (1,3)]
        d = [1,1,2,2]
        print(e)
        print(d)
        """
        N, seed = (50, 42)
        A = mg.random_binary_matrix_generator_dense(N, sym=True, seed=seed)
        # number of copies to generate

        g = sample.UndirectedGraph(A)

        g._solve_problem(
            model="cm",
            method="fixed-point",
            max_steps=100,
            verbose=False,
            linsearch=True,
            initial_guess="uniform",
        )

        x = g.x
        # g._solution_error()
        err = g.error

        # print('\ntest 5: error = {}'.format(g.error))
        n = 100
        output_dir = "sample_cm/"
        # random.seed(100)
        g.ensemble_sampler(n=n, output_dir=output_dir, seed=42)

        d = {'{}'.format(i): g.dseq[i] for i in range(N)}

        # read all sampled graphs and check the average degree distribution is close enough
        d_emp = {'{}'.format(i): 0 for i in range(N)}

        for l in range(n):
            f = output_dir + "{}.txt".format(l)
            if not os.stat(f).st_size == 0:
                g_tmp = nx.read_edgelist(f)
                d_tmp = dict(g_tmp.degree)
                for item in d_tmp.keys():
                    d_emp[item] += d_tmp[item]

        for item in d_emp.keys():
            d_emp[item] = d_emp[item] / n

        a_diff = np.array([abs(d[item] - d_emp[item]) for item in d.keys()])
        d_diff = {item: d[item] - d_emp[item] for item in d.keys()}

        ensemble_error = np.linalg.norm(a_diff, np.inf)

        #debug
        """
        for i in range(N):
            for j in range(N):
                if i!=j:
                    aux = x[i]*x[j]
                    # print("({},{}) p = {}".format(i,j,aux/(1+aux)))
        """

        # debug
        """
        print('original dseq',d)
        print('original dseq sum ',g.dseq.sum())
        print('ensemble average dseq', d_emp)
        print('ensemble dseq sum ',np.array([d_emp[key] for key in d_emp.keys()]).sum())
        print(d_diff)
        print('empirical error', ensemble_error)
        print('theoretical error', err)
        """

        l = os.listdir(output_dir)
        for f in l:
            os.remove(output_dir + f)
        os.rmdir(output_dir)

        # test result
        self.assertTrue(ensemble_error < 3)
    def test_0(self):
        """test with 3 classes of cardinality 1
        and no zero degrees
        """
        """
        A = np.array(
            [
                [0, 1, 1, 0],
                [1, 0, 0, 1],
                [1, 0, 0, 0],
                [0, 1, 0, 0],
            ]
        )
        e = [(0,1), (0,2), (1,3)]
        d = [1,1,2,2]
        print(e)
        print(d)
        """
        N, seed = (10, 42)
        A = mg.random_binary_matrix_generator_dense(N, sym=True, seed=seed)
        # number of copies to generate

        g = sample.UndirectedGraph(A)

        g._solve_problem(
            model="cm",
            method="fixed-point",
            max_steps=100,
            verbose=False,
            linsearch=True,
            initial_guess="uniform",
        )

        x = g.x
        # g._solution_error()
        err = g.error

        # print('\ntest 5: error = {}'.format(g.error))
        n = 10
        output_dir = "sample/"
        # random.seed(100)
        g_list = []
        for i in range(n):
            g.ensemble_sampler(n=1, output_dir=output_dir)
            g_list.append(np.loadtxt("sample/0.txt"))

        appo = True
        old = g_list[0]
        for i in range(1, n):
            appo = appo * np.all(old == g_list[i])

        # debug
        """
        print('original dseq',d)
        print('original dseq sum ',g.dseq.sum())
        print('ensemble average dseq', d_emp)
        print('ensemble dseq sum ',np.array([d_emp[key] for key in d_emp.keys()]).sum())
        print(d_diff)
        print('empirical error', ensemble_error)
        print('theoretical error', err)
        """

        l = os.listdir(output_dir)
        for f in l:
            os.remove(output_dir + f)
        os.rmdir(output_dir)

        # test result
        self.assertTrue(not appo)
    def test_0(self):
        N, seed = (5, 42)
        A = mg.random_binary_matrix_generator_dense(N, sym=False, seed=seed)
        # number of copies to generate

        g = sample.DirectedGraph(A)

        g._solve_problem(
            model="dcm",
            method="fixed-point",
            max_steps=100,
            verbose=False,
            linsearch=True,
            initial_guess="uniform",
        )

        # g._solution_error()
        err = g.error

        # print('\ntest 5: error = {}'.format(g.error))
        n = 100
        output_dir = "sample_dcm/"
        # random.seed(100)
        g.ensemble_sampler(n=n, output_dir=output_dir, seed=seed)

        d_out = {'{}'.format(i):g.dseq_out[i] for i in range(N)}
        d_in = {'{}'.format(i):g.dseq_in[i] for i in range(N)}


        # read all sampled graphs and check the average degree distribution is close enough
        d_out_emp = {'{}'.format(i):0 for i in range(N)}
        d_in_emp = {'{}'.format(i):0 for i in range(N)}

        for l in range(n):
            f = output_dir + "{}.txt".format(l)
            if not os.stat(f).st_size == 0:
                g_tmp = nx.read_edgelist(f, create_using=nx.DiGraph())
                d_out_tmp = dict(g_tmp.out_degree)
                d_in_tmp = dict(g_tmp.in_degree)
                for item in d_out_tmp.keys(): 
                    d_out_emp[item] += d_out_tmp[item]
                    d_in_emp[item] += d_in_tmp[item]


        for item in d_out_emp.keys(): 
            d_out_emp[item] = d_out_emp[item]/n
            d_in_emp[item] = d_in_emp[item]/n

        a_out_diff = np.array([abs(d_out[item] - d_out_emp[item]) for item in d_out.keys()])
        a_in_diff = np.array([abs(d_in[item] - d_in_emp[item]) for item in d_in.keys()])
        d_out_diff = {item:d_out[item] - d_out_emp[item] for item in d_out.keys()}
        d_in_diff = {item:d_in[item] - d_in_emp[item] for item in d_in.keys()}

        ensemble_error = np.linalg.norm(np.concatenate((a_out_diff, a_in_diff)), np.inf)

        #debug
        """
        for i in range(N):
            for j in range(N):
                if i!=j:
                    aux = x[i]*x[j]
                    # print("({},{}) p = {}".format(i,j,aux/(1+aux)))
        """


        # debug
        # print('original dseq',d_out,d_in)
        # print('original dseq out sum ',g.dseq_out.sum())
        # print('original dseq in sum ',g.dseq_in.sum())
        # print('ensemble average dseq out', d_out_emp)
        # print('ensemble average dseq in', d_in_emp)
        # print('ensemble dseq out sum ',np.array([d_out_emp[key] for key in d_out_emp.keys()]).sum())
        # print('ensemble dseq in sum ',np.array([d_in_emp[key] for key in d_in_emp.keys()]).sum())
        # print(d_out_diff)
        # print(d_in_diff)
        # print('empirical error', ensemble_error)
        # print('theoretical error', err)


        l = os.listdir(output_dir)
        for f in l:
            os.remove(output_dir + f)
        os.rmdir(output_dir)

        # test result
        self.assertTrue(ensemble_error < 3)
Exemple #22
0
    def test_quasinewton_2(self):

        n, seed = (40, 26)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)

        k_out = np.sum(a, 1)
        k_in = np.sum(a, 0)
        """
        nz_index_out = np.array([0,1,2])
        nz_index_in = np.array([0,1,2,3])
        c = np.array([2,1,1])
        """
        g = sample.DirectedGraph(a)
        g.degree_reduction()
        g.initial_guess = "random"
        g.full_return = False
        g._set_initial_guess("dcm")
        g._set_args("dcm")

        x0 = g.x0
        x0[x0 == 0] = np.infty
        args = g.args

        fun = lambda x: -loglikelihood_prime_dcm_exp(x, args)
        step_fun = lambda x: -loglikelihood_dcm_exp(x, args)
        fun_jac = lambda x: -loglikelihood_hessian_diag_dcm_exp(x, args)
        lin_fun = lambda x: linsearch_fun_DCM_exp(x, (step_fun, ))
        hes_reg = sof.matrix_regulariser_function

        f = fun(x0)
        norm = np.linalg.norm(f)

        theta_sol = sof.solver(
            x0,
            fun=fun,
            step_fun=step_fun,
            fun_jac=fun_jac,
            linsearch_fun=lin_fun,
            tol=1e-6,
            eps=1e-1,
            max_steps=100,
            method="quasinewton",
            verbose=False,
            regularise=True,
            full_return=False,
            linsearch=True,
            hessian_regulariser=hes_reg,
        )

        g._set_solved_problem_dcm(theta_sol)
        theta_sol_full = np.concatenate((g.x, g.y))

        sol = np.exp(-theta_sol_full)
        sol[np.isnan(sol)] = 0

        ek = np.concatenate((
            expected_out_degree_dcm(sol),
            expected_in_degree_dcm(sol),
        ))
        k = np.concatenate((k_out, k_in))
        err = np.max(abs(ek - k))
        # debug
        # print(ek)
        # print(k)
        # print('\ntest 6: error = {}'.format(err))

        # test result
        self.assertTrue(err < 1e-2)

        # debug
        # print(ek)
        # print(k)
        # print('\ntest 7: error = {}'.format(err))

        # test result
        self.assertTrue(err < 1e-2)
Exemple #23
0
    def test_iterative_1(self):

        n, seed = (4, 22)
        a = mg.random_binary_matrix_generator_dense(n, sym=False, seed=seed)
        a[0, :] = 0

        k_out = np.sum(a, 1)
        k_in = np.sum(a, 0)

        g = sample.DirectedGraph(a)
        g.degree_reduction()
        g.initial_guess = "random"
        g.full_return = False
        g._set_initial_guess("dcm")
        g._set_args("dcm")

        x0 = g.x0
        x0[x0 == 0] = 100
        args = g.args

        fun = lambda x: iterative_dcm_exp(x, args)
        step_fun = lambda x: -loglikelihood_dcm_exp(x, args)
        lin_fun = lambda x: linsearch_fun_DCM_exp(x, (step_fun, ))
        hes_reg = sof.matrix_regulariser_function

        f = fun(x0)
        norm = np.linalg.norm(f)

        theta_sol = sof.solver(
            x0,
            fun=fun,
            step_fun=step_fun,
            linsearch_fun=lin_fun,
            tol=1e-6,
            eps=1e-10,
            max_steps=700,
            method="fixed-point",
            verbose=False,
            regularise=True,
            full_return=False,
            linsearch=False,
            hessian_regulariser=hes_reg,
        )

        g._set_solved_problem_dcm(theta_sol)
        theta_sol_full = np.concatenate((g.x, g.y))

        sol = np.exp(-theta_sol_full)
        sol[np.isnan(sol)] = 0

        ek = np.concatenate((
            expected_out_degree_dcm(sol),
            expected_in_degree_dcm(sol),
        ))
        k = np.concatenate((k_out, k_in))
        err = np.max(abs(ek - k))
        # debug
        # print(ek)
        # print(k)
        # print('\ntest 0: error = {}'.format(err))

        # test result
        self.assertTrue(err < 1e-2)