//===--- PrimsNonStrongRefAdjacencyList.swift -----------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// /// /// \file /// /// The test implements Prim's algorithm for minimum spanning tree building. /// http://en.wikipedia.org/wiki/Prim%27s_algorithm /// /// This class implements array-based heap (priority queue). It is used to store /// edges from nodes in spanning tree to nodes outside of it. We are interested /// only in the edges with the smallest costs, so if there are several edges /// pointing to the same node, we keep only one from them. Thus, it is enough to /// record this node instead. We maintain a map (node index in graph)->(node /// index in heap) to be able to update the heap fast when we add a new node to /// the tree. /// /// NOTE: This benchmark purposely internally uses non strong references for its /// adjacency list instead of integers to test that code path for the various /// types of weak pointers that we use. /// //===----------------------------------------------------------------------===// import TestsUtils public let benchmarks: [BenchmarkInfo] = ({ var benchmarks: [BenchmarkInfo] = [] #if false // TODO: Stabilize weak benchmark. benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.Weak", runFunction: run_PrimsWeak, tags: [.validation, .algorithm], setUpFunction: { touchGlobalInfo() blackHole(weakPrimsState) })) // TODO: Stabilize weak benchmark. benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.Weak.Closure", runFunction: run_PrimsWeakClosureAccess, tags: [.validation, .algorithm], setUpFunction: { touchGlobalInfo() blackHole(weakPrimsState) })) #endif benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.UnownedSafe", runFunction: run_PrimsUnownedSafe, tags: [.validation, .algorithm], setUpFunction: { touchGlobalInfo() blackHole(unownedSafePrimsState) })) benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.UnownedSafe.Closure", runFunction: run_PrimsUnownedSafeClosureAccess, tags: [.validation, .algorithm], setUpFunction: { touchGlobalInfo() blackHole(unownedSafePrimsState) })) benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.UnownedUnsafe", runFunction: run_PrimsUnownedUnsafe, tags: [.validation, .algorithm], setUpFunction: { touchGlobalInfo() blackHole(unownedUnsafePrimsState) })) benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.UnownedUnsafe.Closure", runFunction: run_PrimsUnownedUnsafeClosureAccess, tags: [.validation, .algorithm], setUpFunction: { touchGlobalInfo() blackHole(unownedUnsafePrimsState) })) benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.Unmanaged", runFunction: run_PrimsUnmanaged, tags: [.validation, .algorithm, .api], setUpFunction: { touchGlobalInfo() blackHole(unmanagedPrimsState) })) benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.Unmanaged.Closure", runFunction: run_PrimsUnmanagedClosureAccess, tags: [.validation, .algorithm, .api], setUpFunction: { touchGlobalInfo() blackHole(unmanagedPrimsState) })) benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.UnmanagedUGR", runFunction: run_PrimsUnmanagedUGR, tags: [.validation, .algorithm, .api], setUpFunction: { touchGlobalInfo() blackHole(unmanagedUGRPrimsState) })) benchmarks.append(BenchmarkInfo( name: "Prims.NonStrongRef.UnmanagedUGR.Closure", runFunction: run_PrimsUnmanagedUGRClosureAccess, tags: [.validation, .algorithm, .api], setUpFunction: { touchGlobalInfo() blackHole(unmanagedUGRPrimsState) })) return benchmarks })() //===----------------------------------------------------------------------===// // Globals //===----------------------------------------------------------------------===// private func touchGlobalInfo() { blackHole(nodes) blackHole(edges) } let nodes : [Int] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 ] // Prim's algorithm is designed for undirected graphs. // Due to that, in our set all the edges are paired, i.e. for any // edge (start, end, C) there is also an edge (end, start, C). let edges : [(Int, Int, Double)] = [ (26, 47, 921), (20, 25, 971), (92, 59, 250), (33, 55, 1391), (78, 39, 313), (7, 25, 637), (18, 19, 1817), (33, 41, 993), (64, 41, 926), (88, 86, 574), (93, 15, 1462), (86, 33, 1649), (37, 35, 841), (98, 51, 1160), (15, 30, 1125), (65, 78, 1052), (58, 12, 1273), (12, 17, 285), (45, 61, 1608), (75, 53, 545), (99, 48, 410), (97, 0, 1303), (48, 17, 1807), (1, 54, 1491), (15, 34, 807), (94, 98, 646), (12, 69, 136), (65, 11, 983), (63, 83, 1604), (78, 89, 1828), (61, 63, 845), (18, 36, 1626), (68, 52, 1324), (14, 50, 690), (3, 11, 943), (21, 68, 914), (19, 44, 1762), (85, 80, 270), (59, 92, 250), (86, 84, 1431), (19, 18, 1817), (52, 68, 1324), (16, 29, 1108), (36, 80, 395), (67, 18, 803), (63, 88, 1717), (68, 21, 914), (75, 82, 306), (49, 82, 1292), (73, 45, 1876), (89, 82, 409), (45, 47, 272), (22, 83, 597), (61, 12, 1791), (44, 68, 1229), (50, 51, 917), (14, 53, 355), (77, 41, 138), (54, 21, 1870), (93, 70, 1582), (76, 2, 1658), (83, 73, 1162), (6, 1, 482), (11, 65, 983), (81, 90, 1024), (19, 1, 970), (8, 58, 1131), (60, 42, 477), (86, 29, 258), (69, 59, 903), (34, 15, 807), (37, 2, 1451), (7, 73, 754), (47, 86, 184), (67, 17, 449), (18, 67, 803), (25, 4, 595), (3, 31, 1337), (64, 31, 1928), (9, 43, 237), (83, 63, 1604), (47, 45, 272), (86, 88, 574), (87, 74, 934), (98, 94, 646), (20, 1, 642), (26, 92, 1344), (18, 17, 565), (47, 11, 595), (10, 59, 1558), (2, 76, 1658), (77, 74, 1277), (42, 60, 477), (80, 36, 395), (35, 23, 589), (50, 37, 203), (6, 96, 481), (78, 65, 1052), (1, 52, 127), (65, 23, 1932), (46, 51, 213), (59, 89, 89), (15, 93, 1462), (69, 3, 1305), (17, 37, 1177), (30, 3, 193), (9, 15, 818), (75, 95, 977), (86, 47, 184), (10, 12, 1736), (80, 27, 1010), (12, 10, 1736), (86, 1, 1958), (60, 12, 1240), (43, 71, 683), (91, 65, 1519), (33, 86, 1649), (62, 26, 1773), (1, 13, 1187), (2, 10, 1018), (91, 29, 351), (69, 12, 136), (43, 9, 237), (29, 86, 258), (17, 48, 1807), (31, 64, 1928), (68, 61, 1936), (76, 38, 1724), (1, 6, 482), (53, 14, 355), (51, 50, 917), (54, 13, 815), (19, 29, 883), (35, 87, 974), (70, 96, 511), (23, 35, 589), (39, 69, 1588), (93, 73, 1093), (13, 73, 435), (5, 60, 1619), (42, 41, 1523), (66, 58, 1596), (1, 67, 431), (17, 67, 449), (30, 95, 906), (71, 43, 683), (5, 87, 190), (12, 78, 891), (30, 97, 402), (28, 17, 1131), (7, 97, 1356), (58, 66, 1596), (20, 37, 1294), (73, 76, 514), (54, 8, 613), (68, 35, 1252), (92, 32, 701), (3, 90, 652), (99, 46, 1576), (13, 54, 815), (20, 87, 1390), (36, 18, 1626), (51, 26, 1146), (2, 23, 581), (29, 7, 1558), (88, 59, 173), (17, 1, 1071), (37, 49, 1011), (18, 6, 696), (88, 33, 225), (58, 38, 802), (87, 50, 1744), (29, 91, 351), (6, 71, 1053), (45, 24, 1720), (65, 91, 1519), (37, 50, 203), (11, 3, 943), (72, 65, 1330), (45, 50, 339), (25, 20, 971), (15, 9, 818), (14, 54, 1353), (69, 95, 393), (8, 66, 1213), (52, 2, 1608), (50, 14, 690), (50, 45, 339), (1, 37, 1273), (45, 93, 1650), (39, 78, 313), (1, 86, 1958), (17, 28, 1131), (35, 33, 1667), (23, 2, 581), (51, 66, 245), (17, 54, 924), (41, 49, 1629), (60, 5, 1619), (56, 93, 1110), (96, 13, 461), (25, 7, 637), (11, 69, 370), (90, 3, 652), (39, 71, 1485), (65, 51, 1529), (20, 6, 1414), (80, 85, 270), (73, 83, 1162), (0, 97, 1303), (13, 33, 826), (29, 71, 1788), (33, 12, 461), (12, 58, 1273), (69, 39, 1588), (67, 75, 1504), (87, 20, 1390), (88, 97, 526), (33, 88, 225), (95, 69, 393), (2, 52, 1608), (5, 25, 719), (34, 78, 510), (53, 99, 1074), (33, 35, 1667), (57, 30, 361), (87, 58, 1574), (13, 90, 1030), (79, 74, 91), (4, 86, 1107), (64, 94, 1609), (11, 12, 167), (30, 45, 272), (47, 91, 561), (37, 17, 1177), (77, 49, 883), (88, 23, 1747), (70, 80, 995), (62, 77, 907), (18, 4, 371), (73, 93, 1093), (11, 47, 595), (44, 23, 1990), (20, 0, 512), (3, 69, 1305), (82, 3, 1815), (20, 88, 368), (44, 45, 364), (26, 51, 1146), (7, 65, 349), (71, 39, 1485), (56, 88, 1954), (94, 69, 1397), (12, 28, 544), (95, 75, 977), (32, 90, 789), (53, 1, 772), (54, 14, 1353), (49, 77, 883), (92, 26, 1344), (17, 18, 565), (97, 88, 526), (48, 80, 1203), (90, 32, 789), (71, 6, 1053), (87, 35, 974), (55, 90, 1808), (12, 61, 1791), (1, 96, 328), (63, 10, 1681), (76, 34, 871), (41, 64, 926), (42, 97, 482), (25, 5, 719), (23, 65, 1932), (54, 1, 1491), (28, 12, 544), (89, 10, 108), (27, 33, 143), (67, 1, 431), (32, 45, 52), (79, 33, 1871), (6, 55, 717), (10, 58, 459), (67, 39, 393), (10, 4, 1808), (96, 6, 481), (1, 19, 970), (97, 7, 1356), (29, 16, 1108), (1, 53, 772), (30, 15, 1125), (4, 6, 634), (6, 20, 1414), (88, 56, 1954), (87, 64, 1950), (34, 76, 871), (17, 12, 285), (55, 59, 321), (61, 68, 1936), (50, 87, 1744), (84, 44, 952), (41, 33, 993), (59, 18, 1352), (33, 27, 143), (38, 32, 1210), (55, 70, 1264), (38, 58, 802), (1, 20, 642), (73, 13, 435), (80, 48, 1203), (94, 64, 1609), (38, 28, 414), (73, 23, 1113), (78, 12, 891), (26, 62, 1773), (87, 43, 579), (53, 6, 95), (59, 95, 285), (88, 63, 1717), (17, 5, 633), (66, 8, 1213), (41, 42, 1523), (83, 22, 597), (95, 30, 906), (51, 65, 1529), (17, 49, 1727), (64, 87, 1950), (86, 4, 1107), (37, 98, 1102), (32, 92, 701), (60, 94, 198), (73, 98, 1749), (4, 18, 371), (96, 70, 511), (7, 29, 1558), (35, 37, 841), (27, 64, 384), (12, 33, 461), (36, 38, 529), (69, 16, 1183), (91, 47, 561), (85, 29, 1676), (3, 82, 1815), (69, 58, 1579), (93, 45, 1650), (97, 42, 482), (37, 1, 1273), (61, 4, 543), (96, 1, 328), (26, 0, 1993), (70, 64, 878), (3, 30, 193), (58, 69, 1579), (4, 25, 595), (31, 3, 1337), (55, 6, 717), (39, 67, 393), (78, 34, 510), (75, 67, 1504), (6, 53, 95), (51, 79, 175), (28, 91, 1040), (89, 78, 1828), (74, 93, 1587), (45, 32, 52), (10, 2, 1018), (49, 37, 1011), (63, 61, 845), (0, 20, 512), (1, 17, 1071), (99, 53, 1074), (37, 20, 1294), (10, 89, 108), (33, 92, 946), (23, 73, 1113), (23, 88, 1747), (49, 17, 1727), (88, 20, 368), (21, 54, 1870), (70, 93, 1582), (59, 88, 173), (32, 38, 1210), (89, 59, 89), (23, 44, 1990), (38, 76, 1724), (30, 57, 361), (94, 60, 198), (59, 10, 1558), (55, 64, 1996), (12, 11, 167), (36, 24, 1801), (97, 30, 402), (52, 1, 127), (58, 87, 1574), (54, 17, 924), (93, 74, 1587), (24, 36, 1801), (2, 37, 1451), (91, 28, 1040), (59, 55, 321), (69, 11, 370), (8, 54, 613), (29, 85, 1676), (44, 19, 1762), (74, 79, 91), (93, 56, 1110), (58, 10, 459), (41, 50, 1559), (66, 51, 245), (80, 19, 1838), (33, 79, 1871), (76, 73, 514), (98, 37, 1102), (45, 44, 364), (16, 69, 1183), (49, 41, 1629), (19, 80, 1838), (71, 57, 500), (6, 4, 634), (64, 27, 384), (84, 86, 1431), (5, 17, 633), (96, 88, 334), (87, 5, 190), (70, 21, 1619), (55, 33, 1391), (10, 63, 1681), (11, 62, 1339), (33, 13, 826), (64, 70, 878), (65, 72, 1330), (70, 55, 1264), (64, 55, 1996), (50, 41, 1559), (46, 99, 1576), (88, 96, 334), (51, 20, 868), (73, 7, 754), (80, 70, 995), (44, 84, 952), (29, 19, 883), (59, 69, 903), (57, 53, 1575), (90, 13, 1030), (28, 38, 414), (12, 60, 1240), (85, 58, 573), (90, 55, 1808), (4, 10, 1808), (68, 44, 1229), (92, 33, 946), (90, 81, 1024), (53, 75, 545), (45, 30, 272), (41, 77, 138), (21, 70, 1619), (45, 73, 1876), (35, 68, 1252), (13, 96, 461), (53, 57, 1575), (82, 89, 409), (28, 61, 449), (58, 61, 78), (27, 80, 1010), (61, 58, 78), (38, 36, 529), (80, 30, 397), (18, 59, 1352), (62, 11, 1339), (95, 59, 285), (51, 98, 1160), (6, 18, 696), (30, 80, 397), (69, 94, 1397), (58, 85, 573), (48, 99, 410), (51, 46, 213), (57, 71, 500), (91, 30, 104), (65, 7, 349), (79, 51, 175), (47, 26, 921), (4, 61, 543), (98, 73, 1749), (74, 77, 1277), (61, 28, 449), (58, 8, 1131), (61, 45, 1608), (74, 87, 934), (71, 29, 1788), (30, 91, 104), (13, 1, 1187), (0, 26, 1993), (82, 49, 1292), (43, 87, 579), (24, 45, 1720), (20, 51, 868), (77, 62, 907), (82, 75, 306), ] struct PrimsState where Node.BoxType == Box, Box.ValueType == Node { var graph: Array var edgeToCostMap: Dictionary, Double> init(_ _: Node.Type) { // Prepare graph and edge->cost map graph = Array() for nodeId in nodes { graph.append(Node(id: nodeId)) } edgeToCostMap = Dictionary, Double>() for tup in edges { edgeToCostMap[Edge(start: Box(graph[tup.0]), end: Box(graph[tup.1]))] = tup.2 graph[tup.0].adjList.append(Box(graph[tup.1])) } } } let weakPrimsState = PrimsState(WeakGraphNode.self) let unownedSafePrimsState = PrimsState(UnownedSafeGraphNode.self) let unownedUnsafePrimsState = PrimsState(UnownedUnsafeGraphNode.self) let unmanagedPrimsState = PrimsState(UnmanagedGraphNode.self) let unmanagedUGRPrimsState = PrimsState(UnmanagedUGRGraphNode.self) //===----------------------------------------------------------------------===// // Protocols //===----------------------------------------------------------------------===// protocol ValueBox : Hashable { associatedtype ValueType : AnyObject init(_ inputValue: ValueType) var value: ValueType { get } func withValue(_ f: (ValueType) throws -> Result) rethrows -> Result func free() } extension ValueBox { func free() {} @_transparent func withValue(_ f: (ValueType) throws -> Result) rethrows -> Result { return try f(value) } } protocol GraphNode { associatedtype BoxType : ValueBox where BoxType.ValueType == Self init(id inputId: Int) var id: Int { get } var adjList: Array { get set } } //===----------------------------------------------------------------------===// // Box Implementations //===----------------------------------------------------------------------===// struct WeakVarBox { weak var _value: T? init(_ inputValue: T) { _value = inputValue } } extension WeakVarBox : ValueBox where T : GraphNode { typealias ValueType = T var value: T { return _value! } } extension WeakVarBox : Equatable where T : Equatable {} extension WeakVarBox : Hashable where T : Hashable {} struct UnownedSafeVarBox { unowned var value: T init(_ inputValue: T) { value = inputValue } } extension UnownedSafeVarBox : ValueBox where T : GraphNode { typealias ValueType = T } extension UnownedSafeVarBox : Equatable where T : Equatable {} extension UnownedSafeVarBox : Hashable where T : Hashable {} struct UnownedUnsafeVarBox { unowned(unsafe) var value: T init(_ inputValue: T) { value = inputValue } } extension UnownedUnsafeVarBox : ValueBox where T : GraphNode { typealias ValueType = T } extension UnownedUnsafeVarBox : Equatable where T : Equatable {} extension UnownedUnsafeVarBox : Hashable where T : Hashable {} struct UnmanagedVarBox { var _value: Unmanaged var value: T { return _value.takeUnretainedValue() } init(_ inputValue: T) { _value = Unmanaged.passRetained(inputValue) } } extension UnmanagedVarBox : ValueBox where T : GraphNode { typealias ValueType = T func free() { _value.release() } } extension UnmanagedVarBox : Equatable where T : Equatable { } func ==(lhs: UnmanagedVarBox, rhs: UnmanagedVarBox) -> Bool { return lhs.value === rhs.value } extension UnmanagedVarBox : Hashable where T : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(value)) } } struct UnmanagedUGRVarBox { var _value: Unmanaged init(_ inputValue: T) { _value = Unmanaged.passRetained(inputValue) } } extension UnmanagedUGRVarBox : ValueBox where T : GraphNode { typealias ValueType = T func free() { _value.release() } var value: T { return _value._withUnsafeGuaranteedRef { $0 } } func withValue(_ f: (ValueType) throws -> Result) rethrows -> Result { try _value._withUnsafeGuaranteedRef { try f($0) } } } extension UnmanagedUGRVarBox : Equatable where T : Equatable { } func ==(lhs: UnmanagedUGRVarBox, rhs: UnmanagedUGRVarBox) -> Bool { return lhs._value._withUnsafeGuaranteedRef { x in return rhs._value._withUnsafeGuaranteedRef { y in return x == y }} } extension UnmanagedUGRVarBox : Hashable where T : Hashable { func hash(into hasher: inout Hasher) { _value._withUnsafeGuaranteedRef { hasher.combine(ObjectIdentifier($0)) } } } //===----------------------------------------------------------------------===// // Graph Node Implementations //===----------------------------------------------------------------------===// final class WeakGraphNode { /// This id is only meant for dumping the state of the graph. It is not meant /// to be used functionally by the algorithm. var id: Int var adjList: Array> init(id inputId: Int) { id = inputId adjList = Array>() } } extension WeakGraphNode : GraphNode { typealias BoxType = WeakVarBox } extension WeakGraphNode : Equatable {} extension WeakGraphNode : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } func ==(lhs: WeakGraphNode, rhs: WeakGraphNode) -> Bool { return lhs === rhs } final class UnownedSafeGraphNode { /// This id is only meant for dumping the state of the graph. It is not meant /// to be used functionally by the algorithm. var id: Int var adjList: Array> init(id inputId: Int) { id = inputId adjList = Array>() } } extension UnownedSafeGraphNode : GraphNode { typealias BoxType = UnownedSafeVarBox } extension UnownedSafeGraphNode : Equatable {} extension UnownedSafeGraphNode : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } final class UnownedUnsafeGraphNode { /// This id is only meant for dumping the state of the graph. It is not meant /// to be used functionally by the algorithm. var id: Int var adjList: Array> init(id inputId: Int) { id = inputId adjList = Array>() } } func ==(lhs: UnownedSafeGraphNode, rhs: UnownedSafeGraphNode) -> Bool { return lhs === rhs } extension UnownedUnsafeGraphNode : GraphNode { typealias BoxType = UnownedUnsafeVarBox } extension UnownedUnsafeGraphNode : Equatable {} extension UnownedUnsafeGraphNode : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } func ==(lhs: UnownedUnsafeGraphNode, rhs: UnownedUnsafeGraphNode) -> Bool { return lhs === rhs } final class UnmanagedGraphNode { /// This id is only meant for dumping the state of the graph. It is not meant /// to be used functionally by the algorithm. var id: Int var adjList: Array> init(id inputId: Int) { id = inputId adjList = Array>() } deinit { for x in adjList { x.free() } } } extension UnmanagedGraphNode : GraphNode { typealias BoxType = UnmanagedVarBox } extension UnmanagedGraphNode : Equatable {} extension UnmanagedGraphNode : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } func ==(lhs: UnmanagedGraphNode, rhs: UnmanagedGraphNode) -> Bool { return lhs === rhs } final class UnmanagedUGRGraphNode { /// This id is only meant for dumping the state of the graph. It is not meant /// to be used functionally by the algorithm. var id: Int var adjList: Array> init(id inputId: Int) { id = inputId adjList = Array>() } deinit { for x in adjList { x.free() } } } extension UnmanagedUGRGraphNode : GraphNode { typealias BoxType = UnmanagedUGRVarBox } extension UnmanagedUGRGraphNode : Equatable {} extension UnmanagedUGRGraphNode : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } func ==(lhs: UnmanagedUGRGraphNode, rhs: UnmanagedUGRGraphNode) -> Bool { return lhs === rhs } //===----------------------------------------------------------------------===// // Edge Implementation //===----------------------------------------------------------------------===// struct Edge { var start: Node.BoxType var end: Node.BoxType } extension Edge : Equatable {} func ==(lhs: Edge, rhs: Edge) -> Bool { return lhs.start == rhs.start && lhs.end == rhs.end } extension Edge : Hashable { func hash(into hasher: inout Hasher) { hasher.combine(start) hasher.combine(end) } } //===----------------------------------------------------------------------===// // Algorithm //===----------------------------------------------------------------------===// class PriorityQueue { final var heap: Array> final var graphIndexToHeapIndexMap: Dictionary // Create heap for graph with NUM nodes. init(count: Int) { heap = Array>() graphIndexToHeapIndexMap = Dictionary() } var isEmpty: Bool { return heap.isEmpty } // Insert element N to heap, maintaining the heap property. func insert(_ n: EdgeCost) { let ind: Int = heap.count heap.append(n) graphIndexToHeapIndexMap[n.to] = heap.count - 1 bubbleUp(ind) } // Insert element N if in's not in the heap, or update its cost if the new // value is less than the existing one. func insertOrUpdate(_ n: EdgeCost) { let id = n.to let c = n.cost if let ind = graphIndexToHeapIndexMap[id] { if heap[ind].cost <= c { // We don't need an edge with a bigger cost return } heap[ind].cost = c heap[ind].from = n.from bubbleUp(ind) } else { insert(n) } } // Restore heap property by moving element at index IND up. // This is needed after insertion, and after decreasing an element's cost. func bubbleUp(_ ind: Int) { var ind = ind let c = heap[ind].cost while (ind != 0) { let p = getParentIndex(ind) if heap[p].cost > c { swap(p, with: ind) ind = p } else { break } } } // Pop minimum element from heap and restore the heap property after that. func pop() -> EdgeCost? { if (heap.isEmpty) { return nil } swap(0, with:heap.count-1) let r = heap.removeLast() graphIndexToHeapIndexMap[r.to] = nil bubbleDown(0) return r } // Restore heap property by moving element at index IND down. // This is needed after removing an element, and after increasing an // element's cost. func bubbleDown(_ ind: Int) { var ind = ind let n = heap.count while (ind < n) { let l = getLeftChildIndex(ind) let r = getRightChildIndex(ind) if (l >= n) { break } var min: Int if (r < n && heap[r].cost < heap[l].cost) { min = r } else { min = l } if (heap[ind].cost <= heap[min].cost) { break } swap(ind, with: min) ind = min } } // Swaps elements I and J in the heap and correspondingly updates // graphIndexToHeapIndexMap. func swap(_ i: Int, with j : Int) { if (i == j) { return } (heap[i], heap[j]) = (heap[j], heap[i]) let (I, J) = (heap[i].to, heap[j].to) (graphIndexToHeapIndexMap[I], graphIndexToHeapIndexMap[J]) = (graphIndexToHeapIndexMap[J], graphIndexToHeapIndexMap[I]) } // Dumps the heap. func dump() { print("QUEUE") for nodeCost in heap { let to: Int = nodeCost.to.value.id let from: Int = nodeCost.from.value.id let cost: Double = nodeCost.cost print("(\(from)->\(to), \(cost))") } } func getLeftChildIndex(_ index : Int) -> Int { return index*2 + 1 } func getRightChildIndex(_ index : Int) -> Int { return (index + 1)*2 } func getParentIndex(_ childIndex : Int) -> Int { return (childIndex - 1)/2 } } struct EdgeCost where Node.BoxType == Box, Box.ValueType == Node { var to: Box var cost: Double var from: Box init(to inputTo: Node, cost inputCost: Double, from inputFrom: Node) { to = Box(inputTo) cost = inputCost from = Box(inputFrom) } init(to inputTo: Box, cost inputCost: Double, from inputFrom: Box) { to = inputTo cost = inputCost from = inputFrom } } func primsMainLoop( _ graph : Array, _ fun : (Node.BoxType, Node.BoxType) -> Double) -> Array where Node.BoxType == Box, Box.ValueType == Node { var treeEdges = Array(repeating:nil, count:graph.count) let queue = PriorityQueue(count: graph.count) // Make the minimum spanning tree root its own parent for simplicity. queue.insert(EdgeCost(to: graph[0], cost: 0.0, from: graph[0])) // Take an element with the smallest cost from the queue and add its // neighbors to the queue if their cost was updated while !queue.isEmpty { // Add an edge with minimum cost to the spanning tree let e = queue.pop()! let newnode: Node.BoxType = e.to // Add record about the edge newnode->e.from to treeEdges treeEdges[newnode.value.id] = e.from.value.id // Check all adjacent nodes and add edges, ending outside the tree, to the // queue. If the queue already contains an edge to an adjacent node, we // replace existing one with the new one in case the new one costs less. for toNode: Box in newnode.value.adjList { if treeEdges[toNode.value.id] != nil { continue } let newcost = fun(newnode, toNode) queue.insertOrUpdate(EdgeCost(to: toNode, cost: newcost, from: newnode)) } } return treeEdges } func primsMainLoopClosureAccess( _ graph : Array, _ fun : (Node.BoxType, Node.BoxType) -> Double) -> Array where Node.BoxType == Box, Box.ValueType == Node { var treeEdges = Array(repeating:nil, count:graph.count) let queue = PriorityQueue(count: graph.count) // Make the minimum spanning tree root its own parent for simplicity. queue.insert(EdgeCost(to: graph[0], cost: 0.0, from: graph[0])) // Take an element with the smallest cost from the queue and add its // neighbors to the queue if their cost was updated while !queue.isEmpty { // Add an edge with minimum cost to the spanning tree let e = queue.pop()! let newnode: Node.BoxType = e.to // Add record about the edge newnode->e.from to treeEdges treeEdges[newnode.withValue { $0.id }] = e.from.withValue { $0.id } // Check all adjacent nodes and add edges, ending outside the tree, to the // queue. If the queue already contains an edge to an adjacent node, we // replace existing one with the new one in case the new one costs less. for toNode: Box in (newnode.withValue { $0.adjList }) { if treeEdges[toNode.withValue({ $0.id })] != nil { continue } let newcost = fun(newnode, toNode) queue.insertOrUpdate(EdgeCost(to: toNode, cost: newcost, from: newnode)) } } return treeEdges } //===----------------------------------------------------------------------===// // Top Level Entrypoints //===----------------------------------------------------------------------===// @inline(__always) func run_PrimsNonStrongRef(_ state: PrimsState) where Node.BoxType == Box, Box.ValueType == Node { let graph = state.graph let map = state.edgeToCostMap // Find spanning tree let treeEdges = primsMainLoop(graph, { (start: Box, end: Box) in return map[Edge(start: start, end: end)]! }) // Compute its cost in order to check results var cost = 0.0 for i in 1..(_ state: PrimsState) where Node.BoxType == Box, Box.ValueType == Node { let graph = state.graph let map = state.edgeToCostMap // Find spanning tree let treeEdges = primsMainLoopClosureAccess(graph, { (start: Box, end: Box) in return map[Edge(start: start, end: end)]! }) // Compute its cost in order to check results var cost = 0.0 for i in 1..