<commit_before>//
//  Graph.swift
//  Edgy
//
//  Created by <NAME> on 1/22/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

public struct Graph<Node: Hashable> {    
	private var edgeBacking = EdgeBacking<Node>()
	private(set) var nodes = Set<Node>()
    
    public init<N: SequenceType, E: SequenceType where N.Generator.Element == Node, E.Generator.Element == (Node, Node)>(nodes: N, edges: E) {
        for node in nodes { addNode(node) }
        for edge in edges { addEdge(edge) }
    }
    
    public func adjacentNodes(node: Node) -> Set<Node> {
        return (edgeBacking.nodesReachableFromNode[node] ?? []).intersect(nodes)
    }
}

extension Graph {
    public init() {
        self.init(nodes: [])
    }
    
    public init<N: SequenceType where N.Generator.Element == Node>(nodes: N) {
        self.init(nodes: nodes, edges: [])
    }
}

extension Graph {
    public var edges: Set<Edge<Node>> {
        return Set(nodes.flatMap { a in
            self.adjacentNodes(a).map { b in
                Edge(a, b)
            }
        })
    }
}

extension Graph {
	private mutating func requireUniqueBacking() {
		if !isUniquelyReferencedNonObjC(&edgeBacking) {
			edgeBacking = edgeBacking.copyByTrimmingIrrelevantNodes(relevantNodes: nodes)
		}
	}
	
	public mutating func addNode(node: Node) {
		requireUniqueBacking()
		
		nodes.insert(node)
		edgeBacking.nodesReachableFromNode[node] = []
	}
		
	public mutating func addEdge(lhs: Node, _ rhs: Node) {
		requireUniqueBacking()
		assert(nodes.contains(lhs) && nodes.contains(rhs), "An edge must be between nodes in the graph.")
		edgeBacking.nodesReachableFromNode[lhs]?.insert(rhs)
		edgeBacking.nodesReachableFromNode[rhs]?.insert(lhs)
	}
}
<commit_msg>Directed edges<commit_after>//
//  Graph.swift
//  Edgy
//
//  Created by <NAME> on 1/22/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

public struct Graph<Node: Hashable> {    
	private var edgeBacking = EdgeBacking<Node>()
	private(set) var nodes = Set<Node>()
    
    public init<N: SequenceType, E: SequenceType where N.Generator.Element == Node, E.Generator.Element == (Node, Node)>(nodes: N, edges: E) {
        for node in nodes { addNode(node) }
        for edge in edges { addEdge(edge) }
    }
    
    public func adjacentNodes(node: Node) -> Set<Node> {
        return (edgeBacking.nodesReachableFromNode[node] ?? []).intersect(nodes)
    }
}

extension Graph {
    public init() {
        self.init(nodes: [])
    }
    
    public init<N: SequenceType where N.Generator.Element == Node>(nodes: N) {
        self.init(nodes: nodes, edges: [])
    }
}

extension Graph {
    public var edges: Set<Edge<Node>> {
        return Set(nodes.flatMap { a in
            self.adjacentNodes(a).map { b in
                Edge(a, b)
            }
        })
    }
}

extension Graph {
	private mutating func requireUniqueBacking() {
		if !isUniquelyReferencedNonObjC(&edgeBacking) {
			edgeBacking = edgeBacking.copyByTrimmingIrrelevantNodes(relevantNodes: nodes)
		}
	}
	
	public mutating func addNode(node: Node) {
		requireUniqueBacking()
		
		nodes.insert(node)
		edgeBacking.nodesReachableFromNode[node] = []
	}
		
	public mutating func addUndirectionalEdge(lhs: Node, _ rhs: Node) {
		requireUniqueBacking()
		assert(nodes.contains(lhs) && nodes.contains(rhs), "An edge must be between nodes in the graph.")
		edgeBacking.nodesReachableFromNode[lhs]?.insert(rhs)
		edgeBacking.nodesReachableFromNode[rhs]?.insert(lhs)
	}
    
    public mutating func addDirectedEdge(from lhs: Node, to rhs: Node) {
        requireUniqueBacking()
        assert(nodes.contains(lhs) && nodes.contains(rhs), "An edge must be between nodes in the graph.")
        edgeBacking.nodesReachableFromNode[lhs]?.insert(rhs)
    }
}

{'fraction_non_alphanumeric': 0.1267980820458178, 'fraction_numerical': 0.004794885455514118, 'mean_word_length': 3.068255687973998, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '764902', 'n_tokens_mistral': 1291, 'n_tokens_neox': 1229, 'n_words': 281}