def create_dtree_dict(data_l, cl_parts_l, conj_vars_l, alpha):
    n_vars = data_l[0].shape[1]
    sum_mut_info = np.zeros((n_vars, n_vars))
    for i in range(len(data_l)):
        for part in cl_parts_l[i]:
            mi = compute_mi(part.get_slice(data_l[i]), alpha)
            sum_mut_info[(part.col_ids[:, None], part.col_ids)] += mi
    free_vars = list((set(np.arange(n_vars)) - set([var for conj_vars in conj_vars_l for var in conj_vars])))
    if free_vars:
        scopes = (conj_vars_l + [free_vars])
    else:
        scopes = conj_vars_l
    dtrees = []
    for scope in scopes:
        dtrees.append(build_dependency_tree_from_mi(sum_mut_info[scope][:, scope], scope))
    scope = dtrees[(- 1)].get_tree()[0].copy()
    tree = dtrees[(- 1)].get_tree()[1].copy()
    for k in reversed(range(0, (len(dtrees) - 1))):
        tree += [((t + len(scope)) if (t != ROOT) else t) for t in dtrees[k].get_tree()[1]]
        tree[tree.index(ROOT)] = tree.index(ROOT, len(scope))
        scope += dtrees[k].get_tree()[0]
        dtrees[k].set_tree(scope.copy(), tree.copy())
        dtrees[(k + 1)].set_parent(dtrees[k])
    return {len(dtree.get_tree()[0]): dtree for dtree in dtrees}
def create_dtree_dict(data_l, cl_parts_l, conj_vars_l, alpha):
    n_vars = data_l[0].shape[1]
    sum_mut_info = np.zeros((n_vars, n_vars))
    for i in range(len(data_l)):
        for part in cl_parts_l[i]:
            mi = compute_mi(part.get_slice(data_l[i]), alpha)
            sum_mut_info[(part.col_ids[:, None], part.col_ids)] += mi
    free_vars = list((set(np.arange(n_vars)) - set([var for conj_vars in conj_vars_l for var in conj_vars])))
    if free_vars:
        scopes = (conj_vars_l + [free_vars])
    else:
        scopes = conj_vars_l
    dtrees = []
    for scope in scopes:
        dtrees.append(build_dependency_tree_from_mi(sum_mut_info[scope][:, scope], scope))
    scope = dtrees[(- 1)].get_tree()[0].copy()
    tree = dtrees[(- 1)].get_tree()[1].copy()
    for k in reversed(range(0, (len(dtrees) - 1))):
        tree += [((t + len(scope)) if (t != ROOT) else t) for t in dtrees[k].get_tree()[1]]
        tree[tree.index(ROOT)] = tree.index(ROOT, len(scope))
        scope += dtrees[k].get_tree()[0]
        dtrees[k].set_tree(scope.copy(), tree.copy())
        dtrees[(k + 1)].set_parent(dtrees[k])
    return {len(dtree.get_tree()[0]): dtree for dtree in dtrees}