import networkx as nx

def crea_digraf_exps (le):
    g =nx.DiGraph()
    g.add_edges_from(le)
    return g

def crea_digraf_camins (le):
    g =nx.DiGraph()
    for cami in le:
        nx.add_path(g, cami)
    return g

def vars_usades_1(g):
    lvars = []
    for node in g:
        if g.out_degree(node) == 0:
            lvars.append(node)
    lvars.sort()
    return lvars

def vars_usades_2(g):
    lvars = list(filter(lambda node: g.out_degree(node) == 0, g))
    lvars.sort()
    return lvars

# tria la funció
#vars_usades = vars_usades_1
vars_usades = vars_usades_2

def vars_mes_usades(g):
    maxus = 0
    lmax = []
    for node in g:
        if g.out_degree(node) == 0:
            idnode = g.in_degree(node)
            if idnode > maxus:
                maxus = idnode
                lmax = [node]
            elif idnode == maxus:
                lmax.append(node)
    lmax.sort()
    return lmax

def vars_directes (g, e):
    lvars = list(filter(lambda node: g.out_degree(node) == 0, g.successors(e)))
    lvars.sort()
    return lvars

def exps_mes_usades(g):
    lmax = []
    maxus = 0
    for node in g:
        if g.out_degree(node) > 0:
            idnode = g.in_degree(node)
            if idnode > maxus:
                lmax = [node]
                maxus = idnode
            elif idnode == maxus:
                lmax.append(node)
    return lmax

def vars_expr(g, e):
    l = filter(lambda node: g.out_degree(node) == 0, nx.dfs_tree(g, e))
    return list(l)

def exps_completes(g):
    l = filter(lambda node: g.in_degree(node) == 0, g)
    return list(l)

def ordre_avaluacio(g, e):
    return list(nx.dfs_postorder_nodes(g, e))

def exps_depenen_1(g, v):
    return list(nx.dfs_preorder_nodes(g.reverse(), v))
    
def exps_depenen_2(g, v):
    return nx.bfs_tree(g.reverse(), v).nodes()

# tria la funció
exps_depenen = exps_depenen_1
#exps_depenen = exps_depenen_2
