<commit_before>
if VERSION < v"0.4-"
    typealias IntTuple2(Int, Int)
else
    typealias IntTuple2 Tuple{Int, Int}
end

typealias IntTimeEdge TimeEdge{Int, Int}


type IntEvolvingGraph <: AbstractEvolvingGraph{Int}
    is_directed::Bool
    nodes::Vector{IntTuple2}
    timestamps::Vector{Int}
    nedges::Int
    edges::Dict{Int, Vector{IntTimeEdge}}
    adjlist::Dict{IntTuple2, Vector{IntTuple2}}
end

evolving_graph(;is_directed::Bool = true) = 
IntEvolvingGraph(is_directed, 
                 IntTuple2[],
                 Int[],
                 0,
                 Dict{Int, Vector{IntTimeEdge}}(),
                 Dict{IntTuple2, Vector{IntTuple2}}())

nodes(g::IntEvolvingGraph) = unique(map(x -> x[1], g.nodes))
num_nodes(g::IntEvolvingGraph) = length(nodes(g))

num_edges(g::IntEvolvingGraph) = g.nedges

edges(g::IntEvolvingGraph, t::Int) = g.edges[t]
num_edges(g::IntEvolvingGraph, t::Int) = length(edges(g, t))

copy(g::IntEvolvingGraph) = IntEvolvingGraph(is_directed(g), 
                                             deepcopy(g.nodes), 
                                             deepcopy(g.timestamps), 
                                             deepcopy(g.nedges), 
                                             deepcopy(g.edges), 
                                             deepcopy(g.adjlist))


function edges(g::IntEvolvingGraph)
    elist = IntTimeEdge[]
    for t in timestamps(g)
        append!(elist, edges(g, t))
    end
    elist
end



function out_neighbors(g::IntEvolvingGraph, v::Tuple)
    try 
        return g.adjlist[v]
    catch KeyError
        return collect(zip([], []))
    end
end
out_neighbors(g::IntEvolvingGraph, v, t) = out_neighbors(g, (int(v), int(t)))

has_node(g::IntEvolvingGraph, v::IntTuple2) = (v in g.nodes)

timestamps(g::IntEvolvingGraph) = g.timestamps

function add_node!(g::IntEvolvingGraph, v::IntTuple2)
    if !(v in g.nodes)
        push!(g.nodes, v)
        if !(v[2] in keys(g.edges))
             g.edges[v[2]] = IntTimeEdge[]
        end
             
        g.adjlist[v] = IntTuple2[]
   
        if !(v[2] in g.timestamps)
            push!(g.timestamps, v[2])
            sort!(g.timestamps)
        end
    end
    v
end

function add_edge!(g::IntEvolvingGraph, v1::IntTuple2, v2::IntTuple2)
    v1[2] == v2[2] || error("Input nodes $(v1[1]) and $(v2[1]) must at the same timestamps")
    v1 in g.nodes || add_node!(g, v1)
    v2 in g.nodes || add_node!(g, v2)
    index = findin(map(x -> x[1], g.nodes), v1[1])
    for node in g.nodes[index]
        if node < v1
            v1 in g.adjlist[node] || push!(g.adjlist[node], v1)
        end
    end

    if !(v2 in g.adjlist[v1]) 
        push!(g.adjlist[v1], v2)
        push!(g.edges[v1[2]], TimeEdge(v1[1], v2[1], v1[2]))
        if !(g.is_directed)
            push!(g.adjlist[v2], v1)
            push!(g.edges[v1[2]], TimeEdge(v2[1], v1[1], v1[2]))
        end
        g.nedges += 1
    end
    g
end

add_edge!(g::IntEvolvingGraph, v1::Int, v2::Int, t::Int) = add_edge!(g, (v1, t), (v2, t))
add_edge!(g::IntEvolvingGraph, te::TimeEdge{Int, Int}) = add_edge!(g, source(te), target(te), time(te))


function undirected!(g::IntEvolvingGraph)
    for t in timestamps(g)
        for e in edges(g, t)
            add_edge!(g, target(e), source(e), time(e))
        end
    end
    g.is_directed = false
    g
end
            


<commit_msg>define slice function for IntEvolvingGraph<commit_after>
if VERSION < v"0.4-"
    typealias IntTuple2(Int, Int)
else
    typealias IntTuple2 Tuple{Int, Int}
end

typealias IntTimeEdge TimeEdge{Int, Int}


type IntEvolvingGraph <: AbstractEvolvingGraph{Int}
    is_directed::Bool
    nodes::Vector{IntTuple2}
    timestamps::Vector{Int}
    nedges::Int
    edges::Dict{Int, Vector{IntTimeEdge}}
    adjlist::Dict{IntTuple2, Vector{IntTuple2}}
end

evolving_graph(;is_directed::Bool = true) = 
IntEvolvingGraph(is_directed, 
                 IntTuple2[],
                 Int[],
                 0,
                 Dict{Int, Vector{IntTimeEdge}}(),
                 Dict{IntTuple2, Vector{IntTuple2}}())

nodes(g::IntEvolvingGraph) = unique(map(x -> x[1], g.nodes))
num_nodes(g::IntEvolvingGraph) = length(nodes(g))

num_edges(g::IntEvolvingGraph) = g.nedges

edges(g::IntEvolvingGraph, t::Int) = g.edges[t]
num_edges(g::IntEvolvingGraph, t::Int) = length(edges(g, t))

copy(g::IntEvolvingGraph) = IntEvolvingGraph(is_directed(g), 
                                             deepcopy(g.nodes), 
                                             deepcopy(g.timestamps), 
                                             deepcopy(g.nedges), 
                                             deepcopy(g.edges), 
                                             deepcopy(g.adjlist))


function edges(g::IntEvolvingGraph)
    elist = IntTimeEdge[]
    for t in timestamps(g)
        append!(elist, edges(g, t))
    end
    elist
end



function out_neighbors(g::IntEvolvingGraph, v::Tuple)
    try 
        return g.adjlist[v]
    catch KeyError
        return collect(zip([], []))
    end
end
out_neighbors(g::IntEvolvingGraph, v, t) = out_neighbors(g, (int(v), int(t)))

has_node(g::IntEvolvingGraph, v::IntTuple2) = (v in g.nodes)

timestamps(g::IntEvolvingGraph) = g.timestamps

function add_node!(g::IntEvolvingGraph, v::IntTuple2)
    if !(v in g.nodes)
        push!(g.nodes, v)
        if !(v[2] in keys(g.edges))
             g.edges[v[2]] = IntTimeEdge[]
        end
             
        g.adjlist[v] = IntTuple2[]
   
        if !(v[2] in g.timestamps)
            push!(g.timestamps, v[2])
            sort!(g.timestamps)
        end
    end
    v
end

function add_edge!(g::IntEvolvingGraph, v1::IntTuple2, v2::IntTuple2)
    v1[2] == v2[2] || error("Input nodes $(v1[1]) and $(v2[1]) must at the same timestamps")
    v1 in g.nodes || add_node!(g, v1)
    v2 in g.nodes || add_node!(g, v2)
    index = findin(map(x -> x[1], g.nodes), v1[1])
    for node in g.nodes[index]
        if node < v1
            v1 in g.adjlist[node] || push!(g.adjlist[node], v1)
        end
    end

    if !(v2 in g.adjlist[v1]) 
        push!(g.adjlist[v1], v2)
        push!(g.edges[v1[2]], TimeEdge(v1[1], v2[1], v1[2]))
        if !(g.is_directed)
            push!(g.adjlist[v2], v1)
            push!(g.edges[v1[2]], TimeEdge(v2[1], v1[1], v1[2]))
        end
        g.nedges += 1
    end
    g
end

add_edge!(g::IntEvolvingGraph, v1::Int, v2::Int, t::Int) = add_edge!(g, (v1, t), (v2, t))
add_edge!(g::IntEvolvingGraph, te::TimeEdge{Int, Int}) = add_edge!(g, source(te), target(te), time(te))


function undirected!(g::IntEvolvingGraph)
    for t in timestamps(g)
        for e in edges(g, t)
            add_edge!(g, target(e), source(e), time(e))
        end
    end
    g.is_directed = false
    g
end
            
function slice(g::IntEvolvingGraph, t1::Int, t2::Int)
    ts = timestamps(g)
    st = findfirst(ts, t1) 
    ed = findfirst(ts, t2)
    g1 = evolving_graph()
    for t in ts[st:ed]
        for te in edges(g, t)
            add_edge!(g1, te)
        end
    end
    g1
end


{'fraction_non_alphanumeric': 0.14764338444065872, 'fraction_numerical': 0.020300965360590572, 'mean_word_length': 2.2767441860465114, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7298563', 'n_tokens_mistral': 2618, 'n_tokens_neox': 2565, 'n_words': 503}