{"codebase":{"name":"SwiftNodes","files":[{"name":"Package.swift","symbols":[{"range":{"start":{"line":4,"character":0},"end":{"line":33,"character":1}},"kind":13,"selectionRange":{"start":{"line":4,"character":4},"end":{"line":4,"character":11}},"name":"package"}],"code":"// swift-tools-version:5.6\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"SwiftNodes\",\n    platforms: [.iOS(.v13), .tvOS(.v13), .macOS(.v10_15), .watchOS(.v6)],\n    products: [\n        .library(\n            name: \"SwiftNodes\",\n            targets: [\"SwiftNodes\"]\n        ),\n    ],\n    dependencies: [\n        .package(\n            url: \"https://github.com/flowtoolz/SwiftyToolz.git\",\n            exact: \"0.5.1\"\n        )\n    ],\n    targets: [\n        .target(\n            name: \"SwiftNodes\",\n            dependencies: [\n                \"SwiftyToolz\"\n            ],\n            path: \"Code\"\n        ),\n        .testTarget(\n            name: \"SwiftNodesTests\",\n            dependencies: [\"SwiftNodes\", \"SwiftyToolz\"],\n            path: \"Tests\"\n        ),\n    ]\n)\n"}],"subfolders":[{"name":"Tests","files":[{"name":"EdgeTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":145,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":15}},"name":"EdgeTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":12,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":39}},"name":"testThatCodeInREADMECompiles()","children":[{"range":{"start":{"line":6,"character":8},"end":{"line":6,"character":54}},"kind":13,"selectionRange":{"start":{"line":6,"character":12},"end":{"line":6,"character":17}},"name":"graph"},{"range":{"start":{"line":9,"character":8},"end":{"line":9,"character":64}},"kind":13,"selectionRange":{"start":{"line":9,"character":12},"end":{"line":9,"character":27}},"name":"hasEdgeFrom1To2"},{"range":{"start":{"line":10,"character":8},"end":{"line":10,"character":45}},"kind":13,"selectionRange":{"start":{"line":10,"character":12},"end":{"line":10,"character":16}},"name":"edge"}]},{"range":{"start":{"line":14,"character":4},"end":{"line":31,"character":5}},"kind":6,"selectionRange":{"start":{"line":14,"character":9},"end":{"line":14,"character":43}},"name":"testInitializeWithValuesAndEdges()","children":[{"range":{"start":{"line":16,"character":8},"end":{"line":16,"character":71}},"kind":13,"selectionRange":{"start":{"line":16,"character":12},"end":{"line":16,"character":17}},"name":"graph"},{"range":{"start":{"line":23,"character":8},"end":{"line":23,"character":62}},"kind":23,"selectionRange":{"start":{"line":23,"character":15},"end":{"line":23,"character":32}},"name":"IdentifiableValue","children":[{"range":{"start":{"line":23,"character":49},"end":{"line":23,"character":60}},"kind":7,"selectionRange":{"start":{"line":23,"character":53},"end":{"line":23,"character":55}},"name":"id"}]},{"range":{"start":{"line":25,"character":8},"end":{"line":25,"character":100}},"kind":13,"selectionRange":{"start":{"line":25,"character":12},"end":{"line":25,"character":18}},"name":"values"},{"range":{"start":{"line":26,"character":8},"end":{"line":26,"character":102}},"kind":13,"selectionRange":{"start":{"line":26,"character":12},"end":{"line":26,"character":18}},"name":"graph2"}]},{"range":{"start":{"line":33,"character":4},"end":{"line":41,"character":5}},"kind":6,"selectionRange":{"start":{"line":33,"character":9},"end":{"line":33,"character":26}},"name":"testAddingEdges()","children":[{"range":{"start":{"line":34,"character":8},"end":{"line":34,"character":45}},"kind":13,"selectionRange":{"start":{"line":34,"character":12},"end":{"line":34,"character":17}},"name":"graph"}]},{"range":{"start":{"line":43,"character":4},"end":{"line":51,"character":5}},"kind":6,"selectionRange":{"start":{"line":43,"character":9},"end":{"line":43,"character":37}},"name":"testAddingEdgeWithBigCount()","children":[{"range":{"start":{"line":44,"character":8},"end":{"line":44,"character":45}},"kind":13,"selectionRange":{"start":{"line":44,"character":12},"end":{"line":44,"character":17}},"name":"graph"}]},{"range":{"start":{"line":53,"character":4},"end":{"line":59,"character":5}},"kind":6,"selectionRange":{"start":{"line":53,"character":9},"end":{"line":53,"character":31}},"name":"testEdgesAreDirected()","children":[{"range":{"start":{"line":54,"character":8},"end":{"line":54,"character":45}},"kind":13,"selectionRange":{"start":{"line":54,"character":12},"end":{"line":54,"character":17}},"name":"graph"}]},{"range":{"start":{"line":61,"character":4},"end":{"line":78,"character":5}},"kind":6,"selectionRange":{"start":{"line":61,"character":9},"end":{"line":61,"character":38}},"name":"testThreeWaysToRemoveAnEdge()","children":[{"range":{"start":{"line":62,"character":8},"end":{"line":62,"character":45}},"kind":13,"selectionRange":{"start":{"line":62,"character":12},"end":{"line":62,"character":17}},"name":"graph"},{"range":{"start":{"line":64,"character":8},"end":{"line":64,"character":51}},"kind":13,"selectionRange":{"start":{"line":64,"character":12},"end":{"line":64,"character":16}},"name":"edge"}]},{"range":{"start":{"line":80,"character":4},"end":{"line":144,"character":5}},"kind":6,"selectionRange":{"start":{"line":80,"character":9},"end":{"line":80,"character":56}},"name":"testInsertingConnectingAndDisconnectingValues()","children":[{"range":{"start":{"line":81,"character":8},"end":{"line":81,"character":31}},"kind":13,"selectionRange":{"start":{"line":81,"character":12},"end":{"line":81,"character":17}},"name":"graph"},{"range":{"start":{"line":85,"character":8},"end":{"line":85,"character":35}},"kind":13,"selectionRange":{"start":{"line":85,"character":12},"end":{"line":85,"character":17}},"name":"node1"},{"range":{"start":{"line":94,"character":8},"end":{"line":94,"character":35}},"kind":13,"selectionRange":{"start":{"line":94,"character":12},"end":{"line":94,"character":17}},"name":"node2"},{"range":{"start":{"line":98,"character":8},"end":{"line":98,"character":67}},"kind":13,"selectionRange":{"start":{"line":98,"character":12},"end":{"line":98,"character":18}},"name":"edge12"},{"range":{"start":{"line":108,"character":18},"end":{"line":108,"character":30}},"kind":13,"selectionRange":{"start":{"line":108,"character":18},"end":{"line":108,"character":30}},"name":"updatedNode1"},{"range":{"start":{"line":117,"character":18},"end":{"line":117,"character":30}},"kind":13,"selectionRange":{"start":{"line":117,"character":18},"end":{"line":117,"character":30}},"name":"updatedNode2"},{"range":{"start":{"line":130,"character":18},"end":{"line":130,"character":28}},"kind":13,"selectionRange":{"start":{"line":130,"character":18},"end":{"line":130,"character":28}},"name":"finalNode1"},{"range":{"start":{"line":131,"character":18},"end":{"line":131,"character":28}},"kind":13,"selectionRange":{"start":{"line":131,"character":18},"end":{"line":131,"character":28}},"name":"finalNode2"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass EdgeTests: XCTestCase {\n    \n    func testThatCodeInREADMECompiles() {\n        var graph: Graph<Int, Int, Double> = [1, 2, 3]\n        \n        graph.insertEdge(from: 1, to: 2)\n        let hasEdgeFrom1To2 = graph.containsEdge(from: 1, to: 2)\n        let edge = graph.edge(from: 1, to: 2)\n        graph.removeEdge(from: 1, to: 2)\n    }\n    \n    func testInitializeWithValuesAndEdges() throws {\n        // with values as node IDs\n        let graph = TestGraph(values: [-7, 0, 5, 42], edges: [(-7, 0)])\n        \n        XCTAssertNotNil(graph.edge(from: -7, to: 0))\n        XCTAssertEqual(graph.node(with: -7)?.descendantIDs.contains(0), true)\n        XCTAssertEqual(graph.node(with: 0)?.ancestorIDs.contains(-7), true)\n        \n        // with identifiable values\n        struct IdentifiableValue: Identifiable { let id: Int }\n        \n        let values: [IdentifiableValue] = [.init(id: -7), .init(id: 0), .init(id: 5), .init(id: 42)]\n        let graph2 = IdentifiableValuesGraph<IdentifiableValue, Int>(values: values, edges: [(-7, 0)])\n        \n        XCTAssertNotNil(graph2.edge(from: -7, to: 0))\n        XCTAssertEqual(graph2.node(with: -7)?.descendantIDs.contains(0), true)\n        XCTAssertEqual(graph2.node(with: 0)?.ancestorIDs.contains(-7), true)\n    }\n    \n    func testAddingEdges() throws {\n        var graph = TestGraph(values: [1, 2])\n        graph.insertEdge(from: 1, to: 2)\n        \n        XCTAssertNil(graph.edge(from: 1, to: 3))\n        XCTAssertNil(graph.edge(from: 0, to: 2))\n        XCTAssertNotNil(graph.edge(from: 1, to: 2))\n        XCTAssertEqual(graph.edge(from: 1, to: 2)?.weight, 1)\n    }\n    \n    func testAddingEdgeWithBigCount() throws {\n        var graph = TestGraph(values: [1, 2])\n        \n        graph.insertEdge(from: 1, to: 2, weight: 42)\n        XCTAssertEqual(graph.edge(from: 1, to: 2)?.weight, 42)\n        \n        graph.add(58, toEdgeWith: .init(1, 2))\n        XCTAssertEqual(graph.edge(from: 1, to: 2)?.weight, 100)\n    }\n    \n    func testEdgesAreDirected() throws {\n        var graph = TestGraph(values: [1, 2])\n        graph.insertEdge(from: 1, to: 2)\n        \n        XCTAssertNotNil(graph.edge(from: 1, to: 2))\n        XCTAssertNil(graph.edge(from: 2, to: 1))\n    }\n    \n    func testThreeWaysToRemoveAnEdge() {\n        var graph = TestGraph(values: [5, 3])\n        \n        let edge = graph.insertEdge(from: 5, to: 3)\n        XCTAssertNotNil(graph.edge(from: 5, to: 3))\n        graph.removeEdge(with: edge.id)\n        XCTAssertNil(graph.edge(from: 5, to: 3))\n        \n        graph.insertEdge(from: 5, to: 3)\n        XCTAssertNotNil(graph.edge(from: 5, to: 3))\n        graph.removeEdge(with: .init(5, 3))\n        XCTAssertNil(graph.edge(from: 5, to: 3))\n        \n        graph.insertEdge(from: 5, to: 3)\n        XCTAssertNotNil(graph.edge(from: 5, to: 3))\n        graph.removeEdge(from: 5, to: 3)\n        XCTAssertNil(graph.edge(from: 5, to: 3))\n    }\n    \n    func testInsertingConnectingAndDisconnectingValues() throws {\n        var graph = TestGraph()\n        XCTAssertNil(graph.node(with: 1))\n        XCTAssertNil(graph.value(for: 1))\n        \n        let node1 = graph.insert(1)\n        XCTAssertEqual(graph.value(for: 1), 1)\n        XCTAssertEqual(graph.node(with: 1)?.id, node1.id)\n        XCTAssertEqual(graph.insert(1).id, node1.id)\n        XCTAssertNil(graph.edge(from: 1, to: 2))\n        \n        XCTAssertEqual(node1.id, 1)\n        XCTAssertEqual(node1.value, 1)\n\n        let node2 = graph.insert(2)\n        XCTAssertNil(graph.edge(from: 1, to: 2))\n        XCTAssertNil(graph.edge(from: node1.id, to: node2.id))\n        \n        let edge12 = graph.insertEdge(from: node1.id, to: node2.id)\n        XCTAssertNotNil(graph.edge(from: 1, to: 2))\n        XCTAssertNotNil(graph.edge(from: node1.id, to: node2.id))\n        \n        XCTAssertEqual(edge12.weight, 1)\n        XCTAssertEqual(2, graph.add(1, toEdgeWith: .init(1, 2)))\n        XCTAssertEqual(graph.edge(from: node1.id, to: node2.id)?.weight, 2)\n        XCTAssertEqual(edge12.originID, node1.id)\n        XCTAssertEqual(edge12.destinationID, node2.id)\n        \n        guard let updatedNode1 = graph.node(with: node1.id) else\n        {\n            throw \"There should still exist a node for the id of node 1\"\n        }\n        \n        XCTAssertFalse(updatedNode1.isSink)\n        XCTAssert(updatedNode1.descendantIDs.contains(node2.id))\n        XCTAssert(updatedNode1.isSource)\n        \n        guard let updatedNode2 = graph.node(with: node2.id) else\n        {\n            throw \"There should still exist a node for the id of node 2\"\n        }\n        \n        XCTAssertFalse(updatedNode2.isSource)\n        XCTAssert(updatedNode2.ancestorIDs.contains(node1.id))\n        XCTAssert(updatedNode2.isSink)\n        \n        graph.removeEdge(with: edge12.id)\n        XCTAssertNil(graph.edge(from: 1, to: 2))\n        XCTAssertNil(graph.edge(from: node1.id, to: node2.id))\n        \n        guard let finalNode1 = graph.node(with: node1.id),\n              let finalNode2 = graph.node(with: node2.id) else\n        {\n            throw \"There should still exist node for the ids of nodes 1 and 2\"\n        }\n        \n        XCTAssert(finalNode1.ancestorIDs.isEmpty)\n        XCTAssert(finalNode1.descendantIDs.isEmpty)\n        XCTAssert(finalNode1.isSource)\n        XCTAssert(finalNode1.isSink)\n        XCTAssert(finalNode2.ancestorIDs.isEmpty)\n        XCTAssert(finalNode2.descendantIDs.isEmpty)\n        XCTAssert(finalNode2.isSource)\n        XCTAssert(finalNode2.isSink)\n    }\n}\n"},{"name":"ValueTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":103,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":16}},"name":"ValueTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":43,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":41}},"name":"testThatCodeFromREADMECompiles()","children":[{"range":{"start":{"line":7,"character":8},"end":{"line":8,"character":76}},"kind":13,"selectionRange":{"start":{"line":7,"character":12},"end":{"line":7,"character":17}},"name":"graph"},{"range":{"start":{"line":10,"character":8},"end":{"line":10,"character":55}},"kind":13,"selectionRange":{"start":{"line":10,"character":12},"end":{"line":10,"character":18}},"name":"graph2"},{"range":{"start":{"line":14,"character":8},"end":{"line":15,"character":73}},"kind":13,"selectionRange":{"start":{"line":14,"character":12},"end":{"line":14,"character":18}},"name":"graph3"},{"range":{"start":{"line":17,"character":8},"end":{"line":17,"character":54}},"kind":13,"selectionRange":{"start":{"line":17,"character":12},"end":{"line":17,"character":18}},"name":"graph4"},{"range":{"start":{"line":19,"character":8},"end":{"line":19,"character":66}},"kind":23,"selectionRange":{"start":{"line":19,"character":15},"end":{"line":19,"character":32}},"name":"IdentifiableValue","children":[{"range":{"start":{"line":19,"character":49},"end":{"line":19,"character":64}},"kind":7,"selectionRange":{"start":{"line":19,"character":53},"end":{"line":19,"character":55}},"name":"id"}]},{"range":{"start":{"line":22,"character":8},"end":{"line":22,"character":84}},"kind":13,"selectionRange":{"start":{"line":22,"character":12},"end":{"line":22,"character":18}},"name":"values"},{"range":{"start":{"line":23,"character":8},"end":{"line":23,"character":38}},"kind":13,"selectionRange":{"start":{"line":23,"character":12},"end":{"line":23,"character":15}},"name":"ids"},{"range":{"start":{"line":24,"character":8},"end":{"line":25,"character":91}},"kind":13,"selectionRange":{"start":{"line":24,"character":12},"end":{"line":24,"character":18}},"name":"graph5"},{"range":{"start":{"line":27,"character":8},"end":{"line":27,"character":49}},"kind":13,"selectionRange":{"start":{"line":27,"character":12},"end":{"line":27,"character":18}},"name":"graph6"},{"range":{"start":{"line":30,"character":8},"end":{"line":30,"character":32}},"kind":13,"selectionRange":{"start":{"line":30,"character":12},"end":{"line":30,"character":18}},"name":"valueA"},{"range":{"start":{"line":34,"character":8},"end":{"line":34,"character":43}},"kind":13,"selectionRange":{"start":{"line":34,"character":12},"end":{"line":34,"character":18}},"name":"valueB"},{"range":{"start":{"line":37,"character":8},"end":{"line":37,"character":37}},"kind":13,"selectionRange":{"start":{"line":37,"character":12},"end":{"line":37,"character":21}},"name":"allValues"},{"range":{"start":{"line":39,"character":8},"end":{"line":39,"character":46}},"kind":13,"selectionRange":{"start":{"line":39,"character":12},"end":{"line":39,"character":18}},"name":"graph7"}]},{"range":{"start":{"line":45,"character":4},"end":{"line":47,"character":5}},"kind":6,"selectionRange":{"start":{"line":45,"character":9},"end":{"line":45,"character":43}},"name":"testInitializingWithIDValuePairs()"},{"range":{"start":{"line":49,"character":4},"end":{"line":52,"character":5}},"kind":6,"selectionRange":{"start":{"line":49,"character":9},"end":{"line":49,"character":61}},"name":"testAccessingMutatingAndDeletingValuesViaSubscript()"},{"range":{"start":{"line":54,"character":4},"end":{"line":57,"character":5}},"kind":6,"selectionRange":{"start":{"line":54,"character":9},"end":{"line":54,"character":70}},"name":"testThatProvidingMultipleEdgesWithTheSameIDAddsTheirWeights()"},{"range":{"start":{"line":59,"character":4},"end":{"line":62,"character":5}},"kind":6,"selectionRange":{"start":{"line":59,"character":9},"end":{"line":59,"character":59}},"name":"testThatProvidingOrInferingDuplicateNodeIDsWorks()"},{"range":{"start":{"line":64,"character":4},"end":{"line":66,"character":5}},"kind":6,"selectionRange":{"start":{"line":64,"character":9},"end":{"line":64,"character":58}},"name":"testInitializingWithValuesWhereValuesAreNodeIDs()"},{"range":{"start":{"line":68,"character":4},"end":{"line":70,"character":5}},"kind":6,"selectionRange":{"start":{"line":68,"character":9},"end":{"line":68,"character":63}},"name":"testInitializingWithValuesWhereValuesAreIdentifiable()"},{"range":{"start":{"line":72,"character":4},"end":{"line":74,"character":5}},"kind":6,"selectionRange":{"start":{"line":72,"character":9},"end":{"line":72,"character":31}},"name":"testGettingAllValues()"},{"range":{"start":{"line":76,"character":4},"end":{"line":80,"character":5}},"kind":6,"selectionRange":{"start":{"line":76,"character":9},"end":{"line":76,"character":28}},"name":"testGettingValues()"},{"range":{"start":{"line":82,"character":4},"end":{"line":86,"character":5}},"kind":6,"selectionRange":{"start":{"line":82,"character":9},"end":{"line":82,"character":29}},"name":"testUpdatingValues()"},{"range":{"start":{"line":88,"character":4},"end":{"line":92,"character":5}},"kind":6,"selectionRange":{"start":{"line":88,"character":9},"end":{"line":88,"character":24}},"name":"testSubscript()"},{"range":{"start":{"line":94,"character":4},"end":{"line":98,"character":5}},"kind":6,"selectionRange":{"start":{"line":94,"character":9},"end":{"line":94,"character":51}},"name":"testInsertingValuesWhereValuesAreNodeIDs()"},{"range":{"start":{"line":100,"character":4},"end":{"line":102,"character":5}},"kind":6,"selectionRange":{"start":{"line":100,"character":9},"end":{"line":100,"character":56}},"name":"testInsertingValuesWhereValuesAreIdentifiable()"}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass ValueTests: XCTestCase {\n    \n    func testThatCodeFromREADMECompiles()\n    {\n        let graph = Graph<Int, Int, Double>(values: [1, 2, 3],\n                                            edges: [(1, 2), (2, 3), (1, 3)])\n        \n        let graph2: Graph<Int, Int, Double> = [1, 2, 3]\n        \n        typealias MyGraph = Graph<String, Int, Double>\n        \n        let graph3 = MyGraph(valuesByID: [\"a\": 1, \"b\": 2, \"c\": 3],\n                             edges: [(\"a\", \"b\"), (\"b\", \"c\"), (\"a\", \"c\")])\n        \n        let graph4: MyGraph = [\"a\": 1, \"b\": 2, \"c\": 3]\n        \n        struct IdentifiableValue: Identifiable { let id = UUID() }\n        typealias IVGraph = Graph<UUID, IdentifiableValue, Double>\n        \n        let values = [IdentifiableValue(), IdentifiableValue(), IdentifiableValue()]\n        let ids = values.map { $0.id }\n        let graph5 = IVGraph(values: values,\n                             edges: [(ids[0], ids[1]), (ids[1], ids[2]), (ids[0], ids[2])])\n        \n        var graph6 = Graph<String, Int, Double>()\n        \n        graph6[\"a\"] = 1\n        let valueA = graph6[\"a\"]\n        graph6[\"a\"] = nil\n        \n        graph6.update(2, for: \"b\")  // returns the updated/created `Node` but is `@discardable`\n        let valueB = graph6.value(for: \"b\")\n        graph6.removeValue(for: \"b\")  // returns the removed `NodeValue?` but is `@discardable`\n        \n        let allValues = graph6.values  // returns `some Collection`\n        \n        var graph7 = Graph<Int, Int, Double>()\n        \n        graph7.insert(1)  // returns the updated/created `Node` but is `@discardable`\n        graph7.remove(1)  // returns the removed `Node?` but is `@discardable`\n    }\n    \n    func testInitializingWithIDValuePairs() {\n        \n    }\n    \n    func testAccessingMutatingAndDeletingValuesViaSubscript()\n    {\n        \n    }\n    \n    func testThatProvidingMultipleEdgesWithTheSameIDAddsTheirWeights()\n    {\n        \n    }\n    \n    func testThatProvidingOrInferingDuplicateNodeIDsWorks()\n    {\n        \n    }\n    \n    func testInitializingWithValuesWhereValuesAreNodeIDs() {\n        \n    }\n    \n    func testInitializingWithValuesWhereValuesAreIdentifiable() {\n        \n    }\n    \n    func testGettingAllValues() {\n        \n    }\n    \n    func testGettingValues() {\n        \n        \n        \n    }\n    \n    func testUpdatingValues() {\n        \n        \n        \n    }\n    \n    func testSubscript() {\n        \n        \n        \n    }\n    \n    func testInsertingValuesWhereValuesAreNodeIDs() {\n        \n        \n        \n    }\n    \n    func testInsertingValuesWhereValuesAreIdentifiable() {\n        \n    }\n}\n"},{"name":"TestGraph.swift","symbols":[],"code":"import SwiftNodes\n\ntypealias TestGraph = HashableValuesGraph<Int, Int>\n"},{"name":"NodeTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":31,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":15}},"name":"NodeTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":14,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":29}},"name":"testInsertingNodes()","children":[{"range":{"start":{"line":6,"character":8},"end":{"line":6,"character":31}},"kind":13,"selectionRange":{"start":{"line":6,"character":12},"end":{"line":6,"character":17}},"name":"graph"},{"range":{"start":{"line":7,"character":8},"end":{"line":7,"character":35}},"kind":13,"selectionRange":{"start":{"line":7,"character":12},"end":{"line":7,"character":17}},"name":"node1"},{"range":{"start":{"line":9,"character":8},"end":{"line":9,"character":45}},"kind":13,"selectionRange":{"start":{"line":9,"character":12},"end":{"line":9,"character":23}},"name":"valueForID1"},{"range":{"start":{"line":10,"character":8},"end":{"line":10,"character":44}},"kind":13,"selectionRange":{"start":{"line":10,"character":12},"end":{"line":10,"character":22}},"name":"nodeForID1"}]},{"range":{"start":{"line":16,"character":4},"end":{"line":23,"character":5}},"kind":6,"selectionRange":{"start":{"line":16,"character":9},"end":{"line":16,"character":23}},"name":"testUUIDAsID()","children":[{"range":{"start":{"line":17,"character":8},"end":{"line":17,"character":46}},"kind":13,"selectionRange":{"start":{"line":17,"character":12},"end":{"line":17,"character":17}},"name":"graph"},{"range":{"start":{"line":18,"character":8},"end":{"line":18,"character":48}},"kind":13,"selectionRange":{"start":{"line":18,"character":12},"end":{"line":18,"character":17}},"name":"node1"},{"range":{"start":{"line":19,"character":8},"end":{"line":19,"character":48}},"kind":13,"selectionRange":{"start":{"line":19,"character":12},"end":{"line":19,"character":17}},"name":"node2"}]},{"range":{"start":{"line":25,"character":4},"end":{"line":30,"character":5}},"kind":6,"selectionRange":{"start":{"line":25,"character":9},"end":{"line":25,"character":51}},"name":"testOmittingClosureForIdentifiableValues()","children":[{"range":{"start":{"line":26,"character":8},"end":{"line":26,"character":66}},"kind":23,"selectionRange":{"start":{"line":26,"character":15},"end":{"line":26,"character":32}},"name":"IdentifiableValue","children":[{"range":{"start":{"line":26,"character":49},"end":{"line":26,"character":64}},"kind":7,"selectionRange":{"start":{"line":26,"character":53},"end":{"line":26,"character":55}},"name":"id"}]},{"range":{"start":{"line":27,"character":8},"end":{"line":27,"character":60}},"kind":13,"selectionRange":{"start":{"line":27,"character":12},"end":{"line":27,"character":17}},"name":"graph"},{"range":{"start":{"line":28,"character":8},"end":{"line":28,"character":52}},"kind":13,"selectionRange":{"start":{"line":28,"character":12},"end":{"line":28,"character":16}},"name":"node"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass NodeTests: XCTestCase {\n    \n    func testInsertingNodes() throws {\n        var graph = TestGraph()\n        let node1 = graph.insert(1)\n        \n        let valueForID1 = graph.value(for: 1)\n        let nodeForID1 = graph.node(with: 1)\n        \n        XCTAssertEqual(valueForID1, node1.value)\n        XCTAssertEqual(nodeForID1?.id, node1.id)\n    }\n    \n    func testUUIDAsID() throws {\n        var graph = Graph<UUID, Int, Double>()\n        let node1 = graph.update(1, for: UUID())\n        let node2 = graph.update(1, for: UUID())\n        XCTAssertNotEqual(node1.id, node2.id)\n        XCTAssertEqual(node1.value, node2.value)\n        XCTAssertNotEqual(node1.id, node2.id)\n    }\n    \n    func testOmittingClosureForIdentifiableValues() throws {\n        struct IdentifiableValue: Identifiable { let id = UUID() }\n        var graph = Graph<UUID, IdentifiableValue, Double>()\n        let node = graph.insert(IdentifiableValue())  // node.id == node.value.id\n        XCTAssertEqual(node.id, node.value.id)\n    }\n}\n"}],"subfolders":[{"name":"Algorithms","files":[{"name":"AncestorCountsTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":48,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":25}},"name":"AncestorCountsTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":8,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":25}},"name":"testEmptyGraph()"},{"range":{"start":{"line":10,"character":4},"end":{"line":15,"character":5}},"kind":6,"selectionRange":{"start":{"line":10,"character":9},"end":{"line":10,"character":32}},"name":"testGraphWithoutEdges()","children":[{"range":{"start":{"line":11,"character":8},"end":{"line":11,"character":48}},"kind":13,"selectionRange":{"start":{"line":11,"character":12},"end":{"line":11,"character":17}},"name":"graph"}]},{"range":{"start":{"line":17,"character":4},"end":{"line":23,"character":5}},"kind":6,"selectionRange":{"start":{"line":17,"character":9},"end":{"line":17,"character":42}},"name":"testGraphWithoutTransitiveEdges()","children":[{"range":{"start":{"line":18,"character":8},"end":{"line":19,"character":54}},"kind":13,"selectionRange":{"start":{"line":18,"character":12},"end":{"line":18,"character":17}},"name":"graph"}]},{"range":{"start":{"line":25,"character":4},"end":{"line":31,"character":5}},"kind":6,"selectionRange":{"start":{"line":25,"character":9},"end":{"line":25,"character":41}},"name":"testGraphWithOneTransitiveEdge()","children":[{"range":{"start":{"line":26,"character":8},"end":{"line":27,"character":62}},"kind":13,"selectionRange":{"start":{"line":26,"character":12},"end":{"line":26,"character":17}},"name":"graph"}]},{"range":{"start":{"line":33,"character":4},"end":{"line":39,"character":5}},"kind":6,"selectionRange":{"start":{"line":33,"character":9},"end":{"line":33,"character":62}},"name":"testGraphWithTwoComponentsEachWithOneTransitiveEdge()","children":[{"range":{"start":{"line":34,"character":8},"end":{"line":35,"character":86}},"kind":13,"selectionRange":{"start":{"line":34,"character":12},"end":{"line":34,"character":17}},"name":"graph"}]},{"range":{"start":{"line":41,"character":4},"end":{"line":47,"character":5}},"kind":6,"selectionRange":{"start":{"line":41,"character":9},"end":{"line":41,"character":49}},"name":"testGraphWithTwoSourcesAnd4PathsToSink()","children":[{"range":{"start":{"line":42,"character":8},"end":{"line":43,"character":86}},"kind":13,"selectionRange":{"start":{"line":42,"character":12},"end":{"line":42,"character":17}},"name":"graph"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass AncestorCountsTests: XCTestCase {\n    \n    func testEmptyGraph() {\n        XCTAssertEqual(TestGraph().findNumberOfNodeAncestors(),\n                       [:])\n    }\n    \n    func testGraphWithoutEdges() {\n        let graph = TestGraph(values: [1, 2, 3])\n        \n        XCTAssertEqual(graph.findNumberOfNodeAncestors(),\n                       [1: 0, 2: 0, 3: 0])\n    }\n    \n    func testGraphWithoutTransitiveEdges() {\n        let graph = TestGraph(values: [1, 2, 3],\n                              edges: [(1, 2), (2, 3)])\n        \n        XCTAssertEqual(graph.findNumberOfNodeAncestors(),\n                       [1: 0, 2: 1, 3: 2])\n    }\n    \n    func testGraphWithOneTransitiveEdge() {\n        let graph = TestGraph(values: [1, 2, 3],\n                              edges: [(1, 2), (2, 3), (1, 3)])\n        \n        XCTAssertEqual(graph.findNumberOfNodeAncestors(),\n                       [1: 0, 2: 1, 3: 2])\n    }\n    \n    func testGraphWithTwoComponentsEachWithOneTransitiveEdge() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(1, 2), (2, 3), (1, 3), (4, 5), (5, 6), (4, 6)])\n        \n        XCTAssertEqual(graph.findNumberOfNodeAncestors(),\n                       [1: 0, 2: 1, 3: 2, 4: 0, 5: 1, 6: 2])\n    }\n    \n    func testGraphWithTwoSourcesAnd4PathsToSink() {\n        let graph = TestGraph(values: [0, 1, 2, 3, 4, 5],\n                              edges: [(0, 2), (1, 2), (2, 3), (2, 4), (3, 5), (4, 5)])\n        \n        XCTAssertEqual(graph.findNumberOfNodeAncestors(),\n                       [0: 0, 1: 0, 2: 2, 3: 3, 4: 3, 5: 5])\n    }\n}\n"},{"name":"CondensationGraphTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":110,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":28}},"name":"CondensationGraphTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":19,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":32}},"name":"testGraphWithoutEdges()","children":[{"range":{"start":{"line":6,"character":8},"end":{"line":6,"character":48}},"kind":13,"selectionRange":{"start":{"line":6,"character":12},"end":{"line":6,"character":17}},"name":"graph"},{"range":{"start":{"line":8,"character":8},"end":{"line":8,"character":61}},"kind":13,"selectionRange":{"start":{"line":8,"character":12},"end":{"line":8,"character":29}},"name":"condensationGraph"},{"range":{"start":{"line":10,"character":8},"end":{"line":16,"character":9}},"kind":13,"selectionRange":{"start":{"line":10,"character":12},"end":{"line":10,"character":37}},"name":"expectedCondensationGraph"}]},{"range":{"start":{"line":21,"character":4},"end":{"line":43,"character":5}},"kind":6,"selectionRange":{"start":{"line":21,"character":9},"end":{"line":21,"character":33}},"name":"testGraphWithoutCycles()","children":[{"range":{"start":{"line":22,"character":8},"end":{"line":23,"character":78}},"kind":13,"selectionRange":{"start":{"line":22,"character":12},"end":{"line":22,"character":17}},"name":"graph"},{"range":{"start":{"line":25,"character":8},"end":{"line":25,"character":61}},"kind":13,"selectionRange":{"start":{"line":25,"character":12},"end":{"line":25,"character":29}},"name":"condensationGraph"},{"range":{"start":{"line":27,"character":8},"end":{"line":30,"character":9}},"kind":13,"selectionRange":{"start":{"line":27,"character":12},"end":{"line":27,"character":25}},"name":"expectedEdges"},{"range":{"start":{"line":32,"character":8},"end":{"line":40,"character":9}},"kind":13,"selectionRange":{"start":{"line":32,"character":12},"end":{"line":32,"character":37}},"name":"expectedCondensationGraph"}]},{"range":{"start":{"line":45,"character":4},"end":{"line":56,"character":5}},"kind":6,"selectionRange":{"start":{"line":45,"character":9},"end":{"line":45,"character":34}},"name":"testGraphMadeOfOneCycle()","children":[{"range":{"start":{"line":46,"character":8},"end":{"line":47,"character":70}},"kind":13,"selectionRange":{"start":{"line":46,"character":12},"end":{"line":46,"character":17}},"name":"graph"},{"range":{"start":{"line":49,"character":8},"end":{"line":49,"character":61}},"kind":13,"selectionRange":{"start":{"line":49,"character":12},"end":{"line":49,"character":29}},"name":"condensationGraph"},{"range":{"start":{"line":51,"character":8},"end":{"line":53,"character":9}},"kind":13,"selectionRange":{"start":{"line":51,"character":12},"end":{"line":51,"character":37}},"name":"expectedCondensationGraph"}]},{"range":{"start":{"line":58,"character":4},"end":{"line":72,"character":5}},"kind":6,"selectionRange":{"start":{"line":58,"character":9},"end":{"line":58,"character":38}},"name":"testGraphContainingOneCycle()","children":[{"range":{"start":{"line":59,"character":8},"end":{"line":60,"character":70}},"kind":13,"selectionRange":{"start":{"line":59,"character":12},"end":{"line":59,"character":17}},"name":"graph"},{"range":{"start":{"line":62,"character":8},"end":{"line":62,"character":61}},"kind":13,"selectionRange":{"start":{"line":62,"character":12},"end":{"line":62,"character":29}},"name":"condensationGraph"},{"range":{"start":{"line":64,"character":8},"end":{"line":64,"character":70}},"kind":13,"selectionRange":{"start":{"line":64,"character":12},"end":{"line":64,"character":25}},"name":"expectedEdges"},{"range":{"start":{"line":66,"character":8},"end":{"line":69,"character":9}},"kind":13,"selectionRange":{"start":{"line":66,"character":12},"end":{"line":66,"character":37}},"name":"expectedCondensationGraph"}]},{"range":{"start":{"line":74,"character":4},"end":{"line":88,"character":5}},"kind":6,"selectionRange":{"start":{"line":74,"character":9},"end":{"line":74,"character":39}},"name":"testGraphContainingTwoCycles()","children":[{"range":{"start":{"line":75,"character":8},"end":{"line":76,"character":94}},"kind":13,"selectionRange":{"start":{"line":75,"character":12},"end":{"line":75,"character":17}},"name":"graph"},{"range":{"start":{"line":78,"character":8},"end":{"line":78,"character":61}},"kind":13,"selectionRange":{"start":{"line":78,"character":12},"end":{"line":78,"character":29}},"name":"condensationGraph"},{"range":{"start":{"line":80,"character":8},"end":{"line":80,"character":76}},"kind":13,"selectionRange":{"start":{"line":80,"character":12},"end":{"line":80,"character":25}},"name":"expectedEdges"},{"range":{"start":{"line":82,"character":8},"end":{"line":85,"character":9}},"kind":13,"selectionRange":{"start":{"line":82,"character":12},"end":{"line":82,"character":37}},"name":"expectedCondensationGraph"}]},{"range":{"start":{"line":90,"character":4},"end":{"line":109,"character":5}},"kind":6,"selectionRange":{"start":{"line":90,"character":9},"end":{"line":90,"character":43}},"name":"testGraphContainingTwoComponents()","children":[{"range":{"start":{"line":91,"character":8},"end":{"line":92,"character":86}},"kind":13,"selectionRange":{"start":{"line":91,"character":12},"end":{"line":91,"character":17}},"name":"graph"},{"range":{"start":{"line":94,"character":8},"end":{"line":94,"character":61}},"kind":13,"selectionRange":{"start":{"line":94,"character":12},"end":{"line":94,"character":29}},"name":"condensationGraph"},{"range":{"start":{"line":96,"character":8},"end":{"line":96,"character":88}},"kind":13,"selectionRange":{"start":{"line":96,"character":12},"end":{"line":96,"character":25}},"name":"expectedEdges"},{"range":{"start":{"line":98,"character":8},"end":{"line":106,"character":9}},"kind":13,"selectionRange":{"start":{"line":98,"character":12},"end":{"line":98,"character":37}},"name":"expectedCondensationGraph"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass CondensationGraphTests: XCTestCase {\n    \n    func testGraphWithoutEdges() {\n        let graph = TestGraph(values: [1, 2, 3])\n        \n        let condensationGraph = graph.makeCondensationGraph()\n        \n        let expectedCondensationGraph = TestGraph.CondensationGraph(\n            values: [\n                .init(nodeIDs: [1]),\n                .init(nodeIDs: [2]),\n                .init(nodeIDs: [3])\n            ]\n        )\n        \n        XCTAssertEqual(condensationGraph, expectedCondensationGraph)\n    }\n    \n    func testGraphWithoutCycles() {\n        let graph = TestGraph(values: [1, 2, 3, 4],\n                              edges: [(1, 2), (2, 3), (3, 4), (1, 3), (2, 4)])\n        \n        let condensationGraph = graph.makeCondensationGraph()\n        \n        let expectedEdges: [(Set<Int>, Set<Int>)] =\n        [\n            ([1], [2]), ([2], [3]), ([3], [4]), ([1], [3]), ([2], [4])\n        ]\n        \n        let expectedCondensationGraph = TestGraph.CondensationGraph(\n            values: [\n                .init(nodeIDs: [1]),\n                .init(nodeIDs: [2]),\n                .init(nodeIDs: [3]),\n                .init(nodeIDs: [4])\n            ],\n            edges: expectedEdges\n        )\n        \n        XCTAssertEqual(condensationGraph, expectedCondensationGraph)\n    }\n    \n    func testGraphMadeOfOneCycle() {\n        let graph = TestGraph(values: [1, 2, 3, 4],\n                              edges: [(1, 2), (2, 3), (3, 4), (4, 1)])\n        \n        let condensationGraph = graph.makeCondensationGraph()\n        \n        let expectedCondensationGraph = TestGraph.CondensationGraph(\n            values: [.init(nodeIDs: [1, 2, 3, 4])]\n        )\n        \n        XCTAssertEqual(condensationGraph, expectedCondensationGraph)\n    }\n    \n    func testGraphContainingOneCycle() {\n        let graph = TestGraph(values: [1, 2, 3, 4],\n                              edges: [(1, 2), (2, 3), (3, 1), (3, 4)])\n        \n        let condensationGraph = graph.makeCondensationGraph()\n        \n        let expectedEdges: [(Set<Int>, Set<Int>)] = [([1, 2, 3], [4])]\n        \n        let expectedCondensationGraph = TestGraph.CondensationGraph(\n            values: [.init(nodeIDs: [1, 2, 3]), .init(nodeIDs: [4])],\n            edges: expectedEdges\n        )\n        \n        XCTAssertEqual(condensationGraph, expectedCondensationGraph)\n    }\n    \n    func testGraphContainingTwoCycles() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5), (5, 6), (6, 4)])\n        \n        let condensationGraph = graph.makeCondensationGraph()\n        \n        let expectedEdges: [(Set<Int>, Set<Int>)] = [([1, 2, 3], [4, 5, 6])]\n        \n        let expectedCondensationGraph = TestGraph.CondensationGraph(\n            values: [.init(nodeIDs: [1, 2, 3]), .init(nodeIDs: [4, 5, 6])],\n            edges: expectedEdges\n        )\n        \n        XCTAssertEqual(condensationGraph, expectedCondensationGraph)\n    }\n    \n    func testGraphContainingTwoComponents() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(1, 2), (2, 3), (1, 3), (4, 5), (5, 6), (6, 4)])\n        \n        let condensationGraph = graph.makeCondensationGraph()\n        \n        let expectedEdges: [(Set<Int>, Set<Int>)] = [([1], [2]), ([2], [3]), ([1], [3])]\n        \n        let expectedCondensationGraph = TestGraph.CondensationGraph(\n            values: [\n                .init(nodeIDs: [1]),\n                .init(nodeIDs: [2]),\n                .init(nodeIDs: [3]),\n                .init(nodeIDs: [4, 5, 6])\n            ],\n            edges: expectedEdges\n        )\n        \n        XCTAssertEqual(condensationGraph, expectedCondensationGraph)\n    }\n}\n"},{"name":"EssentialEdgesTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":77,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":25}},"name":"EssentialEdgesTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":7,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":25}},"name":"testEmptyGraph()"},{"range":{"start":{"line":9,"character":4},"end":{"line":13,"character":5}},"kind":6,"selectionRange":{"start":{"line":9,"character":9},"end":{"line":9,"character":32}},"name":"testGraphWithoutEdges()","children":[{"range":{"start":{"line":10,"character":8},"end":{"line":10,"character":48}},"kind":13,"selectionRange":{"start":{"line":10,"character":12},"end":{"line":10,"character":17}},"name":"graph"}]},{"range":{"start":{"line":15,"character":4},"end":{"line":21,"character":5}},"kind":6,"selectionRange":{"start":{"line":15,"character":9},"end":{"line":15,"character":42}},"name":"testGraphWithoutTransitiveEdges()","children":[{"range":{"start":{"line":16,"character":8},"end":{"line":17,"character":54}},"kind":13,"selectionRange":{"start":{"line":16,"character":12},"end":{"line":16,"character":17}},"name":"graph"}]},{"range":{"start":{"line":23,"character":4},"end":{"line":29,"character":5}},"kind":6,"selectionRange":{"start":{"line":23,"character":9},"end":{"line":23,"character":41}},"name":"testGraphWithOneTransitiveEdge()","children":[{"range":{"start":{"line":24,"character":8},"end":{"line":25,"character":62}},"kind":13,"selectionRange":{"start":{"line":24,"character":12},"end":{"line":24,"character":17}},"name":"graph"}]},{"range":{"start":{"line":31,"character":4},"end":{"line":60,"character":5}},"kind":6,"selectionRange":{"start":{"line":31,"character":9},"end":{"line":31,"character":50}},"name":"testAcyclicGraphWithManyTransitiveEdges()","children":[{"range":{"start":{"line":32,"character":8},"end":{"line":32,"character":31}},"kind":13,"selectionRange":{"start":{"line":32,"character":12},"end":{"line":32,"character":17}},"name":"graph"},{"range":{"start":{"line":34,"character":8},"end":{"line":34,"character":30}},"kind":13,"selectionRange":{"start":{"line":34,"character":12},"end":{"line":34,"character":25}},"name":"numberOfNodes"},{"range":{"start":{"line":36,"character":12},"end":{"line":36,"character":13}},"kind":13,"selectionRange":{"start":{"line":36,"character":12},"end":{"line":36,"character":13}},"name":"j"},{"range":{"start":{"line":40,"character":16},"end":{"line":40,"character":17}},"kind":13,"selectionRange":{"start":{"line":40,"character":16},"end":{"line":40,"character":17}},"name":"i"},{"range":{"start":{"line":47,"character":8},"end":{"line":47,"character":89}},"kind":13,"selectionRange":{"start":{"line":47,"character":12},"end":{"line":47,"character":33}},"name":"expectedNumberOfEdges"},{"range":{"start":{"line":52,"character":8},"end":{"line":52,"character":61}},"kind":13,"selectionRange":{"start":{"line":52,"character":12},"end":{"line":52,"character":34}},"name":"expectedEssentialEdges"},{"range":{"start":{"line":54,"character":12},"end":{"line":54,"character":13}},"kind":13,"selectionRange":{"start":{"line":54,"character":12},"end":{"line":54,"character":13}},"name":"i"}]},{"range":{"start":{"line":62,"character":4},"end":{"line":67,"character":5}},"kind":6,"selectionRange":{"start":{"line":62,"character":9},"end":{"line":62,"character":54}},"name":"testGraphWithTwoCyclesAndOnlyEssentialEdges()","children":[{"range":{"start":{"line":63,"character":8},"end":{"line":64,"character":94}},"kind":13,"selectionRange":{"start":{"line":63,"character":12},"end":{"line":63,"character":17}},"name":"graph"}]},{"range":{"start":{"line":69,"character":4},"end":{"line":76,"character":5}},"kind":6,"selectionRange":{"start":{"line":69,"character":9},"end":{"line":69,"character":55}},"name":"testGraphWithTwoCyclesAndOneNonEssentialEdge()","children":[{"range":{"start":{"line":70,"character":8},"end":{"line":71,"character":110}},"kind":13,"selectionRange":{"start":{"line":70,"character":12},"end":{"line":70,"character":17}},"name":"graph"},{"range":{"start":{"line":73,"character":8},"end":{"line":73,"character":89}},"kind":13,"selectionRange":{"start":{"line":73,"character":12},"end":{"line":73,"character":41}},"name":"allEdgesExceptNonEssentialOne"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass EssentialEdgesTests: XCTestCase {\n    \n    func testEmptyGraph() {\n        XCTAssert(TestGraph().findEssentialEdges().isEmpty)\n    }\n    \n    func testGraphWithoutEdges() {\n        let graph = TestGraph(values: [1, 2, 3])\n        \n        XCTAssert(graph.findEssentialEdges().isEmpty)\n    }\n    \n    func testGraphWithoutTransitiveEdges() {\n        let graph = TestGraph(values: [1, 2, 3],\n                              edges: [(1, 2), (2, 3)])\n        \n        XCTAssertEqual(graph.findEssentialEdges(),\n                       [.init(1, 2), .init(2, 3)])\n    }\n    \n    func testGraphWithOneTransitiveEdge() {\n        let graph = TestGraph(values: [1, 2, 3],\n                              edges: [(1, 2), (2, 3), (1, 3)])\n        \n        XCTAssertEqual(graph.findEssentialEdges(),\n                       [.init(1, 2), .init(2, 3)])\n    }\n    \n    func testAcyclicGraphWithManyTransitiveEdges() {\n        var graph = TestGraph()\n        \n        let numberOfNodes = 10\n        \n        for j in 0 ..< numberOfNodes\n        {\n            graph.insert(j)\n            \n            for i in 0 ..< j\n            {\n                graph.insertEdge(from: i, to: j)\n            }\n        }\n        \n        // sanity check\n        let expectedNumberOfEdges = ((numberOfNodes * numberOfNodes) - numberOfNodes) / 2\n        XCTAssertEqual(graph.edges.count, expectedNumberOfEdges)\n        \n        // only edges between neighbouring numbers are essential (0 -> 1 -> 2 ...)\n        \n        var expectedEssentialEdges = Set<TestGraph.Edge.ID>()\n        \n        for i in 1 ..< numberOfNodes\n        {\n            expectedEssentialEdges.insert(.init(i - 1, i))\n        }\n        \n        XCTAssertEqual(graph.findEssentialEdges(), expectedEssentialEdges)\n    }\n    \n    func testGraphWithTwoCyclesAndOnlyEssentialEdges() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5), (5, 6), (6, 4)])\n        \n        XCTAssertEqual(graph.findEssentialEdges(), Set(graph.edgeIDs))\n    }\n    \n    func testGraphWithTwoCyclesAndOneNonEssentialEdge() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6, 7],\n                              edges: [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5), (5, 6), (6, 4), (6, 7), (3, 7)])\n        \n        let allEdgesExceptNonEssentialOne = Set(graph.edgeIDs).subtracting([.init(3, 7)])\n        \n        XCTAssertEqual(graph.findEssentialEdges(), allEdgesExceptNonEssentialOne)\n    }\n}\n"},{"name":"ComponentTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":42,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":20}},"name":"ComponentTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":7,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":25}},"name":"testEmptyGraph()"},{"range":{"start":{"line":9,"character":4},"end":{"line":15,"character":5}},"kind":6,"selectionRange":{"start":{"line":9,"character":9},"end":{"line":9,"character":32}},"name":"testGraphWithoutEdges()","children":[{"range":{"start":{"line":10,"character":8},"end":{"line":10,"character":48}},"kind":13,"selectionRange":{"start":{"line":10,"character":12},"end":{"line":10,"character":17}},"name":"graph"},{"range":{"start":{"line":12,"character":8},"end":{"line":12,"character":63}},"kind":13,"selectionRange":{"start":{"line":12,"character":12},"end":{"line":12,"character":30}},"name":"expectedComponents"}]},{"range":{"start":{"line":17,"character":4},"end":{"line":23,"character":5}},"kind":6,"selectionRange":{"start":{"line":17,"character":9},"end":{"line":17,"character":40}},"name":"testGraphWithOneTrueComponent()","children":[{"range":{"start":{"line":18,"character":8},"end":{"line":18,"character":73}},"kind":13,"selectionRange":{"start":{"line":18,"character":12},"end":{"line":18,"character":17}},"name":"graph"},{"range":{"start":{"line":20,"character":8},"end":{"line":20,"character":59}},"kind":13,"selectionRange":{"start":{"line":20,"character":12},"end":{"line":20,"character":30}},"name":"expectedComponents"}]},{"range":{"start":{"line":25,"character":4},"end":{"line":32,"character":5}},"kind":6,"selectionRange":{"start":{"line":25,"character":9},"end":{"line":25,"character":42}},"name":"testGraphWithMultipleComponents()","children":[{"range":{"start":{"line":26,"character":8},"end":{"line":27,"character":62}},"kind":13,"selectionRange":{"start":{"line":26,"character":12},"end":{"line":26,"character":17}},"name":"graph"},{"range":{"start":{"line":29,"character":8},"end":{"line":29,"character":72}},"kind":13,"selectionRange":{"start":{"line":29,"character":12},"end":{"line":29,"character":30}},"name":"expectedComponents"}]},{"range":{"start":{"line":34,"character":4},"end":{"line":41,"character":5}},"kind":6,"selectionRange":{"start":{"line":34,"character":9},"end":{"line":34,"character":51}},"name":"testGraphWithMultipleComponentsAndCycles()","children":[{"range":{"start":{"line":35,"character":8},"end":{"line":36,"character":78}},"kind":13,"selectionRange":{"start":{"line":35,"character":12},"end":{"line":35,"character":17}},"name":"graph"},{"range":{"start":{"line":38,"character":8},"end":{"line":38,"character":72}},"kind":13,"selectionRange":{"start":{"line":38,"character":12},"end":{"line":38,"character":30}},"name":"expectedComponents"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass ComponentTests: XCTestCase {\n    \n    func testEmptyGraph() {\n        XCTAssertEqual(TestGraph().findComponents().count, 0)\n    }\n    \n    func testGraphWithoutEdges() {\n        let graph = TestGraph(values: [1, 2, 3])\n        \n        let expectedComponents: Set<Set<Int>> = [[1], [2], [3]]\n        \n        XCTAssertEqual(graph.findComponents(), expectedComponents)\n    }\n    \n    func testGraphWithOneTrueComponent() {\n        let graph = TestGraph(values: [1, 2, 3], edges: [(1, 2), (2, 3)])\n        \n        let expectedComponents: Set<Set<Int>> = [[1, 2, 3]]\n        \n        XCTAssertEqual(graph.findComponents(), expectedComponents)\n    }\n    \n    func testGraphWithMultipleComponents() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(2, 3), (4, 5), (5, 6)])\n        \n        let expectedComponents: Set<Set<Int>> = [[1], [2, 3], [4, 5, 6]]\n        \n        XCTAssertEqual(graph.findComponents(), expectedComponents)\n    }\n    \n    func testGraphWithMultipleComponentsAndCycles() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(2, 3), (3, 2), (4, 5), (5, 6), (6, 4)])\n        \n        let expectedComponents: Set<Set<Int>> = [[1], [2, 3], [4, 5, 6]]\n        \n        XCTAssertEqual(graph.findComponents(), expectedComponents)\n    }\n}\n"},{"name":"SCCTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":60,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":14}},"name":"SCCTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":7,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":25}},"name":"testEmptyGraph()"},{"range":{"start":{"line":9,"character":4},"end":{"line":15,"character":5}},"kind":6,"selectionRange":{"start":{"line":9,"character":9},"end":{"line":9,"character":32}},"name":"testGraphWithoutEdges()","children":[{"range":{"start":{"line":10,"character":8},"end":{"line":10,"character":48}},"kind":13,"selectionRange":{"start":{"line":10,"character":12},"end":{"line":10,"character":17}},"name":"graph"},{"range":{"start":{"line":12,"character":8},"end":{"line":12,"character":63}},"kind":13,"selectionRange":{"start":{"line":12,"character":12},"end":{"line":12,"character":30}},"name":"expectedComponents"}]},{"range":{"start":{"line":17,"character":4},"end":{"line":23,"character":5}},"kind":6,"selectionRange":{"start":{"line":17,"character":9},"end":{"line":17,"character":40}},"name":"testGraphWithOneTrueComponent()","children":[{"range":{"start":{"line":18,"character":8},"end":{"line":18,"character":73}},"kind":13,"selectionRange":{"start":{"line":18,"character":12},"end":{"line":18,"character":17}},"name":"graph"},{"range":{"start":{"line":20,"character":8},"end":{"line":20,"character":63}},"kind":13,"selectionRange":{"start":{"line":20,"character":12},"end":{"line":20,"character":30}},"name":"expectedComponents"}]},{"range":{"start":{"line":25,"character":4},"end":{"line":32,"character":5}},"kind":6,"selectionRange":{"start":{"line":25,"character":9},"end":{"line":25,"character":42}},"name":"testGraphWithMultipleComponents()","children":[{"range":{"start":{"line":26,"character":8},"end":{"line":27,"character":62}},"kind":13,"selectionRange":{"start":{"line":26,"character":12},"end":{"line":26,"character":17}},"name":"graph"},{"range":{"start":{"line":29,"character":8},"end":{"line":29,"character":78}},"kind":13,"selectionRange":{"start":{"line":29,"character":12},"end":{"line":29,"character":30}},"name":"expectedComponents"}]},{"range":{"start":{"line":34,"character":4},"end":{"line":41,"character":5}},"kind":6,"selectionRange":{"start":{"line":34,"character":9},"end":{"line":34,"character":51}},"name":"testGraphWithMultipleComponentsAndCycles()","children":[{"range":{"start":{"line":35,"character":8},"end":{"line":36,"character":78}},"kind":13,"selectionRange":{"start":{"line":35,"character":12},"end":{"line":35,"character":17}},"name":"graph"},{"range":{"start":{"line":38,"character":8},"end":{"line":38,"character":72}},"kind":13,"selectionRange":{"start":{"line":38,"character":12},"end":{"line":38,"character":30}},"name":"expectedComponents"}]},{"range":{"start":{"line":43,"character":4},"end":{"line":50,"character":5}},"kind":6,"selectionRange":{"start":{"line":43,"character":9},"end":{"line":43,"character":35}},"name":"testGraphWithOneBigCycle()","children":[{"range":{"start":{"line":44,"character":8},"end":{"line":45,"character":78}},"kind":13,"selectionRange":{"start":{"line":44,"character":12},"end":{"line":44,"character":17}},"name":"graph"},{"range":{"start":{"line":47,"character":8},"end":{"line":47,"character":65}},"kind":13,"selectionRange":{"start":{"line":47,"character":12},"end":{"line":47,"character":30}},"name":"expectedComponents"}]},{"range":{"start":{"line":52,"character":4},"end":{"line":59,"character":5}},"kind":6,"selectionRange":{"start":{"line":52,"character":9},"end":{"line":52,"character":42}},"name":"testGraphWithTwoConnectedCycles()","children":[{"range":{"start":{"line":53,"character":8},"end":{"line":54,"character":86}},"kind":13,"selectionRange":{"start":{"line":53,"character":12},"end":{"line":53,"character":17}},"name":"graph"},{"range":{"start":{"line":56,"character":8},"end":{"line":56,"character":70}},"kind":13,"selectionRange":{"start":{"line":56,"character":12},"end":{"line":56,"character":30}},"name":"expectedComponents"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass SCCTests: XCTestCase {\n    \n    func testEmptyGraph() {\n        XCTAssertEqual(TestGraph().findStronglyConnectedComponents().count, 0)\n    }\n    \n    func testGraphWithoutEdges() {\n        let graph = TestGraph(values: [1, 2, 3])\n        \n        let expectedComponents: Set<Set<Int>> = [[1], [2], [3]]\n        \n        XCTAssertEqual(graph.findStronglyConnectedComponents(), expectedComponents)\n    }\n    \n    func testGraphWithOneTrueComponent() {\n        let graph = TestGraph(values: [1, 2, 3], edges: [(1, 2), (2, 3)])\n        \n        let expectedComponents: Set<Set<Int>> = [[1], [2], [3]]\n        \n        XCTAssertEqual(graph.findStronglyConnectedComponents(), expectedComponents)\n    }\n    \n    func testGraphWithMultipleComponents() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(2, 3), (4, 5), (5, 6)])\n        \n        let expectedComponents: Set<Set<Int>> = [[1], [2], [3], [4], [5], [6]]\n        \n        XCTAssertEqual(graph.findStronglyConnectedComponents(), expectedComponents)\n    }\n    \n    func testGraphWithMultipleComponentsAndCycles() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(2, 3), (3, 2), (4, 5), (5, 6), (6, 4)])\n        \n        let expectedComponents: Set<Set<Int>> = [[1], [2, 3], [4, 5, 6]]\n        \n        XCTAssertEqual(graph.findStronglyConnectedComponents(), expectedComponents)\n    }\n    \n    func testGraphWithOneBigCycle() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5],\n                              edges: [(1, 2), (2, 3), (3, 4), (4, 5), (5, 1)])\n        \n        let expectedComponents: Set<Set<Int>> = [[1, 2, 3, 4, 5]]\n        \n        XCTAssertEqual(graph.findStronglyConnectedComponents(), expectedComponents)\n    }\n    \n    func testGraphWithTwoConnectedCycles() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(1, 2), (2, 3), (3, 1), (4, 5), (5, 6), (6, 4)])\n        \n        let expectedComponents: Set<Set<Int>> = [[1, 2, 3], [4, 5, 6]]\n        \n        XCTAssertEqual(graph.findStronglyConnectedComponents(), expectedComponents)\n    }\n}\n"},{"name":"TransitiveReductionTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":77,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":14}},"name":"MEGTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":7,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":25}},"name":"testEmptyGraph()"},{"range":{"start":{"line":9,"character":4},"end":{"line":13,"character":5}},"kind":6,"selectionRange":{"start":{"line":9,"character":9},"end":{"line":9,"character":32}},"name":"testGraphWithoutEdges()","children":[{"range":{"start":{"line":10,"character":8},"end":{"line":10,"character":48}},"kind":13,"selectionRange":{"start":{"line":10,"character":12},"end":{"line":10,"character":17}},"name":"graph"}]},{"range":{"start":{"line":15,"character":4},"end":{"line":20,"character":5}},"kind":6,"selectionRange":{"start":{"line":15,"character":9},"end":{"line":15,"character":42}},"name":"testGraphWithoutTransitiveEdges()","children":[{"range":{"start":{"line":16,"character":8},"end":{"line":17,"character":54}},"kind":13,"selectionRange":{"start":{"line":16,"character":12},"end":{"line":16,"character":17}},"name":"graph"}]},{"range":{"start":{"line":22,"character":4},"end":{"line":30,"character":5}},"kind":6,"selectionRange":{"start":{"line":22,"character":9},"end":{"line":22,"character":41}},"name":"testGraphWithOneTransitiveEdge()","children":[{"range":{"start":{"line":23,"character":8},"end":{"line":24,"character":62}},"kind":13,"selectionRange":{"start":{"line":23,"character":12},"end":{"line":23,"character":17}},"name":"graph"},{"range":{"start":{"line":26,"character":8},"end":{"line":27,"character":60}},"kind":13,"selectionRange":{"start":{"line":26,"character":12},"end":{"line":26,"character":23}},"name":"expectedMEG"}]},{"range":{"start":{"line":32,"character":4},"end":{"line":40,"character":5}},"kind":6,"selectionRange":{"start":{"line":32,"character":9},"end":{"line":32,"character":62}},"name":"testGraphWithTwoComponentsEachWithOneTransitiveEdge()","children":[{"range":{"start":{"line":33,"character":8},"end":{"line":34,"character":86}},"kind":13,"selectionRange":{"start":{"line":33,"character":12},"end":{"line":33,"character":17}},"name":"graph"},{"range":{"start":{"line":36,"character":8},"end":{"line":37,"character":76}},"kind":13,"selectionRange":{"start":{"line":36,"character":12},"end":{"line":36,"character":23}},"name":"expectedMEG"}]},{"range":{"start":{"line":42,"character":4},"end":{"line":76,"character":5}},"kind":6,"selectionRange":{"start":{"line":42,"character":9},"end":{"line":42,"character":43}},"name":"testGraphWithManyTransitiveEdges()","children":[{"range":{"start":{"line":43,"character":8},"end":{"line":43,"character":31}},"kind":13,"selectionRange":{"start":{"line":43,"character":12},"end":{"line":43,"character":17}},"name":"graph"},{"range":{"start":{"line":45,"character":8},"end":{"line":45,"character":30}},"kind":13,"selectionRange":{"start":{"line":45,"character":12},"end":{"line":45,"character":25}},"name":"numberOfNodes"},{"range":{"start":{"line":47,"character":12},"end":{"line":47,"character":13}},"kind":13,"selectionRange":{"start":{"line":47,"character":12},"end":{"line":47,"character":13}},"name":"j"},{"range":{"start":{"line":51,"character":16},"end":{"line":51,"character":17}},"kind":13,"selectionRange":{"start":{"line":51,"character":16},"end":{"line":51,"character":17}},"name":"i"},{"range":{"start":{"line":58,"character":8},"end":{"line":58,"character":89}},"kind":13,"selectionRange":{"start":{"line":58,"character":12},"end":{"line":58,"character":33}},"name":"expectedNumberOfEdges"},{"range":{"start":{"line":63,"character":8},"end":{"line":63,"character":37}},"kind":13,"selectionRange":{"start":{"line":63,"character":12},"end":{"line":63,"character":23}},"name":"expectedMEG"},{"range":{"start":{"line":65,"character":12},"end":{"line":65,"character":13}},"kind":13,"selectionRange":{"start":{"line":65,"character":12},"end":{"line":65,"character":13}},"name":"i"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass MEGTests: XCTestCase {\n    \n    func testEmptyGraph() {\n        XCTAssertEqual(TestGraph().filteredTransitiveReduction(), TestGraph())\n    }\n    \n    func testGraphWithoutEdges() {\n        let graph = TestGraph(values: [1, 2, 3])\n        \n        XCTAssertEqual(graph.filteredTransitiveReduction(), graph)\n    }\n    \n    func testGraphWithoutTransitiveEdges() {\n        let graph = TestGraph(values: [1, 2, 3],\n                              edges: [(1, 2), (2, 3)])\n        \n        XCTAssertEqual(graph.filteredTransitiveReduction(), graph)\n    }\n    \n    func testGraphWithOneTransitiveEdge() {\n        let graph = TestGraph(values: [1, 2, 3],\n                              edges: [(1, 2), (2, 3), (1, 3)])\n        \n        let expectedMEG = TestGraph(values: [1, 2, 3],\n                                    edges: [(1, 2), (2, 3)])\n        \n        XCTAssertEqual(graph.filteredTransitiveReduction(), expectedMEG)\n    }\n    \n    func testGraphWithTwoComponentsEachWithOneTransitiveEdge() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                              edges: [(1, 2), (2, 3), (1, 3), (4, 5), (5, 6), (4, 6)])\n        \n        let expectedMEG = TestGraph(values: [1, 2, 3, 4, 5, 6],\n                                    edges: [(1, 2), (2, 3), (4, 5), (5, 6)])\n        \n        XCTAssertEqual(graph.filteredTransitiveReduction(), expectedMEG)\n    }\n    \n    func testGraphWithManyTransitiveEdges() {\n        var graph = TestGraph()\n        \n        let numberOfNodes = 10\n        \n        for j in 0 ..< numberOfNodes\n        {\n            graph.insert(j)\n            \n            for i in 0 ..< j\n            {\n                graph.insertEdge(from: i, to: j)\n            }\n        }\n        \n        // sanity check\n        let expectedNumberOfEdges = ((numberOfNodes * numberOfNodes) - numberOfNodes) / 2\n        XCTAssertEqual(graph.edges.count, expectedNumberOfEdges)\n        \n        // only edges between neighbouring numbers should remain (0 -> 1 -> 2 ...)\n        \n        var expectedMEG = TestGraph()\n        \n        for i in 0 ..< numberOfNodes\n        {\n            expectedMEG.insert(i)\n            \n            if i > 0\n            {\n                expectedMEG.insertEdge(from: i - 1, to: i)\n            }\n        }\n        \n        XCTAssertEqual(graph.filteredTransitiveReduction(), expectedMEG)\n    }\n}\n"}],"subfolders":[{"name":"FilterAndMap","files":[{"name":"ValueFilterTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":11,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":22}},"name":"ValueFilterTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":10,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":26}},"name":"testValueFilter()","children":[{"range":{"start":{"line":6,"character":8},"end":{"line":6,"character":45}},"kind":13,"selectionRange":{"start":{"line":6,"character":12},"end":{"line":6,"character":17}},"name":"graph"},{"range":{"start":{"line":7,"character":8},"end":{"line":7,"character":54}},"kind":13,"selectionRange":{"start":{"line":7,"character":12},"end":{"line":7,"character":25}},"name":"filteredGraph"},{"range":{"start":{"line":8,"character":8},"end":{"line":8,"character":64}},"kind":13,"selectionRange":{"start":{"line":8,"character":12},"end":{"line":8,"character":33}},"name":"expectedFilteredGraph"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass ValueFilterTests: XCTestCase {\n    \n    func testValueFilter() {\n        let graph: TestGraph = [1, 2, 10, 20]\n        let filteredGraph = graph.filtered { $0 < 10 }\n        let expectedFilteredGraph: Graph<Int, Int, Int> = [1, 2]\n        XCTAssertEqual(filteredGraph, expectedFilteredGraph)\n    }\n}\n"},{"name":"MapTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":11,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":14}},"name":"MapTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":10,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":39}},"name":"testMappingIntValuesToString()","children":[{"range":{"start":{"line":6,"character":8},"end":{"line":6,"character":40}},"kind":13,"selectionRange":{"start":{"line":6,"character":12},"end":{"line":6,"character":17}},"name":"graph"},{"range":{"start":{"line":7,"character":8},"end":{"line":7,"character":47}},"kind":13,"selectionRange":{"start":{"line":7,"character":12},"end":{"line":7,"character":23}},"name":"stringGraph"},{"range":{"start":{"line":8,"character":8},"end":{"line":8,"character":83}},"kind":13,"selectionRange":{"start":{"line":8,"character":12},"end":{"line":8,"character":31}},"name":"expectedStringGraph"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass MapTests: XCTestCase {\n        \n    func testMappingIntValuesToString() {\n        let graph: TestGraph = [1, 2, 3]\n        let stringGraph = graph.map { \"\\($0)\" }\n        let expectedStringGraph: Graph<Int, String, Int> = [1: \"1\", 2: \"2\", 3: \"3\"]\n        XCTAssertEqual(stringGraph, expectedStringGraph)\n    }\n}\n"},{"name":"NodeFilterTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":74,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":21}},"name":"NodeFilterTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":19,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":32}},"name":"testGraphWithoutEdges()","children":[{"range":{"start":{"line":6,"character":8},"end":{"line":6,"character":48}},"kind":13,"selectionRange":{"start":{"line":6,"character":12},"end":{"line":6,"character":17}},"name":"graph"}]},{"range":{"start":{"line":21,"character":4},"end":{"line":39,"character":5}},"kind":6,"selectionRange":{"start":{"line":21,"character":9},"end":{"line":21,"character":30}},"name":"testSimpleTestGraph()","children":[{"range":{"start":{"line":22,"character":8},"end":{"line":23,"character":58}},"kind":13,"selectionRange":{"start":{"line":22,"character":12},"end":{"line":22,"character":17}},"name":"graph"}]},{"range":{"start":{"line":41,"character":4},"end":{"line":56,"character":5}},"kind":6,"selectionRange":{"start":{"line":41,"character":9},"end":{"line":41,"character":39}},"name":"testGraphWithTransitiveEdges()","children":[{"range":{"start":{"line":42,"character":8},"end":{"line":43,"character":90}},"kind":13,"selectionRange":{"start":{"line":42,"character":12},"end":{"line":42,"character":17}},"name":"graph"}]},{"range":{"start":{"line":58,"character":4},"end":{"line":73,"character":5}},"kind":6,"selectionRange":{"start":{"line":58,"character":9},"end":{"line":58,"character":30}},"name":"testGraphWithCycles()","children":[{"range":{"start":{"line":59,"character":8},"end":{"line":60,"character":82}},"kind":13,"selectionRange":{"start":{"line":59,"character":12},"end":{"line":59,"character":17}},"name":"graph"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass NodeFilterTests: XCTestCase {\n    \n    func testGraphWithoutEdges() {\n        let graph = TestGraph(values: [1, 2, 3])\n        \n        XCTAssertEqual(graph.filteredNodes([]),\n                       TestGraph(values: []))\n        \n        XCTAssertEqual(graph.filteredNodes([1, 2]),\n                       TestGraph(values: [1, 2]))\n        \n        XCTAssertEqual(graph.filteredNodes([1, 2, 4]),\n                       TestGraph(values: [1, 2]))\n        \n        XCTAssertEqual(graph.filteredNodes([1, 2, 3]),\n                       TestGraph(values: [1, 2, 3]))\n    }\n    \n    func testSimpleTestGraph() {\n        let graph = TestGraph(values: [1, 2, 3, 4],\n                          edges: [(1, 2), (2, 3), (3, 4)])\n        \n        XCTAssertEqual(graph.filteredNodes([]),\n                       TestGraph(values: []))\n        \n        XCTAssertEqual(graph.filteredNodes([1, 3]),\n                       TestGraph(values: [1, 3]))\n        \n        XCTAssertEqual(graph.filteredNodes([2, 4]),\n                       TestGraph(values: [2, 4]))\n        \n        XCTAssertEqual(graph.filteredNodes([2, 3]),\n                       TestGraph(values: [2, 3], edges: [(2, 3)]))\n        \n        XCTAssertEqual(graph.filteredNodes([2, 3, 4]),\n                       TestGraph(values: [2, 3, 4], edges: [(2, 3), (3, 4)]))\n    }\n    \n    func testGraphWithTransitiveEdges() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5],\n                          edges: [(1, 2), (2, 3), (3, 4), (4, 5), (1, 3), (2, 4), (3, 5)])\n        \n        XCTAssertEqual(graph.filteredNodes([]),\n                       TestGraph(values: []))\n        \n        XCTAssertEqual(graph.filteredNodes([2, 3]),\n                       TestGraph(values: [2, 3], edges: [(2, 3)]))\n        \n        XCTAssertEqual(graph.filteredNodes([2, 3, 4]),\n                       TestGraph(values: [2, 3, 4], edges: [(2, 3), (3, 4), (2, 4)]))\n        \n        XCTAssertEqual(graph.filteredNodes([1, 3, 5]),\n                       TestGraph(values: [1, 3, 5], edges: [(1, 3), (3, 5)]))\n    }\n    \n    func testGraphWithCycles() {\n        let graph = TestGraph(values: [1, 2, 3, 4, 5],\n                          edges: [(1, 2), (2, 3), (3, 1), (3, 4), (4, 5), (5, 3)])\n        \n        XCTAssertEqual(graph.filteredNodes([]),\n                       TestGraph(values: []))\n        \n        XCTAssertEqual(graph.filteredNodes([1, 4]),\n                       TestGraph(values: [1, 4]))\n        \n        XCTAssertEqual(graph.filteredNodes([2, 3, 4]),\n                       TestGraph(values: [2, 3, 4], edges: [(2, 3), (3, 4)]))\n        \n        XCTAssertEqual(graph.filteredNodes([3, 4, 5]),\n                       TestGraph(values: [3, 4, 5], edges: [(3, 4), (4, 5), (5, 3)]))\n    }\n}\n"},{"name":"EdgeFilterTests.swift","symbols":[{"range":{"start":{"line":3,"character":0},"end":{"line":34,"character":1}},"kind":5,"selectionRange":{"start":{"line":3,"character":6},"end":{"line":3,"character":21}},"name":"EdgeFilterTests","children":[{"range":{"start":{"line":5,"character":4},"end":{"line":18,"character":5}},"kind":6,"selectionRange":{"start":{"line":5,"character":9},"end":{"line":5,"character":37}},"name":"testEdgeFilterCopyingGraph()","children":[{"range":{"start":{"line":6,"character":8},"end":{"line":7,"character":62}},"kind":13,"selectionRange":{"start":{"line":6,"character":12},"end":{"line":6,"character":17}},"name":"graph"},{"range":{"start":{"line":9,"character":8},"end":{"line":11,"character":9}},"kind":13,"selectionRange":{"start":{"line":9,"character":12},"end":{"line":9,"character":25}},"name":"filteredGraph"},{"range":{"start":{"line":13,"character":8},"end":{"line":14,"character":54}},"kind":13,"selectionRange":{"start":{"line":13,"character":12},"end":{"line":13,"character":25}},"name":"expectedGraph"}]},{"range":{"start":{"line":20,"character":4},"end":{"line":33,"character":5}},"kind":6,"selectionRange":{"start":{"line":20,"character":9},"end":{"line":20,"character":38}},"name":"testEdgeFilterMutatingGraph()","children":[{"range":{"start":{"line":21,"character":8},"end":{"line":22,"character":62}},"kind":13,"selectionRange":{"start":{"line":21,"character":12},"end":{"line":21,"character":17}},"name":"graph"},{"range":{"start":{"line":28,"character":8},"end":{"line":29,"character":54}},"kind":13,"selectionRange":{"start":{"line":28,"character":12},"end":{"line":28,"character":25}},"name":"expectedGraph"}]}]}],"code":"@testable import SwiftNodes\nimport XCTest\n\nclass EdgeFilterTests: XCTestCase {\n    \n    func testEdgeFilterCopyingGraph() {\n        let graph = TestGraph(values: [1, 2, 3, 4],\n                              edges: [(1, 2), (2, 3), (3, 4)])\n        \n        let filteredGraph = graph.filteredEdges {\n            $0.originID != 3 && $0.destinationID != 3\n        }\n        \n        let expectedGraph = TestGraph(values: [1, 2, 3, 4],\n                                      edges: [(1, 2)])\n        \n        // this also compares node neighbour caches, so we also test that the filter correctly updates those...\n        XCTAssertEqual(filteredGraph, expectedGraph)\n    }\n    \n    func testEdgeFilterMutatingGraph() {\n        var graph = TestGraph(values: [1, 2, 3, 4],\n                              edges: [(1, 2), (2, 3), (3, 4)])\n        \n        graph.filterEdges {\n            $0.originID != 3 && $0.destinationID != 3\n        }\n        \n        let expectedGraph = TestGraph(values: [1, 2, 3, 4],\n                                      edges: [(1, 2)])\n        \n        // this also compares node neighbour caches, so we also test that the filter correctly updates those...\n        XCTAssertEqual(graph, expectedGraph)\n    }\n}\n"}]}]}]},{"name":"Code","subfolders":[{"name":"Graph+CreateAndAccess","files":[{"name":"Graph+EdgeAccess.swift","symbols":[{"range":{"start":{"line":2,"character":7},"end":{"line":132,"character":1}},"kind":3,"selectionRange":{"start":{"line":2,"character":17},"end":{"line":2,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":8,"character":13},"end":{"line":12,"character":5}},"kind":6,"selectionRange":{"start":{"line":8,"character":18},"end":{"line":9,"character":54}},"name":"removeEdge(from:to:)","references":[{"range":{"start":{"line":11,"character":14},"end":{"line":11,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":76,"character":14},"end":{"line":76,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"}]},{"range":{"start":{"line":18,"character":13},"end":{"line":26,"character":5}},"kind":6,"selectionRange":{"start":{"line":18,"character":18},"end":{"line":18,"character":46}},"name":"removeEdge(with:)","references":[{"range":{"start":{"line":13,"character":12},"end":{"line":13,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":18,"character":12},"end":{"line":18,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":66,"character":14},"end":{"line":66,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":71,"character":14},"end":{"line":71,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":126,"character":14},"end":{"line":126,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":39,"character":16},"end":{"line":39,"character":16}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":11,"character":8},"end":{"line":11,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":34,"character":13},"end":{"line":39,"character":5}},"kind":6,"selectionRange":{"start":{"line":34,"character":18},"end":{"line":36,"character":47}},"name":"add(_:toEdgeFrom:to:)"},{"range":{"start":{"line":47,"character":13},"end":{"line":63,"character":5}},"kind":6,"selectionRange":{"start":{"line":47,"character":18},"end":{"line":47,"character":67}},"name":"add(_:toEdgeWith:)","references":[{"range":{"start":{"line":49,"character":14},"end":{"line":49,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":103,"character":32},"end":{"line":103,"character":32}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":38,"character":8},"end":{"line":38,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}],"children":[{"range":{"start":{"line":49,"character":15},"end":{"line":49,"character":29}},"kind":13,"selectionRange":{"start":{"line":49,"character":15},"end":{"line":49,"character":29}},"name":"existingWeight"}]},{"range":{"start":{"line":66,"character":13},"end":{"line":73,"character":5}},"kind":6,"selectionRange":{"start":{"line":66,"character":18},"end":{"line":68,"character":52}},"name":"insertEdge(from:to:weight:)","references":[{"range":{"start":{"line":53,"character":22},"end":{"line":53,"character":22}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":71,"character":28},"end":{"line":71,"character":28}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":8,"character":14},"end":{"line":8,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":35,"character":14},"end":{"line":35,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":46,"character":14},"end":{"line":46,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":55,"character":14},"end":{"line":55,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":64,"character":25},"end":{"line":64,"character":25}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":69,"character":14},"end":{"line":69,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":74,"character":14},"end":{"line":74,"character":14}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":98,"character":27},"end":{"line":98,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":42,"character":22},"end":{"line":42,"character":22}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":57,"character":12},"end":{"line":57,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}],"children":[{"range":{"start":{"line":70,"character":8},"end":{"line":70,"character":74}},"kind":13,"selectionRange":{"start":{"line":70,"character":12},"end":{"line":70,"character":16}},"name":"edge"}]},{"range":{"start":{"line":75,"character":13},"end":{"line":85,"character":5}},"kind":6,"selectionRange":{"start":{"line":75,"character":18},"end":{"line":75,"character":38}},"name":"insert(_:)","references":[{"range":{"start":{"line":45,"character":34},"end":{"line":45,"character":34}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":71,"character":8},"end":{"line":71,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":90,"character":4},"end":{"line":93,"character":5}},"kind":6,"selectionRange":{"start":{"line":90,"character":9},"end":{"line":90,"character":62}},"name":"edge(from:to:)","references":[{"range":{"start":{"line":10,"character":25},"end":{"line":10,"character":25}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":18,"character":30},"end":{"line":18,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":28,"character":31},"end":{"line":28,"character":31}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":37,"character":27},"end":{"line":37,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":38,"character":27},"end":{"line":38,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":39,"character":30},"end":{"line":39,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":40,"character":29},"end":{"line":40,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":47,"character":29},"end":{"line":47,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":50,"character":29},"end":{"line":50,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":57,"character":30},"end":{"line":57,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":58,"character":27},"end":{"line":58,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":65,"character":30},"end":{"line":65,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":67,"character":27},"end":{"line":67,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":70,"character":30},"end":{"line":70,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":72,"character":27},"end":{"line":72,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":75,"character":30},"end":{"line":75,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":77,"character":27},"end":{"line":77,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":89,"character":27},"end":{"line":89,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":95,"character":27},"end":{"line":95,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":96,"character":27},"end":{"line":96,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":99,"character":30},"end":{"line":99,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":100,"character":30},"end":{"line":100,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":104,"character":29},"end":{"line":104,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":127,"character":27},"end":{"line":127,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":128,"character":27},"end":{"line":128,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"}]},{"range":{"start":{"line":98,"character":4},"end":{"line":101,"character":5}},"kind":6,"selectionRange":{"start":{"line":98,"character":9},"end":{"line":98,"character":31}},"name":"edge(with:)","references":[{"range":{"start":{"line":92,"character":8},"end":{"line":92,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":103,"character":4},"end":{"line":107,"character":5}},"kind":6,"selectionRange":{"start":{"line":103,"character":9},"end":{"line":104,"character":47}},"name":"containsEdge(from:to:)","references":[{"range":{"start":{"line":9,"character":36},"end":{"line":9,"character":36}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"}]},{"range":{"start":{"line":112,"character":4},"end":{"line":115,"character":5}},"kind":6,"selectionRange":{"start":{"line":112,"character":9},"end":{"line":112,"character":36}},"name":"contains(_:)","references":[{"range":{"start":{"line":76,"character":59},"end":{"line":76,"character":59}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":78,"character":19},"end":{"line":78,"character":19}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":77,"character":12},"end":{"line":77,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":106,"character":8},"end":{"line":106,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":120,"character":4},"end":{"line":123,"character":5}},"kind":7,"selectionRange":{"start":{"line":120,"character":8},"end":{"line":120,"character":13}},"name":"edges","references":[{"range":{"start":{"line":59,"character":29},"end":{"line":59,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":53,"character":20},"end":{"line":53,"character":20}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":48,"character":29},"end":{"line":48,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":9,"character":28},"end":{"line":9,"character":28}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":35,"character":12},"end":{"line":35,"character":12}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"}]},{"range":{"start":{"line":128,"character":4},"end":{"line":131,"character":5}},"kind":7,"selectionRange":{"start":{"line":128,"character":8},"end":{"line":128,"character":15}},"name":"edgeIDs","references":[{"range":{"start":{"line":34,"character":22},"end":{"line":34,"character":22}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":66,"character":61},"end":{"line":66,"character":61}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":73,"character":54},"end":{"line":73,"character":54}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":44,"character":36},"end":{"line":44,"character":36}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"}]}]}],"code":"import SwiftyToolz\n\npublic extension Graph\n{\n    /**\n     Removes the corresponding ``GraphEdge``, see ``Graph/removeEdge(with:)``\n     */\n    @discardableResult\n    mutating func removeEdge(from originID: NodeID,\n                             to destinationID: NodeID) -> Edge?\n    {\n        removeEdge(with: .init(originID, destinationID))\n    }\n    \n    /**\n     Removes the ``GraphEdge`` with the given ID, also removing it from node neighbour caches\n     */\n    @discardableResult\n    mutating func removeEdge(with id: Edge.ID) -> Edge?\n    {\n        // remove from node caches\n        nodesByID[id.originID]?.descendantIDs -= id.destinationID\n        nodesByID[id.destinationID]?.ancestorIDs -= id.originID\n        \n        // remove edge itself\n        return edgesByID.removeValue(forKey: id)\n    }\n    \n    /**\n     Add weight to the existing edge or create the edge with that weight\n     \n     - Returns: The new weight of the edge with the given ID\n     */\n    @discardableResult\n    mutating func add(_ weight: EdgeWeight,\n                      toEdgeFrom originID: NodeID,\n                      to destinationID: NodeID) -> EdgeWeight\n    {\n        add(weight, toEdgeWith: .init(originID, destinationID))\n    }\n    \n    /**\n     Add weight to the existing edge or create the edge with that weight\n     \n     - Returns: The new weight of the edge with the given ID\n     */\n    @discardableResult\n    mutating func add(_ weight: EdgeWeight, toEdgeWith id: Edge.ID) -> EdgeWeight\n    {\n        if let existingWeight = edgesByID[id]?.weight\n        {\n            edgesByID[id]?.weight += weight\n            \n            return existingWeight + weight\n        }\n        else\n        {\n            insertEdge(from: id.originID,\n                       to: id.destinationID,\n                       weight: weight)\n            \n            return weight\n        }\n    }\n    \n    @discardableResult\n    mutating func insertEdge(from originID: NodeID,\n                             to destinationID: NodeID,\n                             weight: EdgeWeight = 1) -> Edge\n    {\n        let edge = Edge(from: originID, to: destinationID, weight: weight)\n        insert(edge)\n        return edge\n    }\n    \n    mutating func insert(_ edge: Edge)\n    {\n        if !contains(edge.id)\n        {\n            // update node caches because edge does not exist yet\n            nodesByID[edge.originID]?.descendantIDs += edge.destinationID\n            nodesByID[edge.destinationID]?.ancestorIDs += edge.originID\n        }\n        \n        edgesByID.insert(edge)\n    }\n    \n    /**\n     The ``GraphEdge`` between the corresponding nodes if it exists, otherwise `nil`\n     */\n    func edge(from originID: NodeID, to destinationID: NodeID) -> Edge?\n    {\n        edge(with: .init(originID, destinationID))\n    }\n    \n    /**\n     The ``GraphEdge`` with the given ID if the edge exists, otherwise `nil`\n     */\n    func edge(with id: Edge.ID) -> Edge?\n    {\n        edgesByID[id]\n    }\n    \n    func containsEdge(from originID: NodeID,\n                      to destinationID: NodeID) -> Bool\n    {\n        contains(.init(originID, destinationID))\n    }\n    \n    /**\n     Whether the `Graph` contains a ``GraphEdge`` with the given ``GraphEdge/id-swift.property``\n     */\n    func contains(_ edgeID: Edge.ID) -> Bool\n    {\n        edgesByID.keys.contains(edgeID)\n    }\n    \n    /**\n     All ``GraphEdge``s of the `Graph`\n     */\n    var edges: some Collection<Edge>\n    {\n        edgesByID.values\n    }\n    \n    /**\n     All ``GraphEdge/id-swift.property``s of the ``GraphEdge``s of the `Graph`\n     */\n    var edgeIDs: some Collection<Edge.ID>\n    {\n        edgesByID.keys\n    }\n}\n"},{"name":"Graph+NodeAccess.swift","symbols":[{"range":{"start":{"line":0,"character":7},"end":{"line":71,"character":1}},"kind":3,"selectionRange":{"start":{"line":0,"character":17},"end":{"line":0,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":4,"character":13},"end":{"line":22,"character":5}},"kind":6,"selectionRange":{"start":{"line":4,"character":18},"end":{"line":4,"character":49}},"name":"removeNode(with:)","references":[{"range":{"start":{"line":85,"character":16},"end":{"line":85,"character":16}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":13,"character":16},"end":{"line":13,"character":16}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":36,"character":8},"end":{"line":36,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":42,"character":8},"end":{"line":42,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":70,"character":8},"end":{"line":70,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"}],"children":[{"range":{"start":{"line":6,"character":18},"end":{"line":6,"character":22}},"kind":13,"selectionRange":{"start":{"line":6,"character":18},"end":{"line":6,"character":22}},"name":"node"},{"range":{"start":{"line":11,"character":12},"end":{"line":11,"character":22}},"kind":13,"selectionRange":{"start":{"line":11,"character":12},"end":{"line":11,"character":22}},"name":"ancestorID"},{"range":{"start":{"line":16,"character":12},"end":{"line":16,"character":24}},"kind":13,"selectionRange":{"start":{"line":16,"character":12},"end":{"line":16,"character":24}},"name":"descendantID"}]},{"range":{"start":{"line":27,"character":4},"end":{"line":30,"character":5}},"kind":7,"selectionRange":{"start":{"line":27,"character":8},"end":{"line":27,"character":15}},"name":"sources","references":[{"range":{"start":{"line":37,"character":26},"end":{"line":37,"character":26}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"}]},{"range":{"start":{"line":35,"character":4},"end":{"line":38,"character":5}},"kind":7,"selectionRange":{"start":{"line":35,"character":8},"end":{"line":35,"character":13}},"name":"sinks","references":[{"range":{"start":{"line":19,"character":8},"end":{"line":19,"character":8}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"}]},{"range":{"start":{"line":43,"character":4},"end":{"line":46,"character":5}},"kind":6,"selectionRange":{"start":{"line":43,"character":9},"end":{"line":43,"character":35}},"name":"contains(_:)"},{"range":{"start":{"line":51,"character":4},"end":{"line":54,"character":5}},"kind":6,"selectionRange":{"start":{"line":51,"character":9},"end":{"line":51,"character":30}},"name":"node(with:)","references":[{"range":{"start":{"line":46,"character":35},"end":{"line":46,"character":35}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":19,"character":29},"end":{"line":19,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":20,"character":29},"end":{"line":20,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":29,"character":30},"end":{"line":29,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":30,"character":30},"end":{"line":30,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":82,"character":27},"end":{"line":82,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":87,"character":29},"end":{"line":87,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":108,"character":39},"end":{"line":108,"character":39}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":117,"character":39},"end":{"line":117,"character":39}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":130,"character":37},"end":{"line":130,"character":37}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":131,"character":37},"end":{"line":131,"character":37}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":10,"character":31},"end":{"line":10,"character":31}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":40,"character":25},"end":{"line":40,"character":25}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"},{"range":{"start":{"line":35,"character":41},"end":{"line":35,"character":41}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":89,"character":40},"end":{"line":89,"character":40}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"}]},{"range":{"start":{"line":59,"character":4},"end":{"line":62,"character":5}},"kind":7,"selectionRange":{"start":{"line":59,"character":8},"end":{"line":59,"character":13}},"name":"nodes","references":[{"range":{"start":{"line":41,"character":50},"end":{"line":41,"character":50}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":6,"character":38},"end":{"line":6,"character":38}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":81,"character":12},"end":{"line":81,"character":12}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"}]},{"range":{"start":{"line":67,"character":4},"end":{"line":70,"character":5}},"kind":7,"selectionRange":{"start":{"line":67,"character":8},"end":{"line":67,"character":15}},"name":"nodeIDs","references":[{"range":{"start":{"line":17,"character":20},"end":{"line":17,"character":20}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":15,"character":20},"end":{"line":15,"character":20}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"}]}]}],"code":"public extension Graph\n{\n    /// Remove the node with the given ID also removing its in- and outgoing edges\n    @discardableResult\n    mutating func removeNode(with nodeID: NodeID) -> Node?\n    {\n        guard let node = nodesByID.removeValue(forKey: nodeID) else\n        {\n            return nil\n        }\n        \n        for ancestorID in node.ancestorIDs\n        {\n            removeEdge(with: .init(ancestorID, nodeID))\n        }\n        \n        for descendantID in node.descendantIDs\n        {\n            removeEdge(with: .init(nodeID, descendantID))\n        }\n        \n        return node\n    }\n    \n    /**\n     All source nodes of the `Graph`, see ``GraphNode/isSource``\n     */\n    var sources: some Collection<Node>\n    {\n        nodesByID.values.filter { $0.isSource }\n    }\n    \n    /**\n     All sink nodes of the `Graph`, see ``GraphNode/isSink``\n     */\n    var sinks: some Collection<Node>\n    {\n        nodesByID.values.filter { $0.isSink }\n    }\n    \n    /**\n     Whether the `Graph` contains a ``GraphNode`` with the given ``GraphNode/id``\n     */\n    func contains(_ nodeID: NodeID) -> Bool\n    {\n        nodesByID.keys.contains(nodeID)\n    }\n    \n    /**\n     ``GraphNode`` with the given ``GraphNode/id`` if one exists, otherwise `nil`\n     */\n    func node(with id: NodeID) -> Node?\n    {\n        nodesByID[id]\n    }\n    \n    /**\n     All ``GraphNode``s of the `Graph`\n     */\n    var nodes: some Collection<Node>\n    {\n        nodesByID.values\n    }\n    \n    /**\n     The ``GraphNode/id``s of all ``GraphNode``s of the `Graph`\n     */\n    var nodeIDs: some Collection<NodeID>\n    {\n        nodesByID.keys\n    }\n}\n"},{"name":"Graph+ConvenientInitializers.swift","symbols":[{"range":{"start":{"line":8,"character":0},"end":{"line":14,"character":1}},"kind":3,"selectionRange":{"start":{"line":8,"character":10},"end":{"line":8,"character":15}},"name":"Graph","children":[{"range":{"start":{"line":10,"character":11},"end":{"line":13,"character":5}},"kind":6,"selectionRange":{"start":{"line":10,"character":11},"end":{"line":10,"character":52}},"name":"init(arrayLiteral:)","references":[{"range":{"start":{"line":6,"character":45},"end":{"line":6,"character":45}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":10,"character":46},"end":{"line":10,"character":46}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":6,"character":31},"end":{"line":6,"character":31}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/ValueFilterTests.swift"},{"range":{"start":{"line":8,"character":58},"end":{"line":8,"character":58}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/ValueFilterTests.swift"},{"range":{"start":{"line":6,"character":31},"end":{"line":6,"character":31}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/MapTests.swift"}]}]},{"range":{"start":{"line":16,"character":0},"end":{"line":22,"character":1}},"kind":3,"selectionRange":{"start":{"line":16,"character":10},"end":{"line":16,"character":15}},"name":"Graph","children":[{"range":{"start":{"line":18,"character":11},"end":{"line":21,"character":5}},"kind":6,"selectionRange":{"start":{"line":18,"character":11},"end":{"line":18,"character":67}},"name":"init(dictionaryLiteral:)","references":[{"range":{"start":{"line":17,"character":30},"end":{"line":17,"character":30}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":8,"character":59},"end":{"line":8,"character":59}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/MapTests.swift"}]}]},{"range":{"start":{"line":24,"character":7},"end":{"line":101,"character":1}},"kind":3,"selectionRange":{"start":{"line":24,"character":17},"end":{"line":24,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":26,"character":4},"end":{"line":30,"character":5}},"kind":6,"selectionRange":{"start":{"line":26,"character":4},"end":{"line":26,"character":42}},"name":"init(values:)","references":[{"range":{"start":{"line":31,"character":32},"end":{"line":31,"character":32}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":10,"character":50},"end":{"line":10,"character":50}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":51,"character":50},"end":{"line":51,"character":50}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"}]},{"range":{"start":{"line":35,"character":4},"end":{"line":40,"character":5}},"kind":6,"selectionRange":{"start":{"line":35,"character":4},"end":{"line":36,"character":48}},"name":"init(values:edges:)","references":[{"range":{"start":{"line":32,"character":50},"end":{"line":32,"character":50}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":66,"character":50},"end":{"line":66,"character":50}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":82,"character":50},"end":{"line":82,"character":50}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":98,"character":50},"end":{"line":98,"character":50}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":24,"character":21},"end":{"line":24,"character":21}},"filePathRelativeToRoot":"Tests/ValueTests.swift"}]},{"range":{"start":{"line":42,"character":4},"end":{"line":47,"character":5}},"kind":6,"selectionRange":{"start":{"line":42,"character":4},"end":{"line":43,"character":53}},"name":"init(values:edgeTuples:)"},{"range":{"start":{"line":52,"character":4},"end":{"line":57,"character":5}},"kind":6,"selectionRange":{"start":{"line":52,"character":4},"end":{"line":53,"character":36}},"name":"init(values:edges:)"},{"range":{"start":{"line":59,"character":4},"end":{"line":63,"character":5}},"kind":6,"selectionRange":{"start":{"line":59,"character":4},"end":{"line":59,"character":42}},"name":"init(values:)","references":[{"range":{"start":{"line":10,"character":20},"end":{"line":10,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":10,"character":20},"end":{"line":10,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":34,"character":20},"end":{"line":34,"character":20}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":44,"character":20},"end":{"line":44,"character":20}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":54,"character":20},"end":{"line":54,"character":20}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":62,"character":20},"end":{"line":62,"character":20}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":11,"character":20},"end":{"line":11,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":6,"character":20},"end":{"line":6,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":12,"character":13},"end":{"line":12,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":10,"character":20},"end":{"line":10,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":10,"character":20},"end":{"line":10,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":6,"character":20},"end":{"line":6,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":9,"character":23},"end":{"line":9,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":12,"character":23},"end":{"line":12,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":15,"character":23},"end":{"line":15,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":18,"character":23},"end":{"line":18,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":26,"character":23},"end":{"line":26,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":29,"character":23},"end":{"line":29,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":32,"character":23},"end":{"line":32,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":46,"character":23},"end":{"line":46,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":63,"character":23},"end":{"line":63,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":66,"character":23},"end":{"line":66,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"}]},{"range":{"start":{"line":68,"character":4},"end":{"line":74,"character":5}},"kind":6,"selectionRange":{"start":{"line":68,"character":4},"end":{"line":69,"character":48}},"name":"init(values:edges:)","references":[{"range":{"start":{"line":16,"character":20},"end":{"line":16,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":23,"character":20},"end":{"line":23,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":26,"character":26},"end":{"line":26,"character":26}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":33,"character":20},"end":{"line":33,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":36,"character":26},"end":{"line":36,"character":26}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":18,"character":20},"end":{"line":18,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":26,"character":20},"end":{"line":26,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":35,"character":20},"end":{"line":35,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":16,"character":20},"end":{"line":16,"character":20}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":18,"character":20},"end":{"line":18,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":26,"character":20},"end":{"line":26,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":34,"character":20},"end":{"line":34,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":42,"character":20},"end":{"line":42,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":22,"character":20},"end":{"line":22,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":46,"character":20},"end":{"line":46,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":59,"character":20},"end":{"line":59,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":75,"character":20},"end":{"line":75,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":91,"character":20},"end":{"line":91,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":16,"character":20},"end":{"line":16,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":24,"character":20},"end":{"line":24,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":63,"character":20},"end":{"line":63,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":70,"character":20},"end":{"line":70,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":18,"character":20},"end":{"line":18,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":26,"character":20},"end":{"line":26,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":35,"character":20},"end":{"line":35,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":44,"character":20},"end":{"line":44,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":53,"character":20},"end":{"line":53,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":6,"character":20},"end":{"line":6,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"},{"range":{"start":{"line":13,"character":28},"end":{"line":13,"character":28}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"},{"range":{"start":{"line":21,"character":20},"end":{"line":21,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"},{"range":{"start":{"line":28,"character":28},"end":{"line":28,"character":28}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"},{"range":{"start":{"line":22,"character":20},"end":{"line":22,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":35,"character":23},"end":{"line":35,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":38,"character":23},"end":{"line":38,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":42,"character":20},"end":{"line":42,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":49,"character":23},"end":{"line":49,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":52,"character":23},"end":{"line":52,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":55,"character":23},"end":{"line":55,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":59,"character":20},"end":{"line":59,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":69,"character":23},"end":{"line":69,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":72,"character":23},"end":{"line":72,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"}]},{"range":{"start":{"line":79,"character":4},"end":{"line":84,"character":5}},"kind":6,"selectionRange":{"start":{"line":79,"character":4},"end":{"line":80,"character":36}},"name":"init(values:edges:)"},{"range":{"start":{"line":86,"character":4},"end":{"line":89,"character":5}},"kind":6,"selectionRange":{"start":{"line":86,"character":4},"end":{"line":86,"character":51}},"name":"init(valuesByID:)","references":[{"range":{"start":{"line":20,"character":13},"end":{"line":20,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":29,"character":13},"end":{"line":29,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":62,"character":13},"end":{"line":62,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"}]},{"range":{"start":{"line":94,"character":4},"end":{"line":100,"character":5}},"kind":6,"selectionRange":{"start":{"line":94,"character":4},"end":{"line":95,"character":48}},"name":"init(valuesByID:edges:)","references":[{"range":{"start":{"line":14,"character":21},"end":{"line":14,"character":21}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":39,"character":13},"end":{"line":39,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":46,"character":13},"end":{"line":46,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":72,"character":13},"end":{"line":72,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"}],"children":[{"range":{"start":{"line":97,"character":8},"end":{"line":97,"character":66}},"kind":13,"selectionRange":{"start":{"line":97,"character":12},"end":{"line":97,"character":23}},"name":"actualEdges"}]}]}],"code":"//extension Graph: ExpressibleByArrayLiteral where NodeValue: Identifiable, NodeValue.ID == NodeID\n//{\n//    public init(arrayLiteral elements: NodeValue...)\n//    {\n//        self.init(values: elements)\n//    }\n//}\n\nextension Graph: ExpressibleByArrayLiteral where NodeID == NodeValue\n{\n    public init(arrayLiteral elements: NodeValue...)\n    {\n        self.init(values: elements)\n    }\n}\n\nextension Graph: ExpressibleByDictionaryLiteral\n{\n    public init(dictionaryLiteral elements: (NodeID, NodeValue)...)\n    {\n        self.init(valuesByID: .init(uniqueKeysWithValues: elements))\n    }\n}\n\npublic extension Graph\n{\n    init(values: some Sequence<NodeValue>)\n        where NodeValue: Identifiable, NodeValue.ID == NodeID\n    {\n        self.init(valuesByID: .init(values: values))\n    }\n    \n    /**\n     Uses the `NodeValue.ID` of a value as the ``GraphNode/id`` for its corresponding node\n     */\n    init(values: some Sequence<NodeValue>,\n         edges: some Sequence<(NodeID, NodeID)>)\n        where NodeValue: Identifiable, NodeValue.ID == NodeID\n    {\n        self.init(valuesByID: .init(values: values), edges: edges)\n    }\n    \n    init(values: some Sequence<NodeValue>,\n         edgeTuples: some Sequence<(NodeID, NodeID)>)\n        where NodeValue: Identifiable, NodeValue.ID == NodeID\n    {\n        self.init(valuesByID: .init(values: values), edges: edgeTuples)\n    }\n    \n    /**\n     Uses the `NodeValue.ID` of a value as the ``GraphNode/id`` for its corresponding node\n     */\n    init(values: some Sequence<NodeValue>,\n         edges: some Sequence<Edge>)\n        where NodeValue: Identifiable, NodeValue.ID == NodeID\n    {\n        self.init(valuesByID: .init(values: values), edges: edges)\n    }\n    \n    init(values: some Sequence<NodeValue>)\n        where NodeID == NodeValue\n    {\n        self.init(valuesByID: .init(values: values))\n    }\n    \n    /**\n     Uses a `NodeValue` itself as the ``GraphNode/id`` for its corresponding node\n     */\n    init(values: some Sequence<NodeValue>,\n         edges: some Sequence<(NodeID, NodeID)>)\n        where NodeID == NodeValue\n    {\n        self.init(valuesByID: .init(values: values),\n                  edges: edges)\n    }\n    \n    /**\n     Uses a `NodeValue` itself as the ``GraphNode/id`` for its corresponding node\n     */\n    init(values: some Sequence<NodeValue>,\n         edges: some Sequence<Edge>)\n        where NodeID == NodeValue\n    {\n        self.init(valuesByID: .init(values: values), edges: edges)\n    }\n    \n    init(valuesByID: Dictionary<NodeID, NodeValue>)\n    {\n        self.init(valuesByID: valuesByID, edges: [Edge]())\n    }\n    \n    /**\n     Create a `Graph` that determines ``GraphNode/id``s for new `NodeValue`s via the given closure\n     */\n    init(valuesByID: Dictionary<NodeID, NodeValue>,\n         edges: some Sequence<(NodeID, NodeID)>)\n    {\n        let actualEdges = edges.map { Edge(from: $0.0, to: $0.1) }\n        \n        self.init(valuesByID: valuesByID, edges: actualEdges)\n    }\n}\n"},{"name":"Graph+ValueAccess.swift","symbols":[{"range":{"start":{"line":0,"character":7},"end":{"line":88,"character":1}},"kind":3,"selectionRange":{"start":{"line":0,"character":17},"end":{"line":0,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":11,"character":22},"end":{"line":11,"character":30}},"kind":13,"selectionRange":{"start":{"line":11,"character":22},"end":{"line":11,"character":30}},"name":"newValue"},{"range":{"start":{"line":22,"character":13},"end":{"line":25,"character":5}},"kind":6,"selectionRange":{"start":{"line":22,"character":18},"end":{"line":22,"character":44}},"name":"insert(_:)","references":[{"range":{"start":{"line":28,"character":25},"end":{"line":28,"character":25}},"filePathRelativeToRoot":"Tests/NodeTests.swift"}]},{"range":{"start":{"line":28,"character":13},"end":{"line":31,"character":5}},"kind":6,"selectionRange":{"start":{"line":28,"character":18},"end":{"line":28,"character":44}},"name":"insert(_:)","references":[{"range":{"start":{"line":49,"character":18},"end":{"line":49,"character":18}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":67,"character":24},"end":{"line":67,"character":24}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":85,"character":26},"end":{"line":85,"character":26}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":88,"character":29},"end":{"line":88,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":94,"character":26},"end":{"line":94,"character":26}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":41,"character":15},"end":{"line":41,"character":15}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":7,"character":26},"end":{"line":7,"character":26}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":38,"character":18},"end":{"line":38,"character":18}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"}]},{"range":{"start":{"line":34,"character":13},"end":{"line":37,"character":5}},"kind":6,"selectionRange":{"start":{"line":34,"character":18},"end":{"line":34,"character":44}},"name":"remove(_:)"},{"range":{"start":{"line":40,"character":13},"end":{"line":43,"character":5}},"kind":6,"selectionRange":{"start":{"line":40,"character":18},"end":{"line":40,"character":44}},"name":"remove(_:)","references":[{"range":{"start":{"line":42,"character":15},"end":{"line":42,"character":15}},"filePathRelativeToRoot":"Tests/ValueTests.swift"}]},{"range":{"start":{"line":51,"character":13},"end":{"line":65,"character":5}},"kind":6,"selectionRange":{"start":{"line":51,"character":18},"end":{"line":51,"character":64}},"name":"update(_:for:)","references":[{"range":{"start":{"line":33,"character":15},"end":{"line":33,"character":15}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":18,"character":26},"end":{"line":18,"character":26}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":19,"character":26},"end":{"line":19,"character":26}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":17,"character":12},"end":{"line":17,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":24,"character":8},"end":{"line":24,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":30,"character":8},"end":{"line":30,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"}],"children":[{"range":{"start":{"line":53,"character":15},"end":{"line":53,"character":19}},"kind":13,"selectionRange":{"start":{"line":53,"character":15},"end":{"line":53,"character":19}},"name":"node"},{"range":{"start":{"line":61,"character":12},"end":{"line":61,"character":53}},"kind":13,"selectionRange":{"start":{"line":61,"character":16},"end":{"line":61,"character":20}},"name":"node"}]},{"range":{"start":{"line":68,"character":13},"end":{"line":71,"character":5}},"kind":6,"selectionRange":{"start":{"line":68,"character":18},"end":{"line":68,"character":49}},"name":"removeValue(for:)","references":[{"range":{"start":{"line":35,"character":15},"end":{"line":35,"character":15}},"filePathRelativeToRoot":"Tests/ValueTests.swift"}]},{"range":{"start":{"line":76,"character":4},"end":{"line":79,"character":5}},"kind":6,"selectionRange":{"start":{"line":76,"character":9},"end":{"line":76,"character":34}},"name":"value(for:)","references":[{"range":{"start":{"line":83,"character":27},"end":{"line":83,"character":27}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":86,"character":29},"end":{"line":86,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":34,"character":28},"end":{"line":34,"character":28}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":9,"character":32},"end":{"line":9,"character":32}},"filePathRelativeToRoot":"Tests/NodeTests.swift"}]},{"range":{"start":{"line":84,"character":4},"end":{"line":87,"character":5}},"kind":7,"selectionRange":{"start":{"line":84,"character":8},"end":{"line":84,"character":14}},"name":"values","references":[{"range":{"start":{"line":37,"character":31},"end":{"line":37,"character":31}},"filePathRelativeToRoot":"Tests/ValueTests.swift"}]}]}],"code":"public extension Graph\n{\n    subscript(_ nodeID: NodeID) -> NodeValue?\n    {\n        get\n        {\n            nodesByID[nodeID]?.value\n        }\n        \n        set\n        {\n            guard let newValue else\n            {\n                removeNode(with: nodeID)\n                return\n            }\n            \n            update(newValue, for: nodeID)\n        }\n    }\n    \n    @discardableResult\n    mutating func insert(_ value: NodeValue) -> Node where NodeValue: Identifiable, NodeValue.ID == NodeID\n    {\n        update(value, for: value.id)\n    }\n    \n    @discardableResult\n    mutating func insert(_ value: NodeValue) -> Node where NodeID == NodeValue\n    {\n        update(value, for: value)\n    }\n    \n    @discardableResult\n    mutating func remove(_ value: NodeValue) -> Node? where NodeValue: Identifiable, NodeValue.ID == NodeID\n    {\n        removeNode(with: value.id)\n    }\n    \n    @discardableResult\n    mutating func remove(_ value: NodeValue) -> Node? where NodeID == NodeValue\n    {\n        removeNode(with: value)\n    }\n    \n    /**\n     Insert a `NodeValue` and get the (new) ``GraphNode`` that stores it\n     \n     - Returns: The (possibly new) ``GraphNode`` holding the value\n     */\n    @discardableResult\n    mutating func update(_ value: NodeValue, for nodeID: NodeID) -> Node\n    {\n        if var node = nodesByID[nodeID]\n        {\n            node.value = value\n            nodesByID[nodeID] = node\n            return node\n        }\n        else\n        {\n            let node = Node(id: nodeID, value: value)\n            nodesByID[nodeID] = node\n            return node\n        }\n    }\n    \n    @discardableResult\n    mutating func removeValue(for nodeID: NodeID) -> NodeValue?\n    {\n        removeNode(with: nodeID)?.value\n    }\n    \n    /**\n     ``GraphNode/value`` of the ``GraphNode`` with the given ``GraphNode/id`` if one exists, otherwise `nil`\n     */\n    func value(for nodeID: NodeID) -> NodeValue?\n    {\n        nodesByID[nodeID]?.value\n    }\n    \n    /**\n     All `NodeValue`s of the `Graph`\n     */\n    var values: some Collection<NodeValue>\n    {\n        nodesByID.values.map { $0.value }\n    }\n}\n"}]},{"name":"Graph+Algorithms","files":[{"name":"Graph+Components.swift","symbols":[{"range":{"start":{"line":2,"character":7},"end":{"line":54,"character":1}},"kind":3,"selectionRange":{"start":{"line":2,"character":17},"end":{"line":2,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":9,"character":4},"end":{"line":29,"character":5}},"kind":6,"selectionRange":{"start":{"line":9,"character":9},"end":{"line":9,"character":25}},"name":"findComponents()","references":[{"range":{"start":{"line":6,"character":35},"end":{"line":6,"character":35}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":14,"character":29},"end":{"line":14,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":22,"character":29},"end":{"line":22,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":31,"character":29},"end":{"line":31,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":40,"character":29},"end":{"line":40,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"}],"children":[{"range":{"start":{"line":11,"character":8},"end":{"line":11,"character":36}},"kind":13,"selectionRange":{"start":{"line":11,"character":12},"end":{"line":11,"character":24}},"name":"visitedNodes"},{"range":{"start":{"line":13,"character":8},"end":{"line":13,"character":39}},"kind":13,"selectionRange":{"start":{"line":13,"character":12},"end":{"line":13,"character":22}},"name":"components"},{"range":{"start":{"line":15,"character":12},"end":{"line":15,"character":16}},"kind":13,"selectionRange":{"start":{"line":15,"character":12},"end":{"line":15,"character":16}},"name":"node"}]},{"range":{"start":{"line":32,"character":12},"end":{"line":53,"character":5}},"kind":6,"selectionRange":{"start":{"line":32,"character":17},"end":{"line":34,"character":62}},"name":"findLackingNodes(forComponent:startingAt:visitedNodes:)","references":[{"range":{"start":{"line":21,"character":30},"end":{"line":21,"character":30}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"},{"range":{"start":{"line":47,"character":28},"end":{"line":47,"character":28}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"}],"children":[{"range":{"start":{"line":36,"character":8},"end":{"line":36,"character":38}},"kind":13,"selectionRange":{"start":{"line":36,"character":12},"end":{"line":36,"character":24}},"name":"lackingNodes"},{"range":{"start":{"line":40,"character":8},"end":{"line":40,"character":66}},"kind":13,"selectionRange":{"start":{"line":40,"character":12},"end":{"line":40,"character":22}},"name":"neighbours"},{"range":{"start":{"line":42,"character":12},"end":{"line":42,"character":21}},"kind":13,"selectionRange":{"start":{"line":42,"character":12},"end":{"line":42,"character":21}},"name":"neighbour"},{"range":{"start":{"line":46,"character":12},"end":{"line":46,"character":70}},"kind":13,"selectionRange":{"start":{"line":46,"character":16},"end":{"line":46,"character":33}},"name":"extendedComponent"}]}]}],"code":"import SwiftyToolz\n\npublic extension Graph\n{\n    /**\n     Find the [components](https://en.wikipedia.org/wiki/Component_(graph_theory)) of the `Graph`\n     \n     - Returns: Multiple sets of nodes which represent the components of the graph\n     */\n    func findComponents() -> Set<NodeIDs>\n    {\n        var visitedNodes = NodeIDs()\n        \n        var components = Set<NodeIDs>()\n\n        for node in nodeIDs\n        {\n            if visitedNodes.contains(node) { continue }\n            \n            // this node has not been visited yet\n            \n            components += Set(findLackingNodes(forComponent: [],\n                                               startingAt: node,\n                                               visitedNodes: &visitedNodes))\n            \n            visitedNodes.insert(node)\n        }\n\n        return components\n    }\n    \n    /// startNode is connected to the incompleteComponent but not contained in it. both will be in the resulting actual component.\n    private func findLackingNodes(forComponent incompleteComponent: [NodeID],\n                                  startingAt startNode: NodeID,\n                                  visitedNodes: inout NodeIDs) -> [NodeID]\n    {\n        var lackingNodes = [startNode]\n        \n        visitedNodes += startNode\n        \n        let neighbours = node(with: startNode)?.neighbourIDs ?? []\n        \n        for neighbour in neighbours\n        {\n            if visitedNodes.contains(neighbour) { continue }\n            \n            let extendedComponent = incompleteComponent + lackingNodes\n            lackingNodes += findLackingNodes(forComponent: extendedComponent,\n                                             startingAt: neighbour,\n                                             visitedNodes: &visitedNodes)\n        }\n        \n        return lackingNodes\n    }\n}\n"},{"name":"Graph+AncestorCount.swift","symbols":[{"range":{"start":{"line":2,"character":7},"end":{"line":53,"character":1}},"kind":3,"selectionRange":{"start":{"line":2,"character":17},"end":{"line":2,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":15,"character":4},"end":{"line":25,"character":5}},"kind":6,"selectionRange":{"start":{"line":15,"character":9},"end":{"line":15,"character":36}},"name":"findNumberOfNodeAncestors()","references":[{"range":{"start":{"line":6,"character":35},"end":{"line":6,"character":35}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":13,"character":29},"end":{"line":13,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":21,"character":29},"end":{"line":21,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":29,"character":29},"end":{"line":29,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":37,"character":29},"end":{"line":37,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":45,"character":29},"end":{"line":45,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"}],"children":[{"range":{"start":{"line":17,"character":8},"end":{"line":17,"character":55}},"kind":13,"selectionRange":{"start":{"line":17,"character":12},"end":{"line":17,"character":29}},"name":"ancestorsByNodeID"}]},{"range":{"start":{"line":28,"character":12},"end":{"line":52,"character":5}},"kind":6,"selectionRange":{"start":{"line":28,"character":17},"end":{"line":29,"character":77}},"name":"getAncestors(for:ancestorsByNodeID:)","references":[{"range":{"start":{"line":21,"character":12},"end":{"line":21,"character":12}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":45,"character":25},"end":{"line":45,"character":25}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"}],"children":[{"range":{"start":{"line":31,"character":15},"end":{"line":31,"character":24}},"kind":13,"selectionRange":{"start":{"line":31,"character":15},"end":{"line":31,"character":24}},"name":"ancestors"},{"range":{"start":{"line":35,"character":18},"end":{"line":35,"character":33}},"kind":13,"selectionRange":{"start":{"line":35,"character":18},"end":{"line":35,"character":33}},"name":"directAncestors"},{"range":{"start":{"line":41,"character":8},"end":{"line":41,"character":39}},"kind":13,"selectionRange":{"start":{"line":41,"character":12},"end":{"line":41,"character":21}},"name":"ancestors"},{"range":{"start":{"line":43,"character":12},"end":{"line":43,"character":26}},"kind":13,"selectionRange":{"start":{"line":43,"character":12},"end":{"line":43,"character":26}},"name":"directAncestor"}]}]}],"code":"import SwiftyToolz\n\npublic extension Graph\n{\n    /**\n     Find the total (recursive) number of ancestors for each ``GraphNode`` of an **acyclic** `Graph`\n     \n     The ancestor count of a node is basically the number of other nodes from which the node can be reached. This only works on acyclic graphs right now and might return incorrect results for nodes in cycles.\n     \n     Ancestor counts can serve as a proxy for [topological sorting](https://en.wikipedia.org/wiki/Topological_sorting).\n     \n     Note that the worst case space complexity is quadratic in the number of nodes.\n     \n     - Returns: A dictionary containing the ancestor count for every node ``GraphNode/id`` of the `Graph`\n     */\n    func findNumberOfNodeAncestors() -> [NodeID: Int]\n    {\n        var ancestorsByNodeID = [NodeID: Set<NodeID>]()\n        \n        sinks.forEach\n        {\n            getAncestors(for: $0.id, ancestorsByNodeID: &ancestorsByNodeID)\n        }\n\n        return ancestorsByNodeID.mapValues { $0.count }\n    }\n\n    @discardableResult\n    private func getAncestors(for node: NodeID,\n                              ancestorsByNodeID: inout [NodeID: Set<NodeID>]) -> Set<NodeID>\n    {\n        if let ancestors = ancestorsByNodeID[node] { return ancestors }\n        \n        ancestorsByNodeID[node] = [] // mark node as visited to avoid infinite loops in cyclic graphs\n        \n        guard let directAncestors = self.node(with: node)?.ancestorIDs else\n        {\n            log(error: \"No node for node ID exists, but it should.\")\n            return []\n        }\n        \n        var ancestors = directAncestors\n        \n        for directAncestor in directAncestors\n        {\n            ancestors += getAncestors(for: directAncestor,\n                                      ancestorsByNodeID: &ancestorsByNodeID)\n        }\n        \n        ancestorsByNodeID[node] = ancestors\n        \n        return ancestors\n    }\n}\n"},{"name":"Graph+CondensationGraph.swift","symbols":[{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":78}},"kind":3,"selectionRange":{"start":{"line":2,"character":10},"end":{"line":2,"character":42}},"name":"Graph.StronglyConnectedComponent"},{"range":{"start":{"line":4,"character":7},"end":{"line":72,"character":1}},"kind":3,"selectionRange":{"start":{"line":4,"character":17},"end":{"line":4,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":11,"character":4},"end":{"line":52,"character":5}},"kind":6,"selectionRange":{"start":{"line":11,"character":9},"end":{"line":11,"character":32}},"name":"makeCondensationGraph()","references":[{"range":{"start":{"line":36,"character":32},"end":{"line":36,"character":32}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":8,"character":38},"end":{"line":8,"character":38}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":25,"character":38},"end":{"line":25,"character":38}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":49,"character":38},"end":{"line":49,"character":38}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":62,"character":38},"end":{"line":62,"character":38}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":78,"character":38},"end":{"line":78,"character":38}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":94,"character":38},"end":{"line":94,"character":38}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"}],"children":[{"range":{"start":{"line":14,"character":8},"end":{"line":17,"character":9}},"kind":13,"selectionRange":{"start":{"line":14,"character":12},"end":{"line":14,"character":16}},"name":"sccs"},{"range":{"start":{"line":20,"character":8},"end":{"line":20,"character":65}},"kind":13,"selectionRange":{"start":{"line":20,"character":12},"end":{"line":20,"character":23}},"name":"sccByNodeID"},{"range":{"start":{"line":22,"character":12},"end":{"line":22,"character":15}},"kind":13,"selectionRange":{"start":{"line":22,"character":12},"end":{"line":22,"character":15}},"name":"scc"},{"range":{"start":{"line":24,"character":16},"end":{"line":24,"character":22}},"kind":13,"selectionRange":{"start":{"line":24,"character":16},"end":{"line":24,"character":22}},"name":"nodeID"},{"range":{"start":{"line":31,"character":8},"end":{"line":31,"character":63}},"kind":13,"selectionRange":{"start":{"line":31,"character":12},"end":{"line":31,"character":29}},"name":"condensationGraph"},{"range":{"start":{"line":34,"character":12},"end":{"line":34,"character":18}},"kind":13,"selectionRange":{"start":{"line":34,"character":12},"end":{"line":34,"character":18}},"name":"edgeID"},{"range":{"start":{"line":36,"character":22},"end":{"line":36,"character":31}},"kind":13,"selectionRange":{"start":{"line":36,"character":22},"end":{"line":36,"character":31}},"name":"originSCC"},{"range":{"start":{"line":37,"character":22},"end":{"line":37,"character":36}},"kind":13,"selectionRange":{"start":{"line":37,"character":22},"end":{"line":37,"character":36}},"name":"destinationSCC"}]},{"range":{"start":{"line":59,"character":4},"end":{"line":71,"character":5}},"kind":23,"selectionRange":{"start":{"line":59,"character":11},"end":{"line":59,"character":37}},"name":"StronglyConnectedComponent","references":[{"range":{"start":{"line":39,"character":50},"end":{"line":39,"character":50}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":2,"character":16},"end":{"line":2,"character":16}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":16,"character":12},"end":{"line":16,"character":12}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":20,"character":36},"end":{"line":20,"character":36}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":57,"character":40},"end":{"line":57,"character":40}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":57,"character":71},"end":{"line":57,"character":71}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"}],"children":[{"range":{"start":{"line":61,"character":15},"end":{"line":61,"character":37}},"kind":7,"selectionRange":{"start":{"line":61,"character":19},"end":{"line":61,"character":21}},"name":"id","references":[{"range":{"start":{"line":43,"character":25},"end":{"line":43,"character":25}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":43,"character":46},"end":{"line":43,"character":46}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":45,"character":74},"end":{"line":45,"character":74}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":46,"character":77},"end":{"line":46,"character":77}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"}]},{"range":{"start":{"line":65,"character":8},"end":{"line":68,"character":9}},"kind":6,"selectionRange":{"start":{"line":65,"character":8},"end":{"line":65,"character":30}},"name":"init(nodeIDs:)","references":[{"range":{"start":{"line":16,"character":12},"end":{"line":16,"character":12}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":12,"character":17},"end":{"line":12,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":13,"character":17},"end":{"line":13,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":14,"character":17},"end":{"line":14,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":34,"character":17},"end":{"line":34,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":35,"character":17},"end":{"line":35,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":36,"character":17},"end":{"line":36,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":37,"character":17},"end":{"line":37,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":52,"character":22},"end":{"line":52,"character":22}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":67,"character":22},"end":{"line":67,"character":22}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":67,"character":49},"end":{"line":67,"character":49}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":83,"character":22},"end":{"line":83,"character":22}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":83,"character":49},"end":{"line":83,"character":49}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":100,"character":17},"end":{"line":100,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":101,"character":17},"end":{"line":101,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":102,"character":17},"end":{"line":102,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"},{"range":{"start":{"line":103,"character":17},"end":{"line":103,"character":17}},"filePathRelativeToRoot":"Tests/Algorithms/CondensationGraphTests.swift"}]},{"range":{"start":{"line":70,"character":15},"end":{"line":70,"character":35}},"kind":7,"selectionRange":{"start":{"line":70,"character":19},"end":{"line":70,"character":26}},"name":"nodeIDs","references":[{"range":{"start":{"line":43,"character":47},"end":{"line":43,"character":47}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":24,"character":30},"end":{"line":24,"character":30}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":61,"character":28},"end":{"line":61,"character":28}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":67,"character":17},"end":{"line":67,"character":17}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"}]}]}]}],"code":"import SwiftyToolz\n\nextension Graph.StronglyConnectedComponent: Sendable where NodeID: Sendable {}\n\npublic extension Graph\n{\n    /**\n     Creates the acyclic [condensation graph](https://en.wikipedia.org/wiki/Strongly_connected_component) of the `Graph`\n     \n     The condensation graph is the graph in which the [strongly connected components](https://en.wikipedia.org/wiki/Strongly_connected_component) of the original graph have been collapsed into single nodes, so the resulting condensation graph is acyclic.\n     */\n    func makeCondensationGraph() -> CondensationGraph\n    {\n        // get SCCs\n        let sccs = findStronglyConnectedComponents().map\n        {\n            StronglyConnectedComponent(nodeIDs: $0)\n        }\n        \n        // create hashmap from node IDs to the containing SCCs\n        var sccByNodeID = [Node.ID: StronglyConnectedComponent]()\n        \n        for scc in sccs\n        {\n            for nodeID in scc.nodeIDs\n            {\n                sccByNodeID[nodeID] = scc\n            }\n        }\n        \n        // create condensation graph\n        var condensationGraph = CondensationGraph(values: sccs)\n        \n        // add condensation edges\n        for edgeID in edgeIDs\n        {\n            guard let originSCC = sccByNodeID[edgeID.originID],\n                  let destinationSCC = sccByNodeID[edgeID.destinationID] else\n            {\n                log(error: \"mising scc in hash map\")\n                continue\n            }\n            \n            if originSCC.id != destinationSCC.id\n            {\n                condensationGraph.insert(CondensationEdge(from: originSCC.id,\n                                                          to: destinationSCC.id))\n            }\n        }\n        \n        // return graph\n        return condensationGraph\n    }\n    \n    typealias CondensationNode = CondensationGraph.Node\n    typealias CondensationEdge = CondensationGraph.Edge\n    \n    typealias CondensationGraph = Graph<StronglyConnectedComponent.ID, StronglyConnectedComponent, EdgeWeight>\n    \n    struct StronglyConnectedComponent: Identifiable, Hashable\n    {\n        public var id: ID { nodeIDs }\n        \n        public typealias ID = NodeIDs\n        \n        init(nodeIDs: NodeIDs)\n        {\n            self.nodeIDs = nodeIDs\n        }\n        \n        public let nodeIDs: NodeIDs\n    }\n}\n"},{"name":"Graph+TransitiveReduction.swift","symbols":[{"range":{"start":{"line":2,"character":7},"end":{"line":98,"character":1}},"kind":3,"selectionRange":{"start":{"line":2,"character":17},"end":{"line":2,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":9,"character":4},"end":{"line":14,"character":5}},"kind":6,"selectionRange":{"start":{"line":9,"character":9},"end":{"line":9,"character":38}},"name":"filteredTransitiveReduction()","references":[{"range":{"start":{"line":6,"character":35},"end":{"line":6,"character":35}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":12,"character":29},"end":{"line":12,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":19,"character":29},"end":{"line":19,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":29,"character":29},"end":{"line":29,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":39,"character":29},"end":{"line":39,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":75,"character":29},"end":{"line":75,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":50,"character":57},"end":{"line":50,"character":57}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"}],"children":[{"range":{"start":{"line":11,"character":8},"end":{"line":11,"character":41}},"kind":13,"selectionRange":{"start":{"line":11,"character":12},"end":{"line":11,"character":34}},"name":"minimumEquivalentGraph"}]},{"range":{"start":{"line":21,"character":13},"end":{"line":24,"character":5}},"kind":6,"selectionRange":{"start":{"line":21,"character":18},"end":{"line":21,"character":45}},"name":"filterTransitiveReduction()","references":[{"range":{"start":{"line":12,"character":31},"end":{"line":12,"character":31}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"}]},{"range":{"start":{"line":31,"character":4},"end":{"line":47,"character":5}},"kind":6,"selectionRange":{"start":{"line":31,"character":9},"end":{"line":31,"character":39}},"name":"findTransitiveReductionEdges()","references":[{"range":{"start":{"line":23,"character":20},"end":{"line":23,"character":20}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"}],"children":[{"range":{"start":{"line":33,"character":8},"end":{"line":33,"character":44}},"kind":13,"selectionRange":{"start":{"line":33,"character":12},"end":{"line":33,"character":32}},"name":"idsOfTransitiveEdges"},{"range":{"start":{"line":35,"character":8},"end":{"line":35,"character":57}},"kind":13,"selectionRange":{"start":{"line":35,"character":12},"end":{"line":35,"character":35}},"name":"consideredAncestorsHash"},{"range":{"start":{"line":37,"character":12},"end":{"line":37,"character":22}},"kind":13,"selectionRange":{"start":{"line":37,"character":12},"end":{"line":37,"character":22}},"name":"sourceNode"},{"range":{"start":{"line":44,"character":8},"end":{"line":44,"character":44}},"kind":13,"selectionRange":{"start":{"line":44,"character":12},"end":{"line":44,"character":25}},"name":"idsOfAllEdges"}]},{"range":{"start":{"line":49,"character":12},"end":{"line":97,"character":5}},"kind":6,"selectionRange":{"start":{"line":49,"character":17},"end":{"line":51,"character":86}},"name":"findTransitiveEdges(around:reachedAncestors:consideredAncestorsHash:)","references":[{"range":{"start":{"line":39,"character":36},"end":{"line":39,"character":36}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":91,"character":36},"end":{"line":91,"character":36}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"}],"children":[{"range":{"start":{"line":55,"character":8},"end":{"line":55,"character":86}},"kind":13,"selectionRange":{"start":{"line":55,"character":12},"end":{"line":55,"character":31}},"name":"consideredAncestors"},{"range":{"start":{"line":56,"character":8},"end":{"line":56,"character":72}},"kind":13,"selectionRange":{"start":{"line":56,"character":12},"end":{"line":56,"character":31}},"name":"ancestorsToConsider"},{"range":{"start":{"line":66,"character":8},"end":{"line":66,"character":44}},"kind":13,"selectionRange":{"start":{"line":66,"character":12},"end":{"line":66,"character":32}},"name":"idsOfTransitiveEdges"},{"range":{"start":{"line":70,"character":8},"end":{"line":70,"character":44}},"kind":13,"selectionRange":{"start":{"line":70,"character":12},"end":{"line":70,"character":23}},"name":"descendants"},{"range":{"start":{"line":72,"character":12},"end":{"line":72,"character":22}},"kind":13,"selectionRange":{"start":{"line":72,"character":12},"end":{"line":72,"character":22}},"name":"descendant"},{"range":{"start":{"line":74,"character":16},"end":{"line":74,"character":24}},"kind":13,"selectionRange":{"start":{"line":74,"character":16},"end":{"line":74,"character":24}},"name":"ancestor"},{"range":{"start":{"line":76,"character":16},"end":{"line":76,"character":58}},"kind":13,"selectionRange":{"start":{"line":76,"character":20},"end":{"line":76,"character":26}},"name":"edgeID"},{"range":{"start":{"line":87,"character":12},"end":{"line":87,"character":24}},"kind":13,"selectionRange":{"start":{"line":87,"character":12},"end":{"line":87,"character":24}},"name":"descendantID"},{"range":{"start":{"line":89,"character":22},"end":{"line":89,"character":32}},"kind":13,"selectionRange":{"start":{"line":89,"character":22},"end":{"line":89,"character":32}},"name":"descendant"}]}]}],"code":"import SwiftyToolz\n\npublic extension Graph\n{\n    /**\n     The [minumum equivalent graph](https://en.wikipedia.org/wiki/Transitive_reduction) of an **acyclic** `Graph`\n     \n     🛑 This only works on acyclic graphs and might even hang or crash on cyclic ones!\n     */\n    func filteredTransitiveReduction() -> Self\n    {\n        var minimumEquivalentGraph = self\n        minimumEquivalentGraph.filterTransitiveReduction()\n        return minimumEquivalentGraph\n    }\n    \n    /**\n     Filter an **acyclic** `Graph` down to its [minumum equivalent graph](https://en.wikipedia.org/wiki/Transitive_reduction)\n     \n     🛑 This only works on acyclic graphs and might even hang or crash on cyclic ones!\n     */\n    mutating func filterTransitiveReduction()\n    {\n        filterEdges(findTransitiveReductionEdges())\n    }\n    \n    /**\n     Edges that are *not* in the [minumum equivalent graph](https://en.wikipedia.org/wiki/Transitive_reduction) of an **acyclic** `Graph`\n     \n     🛑 This only works on acyclic graphs and might even hang or crash on cyclic ones!\n     */\n    func findTransitiveReductionEdges() -> EdgeIDs\n    {\n        var idsOfTransitiveEdges = EdgeIDs() // or \"shortcuts\" of longer paths; or \"implied\" edges\n        \n        var consideredAncestorsHash = [NodeID: NodeIDs]()\n        \n        for sourceNode in sources\n        {\n            idsOfTransitiveEdges += findTransitiveEdges(around: sourceNode,\n                                                       reachedAncestors: [],\n                                                       consideredAncestorsHash: &consideredAncestorsHash)\n        }\n        \n        let idsOfAllEdges = EdgeIDs(edgeIDs)\n        \n        return idsOfAllEdges - idsOfTransitiveEdges\n    }\n    \n    private func findTransitiveEdges(around node: Node,\n                                     reachedAncestors: NodeIDs,\n                                     consideredAncestorsHash: inout [NodeID: NodeIDs]) -> EdgeIDs\n    {\n        // to make this not hang in cycles it might be enough to just ensure that node is not in reachedAncestors ...\n        \n        let consideredAncestors = consideredAncestorsHash[node.id, default: NodeIDs()]\n        let ancestorsToConsider = reachedAncestors - consideredAncestors\n        \n        if !reachedAncestors.isEmpty && ancestorsToConsider.isEmpty\n        {\n            // found shortcut edge on a path we've already traversed, so we reached no new ancestors\n            return []\n        }\n        \n        consideredAncestorsHash[node.id, default: NodeIDs()] += ancestorsToConsider\n        \n        var idsOfTransitiveEdges = EdgeIDs()\n        \n        // base case: add edges from all reached ancestors to all reachable neighbours of node\n        \n        let descendants = node.descendantIDs\n        \n        for descendant in descendants\n        {\n            for ancestor in ancestorsToConsider\n            {\n                let edgeID = Edge.ID(ancestor, descendant)\n                \n                if contains(edgeID)\n                {\n                    idsOfTransitiveEdges += edgeID\n                }\n            }\n        }\n        \n        // recursive calls on descendants\n        \n        for descendantID in descendants\n        {\n            guard let descendant = self.node(with: descendantID) else { continue }\n            \n            idsOfTransitiveEdges += findTransitiveEdges(around: descendant,\n                                                        reachedAncestors: ancestorsToConsider + node.id,\n                                                        consideredAncestorsHash: &consideredAncestorsHash)\n        }\n        \n        return idsOfTransitiveEdges\n    }\n}\n"},{"name":"Graph+FilterAndMap.swift","symbols":[{"range":{"start":{"line":0,"character":7},"end":{"line":89,"character":1}},"kind":3,"selectionRange":{"start":{"line":0,"character":17},"end":{"line":0,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":4,"character":4},"end":{"line":10,"character":5}},"kind":6,"selectionRange":{"start":{"line":4,"character":9},"end":{"line":4,"character":73}},"name":"map(_:)","references":[{"range":{"start":{"line":7,"character":32},"end":{"line":7,"character":32}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/MapTests.swift"}],"children":[{"range":{"start":{"line":4,"character":13},"end":{"line":4,"character":24}},"kind":26,"selectionRange":{"start":{"line":4,"character":13},"end":{"line":4,"character":24}},"name":"MappedValue"},{"range":{"start":{"line":6,"character":8},"end":{"line":6,"character":84}},"kind":13,"selectionRange":{"start":{"line":6,"character":12},"end":{"line":6,"character":31}},"name":"idsWithMappedValues"}]},{"range":{"start":{"line":14,"character":4},"end":{"line":19,"character":5}},"kind":6,"selectionRange":{"start":{"line":14,"character":9},"end":{"line":14,"character":45}},"name":"filteredEdges(_:)","children":[{"range":{"start":{"line":16,"character":8},"end":{"line":16,"character":25}},"kind":13,"selectionRange":{"start":{"line":16,"character":12},"end":{"line":16,"character":18}},"name":"result"}]},{"range":{"start":{"line":21,"character":13},"end":{"line":24,"character":5}},"kind":6,"selectionRange":{"start":{"line":21,"character":18},"end":{"line":21,"character":52}},"name":"filterEdges(_:)","references":[{"range":{"start":{"line":23,"character":8},"end":{"line":23,"character":8}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":17,"character":15},"end":{"line":17,"character":15}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":23,"character":8},"end":{"line":23,"character":8}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"}]},{"range":{"start":{"line":26,"character":4},"end":{"line":31,"character":5}},"kind":6,"selectionRange":{"start":{"line":26,"character":9},"end":{"line":26,"character":59}},"name":"filteredEdges(_:)","references":[{"range":{"start":{"line":9,"character":34},"end":{"line":9,"character":34}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"}],"children":[{"range":{"start":{"line":28,"character":8},"end":{"line":28,"character":25}},"kind":13,"selectionRange":{"start":{"line":28,"character":12},"end":{"line":28,"character":18}},"name":"result"}]},{"range":{"start":{"line":33,"character":13},"end":{"line":42,"character":5}},"kind":6,"selectionRange":{"start":{"line":33,"character":18},"end":{"line":33,"character":66}},"name":"filterEdges(_:)","references":[{"range":{"start":{"line":23,"character":8},"end":{"line":23,"character":8}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":29,"character":19},"end":{"line":29,"character":19}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":24,"character":14},"end":{"line":24,"character":14}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"}]},{"range":{"start":{"line":46,"character":4},"end":{"line":51,"character":5}},"kind":6,"selectionRange":{"start":{"line":46,"character":9},"end":{"line":46,"character":59}},"name":"filtered(_:)","references":[{"range":{"start":{"line":7,"character":34},"end":{"line":7,"character":34}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/ValueFilterTests.swift"}],"children":[{"range":{"start":{"line":48,"character":8},"end":{"line":48,"character":25}},"kind":13,"selectionRange":{"start":{"line":48,"character":12},"end":{"line":48,"character":18}},"name":"result"}]},{"range":{"start":{"line":53,"character":13},"end":{"line":56,"character":5}},"kind":6,"selectionRange":{"start":{"line":53,"character":18},"end":{"line":53,"character":66}},"name":"filter(_:)","references":[{"range":{"start":{"line":49,"character":19},"end":{"line":49,"character":19}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"}]},{"range":{"start":{"line":60,"character":4},"end":{"line":65,"character":5}},"kind":6,"selectionRange":{"start":{"line":60,"character":9},"end":{"line":60,"character":45}},"name":"filteredNodes(_:)","references":[{"range":{"start":{"line":8,"character":29},"end":{"line":8,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":11,"character":29},"end":{"line":11,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":14,"character":29},"end":{"line":14,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":17,"character":29},"end":{"line":17,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":25,"character":29},"end":{"line":25,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":28,"character":29},"end":{"line":28,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":31,"character":29},"end":{"line":31,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":34,"character":29},"end":{"line":34,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":37,"character":29},"end":{"line":37,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":45,"character":29},"end":{"line":45,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":48,"character":29},"end":{"line":48,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":51,"character":29},"end":{"line":51,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":54,"character":29},"end":{"line":54,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":62,"character":29},"end":{"line":62,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":65,"character":29},"end":{"line":65,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":68,"character":29},"end":{"line":68,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"},{"range":{"start":{"line":71,"character":29},"end":{"line":71,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/NodeFilterTests.swift"}],"children":[{"range":{"start":{"line":62,"character":8},"end":{"line":62,"character":25}},"kind":13,"selectionRange":{"start":{"line":62,"character":12},"end":{"line":62,"character":18}},"name":"result"}]},{"range":{"start":{"line":67,"character":13},"end":{"line":70,"character":5}},"kind":6,"selectionRange":{"start":{"line":67,"character":18},"end":{"line":67,"character":52}},"name":"filterNodes(_:)","references":[{"range":{"start":{"line":63,"character":15},"end":{"line":63,"character":15}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"}]},{"range":{"start":{"line":72,"character":4},"end":{"line":77,"character":5}},"kind":6,"selectionRange":{"start":{"line":72,"character":9},"end":{"line":72,"character":59}},"name":"filteredNodes(_:)","children":[{"range":{"start":{"line":74,"character":8},"end":{"line":74,"character":25}},"kind":13,"selectionRange":{"start":{"line":74,"character":12},"end":{"line":74,"character":18}},"name":"result"}]},{"range":{"start":{"line":79,"character":13},"end":{"line":88,"character":5}},"kind":6,"selectionRange":{"start":{"line":79,"character":18},"end":{"line":79,"character":66}},"name":"filterNodes(_:)","references":[{"range":{"start":{"line":55,"character":12},"end":{"line":55,"character":12}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":69,"character":8},"end":{"line":69,"character":8}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":75,"character":19},"end":{"line":75,"character":19}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"}]}]}],"code":"public extension Graph\n{\n    // MARK: - Value Mapper\n    \n    func map<MappedValue>(_ transform: (NodeValue) throws -> MappedValue) rethrows -> Graph<NodeID, MappedValue, EdgeWeight>\n    {\n        let idsWithMappedValues = try nodes.map { ($0.id, try transform($0.value)) }\n        \n        return .init(valuesByID: .init(uniqueKeysWithValues: idsWithMappedValues),\n                     edges: edges)\n    }\n    \n    // MARK: - Edge Filters\n    \n    func filteredEdges(_ isIncluded: EdgeIDs) -> Self\n    {\n        var result = self\n        result.filterEdges(isIncluded)\n        return result\n    }\n    \n    mutating func filterEdges(_ isIncluded: EdgeIDs)\n    {\n        filterEdges { isIncluded.contains($0.id) }\n    }\n    \n    func filteredEdges(_ isIncluded: (Edge) throws -> Bool) rethrows -> Self\n    {\n        var result = self\n        try result.filterEdges(isIncluded)\n        return result\n    }\n    \n    mutating func filterEdges(_ isIncluded: (Edge) throws -> Bool) rethrows\n    {\n        try edges.forEach\n        {\n            if try !isIncluded($0)\n            {\n                removeEdge(with: $0.id)\n            }\n        }\n    }\n    \n    // MARK: - Value Filters\n    \n    func filtered(_ isIncluded: (NodeValue) throws -> Bool) rethrows -> Self\n    {\n        var result = self\n        try result.filter(isIncluded)\n        return result\n    }\n    \n    mutating func filter(_ isIncluded: (NodeValue) throws -> Bool) rethrows\n    {\n        try filterNodes { try isIncluded($0.value) }\n    }\n    \n    // MARK: - Node Filters\n    \n    func filteredNodes(_ isIncluded: NodeIDs) -> Self\n    {\n        var result = self\n        result.filterNodes(isIncluded)\n        return result\n    }\n    \n    mutating func filterNodes(_ isIncluded: NodeIDs)\n    {\n        filterNodes { isIncluded.contains($0.id) }\n    }\n    \n    func filteredNodes(_ isIncluded: (Node) throws -> Bool) rethrows -> Self\n    {\n        var result = self\n        try result.filterNodes(isIncluded)\n        return result\n    }\n    \n    mutating func filterNodes(_ isIncluded: (Node) throws -> Bool) rethrows\n    {\n        try nodes.forEach\n        {\n            if try !isIncluded($0)\n            {\n                removeNode(with: $0.id)\n            }\n        }\n    }\n}\n"},{"name":"Graph+StronglyConnectedComponents.swift","symbols":[{"range":{"start":{"line":2,"character":0},"end":{"line":97,"character":1}},"kind":3,"selectionRange":{"start":{"line":2,"character":10},"end":{"line":2,"character":15}},"name":"Graph","children":[{"range":{"start":{"line":9,"character":4},"end":{"line":29,"character":5}},"kind":6,"selectionRange":{"start":{"line":9,"character":9},"end":{"line":9,"character":42}},"name":"findStronglyConnectedComponents()","references":[{"range":{"start":{"line":14,"character":19},"end":{"line":14,"character":19}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":6,"character":35},"end":{"line":6,"character":35}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":14,"character":29},"end":{"line":14,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":22,"character":29},"end":{"line":22,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":31,"character":29},"end":{"line":31,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":40,"character":29},"end":{"line":40,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":49,"character":29},"end":{"line":49,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"},{"range":{"start":{"line":58,"character":29},"end":{"line":58,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"}],"children":[{"range":{"start":{"line":11,"character":8},"end":{"line":11,"character":42}},"kind":13,"selectionRange":{"start":{"line":11,"character":12},"end":{"line":11,"character":25}},"name":"resultingSCCs"},{"range":{"start":{"line":13,"character":8},"end":{"line":13,"character":21}},"kind":13,"selectionRange":{"start":{"line":13,"character":12},"end":{"line":13,"character":17}},"name":"index"},{"range":{"start":{"line":14,"character":8},"end":{"line":14,"character":30}},"kind":13,"selectionRange":{"start":{"line":14,"character":12},"end":{"line":14,"character":17}},"name":"stack"},{"range":{"start":{"line":15,"character":8},"end":{"line":15,"character":42}},"kind":13,"selectionRange":{"start":{"line":15,"character":12},"end":{"line":15,"character":20}},"name":"markings"},{"range":{"start":{"line":17,"character":12},"end":{"line":17,"character":16}},"kind":13,"selectionRange":{"start":{"line":17,"character":12},"end":{"line":17,"character":16}},"name":"node"}]},{"range":{"start":{"line":32,"character":12},"end":{"line":96,"character":5}},"kind":6,"selectionRange":{"start":{"line":32,"character":17},"end":{"line":36,"character":69}},"name":"findSCCsRecursively(node:index:stack:markings:handleNewSCC:)","references":[{"range":{"start":{"line":21,"character":16},"end":{"line":21,"character":16}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":62,"character":40},"end":{"line":62,"character":40}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"}],"children":[{"range":{"start":{"line":40,"character":8},"end":{"line":40,"character":80}},"kind":13,"selectionRange":{"start":{"line":40,"character":12},"end":{"line":40,"character":23}},"name":"nodeMarking"},{"range":{"start":{"line":46,"character":8},"end":{"line":46,"character":72}},"kind":13,"selectionRange":{"start":{"line":46,"character":12},"end":{"line":46,"character":27}},"name":"nodeDescendants"},{"range":{"start":{"line":48,"character":12},"end":{"line":48,"character":22}},"kind":13,"selectionRange":{"start":{"line":48,"character":12},"end":{"line":48,"character":22}},"name":"descendant"},{"range":{"start":{"line":50,"character":19},"end":{"line":50,"character":36}},"kind":13,"selectionRange":{"start":{"line":50,"character":19},"end":{"line":50,"character":36}},"name":"descendantMarking"},{"range":{"start":{"line":62,"character":16},"end":{"line":66,"character":87}},"kind":13,"selectionRange":{"start":{"line":62,"character":20},"end":{"line":62,"character":37}},"name":"descendantMarking"},{"range":{"start":{"line":75,"character":12},"end":{"line":75,"character":34}},"kind":13,"selectionRange":{"start":{"line":75,"character":16},"end":{"line":75,"character":22}},"name":"newSCC"},{"range":{"start":{"line":79,"character":16},"end":{"line":79,"character":48}},"kind":13,"selectionRange":{"start":{"line":79,"character":20},"end":{"line":79,"character":27}},"name":"sccNode"}]}]},{"range":{"start":{"line":99,"character":8},"end":{"line":111,"character":1}},"kind":5,"selectionRange":{"start":{"line":99,"character":14},"end":{"line":99,"character":21}},"name":"Marking","references":[{"range":{"start":{"line":15,"character":32},"end":{"line":15,"character":32}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":35,"character":62},"end":{"line":35,"character":62}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":36,"character":73},"end":{"line":36,"character":73}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":40,"character":26},"end":{"line":40,"character":26}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"}],"children":[{"range":{"start":{"line":101,"character":4},"end":{"line":106,"character":5}},"kind":6,"selectionRange":{"start":{"line":101,"character":4},"end":{"line":101,"character":51}},"name":"init(index:lowLink:isOnStack:)","references":[{"range":{"start":{"line":40,"character":26},"end":{"line":40,"character":26}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"}]},{"range":{"start":{"line":108,"character":4},"end":{"line":108,"character":18}},"kind":7,"selectionRange":{"start":{"line":108,"character":8},"end":{"line":108,"character":13}},"name":"index","references":[{"range":{"start":{"line":56,"character":85},"end":{"line":56,"character":85}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":73,"character":46},"end":{"line":73,"character":46}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":103,"character":13},"end":{"line":103,"character":13}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"}]},{"range":{"start":{"line":109,"character":4},"end":{"line":109,"character":20}},"kind":7,"selectionRange":{"start":{"line":109,"character":8},"end":{"line":109,"character":15}},"name":"lowLink","references":[{"range":{"start":{"line":56,"character":32},"end":{"line":56,"character":32}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":56,"character":58},"end":{"line":56,"character":58}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":68,"character":28},"end":{"line":68,"character":28}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":68,"character":54},"end":{"line":68,"character":54}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":68,"character":81},"end":{"line":68,"character":81}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":73,"character":23},"end":{"line":73,"character":23}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":104,"character":13},"end":{"line":104,"character":13}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"}]},{"range":{"start":{"line":110,"character":4},"end":{"line":110,"character":23}},"kind":7,"selectionRange":{"start":{"line":110,"character":8},"end":{"line":110,"character":17}},"name":"isOnStack","references":[{"range":{"start":{"line":53,"character":37},"end":{"line":53,"character":37}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":86,"character":35},"end":{"line":86,"character":35}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":105,"character":13},"end":{"line":105,"character":13}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"}]}]}],"code":"import SwiftyToolz\n\nextension Graph\n{\n    /**\n     Find the [strongly connected components](https://en.wikipedia.org/wiki/Strongly_connected_component) of the `Graph`\n     \n     - Returns: Multiple sets of node IDs, each set representing a strongly connected components of the graph\n     */\n    func findStronglyConnectedComponents() -> Set<NodeIDs>\n    {\n        var resultingSCCs = Set<NodeIDs>()\n        \n        var index = 0\n        var stack = [NodeID]()\n        var markings = [NodeID: Marking]()\n        \n        for node in nodeIDs\n        {\n            if markings[node] == nil\n            {\n                findSCCsRecursively(node: node,\n                                    index: &index,\n                                    stack: &stack,\n                                    markings: &markings) { resultingSCCs += $0 }\n            }\n        }\n        \n        return resultingSCCs\n    }\n    \n    @discardableResult\n    private func findSCCsRecursively(node: NodeID,\n                                     index: inout Int,\n                                     stack: inout [NodeID],\n                                     markings: inout [NodeID: Marking],\n                                     handleNewSCC: (NodeIDs) -> Void) -> Marking\n    {\n        // Set the depth index for node to the smallest unused index\n        assert(markings[node] == nil, \"there shouldn't be a marking value for this node yet\")\n        let nodeMarking = Marking(index: index, lowLink: index, isOnStack: true)\n        markings[node] = nodeMarking\n        index += 1\n        stack.append(node)\n        \n        // Consider descendants of node\n        let nodeDescendants = self.node(with: node)?.descendantIDs ?? []\n        \n        for descendant in nodeDescendants\n        {\n            if let descendantMarking = markings[descendant]\n            {\n                // If descendant is not on stack, then edge (from node to descendant) is pointing to an SCC already found and must be ignored\n                if descendantMarking.isOnStack\n                {\n                    // Successor \"descendant\" is in stack and hence in the current SCC\n                    nodeMarking.lowLink = min(nodeMarking.lowLink, descendantMarking.index)\n                }\n            }\n            else // if descendant index is undefined then\n            {\n                // Successor \"descendant\" has not yet been visited; recurse on it\n                let descendantMarking = findSCCsRecursively(node: descendant,\n                                                            index: &index,\n                                                            stack: &stack,\n                                                            markings: &markings,\n                                                            handleNewSCC: handleNewSCC)\n                \n                nodeMarking.lowLink = min(nodeMarking.lowLink, descendantMarking.lowLink)\n            }\n        }\n        \n        // If node is a root node, pop the stack and generate an SCC\n        if nodeMarking.lowLink == nodeMarking.index\n        {\n            var newSCC = NodeIDs()\n            \n            while !stack.isEmpty\n            {\n                let sccNode = stack.removeLast()\n                \n                guard markings[sccNode] != nil else\n                {\n                    fatalError(\"node that is on the stack should have a markings object\")\n                }\n                \n                markings[sccNode]?.isOnStack = false\n                newSCC += sccNode\n                \n                if node == sccNode { break }\n            }\n            \n            handleNewSCC(newSCC)\n        }\n        \n        return nodeMarking\n    }\n}\n\nprivate class Marking\n{\n    init(index: Int, lowLink: Int, isOnStack: Bool)\n    {\n        self.index = index\n        self.lowLink = lowLink\n        self.isOnStack = isOnStack\n    }\n    \n    var index: Int\n    var lowLink: Int\n    var isOnStack: Bool\n}\n"},{"name":"Graph+EssentialEdges.swift","symbols":[{"range":{"start":{"line":2,"character":7},"end":{"line":86,"character":1}},"kind":3,"selectionRange":{"start":{"line":2,"character":17},"end":{"line":2,"character":22}},"name":"Graph","children":[{"range":{"start":{"line":9,"character":4},"end":{"line":14,"character":5}},"kind":6,"selectionRange":{"start":{"line":9,"character":9},"end":{"line":9,"character":33}},"name":"filteredEssentialEdges()","children":[{"range":{"start":{"line":11,"character":8},"end":{"line":11,"character":25}},"kind":13,"selectionRange":{"start":{"line":11,"character":12},"end":{"line":11,"character":18}},"name":"result"}]},{"range":{"start":{"line":21,"character":13},"end":{"line":24,"character":5}},"kind":6,"selectionRange":{"start":{"line":21,"character":18},"end":{"line":21,"character":40}},"name":"filterEssentialEdges()","references":[{"range":{"start":{"line":12,"character":15},"end":{"line":12,"character":15}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"}]},{"range":{"start":{"line":31,"character":4},"end":{"line":85,"character":5}},"kind":6,"selectionRange":{"start":{"line":31,"character":9},"end":{"line":31,"character":29}},"name":"findEssentialEdges()","references":[{"range":{"start":{"line":23,"character":20},"end":{"line":23,"character":20}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":6,"character":30},"end":{"line":6,"character":30}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":12,"character":24},"end":{"line":12,"character":24}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":19,"character":29},"end":{"line":19,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":27,"character":29},"end":{"line":27,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":59,"character":29},"end":{"line":59,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":66,"character":29},"end":{"line":66,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":75,"character":29},"end":{"line":75,"character":29}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"}],"children":[{"range":{"start":{"line":33,"character":8},"end":{"line":33,"character":43}},"kind":13,"selectionRange":{"start":{"line":33,"character":12},"end":{"line":33,"character":31}},"name":"idsOfEssentialEdges"},{"range":{"start":{"line":36,"character":8},"end":{"line":36,"character":55}},"kind":13,"selectionRange":{"start":{"line":36,"character":12},"end":{"line":36,"character":29}},"name":"condensationGraph"},{"range":{"start":{"line":39,"character":8},"end":{"line":39,"character":82}},"kind":13,"selectionRange":{"start":{"line":39,"character":12},"end":{"line":39,"character":38}},"name":"condensationNodeIDByNodeID"},{"range":{"start":{"line":41,"character":12},"end":{"line":41,"character":28}},"kind":13,"selectionRange":{"start":{"line":41,"character":12},"end":{"line":41,"character":28}},"name":"condensationNode"},{"range":{"start":{"line":43,"character":16},"end":{"line":43,"character":20}},"kind":13,"selectionRange":{"start":{"line":43,"character":16},"end":{"line":43,"character":20}},"name":"node"},{"range":{"start":{"line":50,"character":8},"end":{"line":50,"character":86}},"kind":13,"selectionRange":{"start":{"line":50,"character":12},"end":{"line":50,"character":36}},"name":"minimumCondensationGraph"},{"range":{"start":{"line":53,"character":12},"end":{"line":53,"character":16}},"kind":13,"selectionRange":{"start":{"line":53,"character":12},"end":{"line":53,"character":16}},"name":"edge"},{"range":{"start":{"line":55,"character":22},"end":{"line":55,"character":46}},"kind":13,"selectionRange":{"start":{"line":55,"character":22},"end":{"line":55,"character":46}},"name":"originCondensationNodeID"},{"range":{"start":{"line":56,"character":22},"end":{"line":56,"character":51}},"kind":13,"selectionRange":{"start":{"line":56,"character":22},"end":{"line":56,"character":51}},"name":"destinationCondensationNodeID"},{"range":{"start":{"line":73,"character":12},"end":{"line":74,"character":87}},"kind":13,"selectionRange":{"start":{"line":73,"character":16},"end":{"line":73,"character":34}},"name":"condensationEdgeID"},{"range":{"start":{"line":76,"character":12},"end":{"line":76,"character":87}},"kind":13,"selectionRange":{"start":{"line":76,"character":16},"end":{"line":76,"character":31}},"name":"edgeIsEssential"}]}]}],"code":"import SwiftyToolz\n\npublic extension Graph\n{\n    /**\n     Graph with only the edges of the transitive reduction of the condensation graph\n     \n     Note that this will not remove any edges that are part of cycles (i.e. part of strongly connected components), since only considers edges of the condensation graph can be \"non-essential\". This is because it's [algorithmically](https://en.wikipedia.org/wiki/Feedback_arc_set#Hardness) as well as conceptually hard to decide which edges in cycles are \"non-essential\". We recommend dealing with cycles independently of using this function.\n     */\n    func filteredEssentialEdges() -> Self\n    {\n        var result = self\n        result.filterEssentialEdges()\n        return result\n    }\n    \n    /**\n     Remove edges that are not in the transitive reduction of the condensation graph\n     \n     Note that this will not remove any edges that are part of cycles (i.e. part of strongly connected components), since only considers edges of the condensation graph can be \"non-essential\". This is because it's [algorithmically](https://en.wikipedia.org/wiki/Feedback_arc_set#Hardness) as well as conceptually hard to decide which edges in cycles are \"non-essential\". We recommend dealing with cycles independently of using this function.\n     */\n    mutating func filterEssentialEdges()\n    {\n        filterEdges(findEssentialEdges())\n    }\n    \n    /**\n     Find edges that are in the minimum equivalent graph of the condensation graph\n     \n     Note that this includes all edges that are part of cycles (i.e. part of strongly connected components), since only edges of the condensation graph can be \"non-essential\". This is because it's [algorithmically](https://en.wikipedia.org/wiki/Feedback_arc_set#Hardness) as well as conceptually hard to decide which edges in cycles are \"non-essential\". We recommend dealing with cycles independently of using this function.\n     */\n    func findEssentialEdges() -> EdgeIDs\n    {\n        var idsOfEssentialEdges = EdgeIDs()\n        \n        // make condensation graph\n        let condensationGraph = makeCondensationGraph()\n        \n        // remember in which condensation node each original node is contained\n        var condensationNodeIDByNodeID = [NodeID: StronglyConnectedComponent.ID]()\n        \n        for condensationNode in condensationGraph.nodes\n        {\n            for node in condensationNode.value.nodeIDs\n            {\n                condensationNodeIDByNodeID[node] = condensationNode.id\n            }\n        }\n        \n        // make minimum equivalent condensation graph\n        let minimumCondensationGraph = condensationGraph.filteredTransitiveReduction()\n        \n        // for each original edge in the component graph ...\n        for edge in edges\n        {\n            guard let originCondensationNodeID = condensationNodeIDByNodeID[edge.originID],\n                  let destinationCondensationNodeID = condensationNodeIDByNodeID[edge.destinationID]\n            else\n            {\n                log(error: \"Nodes don't have their condensation node IDs set (but must have at this point)\")\n                continue\n            }\n            \n            // add this edge if it is within the same condensation node (within a strongly connected component and thereby within a cycle)\n            \n            if originCondensationNodeID == destinationCondensationNodeID\n            {\n                idsOfEssentialEdges += edge.id\n                continue\n            }\n            \n            // the non-cyclic edge is essential if its equivalent is in the minimum equivalent condensation graph\n            \n            let condensationEdgeID = CondensationEdge.ID(originCondensationNodeID,\n                                                         destinationCondensationNodeID)\n            \n            let edgeIsEssential = minimumCondensationGraph.contains(condensationEdgeID)\n            \n            if edgeIsEssential\n            {\n                idsOfEssentialEdges += edge.id\n            }\n        }\n        \n        return idsOfEssentialEdges\n    }\n}\n"}]},{"name":"Graph","files":[{"name":"GraphEdge.swift","symbols":[{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":73}},"kind":3,"selectionRange":{"start":{"line":2,"character":10},"end":{"line":2,"character":19}},"name":"GraphEdge"},{"range":{"start":{"line":3,"character":0},"end":{"line":3,"character":58}},"kind":3,"selectionRange":{"start":{"line":3,"character":10},"end":{"line":3,"character":22}},"name":"GraphEdge.ID"},{"range":{"start":{"line":5,"character":0},"end":{"line":5,"character":70}},"kind":3,"selectionRange":{"start":{"line":5,"character":10},"end":{"line":5,"character":19}},"name":"GraphEdge"},{"range":{"start":{"line":6,"character":0},"end":{"line":6,"character":56}},"kind":3,"selectionRange":{"start":{"line":6,"character":10},"end":{"line":6,"character":22}},"name":"GraphEdge.ID"},{"range":{"start":{"line":15,"character":7},"end":{"line":73,"character":1}},"kind":23,"selectionRange":{"start":{"line":15,"character":14},"end":{"line":15,"character":23}},"name":"GraphEdge","references":[{"range":{"start":{"line":64,"character":28},"end":{"line":64,"character":28}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":2,"character":10},"end":{"line":2,"character":10}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":3,"character":10},"end":{"line":3,"character":10}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":5,"character":10},"end":{"line":5,"character":10}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":6,"character":10},"end":{"line":6,"character":10}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":20,"character":28},"end":{"line":20,"character":28}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"}],"children":[{"range":{"start":{"line":15,"character":24},"end":{"line":15,"character":40}},"kind":26,"selectionRange":{"start":{"line":15,"character":24},"end":{"line":15,"character":30}},"name":"NodeID","references":[{"range":{"start":{"line":2,"character":36},"end":{"line":2,"character":36}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":3,"character":39},"end":{"line":3,"character":39}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":5,"character":35},"end":{"line":5,"character":35}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":6,"character":38},"end":{"line":6,"character":38}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":20,"character":38},"end":{"line":20,"character":38}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":34,"character":34},"end":{"line":34,"character":34}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":34,"character":59},"end":{"line":34,"character":59}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":40,"character":29},"end":{"line":40,"character":29}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":41,"character":34},"end":{"line":41,"character":34}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":47,"character":31},"end":{"line":47,"character":31}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":48,"character":34},"end":{"line":48,"character":34}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":67,"character":25},"end":{"line":67,"character":25}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":72,"character":30},"end":{"line":72,"character":30}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"}]},{"range":{"start":{"line":15,"character":42},"end":{"line":15,"character":57}},"kind":26,"selectionRange":{"start":{"line":15,"character":42},"end":{"line":15,"character":48}},"name":"Weight","references":[{"range":{"start":{"line":2,"character":54},"end":{"line":2,"character":54}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":5,"character":52},"end":{"line":5,"character":52}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":20,"character":46},"end":{"line":20,"character":46}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":49,"character":24},"end":{"line":49,"character":24}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":62,"character":37},"end":{"line":62,"character":37}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"}]},{"range":{"start":{"line":27,"character":11},"end":{"line":27,"character":53}},"kind":7,"selectionRange":{"start":{"line":27,"character":15},"end":{"line":27,"character":17}},"name":"id","references":[{"range":{"start":{"line":66,"character":36},"end":{"line":66,"character":36}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":126,"character":38},"end":{"line":126,"character":38}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":67,"character":44},"end":{"line":67,"character":44}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":80,"character":44},"end":{"line":80,"character":44}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":23,"character":45},"end":{"line":23,"character":45}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":39,"character":36},"end":{"line":39,"character":36}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":77,"character":26},"end":{"line":77,"character":26}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":32,"character":11},"end":{"line":42,"character":5}},"kind":23,"selectionRange":{"start":{"line":32,"character":18},"end":{"line":32,"character":20}},"name":"ID","references":[{"range":{"start":{"line":54,"character":46},"end":{"line":54,"character":46}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":59,"character":40},"end":{"line":59,"character":40}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":73,"character":54},"end":{"line":73,"character":54}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":3,"character":20},"end":{"line":3,"character":20}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":6,"character":20},"end":{"line":6,"character":20}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":27,"character":19},"end":{"line":27,"character":19}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":27,"character":24},"end":{"line":27,"character":24}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":52,"character":56},"end":{"line":52,"character":56}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":76,"character":34},"end":{"line":76,"character":34}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":18,"character":43},"end":{"line":18,"character":43}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":47,"character":64},"end":{"line":47,"character":64}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":98,"character":28},"end":{"line":98,"character":28}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":112,"character":33},"end":{"line":112,"character":33}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":128,"character":38},"end":{"line":128,"character":38}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}],"children":[{"range":{"start":{"line":34,"character":17},"end":{"line":38,"character":9}},"kind":6,"selectionRange":{"start":{"line":34,"character":17},"end":{"line":34,"character":66}},"name":"init(_:_:)","references":[{"range":{"start":{"line":13,"character":30},"end":{"line":13,"character":30}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":18,"character":30},"end":{"line":18,"character":30}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":49,"character":35},"end":{"line":49,"character":35}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":71,"character":32},"end":{"line":71,"character":32}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":103,"character":52},"end":{"line":103,"character":52}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":73,"character":54},"end":{"line":73,"character":54}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":27,"character":24},"end":{"line":27,"character":24}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":20,"character":25},"end":{"line":20,"character":25}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":20,"character":38},"end":{"line":20,"character":38}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":28,"character":25},"end":{"line":28,"character":25}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":28,"character":38},"end":{"line":28,"character":38}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":56,"character":43},"end":{"line":56,"character":43}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":73,"character":77},"end":{"line":73,"character":77}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":76,"character":34},"end":{"line":76,"character":34}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":11,"character":26},"end":{"line":11,"character":26}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":38,"character":33},"end":{"line":38,"character":33}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":92,"character":20},"end":{"line":92,"character":20}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":106,"character":18},"end":{"line":106,"character":18}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":40,"character":15},"end":{"line":40,"character":35}},"kind":7,"selectionRange":{"start":{"line":40,"character":19},"end":{"line":40,"character":27}},"name":"originID","references":[{"range":{"start":{"line":36,"character":53},"end":{"line":36,"character":53}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":36,"character":17},"end":{"line":36,"character":17}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":21,"character":21},"end":{"line":21,"character":21}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":22,"character":55},"end":{"line":22,"character":55}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":57,"character":32},"end":{"line":57,"character":32}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":41,"character":15},"end":{"line":41,"character":40}},"kind":7,"selectionRange":{"start":{"line":41,"character":19},"end":{"line":41,"character":32}},"name":"destinationID","references":[{"range":{"start":{"line":37,"character":58},"end":{"line":37,"character":58}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":37,"character":17},"end":{"line":37,"character":17}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":21,"character":52},"end":{"line":21,"character":52}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":22,"character":21},"end":{"line":22,"character":21}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":58,"character":30},"end":{"line":58,"character":30}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]}]},{"range":{"start":{"line":47,"character":11},"end":{"line":55,"character":5}},"kind":6,"selectionRange":{"start":{"line":47,"character":11},"end":{"line":49,"character":35}},"name":"init(from:to:weight:)","references":[{"range":{"start":{"line":45,"character":41},"end":{"line":45,"character":41}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":97,"character":38},"end":{"line":97,"character":38}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":70,"character":19},"end":{"line":70,"character":19}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":62,"character":25},"end":{"line":62,"character":43}},"kind":7,"selectionRange":{"start":{"line":62,"character":29},"end":{"line":62,"character":35}},"name":"weight","references":[{"range":{"start":{"line":40,"character":51},"end":{"line":40,"character":51}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":47,"character":51},"end":{"line":47,"character":51}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":50,"character":51},"end":{"line":50,"character":51}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":102,"character":30},"end":{"line":102,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":104,"character":65},"end":{"line":104,"character":65}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":54,"character":13},"end":{"line":54,"character":13}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":49,"character":47},"end":{"line":49,"character":47}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":51,"character":27},"end":{"line":51,"character":27}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":67,"character":11},"end":{"line":67,"character":31}},"kind":7,"selectionRange":{"start":{"line":67,"character":15},"end":{"line":67,"character":23}},"name":"originID","references":[{"range":{"start":{"line":33,"character":34},"end":{"line":33,"character":34}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":34,"character":72},"end":{"line":34,"character":72}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":105,"character":30},"end":{"line":105,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":55,"character":81},"end":{"line":55,"character":81}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":27,"character":27},"end":{"line":27,"character":27}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":51,"character":13},"end":{"line":51,"character":13}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":10,"character":15},"end":{"line":10,"character":15}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"},{"range":{"start":{"line":25,"character":15},"end":{"line":25,"character":15}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"},{"range":{"start":{"line":80,"character":27},"end":{"line":80,"character":27}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":81,"character":63},"end":{"line":81,"character":63}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":72,"character":11},"end":{"line":72,"character":36}},"kind":7,"selectionRange":{"start":{"line":72,"character":15},"end":{"line":72,"character":28}},"name":"destinationID","references":[{"range":{"start":{"line":33,"character":69},"end":{"line":33,"character":69}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":34,"character":34},"end":{"line":34,"character":34}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":106,"character":30},"end":{"line":106,"character":30}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":56,"character":86},"end":{"line":56,"character":86}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":27,"character":37},"end":{"line":27,"character":37}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":52,"character":13},"end":{"line":52,"character":13}},"filePathRelativeToRoot":"Code/Graph/GraphEdge.swift"},{"range":{"start":{"line":10,"character":35},"end":{"line":10,"character":35}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"},{"range":{"start":{"line":25,"character":35},"end":{"line":25,"character":35}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/EdgeFilterTests.swift"},{"range":{"start":{"line":80,"character":60},"end":{"line":80,"character":60}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":81,"character":27},"end":{"line":81,"character":27}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]}]}],"code":"import SwiftyToolz\n\nextension GraphEdge: Sendable where NodeID: Sendable, Weight: Sendable {}\nextension GraphEdge.ID: Sendable where NodeID: Sendable {}\n\nextension GraphEdge: Codable where NodeID: Codable, Weight: Codable {}\nextension GraphEdge.ID: Codable where NodeID: Codable {}\n\n/**\n Directed connection of two ``GraphNode``s in a ``Graph``\n \n A `GraphEdge` points from an origin- to a destination node and therefor has an ``GraphEdge/originID`` and a ``GraphEdge/destinationID``.\n \n A `GraphEdge` is `Identifiable` by its ``GraphEdge/id-swift.property``, which is a combination of ``GraphEdge/originID`` and ``GraphEdge/destinationID``.\n */\npublic struct GraphEdge<NodeID: Hashable, Weight: Numeric>: Identifiable, Equatable\n{\n    /**\n     A shorthand for the edge's full generic type name `GraphEdge<NodeID>`\n     */\n    public typealias Edge = GraphEdge<NodeID, Weight>\n    \n    // MARK: - Identity\n    \n    /**\n     The edge's `ID` combines the ``GraphNode/id``s of ``GraphEdge/originID`` and ``GraphEdge/destinationID``\n     */\n    public var id: ID { ID(originID, destinationID) }\n    \n    /**\n     An edge's `ID` combines the ``GraphNode/id``s of its ``GraphEdge/originID`` and ``GraphEdge/destinationID``\n     */\n    public struct ID: Hashable\n    {\n        internal init(_ originID: NodeID, _ destinationID: NodeID)\n        {\n            self.originID = originID\n            self.destinationID = destinationID\n        }\n        \n        public let originID: NodeID\n        public let destinationID: NodeID\n    }\n    \n    // MARK: - Basics\n    \n    /// Create a ``GraphEdge``, for instance to pass it to a ``Graph`` initializer.\n    public init(from originID: NodeID,\n                to destinationID: NodeID,\n                weight: Weight = 1)\n    {\n        self.originID = originID\n        self.destinationID = destinationID\n        \n        self.weight = weight\n    }\n    \n    /**\n     The edge weight.\n     \n     If you don't need edge weights and want to save memory, you could specify `UInt8` (a.k.a. Byte) as the edge weight type, so each edge would require just one Byte instead of for example four or 8 Bytes for other numeric types.\n     */\n    public internal(set) var weight: Weight\n    \n    /**\n     The origin ``GraphNode/id`` at which the edge starts / from which it goes out\n     */\n    public let originID: NodeID\n    \n    /**\n     The destination ``GraphNode/id`` at which the edge ends / to which it goes in\n     */\n    public let destinationID: NodeID\n}\n"},{"name":"Graph.swift","symbols":[{"range":{"start":{"line":2,"character":37},"end":{"line":2,"character":52}},"kind":26,"selectionRange":{"start":{"line":2,"character":37},"end":{"line":2,"character":42}},"name":"Value","references":[{"range":{"start":{"line":2,"character":83},"end":{"line":2,"character":83}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":2,"character":90},"end":{"line":2,"character":90}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"}]},{"range":{"start":{"line":2,"character":54},"end":{"line":2,"character":73}},"kind":26,"selectionRange":{"start":{"line":2,"character":54},"end":{"line":2,"character":64}},"name":"EdgeWeight","references":[{"range":{"start":{"line":2,"character":97},"end":{"line":2,"character":97}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"}]},{"range":{"start":{"line":3,"character":41},"end":{"line":3,"character":60}},"kind":26,"selectionRange":{"start":{"line":3,"character":41},"end":{"line":3,"character":46}},"name":"Value","references":[{"range":{"start":{"line":3,"character":91},"end":{"line":3,"character":91}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":3,"character":101},"end":{"line":3,"character":101}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"}]},{"range":{"start":{"line":3,"character":62},"end":{"line":3,"character":81}},"kind":26,"selectionRange":{"start":{"line":3,"character":62},"end":{"line":3,"character":72}},"name":"EdgeWeight","references":[{"range":{"start":{"line":3,"character":108},"end":{"line":3,"character":108}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"}]},{"range":{"start":{"line":5,"character":0},"end":{"line":5,"character":94}},"kind":3,"selectionRange":{"start":{"line":5,"character":10},"end":{"line":5,"character":15}},"name":"Graph"},{"range":{"start":{"line":6,"character":0},"end":{"line":6,"character":56}},"kind":3,"selectionRange":{"start":{"line":6,"character":10},"end":{"line":6,"character":15}},"name":"Graph"},{"range":{"start":{"line":7,"character":0},"end":{"line":7,"character":90}},"kind":3,"selectionRange":{"start":{"line":7,"character":10},"end":{"line":7,"character":15}},"name":"Graph"},{"range":{"start":{"line":16,"character":7},"end":{"line":82,"character":1}},"kind":23,"selectionRange":{"start":{"line":16,"character":14},"end":{"line":16,"character":19}},"name":"Graph","references":[{"range":{"start":{"line":0,"character":17},"end":{"line":0,"character":17}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":2,"character":10},"end":{"line":2,"character":10}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":2,"character":77},"end":{"line":2,"character":77}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":3,"character":85},"end":{"line":3,"character":85}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":5,"character":10},"end":{"line":5,"character":10}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":6,"character":10},"end":{"line":6,"character":10}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":7,"character":10},"end":{"line":7,"character":10}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":6,"character":19},"end":{"line":6,"character":19}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":2,"character":17},"end":{"line":2,"character":17}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":2,"character":10},"end":{"line":2,"character":10}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":4,"character":17},"end":{"line":4,"character":17}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":57,"character":34},"end":{"line":57,"character":34}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":7,"character":20},"end":{"line":7,"character":20}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":10,"character":20},"end":{"line":10,"character":20}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":12,"character":28},"end":{"line":12,"character":28}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":20,"character":28},"end":{"line":20,"character":28}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":27,"character":21},"end":{"line":27,"character":21}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":39,"character":21},"end":{"line":39,"character":21}},"filePathRelativeToRoot":"Tests/ValueTests.swift"},{"range":{"start":{"line":17,"character":20},"end":{"line":17,"character":20}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":27,"character":20},"end":{"line":27,"character":20}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":8,"character":10},"end":{"line":8,"character":10}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":16,"character":10},"end":{"line":16,"character":10}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":24,"character":17},"end":{"line":24,"character":17}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":2,"character":17},"end":{"line":2,"character":17}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"},{"range":{"start":{"line":0,"character":17},"end":{"line":0,"character":17}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":4,"character":86},"end":{"line":4,"character":86}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":2,"character":17},"end":{"line":2,"character":17}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":2,"character":17},"end":{"line":2,"character":17}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":8,"character":35},"end":{"line":8,"character":35}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/ValueFilterTests.swift"},{"range":{"start":{"line":8,"character":33},"end":{"line":8,"character":33}},"filePathRelativeToRoot":"Tests/Algorithms/FilterAndMap/MapTests.swift"},{"range":{"start":{"line":2,"character":17},"end":{"line":2,"character":17}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":0,"character":17},"end":{"line":0,"character":17}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"}],"children":[{"range":{"start":{"line":16,"character":20},"end":{"line":16,"character":36}},"kind":26,"selectionRange":{"start":{"line":16,"character":20},"end":{"line":16,"character":26}},"name":"NodeID","references":[{"range":{"start":{"line":4,"character":42},"end":{"line":4,"character":42}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":43,"character":28},"end":{"line":43,"character":28}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":51,"character":23},"end":{"line":51,"character":23}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":67,"character":33},"end":{"line":67,"character":33}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":14,"character":21},"end":{"line":14,"character":21}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":15,"character":24},"end":{"line":15,"character":24}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":32,"character":43},"end":{"line":32,"character":43}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":34,"character":51},"end":{"line":34,"character":51}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":35,"character":54},"end":{"line":35,"character":54}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":5,"character":32},"end":{"line":5,"character":32}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":7,"character":31},"end":{"line":7,"character":31}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":23,"character":39},"end":{"line":23,"character":39}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":29,"character":34},"end":{"line":29,"character":34}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":64,"character":38},"end":{"line":64,"character":38}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":71,"character":42},"end":{"line":71,"character":42}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":76,"character":38},"end":{"line":76,"character":38}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":81,"character":35},"end":{"line":81,"character":35}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":39,"character":42},"end":{"line":39,"character":42}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":2,"character":59},"end":{"line":2,"character":59}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":8,"character":49},"end":{"line":8,"character":49}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":18,"character":45},"end":{"line":18,"character":45}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":27,"character":55},"end":{"line":27,"character":55}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":36,"character":31},"end":{"line":36,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":36,"character":39},"end":{"line":36,"character":39}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":37,"character":55},"end":{"line":37,"character":55}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":43,"character":36},"end":{"line":43,"character":36}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":43,"character":44},"end":{"line":43,"character":44}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":44,"character":55},"end":{"line":44,"character":55}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":54,"character":55},"end":{"line":54,"character":55}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":60,"character":14},"end":{"line":60,"character":14}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":69,"character":31},"end":{"line":69,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":69,"character":39},"end":{"line":69,"character":39}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":70,"character":14},"end":{"line":70,"character":14}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":81,"character":14},"end":{"line":81,"character":14}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":86,"character":32},"end":{"line":86,"character":32}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":94,"character":32},"end":{"line":94,"character":32}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":95,"character":31},"end":{"line":95,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":95,"character":39},"end":{"line":95,"character":39}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":32,"character":69},"end":{"line":32,"character":69}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"},{"range":{"start":{"line":33,"character":56},"end":{"line":33,"character":56}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"},{"range":{"start":{"line":34,"character":67},"end":{"line":34,"character":67}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"},{"range":{"start":{"line":4,"character":92},"end":{"line":4,"character":92}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":15,"character":41},"end":{"line":15,"character":41}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":17,"character":33},"end":{"line":17,"character":33}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":17,"character":45},"end":{"line":17,"character":45}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":28,"character":40},"end":{"line":28,"character":40}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":29,"character":56},"end":{"line":29,"character":56}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":29,"character":68},"end":{"line":29,"character":68}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":29,"character":85},"end":{"line":29,"character":85}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":35,"character":39},"end":{"line":35,"character":39}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":51,"character":69},"end":{"line":51,"character":69}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":8,"character":44},"end":{"line":8,"character":44}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":9,"character":47},"end":{"line":9,"character":47}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":35,"character":43},"end":{"line":35,"character":43}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":36,"character":40},"end":{"line":36,"character":40}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":66,"character":44},"end":{"line":66,"character":44}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":67,"character":47},"end":{"line":67,"character":47}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":90,"character":29},"end":{"line":90,"character":29}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":90,"character":55},"end":{"line":90,"character":55}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":103,"character":37},"end":{"line":103,"character":37}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":104,"character":40},"end":{"line":104,"character":40}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":2,"character":24},"end":{"line":2,"character":24}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":22,"character":100},"end":{"line":22,"character":100}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":28,"character":59},"end":{"line":28,"character":59}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":34,"character":101},"end":{"line":34,"character":101}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":40,"character":60},"end":{"line":40,"character":60}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":51,"character":57},"end":{"line":51,"character":57}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":68,"character":42},"end":{"line":68,"character":42}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":76,"character":27},"end":{"line":76,"character":27}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"}]},{"range":{"start":{"line":16,"character":38},"end":{"line":16,"character":47}},"kind":26,"selectionRange":{"start":{"line":16,"character":38},"end":{"line":16,"character":47}},"name":"NodeValue","references":[{"range":{"start":{"line":5,"character":50},"end":{"line":5,"character":50}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":6,"character":33},"end":{"line":6,"character":33}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":7,"character":48},"end":{"line":7,"character":48}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":23,"character":47},"end":{"line":23,"character":47}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":76,"character":46},"end":{"line":76,"character":46}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":8,"character":59},"end":{"line":8,"character":59}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":10,"character":39},"end":{"line":10,"character":39}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":18,"character":53},"end":{"line":18,"character":53}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":26,"character":31},"end":{"line":26,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":27,"character":14},"end":{"line":27,"character":14}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":27,"character":39},"end":{"line":27,"character":39}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":35,"character":31},"end":{"line":35,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":37,"character":14},"end":{"line":37,"character":14}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":37,"character":39},"end":{"line":37,"character":39}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":42,"character":31},"end":{"line":42,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":44,"character":14},"end":{"line":44,"character":14}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":44,"character":39},"end":{"line":44,"character":39}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":52,"character":31},"end":{"line":52,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":54,"character":14},"end":{"line":54,"character":14}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":54,"character":39},"end":{"line":54,"character":39}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":59,"character":31},"end":{"line":59,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":60,"character":24},"end":{"line":60,"character":24}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":68,"character":31},"end":{"line":68,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":70,"character":24},"end":{"line":70,"character":24}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":79,"character":31},"end":{"line":79,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":81,"character":24},"end":{"line":81,"character":24}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":86,"character":40},"end":{"line":86,"character":40}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":94,"character":40},"end":{"line":94,"character":40}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":4,"character":40},"end":{"line":4,"character":40}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":46,"character":33},"end":{"line":46,"character":33}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":53,"character":40},"end":{"line":53,"character":40}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":2,"character":35},"end":{"line":2,"character":35}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":22,"character":34},"end":{"line":22,"character":34}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":22,"character":59},"end":{"line":22,"character":59}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":22,"character":84},"end":{"line":22,"character":84}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":28,"character":34},"end":{"line":28,"character":34}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":28,"character":69},"end":{"line":28,"character":69}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":34,"character":34},"end":{"line":34,"character":34}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":34,"character":60},"end":{"line":34,"character":60}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":34,"character":85},"end":{"line":34,"character":85}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":40,"character":34},"end":{"line":40,"character":34}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":40,"character":70},"end":{"line":40,"character":70}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":51,"character":34},"end":{"line":51,"character":34}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":68,"character":53},"end":{"line":68,"character":53}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":76,"character":38},"end":{"line":76,"character":38}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":84,"character":32},"end":{"line":84,"character":32}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"}]},{"range":{"start":{"line":16,"character":49},"end":{"line":16,"character":68}},"kind":26,"selectionRange":{"start":{"line":16,"character":49},"end":{"line":16,"character":59}},"name":"EdgeWeight","references":[{"range":{"start":{"line":5,"character":71},"end":{"line":5,"character":71}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":7,"character":68},"end":{"line":7,"character":68}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":64,"character":46},"end":{"line":64,"character":46}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":57,"character":99},"end":{"line":57,"character":99}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+CondensationGraph.swift"},{"range":{"start":{"line":4,"character":113},"end":{"line":4,"character":113}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":34,"character":32},"end":{"line":34,"character":32}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":36,"character":51},"end":{"line":36,"character":51}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":47,"character":32},"end":{"line":47,"character":32}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":47,"character":71},"end":{"line":47,"character":71}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":68,"character":37},"end":{"line":68,"character":37}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":23,"character":11},"end":{"line":41,"character":5}},"kind":6,"selectionRange":{"start":{"line":23,"character":11},"end":{"line":24,"character":43}},"name":"init(valuesByID:edges:)","references":[{"range":{"start":{"line":56,"character":13},"end":{"line":56,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":83,"character":13},"end":{"line":83,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":88,"character":13},"end":{"line":88,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":99,"character":13},"end":{"line":99,"character":13}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":8,"character":16},"end":{"line":8,"character":16}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"}],"children":[{"range":{"start":{"line":28,"character":8},"end":{"line":28,"character":81}},"kind":13,"selectionRange":{"start":{"line":28,"character":12},"end":{"line":28,"character":23}},"name":"idNodePairs"},{"range":{"start":{"line":29,"character":8},"end":{"line":29,"character":82}},"kind":13,"selectionRange":{"start":{"line":29,"character":12},"end":{"line":29,"character":30}},"name":"nodesByIDTemporary"}]},{"range":{"start":{"line":43,"character":11},"end":{"line":47,"character":5}},"kind":6,"selectionRange":{"start":{"line":43,"character":11},"end":{"line":43,"character":17}},"name":"init()","references":[{"range":{"start":{"line":6,"character":23},"end":{"line":6,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":6,"character":66},"end":{"line":6,"character":66}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":43,"character":20},"end":{"line":43,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":63,"character":26},"end":{"line":63,"character":26}},"filePathRelativeToRoot":"Tests/Algorithms/TransitiveReductionTests.swift"},{"range":{"start":{"line":6,"character":23},"end":{"line":6,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/ComponentTests.swift"},{"range":{"start":{"line":81,"character":20},"end":{"line":81,"character":20}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":6,"character":23},"end":{"line":6,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/AncestorCountsTests.swift"},{"range":{"start":{"line":6,"character":20},"end":{"line":6,"character":20}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":6,"character":18},"end":{"line":6,"character":18}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":32,"character":20},"end":{"line":32,"character":20}},"filePathRelativeToRoot":"Tests/Algorithms/EssentialEdgesTests.swift"},{"range":{"start":{"line":6,"character":23},"end":{"line":6,"character":23}},"filePathRelativeToRoot":"Tests/Algorithms/SCCTests.swift"}]},{"range":{"start":{"line":54,"character":25},"end":{"line":54,"character":55}},"kind":7,"selectionRange":{"start":{"line":54,"character":29},"end":{"line":54,"character":38}},"name":"edgesByID","references":[{"range":{"start":{"line":40,"character":8},"end":{"line":40,"character":8}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":46,"character":8},"end":{"line":46,"character":8}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":25,"character":15},"end":{"line":25,"character":15}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":49,"character":32},"end":{"line":49,"character":32}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":51,"character":12},"end":{"line":51,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":84,"character":8},"end":{"line":84,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":100,"character":8},"end":{"line":100,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":114,"character":8},"end":{"line":114,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":122,"character":8},"end":{"line":122,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":130,"character":8},"end":{"line":130,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":71,"character":25},"end":{"line":71,"character":57}},"kind":7,"selectionRange":{"start":{"line":71,"character":29},"end":{"line":71,"character":38}},"name":"nodesByID","references":[{"range":{"start":{"line":6,"character":25},"end":{"line":6,"character":25}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":29,"character":8},"end":{"line":29,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":37,"character":8},"end":{"line":37,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":45,"character":8},"end":{"line":45,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":53,"character":8},"end":{"line":53,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":61,"character":8},"end":{"line":61,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":69,"character":8},"end":{"line":69,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":39,"character":8},"end":{"line":39,"character":8}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":45,"character":8},"end":{"line":45,"character":8}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":21,"character":8},"end":{"line":21,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":22,"character":8},"end":{"line":22,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":80,"character":12},"end":{"line":80,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":81,"character":12},"end":{"line":81,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":6,"character":12},"end":{"line":6,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":53,"character":22},"end":{"line":53,"character":22}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":56,"character":12},"end":{"line":56,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":62,"character":12},"end":{"line":62,"character":12}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":78,"character":8},"end":{"line":78,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":86,"character":8},"end":{"line":86,"character":8}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"}]}]}],"code":"import SwiftyToolz\n\npublic typealias HashableValuesGraph<Value: Hashable, EdgeWeight: Numeric> = Graph<Value, Value, EdgeWeight>\npublic typealias IdentifiableValuesGraph<Value: Identifiable, EdgeWeight: Numeric> = Graph<Value.ID, Value, EdgeWeight>\n\nextension Graph: Sendable where NodeID: Sendable, NodeValue: Sendable, EdgeWeight: Sendable {}\nextension Graph: Equatable where NodeValue: Equatable {}\nextension Graph: Codable where NodeID: Codable, NodeValue: Codable, EdgeWeight: Codable {}\n\n/**\n Holds `Value`s in unique ``GraphNode``s which can be connected through ``GraphEdge``s\n \n The `Graph` creates `GraphNode`s when you insert `NodeValue`s into it, whereby the `Graph` determines the node IDs for new values according to the closure passed to- or implied by its initializer, see ``Graph/init(nodes:determineNodeIDForNewValue:)`` and other initializers.\n \n A `Graph` is Equatable if its `NodeValue` is. Equatability excludes the `determineNodeIDForNewValue` closure mentioned above.\n */\npublic struct Graph<NodeID: Hashable, NodeValue, EdgeWeight: Numeric>\n{\n    // MARK: - Initialize\n    \n    /**\n     Create a `Graph` that determines ``GraphNode/id``s for new `NodeValue`s via the given closure\n     */\n    public init(valuesByID: Dictionary<NodeID, NodeValue>,\n                edges: some Sequence<Edge>)\n    {\n        // create nodes with their neighbour caches\n        \n        let idNodePairs = valuesByID.map { ($0.0 , Node(id: $0.0, value: $0.1)) }\n        var nodesByIDTemporary = [NodeID: Node](uniqueKeysWithValues: idNodePairs)\n        \n        edges.forEach\n        {\n            nodesByIDTemporary[$0.originID]?.descendantIDs.insert($0.destinationID)\n            nodesByIDTemporary[$0.destinationID]?.ancestorIDs.insert($0.originID)\n        }\n        \n        // set nodes and edges\n        \n        nodesByID = nodesByIDTemporary\n        edgesByID = .init(values: edges)\n    }\n    \n    public init()\n    {\n        nodesByID = .init()\n        edgesByID = .init()\n    }\n\n    // MARK: - Edges\n    \n    /**\n     All ``GraphEdge``s of the `Graph` hashable by their ``GraphEdge/id-swift.property``\n     */\n    public internal(set) var edgesByID: [Edge.ID: Edge]\n    \n    /**\n     Shorthand for `Set<Edge.ID>`\n     */\n    public typealias EdgeIDs = Set<Edge.ID>\n    \n    /**\n     Shorthand for the full generic type name `GraphEdge<NodeID>`\n     */\n    public typealias Edge = GraphEdge<NodeID, EdgeWeight>\n    \n    // MARK: - Nodes\n    \n    /**\n     All ``GraphNode``s of the `Graph` hashable by their ``GraphNode/id``s\n     */\n    public internal(set) var nodesByID = [NodeID: Node]()\n    \n    /**\n     Shorthand for the `Graph`'s full generic node type `GraphNode<NodeID, NodeValue>`\n     */\n    public typealias Node = GraphNode<NodeID, NodeValue>\n    \n    /**\n     Shorthand for `Set<NodeID>`\n     */\n    public typealias NodeIDs = Set<NodeID>\n}\n"},{"name":"GraphNode.swift","symbols":[{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":68}},"kind":3,"selectionRange":{"start":{"line":2,"character":10},"end":{"line":2,"character":19}},"name":"GraphNode"},{"range":{"start":{"line":3,"character":0},"end":{"line":3,"character":56}},"kind":3,"selectionRange":{"start":{"line":3,"character":10},"end":{"line":3,"character":19}},"name":"GraphNode"},{"range":{"start":{"line":4,"character":0},"end":{"line":4,"character":65}},"kind":3,"selectionRange":{"start":{"line":4,"character":10},"end":{"line":4,"character":19}},"name":"GraphNode"},{"range":{"start":{"line":17,"character":7},"end":{"line":71,"character":1}},"kind":23,"selectionRange":{"start":{"line":17,"character":14},"end":{"line":17,"character":23}},"name":"GraphNode","references":[{"range":{"start":{"line":76,"character":28},"end":{"line":76,"character":28}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":2,"character":10},"end":{"line":2,"character":10}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":3,"character":10},"end":{"line":3,"character":10}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":4,"character":10},"end":{"line":4,"character":10}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":49,"character":28},"end":{"line":49,"character":28}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"}],"children":[{"range":{"start":{"line":17,"character":24},"end":{"line":17,"character":36}},"kind":26,"selectionRange":{"start":{"line":17,"character":24},"end":{"line":17,"character":26}},"name":"ID","references":[{"range":{"start":{"line":2,"character":36},"end":{"line":2,"character":36}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":4,"character":35},"end":{"line":4,"character":35}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":34,"character":33},"end":{"line":34,"character":33}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":39,"character":47},"end":{"line":39,"character":47}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":44,"character":49},"end":{"line":44,"character":49}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":49,"character":38},"end":{"line":49,"character":38}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":56,"character":20},"end":{"line":56,"character":20}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":65,"character":19},"end":{"line":65,"character":19}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"}]},{"range":{"start":{"line":17,"character":38},"end":{"line":17,"character":43}},"kind":26,"selectionRange":{"start":{"line":17,"character":38},"end":{"line":17,"character":43}},"name":"Value","references":[{"range":{"start":{"line":2,"character":50},"end":{"line":2,"character":50}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":3,"character":37},"end":{"line":3,"character":37}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":4,"character":48},"end":{"line":4,"character":48}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":49,"character":42},"end":{"line":49,"character":42}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":56,"character":31},"end":{"line":56,"character":31}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":70,"character":36},"end":{"line":70,"character":36}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"}]},{"range":{"start":{"line":24,"character":11},"end":{"line":24,"character":53}},"kind":7,"selectionRange":{"start":{"line":24,"character":15},"end":{"line":24,"character":21}},"name":"isSink","references":[{"range":{"start":{"line":37,"character":37},"end":{"line":37,"character":37}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":113,"character":36},"end":{"line":113,"character":36}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":124,"character":31},"end":{"line":124,"character":31}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":139,"character":29},"end":{"line":139,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":143,"character":29},"end":{"line":143,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"}]},{"range":{"start":{"line":29,"character":11},"end":{"line":29,"character":53}},"kind":7,"selectionRange":{"start":{"line":29,"character":15},"end":{"line":29,"character":23}},"name":"isSource","references":[{"range":{"start":{"line":29,"character":37},"end":{"line":29,"character":37}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":115,"character":31},"end":{"line":115,"character":31}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":122,"character":36},"end":{"line":122,"character":36}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":138,"character":29},"end":{"line":138,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":142,"character":29},"end":{"line":142,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"}]},{"range":{"start":{"line":34,"character":11},"end":{"line":34,"character":68}},"kind":7,"selectionRange":{"start":{"line":34,"character":15},"end":{"line":34,"character":27}},"name":"neighbourIDs","references":[{"range":{"start":{"line":40,"character":48},"end":{"line":40,"character":48}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+Components.swift"}]},{"range":{"start":{"line":39,"character":25},"end":{"line":39,"character":52}},"kind":7,"selectionRange":{"start":{"line":39,"character":29},"end":{"line":39,"character":40}},"name":"ancestorIDs","references":[{"range":{"start":{"line":11,"character":31},"end":{"line":11,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":34,"character":50},"end":{"line":34,"character":50}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":29,"character":32},"end":{"line":29,"character":32}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":34,"character":39},"end":{"line":34,"character":39}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":20,"character":44},"end":{"line":20,"character":44}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":30,"character":45},"end":{"line":30,"character":45}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":123,"character":31},"end":{"line":123,"character":31}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":136,"character":29},"end":{"line":136,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":140,"character":29},"end":{"line":140,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":35,"character":59},"end":{"line":35,"character":59}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":22,"character":37},"end":{"line":22,"character":37}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":81,"character":43},"end":{"line":81,"character":43}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":44,"character":25},"end":{"line":44,"character":54}},"kind":7,"selectionRange":{"start":{"line":44,"character":29},"end":{"line":44,"character":42}},"name":"descendantIDs","references":[{"range":{"start":{"line":16,"character":33},"end":{"line":16,"character":33}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+NodeAccess.swift"},{"range":{"start":{"line":46,"character":53},"end":{"line":46,"character":53}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+StronglyConnectedComponents.swift"},{"range":{"start":{"line":33,"character":45},"end":{"line":33,"character":45}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":24,"character":30},"end":{"line":24,"character":30}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":34,"character":53},"end":{"line":34,"character":53}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":19,"character":45},"end":{"line":19,"character":45}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":29,"character":46},"end":{"line":29,"character":46}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":114,"character":31},"end":{"line":114,"character":31}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":137,"character":29},"end":{"line":137,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":141,"character":29},"end":{"line":141,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":70,"character":31},"end":{"line":70,"character":31}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":21,"character":32},"end":{"line":21,"character":32}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"},{"range":{"start":{"line":80,"character":38},"end":{"line":80,"character":38}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]},{"range":{"start":{"line":56,"character":11},"end":{"line":60,"character":5}},"kind":6,"selectionRange":{"start":{"line":56,"character":11},"end":{"line":56,"character":37}},"name":"init(id:value:)","references":[{"range":{"start":{"line":28,"character":51},"end":{"line":28,"character":51}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":61,"character":23},"end":{"line":61,"character":23}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"}]},{"range":{"start":{"line":65,"character":11},"end":{"line":65,"character":21}},"kind":7,"selectionRange":{"start":{"line":65,"character":15},"end":{"line":65,"character":17}},"name":"id","references":[{"range":{"start":{"line":58,"character":13},"end":{"line":58,"character":13}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":87,"character":44},"end":{"line":87,"character":44}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":87,"character":54},"end":{"line":87,"character":54}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":88,"character":39},"end":{"line":88,"character":39}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":88,"character":49},"end":{"line":88,"character":49}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":91,"character":29},"end":{"line":91,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":96,"character":44},"end":{"line":96,"character":44}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":96,"character":58},"end":{"line":96,"character":58}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":98,"character":50},"end":{"line":98,"character":50}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":98,"character":64},"end":{"line":98,"character":64}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":100,"character":47},"end":{"line":100,"character":47}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":100,"character":61},"end":{"line":100,"character":61}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":104,"character":46},"end":{"line":104,"character":46}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":104,"character":60},"end":{"line":104,"character":60}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":105,"character":46},"end":{"line":105,"character":46}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":106,"character":51},"end":{"line":106,"character":51}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":108,"character":56},"end":{"line":108,"character":56}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":114,"character":60},"end":{"line":114,"character":60}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":117,"character":56},"end":{"line":117,"character":56}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":123,"character":58},"end":{"line":123,"character":58}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":128,"character":44},"end":{"line":128,"character":44}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":128,"character":58},"end":{"line":128,"character":58}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":130,"character":54},"end":{"line":130,"character":54}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":131,"character":54},"end":{"line":131,"character":54}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":45,"character":68},"end":{"line":45,"character":68}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":13,"character":35},"end":{"line":13,"character":35}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":13,"character":45},"end":{"line":13,"character":45}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":20,"character":32},"end":{"line":20,"character":32}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":20,"character":42},"end":{"line":20,"character":42}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":22,"character":32},"end":{"line":22,"character":32}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":22,"character":42},"end":{"line":22,"character":42}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":29,"character":28},"end":{"line":29,"character":28}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":6,"character":54},"end":{"line":6,"character":54}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":69,"character":45},"end":{"line":69,"character":45}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":85,"character":36},"end":{"line":85,"character":36}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":21,"character":33},"end":{"line":21,"character":33}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+AncestorCount.swift"},{"range":{"start":{"line":55,"character":63},"end":{"line":55,"character":63}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":64,"character":37},"end":{"line":64,"character":37}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"},{"range":{"start":{"line":92,"character":101},"end":{"line":92,"character":101}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+TransitiveReduction.swift"}]},{"range":{"start":{"line":70,"character":25},"end":{"line":70,"character":41}},"kind":7,"selectionRange":{"start":{"line":70,"character":29},"end":{"line":70,"character":34}},"name":"value","references":[{"range":{"start":{"line":59,"character":13},"end":{"line":59,"character":13}},"filePathRelativeToRoot":"Code/Graph/GraphNode.swift"},{"range":{"start":{"line":92,"character":29},"end":{"line":92,"character":29}},"filePathRelativeToRoot":"Tests/EdgeTests.swift"},{"range":{"start":{"line":43,"character":41},"end":{"line":43,"character":41}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+EssentialEdges.swift"},{"range":{"start":{"line":12,"character":42},"end":{"line":12,"character":42}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":21,"character":29},"end":{"line":21,"character":29}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":21,"character":42},"end":{"line":21,"character":42}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":29,"character":37},"end":{"line":29,"character":37}},"filePathRelativeToRoot":"Tests/NodeTests.swift"},{"range":{"start":{"line":6,"character":75},"end":{"line":6,"character":75}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":55,"character":44},"end":{"line":55,"character":44}},"filePathRelativeToRoot":"Code/Graph+Algorithms/Graph+FilterAndMap.swift"},{"range":{"start":{"line":6,"character":31},"end":{"line":6,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":55,"character":17},"end":{"line":55,"character":17}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":70,"character":34},"end":{"line":70,"character":34}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":78,"character":27},"end":{"line":78,"character":27}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"},{"range":{"start":{"line":86,"character":34},"end":{"line":86,"character":34}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ValueAccess.swift"}]}]}],"code":"import SwiftyToolz\n\nextension GraphNode: Sendable where ID: Sendable, Value: Sendable {}\nextension GraphNode: Equatable where Value: Equatable {}\nextension GraphNode: Codable where ID: Codable, Value: Codable {}\n\n/**\n Unique node of a ``Graph``, holds a value, can be connected to other nodes of the graph\n \n A `GraphNode` is `Identifiable` by its ``GraphNode/id`` of generic type `ID`.\n \n A `GraphNode` has caches maintained by its ``Graph`` that enable quick access to the node's neighbours, see ``GraphNode/ancestorIDs``, ``GraphNode/descendantIDs`` and related properties.\n \n A `Graph` creates, owns and manages its `GraphNode`s. You can not create a `GraphNode` or mutate the `GraphNode`s contained in a `Graph`, since the contained neighbour caches must always be consistent with the `Graph`'s edges.\n \n When inserting a `NodeValue` into a ``Graph``, the ``Graph`` determines the ID of the node containing that value by use of the closure passed to- (``Graph/init(values:edges:determineNodeIDForNewValue:)``) or implied by its initializer.\n */\npublic struct GraphNode<ID: Hashable, Value>: Identifiable\n{\n    // MARK: - Caches for Accessing Neighbours Quickly\n    \n    /**\n     Indicates whether the node has no descendants (no outgoing edges)\n     */\n    public var isSink: Bool { descendantIDs.isEmpty }\n    \n    /**\n     Indicates whether the node has no ancestors (no ingoing edges)\n     */\n    public var isSource: Bool { ancestorIDs.isEmpty }\n    \n    /**\n     The node's neighbours (nodes connected via in- or outgoing edges)\n     */\n    public var neighbourIDs: Set<ID> { ancestorIDs + descendantIDs }\n    \n    /**\n     The node's ancestors (nodes connected via ingoing edges)\n     */\n    public internal(set) var ancestorIDs = Set<ID>()\n    \n    /**\n     The node's descendants (nodes connected via outgoing edges)\n     */\n    public internal(set) var descendantIDs = Set<ID>()\n    \n    /**\n     A shorthand for the node's full generic type name `GraphNode<ID, Value>`\n     */\n    public typealias Node = GraphNode<ID, Value>\n    \n    // MARK: - Identity & Value\n    \n    /**\n     Create a `GraphNode` as input for a new ``Graph``, see ``Graph/init(nodes:makeNodeIDForValue:)``\n     */\n    public init(id: ID, value: Value)\n    {\n        self.id = id\n        self.value = value\n    }\n    \n    /**\n     The `Hashable` ID by which the node is `Identifiable`\n     */\n    public let id: ID\n    \n    /**\n     The actual stored `Value`\n     */\n    public internal(set) var value: Value\n}\n"}]},{"name":"SwiftyToolz Candidates","files":[{"name":"Dictionary+SwiftyToolz.swift","symbols":[{"range":{"start":{"line":0,"character":7},"end":{"line":16,"character":1}},"kind":3,"selectionRange":{"start":{"line":0,"character":17},"end":{"line":0,"character":27}},"name":"Dictionary","children":[{"range":{"start":{"line":2,"character":4},"end":{"line":5,"character":5}},"kind":6,"selectionRange":{"start":{"line":2,"character":4},"end":{"line":2,"character":38}},"name":"init(values:)","references":[{"range":{"start":{"line":40,"character":21},"end":{"line":40,"character":21}},"filePathRelativeToRoot":"Code/Graph/Graph.swift"},{"range":{"start":{"line":29,"character":31},"end":{"line":29,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":39,"character":31},"end":{"line":39,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":46,"character":31},"end":{"line":46,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":56,"character":31},"end":{"line":56,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"}]},{"range":{"start":{"line":7,"character":4},"end":{"line":10,"character":5}},"kind":6,"selectionRange":{"start":{"line":7,"character":4},"end":{"line":7,"character":38}},"name":"init(values:)","references":[{"range":{"start":{"line":62,"character":31},"end":{"line":62,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":72,"character":31},"end":{"line":72,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"},{"range":{"start":{"line":83,"character":31},"end":{"line":83,"character":31}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+ConvenientInitializers.swift"}]},{"range":{"start":{"line":12,"character":13},"end":{"line":15,"character":5}},"kind":6,"selectionRange":{"start":{"line":12,"character":18},"end":{"line":12,"character":40}},"name":"insert(_:)","references":[{"range":{"start":{"line":84,"character":18},"end":{"line":84,"character":18}},"filePathRelativeToRoot":"Code/Graph+CreateAndAccess/Graph+EdgeAccess.swift"}]}]}],"code":"public extension Dictionary\n{\n    init(values: some Sequence<Value>) where Value: Identifiable, Value.ID == Key\n    {\n        self.init(uniqueKeysWithValues: values.map({ ($0.id, $0) }))\n    }\n    \n    init(values: some Sequence<Value>) where Value: Hashable, Value == Key\n    {\n        self.init(uniqueKeysWithValues: values.map({ ($0, $0) }))\n    }\n    \n    mutating func insert(_ value: Value) where Value: Identifiable, Value.ID == Key\n    {\n        self[value.id] = value\n    }\n}\n"}]}]}]}}