Skip to content

Commit

Permalink
Convert convenience initializers to static members
Browse files Browse the repository at this point in the history
  • Loading branch information
ferranpujolcamins committed Apr 11, 2019
1 parent 81345d8 commit a6c828a
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 51 deletions.
19 changes: 10 additions & 9 deletions Sources/SwiftGraph/Union.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,38 @@ public extension UniqueElementsGraph where E == UnweightedEdge {
///
/// - Parameters:
/// - graphs: Array of graphs to build the union from.
convenience init(unionOf graphs: [UniqueElementsGraph]) {
self.init()
static func unionOf(_ graphs: [UniqueElementsGraph]) -> UniqueElementsGraph{
let union = UniqueElementsGraph()

guard let firstGraph = graphs.first else { return }
guard let firstGraph = graphs.first else { return union }
let others = graphs.dropFirst()

// We know vertices in lhs are unique, so we call Graph.addVertex to avoid the uniqueness check of UniqueElementsGraph.addVertex.
for vertex in firstGraph.vertices {
_ = addVertex(vertex)
_ = union.addVertex(vertex)
}

// When vertices are removed from Graph, edges might mutate,
// so we need to add new copies of them for the result graph.
for edge in firstGraph.edges.joined() {
addEdge(edge, directed: true)
union.addEdge(edge, directed: true)
}

for g in others {
// Vertices in rhs might be equal to some vertex in lhs, so we need to add them
// with self.addVertex to guarantee uniqueness.
for vertex in g.vertices {
_ = addVertex(vertex)
_ = union.addVertex(vertex)
}

for edge in g.edges.joined() {
addEdge(from: g[edge.u], to: g[edge.v], directed: true)
union.addEdge(from: g[edge.u], to: g[edge.v], directed: true)
}
}
return union
}

convenience init(unionOf graphs: UniqueElementsGraph...) {
self.init(unionOf: graphs)
static func unionOf(_ graphs: UniqueElementsGraph...) -> UniqueElementsGraph{
return unionOf(graphs)
}
}
58 changes: 31 additions & 27 deletions Sources/SwiftGraph/UniqueElementsGraph.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,16 @@ extension UniqueElementsGraph where E == UnweightedEdge {
/// - directed: If false, undirected edges are created.
/// If true, edges are directed from vertex i to vertex i+1 in path.
/// Default is false.
public convenience init(withPath path: [V], directed: Bool = false) {
self.init(vertices: path)
public static func withPath(_ path: [V], directed: Bool = false) -> UniqueElementsGraph {
let g = UniqueElementsGraph(vertices: path)

guard path.count >= 2 else {
return
return g
}

let indices = path.map({ indexOfVertex($0)! })
addEdgesForPath(withIndices: indices, directed: directed)
let indices = path.map({ g.indexOfVertex($0)! })
g.addEdgesForPath(withIndices: indices, directed: directed)
return g
}

/// Initialize an UniqueElementsGraph consisting of cycle.
Expand All @@ -114,54 +115,57 @@ extension UniqueElementsGraph where E == UnweightedEdge {
/// - directed: If false, undirected edges are created.
/// If true, edges are directed from vertex i to vertex i+1 in cycle.
/// Default is false.
public convenience init(withCycle cycle: [V], directed: Bool = false) {
self.init(vertices: cycle)
public static func withCycle(_ cycle: [V], directed: Bool = false) -> UniqueElementsGraph {
let g = UniqueElementsGraph(vertices: cycle)

guard cycle.count >= 2 else {
if let v = cycle.first {
let index = addVertex(v)
addEdge(fromIndex: index, toIndex: index)
let index = g.addVertex(v)
g.addEdge(fromIndex: index, toIndex: index)
}
return
return g
}

let indices = cycle.map({ indexOfVertex($0)! })
addEdgesForPath(withIndices: indices, directed: directed)
addEdge(fromIndex: indices.last!, toIndex: indices.first!, directed: directed)
let indices = cycle.map({ g.indexOfVertex($0)! })
g.addEdgesForPath(withIndices: indices, directed: directed)
g.addEdge(fromIndex: indices.last!, toIndex: indices.first!, directed: directed)
return g
}

}

extension UniqueElementsGraph where V: Hashable, E == UnweightedEdge {
public convenience init(withPath path: [V], directed: Bool = false) {
self.init()
public static func withPath(_ path: [V], directed: Bool = false) -> UniqueElementsGraph {
let g = UniqueElementsGraph()

guard path.count >= 2 else {
if let v = path.first {
_ = addVertex(v)
_ = g.addVertex(v)
}
return
return g
}

let indices = indicesForPath(path)
addEdgesForPath(withIndices: indices, directed: directed)
let indices = g.indicesForPath(path)
g.addEdgesForPath(withIndices: indices, directed: directed)
return g
}


public convenience init(withCycle cycle: [V], directed: Bool = false) {
self.init()
public static func withCycle(_ cycle: [V], directed: Bool = false) -> UniqueElementsGraph {
let g = UniqueElementsGraph()

guard cycle.count >= 2 else {
if let v = cycle.first {
let index = addVertex(v)
addEdge(fromIndex: index, toIndex: index)
let index = g.addVertex(v)
g.addEdge(fromIndex: index, toIndex: index)
}
return
return g
}

let indices = indicesForPath(cycle)
addEdgesForPath(withIndices: indices, directed: directed)
addEdge(fromIndex: indices.last!, toIndex: indices.first!, directed: directed)
let indices = g.indicesForPath(cycle)
g.addEdgesForPath(withIndices: indices, directed: directed)
g.addEdge(fromIndex: indices.last!, toIndex: indices.first!, directed: directed)
return g
}

private func indicesForPath(_ path: [V]) -> [Int] {
Expand Down
30 changes: 15 additions & 15 deletions Tests/SwiftGraphTests/UnionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class UnionTests: XCTestCase {
}

func testEmptyGraph() {
let g = UnweightedUniqueElementsGraph<Int>(unionOf: [])
let g = UnweightedUniqueElementsGraph<Int>.unionOf([])
XCTAssertEqual(g.vertexCount, 0, "Expected 0 vertices on the empty graph.")
XCTAssertEqual(g.edgeCount, 0, "Expected 0 edges on the empty graph.")
}
Expand All @@ -43,7 +43,7 @@ class UnionTests: XCTestCase {
let g2 = UnweightedUniqueElementsGraph(vertices: ["Boston", "Chicago"])
g2.addEdge(from: "Boston", to: "Chicago", directed: false)

let u = UnweightedUniqueElementsGraph(unionOf: g1, g2)
let u = UnweightedUniqueElementsGraph.unionOf(g1, g2)

XCTAssertEqual(u.vertices, ["Atlanta", "Boston", "Chicago"], "Expected vertices on the result graph to be Atlanta, Boston and Chicago.")
XCTAssertEqual(u.edgeCount, 3, "Expected 3 edges on the result graph.")
Expand All @@ -58,7 +58,7 @@ class UnionTests: XCTestCase {
let g2 = UnweightedUniqueElementsGraph(vertices: ["Atlanta", "Chicago"])
g2.addEdge(from: "Atlanta", to: "Chicago", directed: false)

let u = UnweightedUniqueElementsGraph(unionOf: g1, g2)
let u = UnweightedUniqueElementsGraph.unionOf(g1, g2)

XCTAssertEqual(u.vertices, ["Atlanta", "Boston", "Chicago"], "Expected vertices on the result graph to be Atlanta, Boston and Chicago.")
XCTAssertEqual(u.edgeCount, 3, "Expected 3 edges on the result graph.")
Expand All @@ -73,7 +73,7 @@ class UnionTests: XCTestCase {
let g2 = UnweightedUniqueElementsGraph(vertices: ["Chicago", "Denver"])
g2.addEdge(from: "Chicago", to: "Denver", directed: false)

let u = UnweightedUniqueElementsGraph(unionOf: g1, g2)
let u = UnweightedUniqueElementsGraph.unionOf(g1, g2)

XCTAssertEqual(u.vertices, ["Atlanta", "Boston", "Chicago", "Denver"], "Expected vertices on the result graph to be Atlanta, Boston, Chicago and Denver.")
XCTAssertEqual(u.edgeCount, 3, "Expected 3 edges on the result graph.")
Expand All @@ -88,7 +88,7 @@ class UnionTests: XCTestCase {
let g2 = UnweightedUniqueElementsGraph(vertices: ["Boston", "Chicago"])
g2.addEdge(from: "Boston", to: "Chicago", directed: false)

let _ = UnweightedUniqueElementsGraph(unionOf: g1, g2)
let _ = UnweightedUniqueElementsGraph.unionOf(g1, g2)

XCTAssertEqual(g1.vertices, ["Atlanta", "Boston"], "g1: Expected vertices to be Atlanta and Boston.")
XCTAssertEqual(g1.edgeCount, 1, "g1: Expected exactly 1 edge")
Expand All @@ -105,13 +105,13 @@ class UnionTests: XCTestCase {
let g = UnweightedUniqueElementsGraph<String>(vertices:["Atlanta", "Chicago"])
g.addEdge(from: "Atlanta", to: "Chicago", directed: true)

let result1 = UnweightedUniqueElementsGraph(unionOf: eg, g)
let result1 = UnweightedUniqueElementsGraph.unionOf(eg, g)

XCTAssertEqual(result1.vertices, g.vertices, "Expected same vertices after left union with empty graph")
XCTAssertEqual(result1.edgeCount, 1, "Expected same edge count after left union with empty graph")
XCTAssertTrue(result1.edgeExists(from: "Atlanta", to: "Chicago"), "Expected an edge from Chicago to Atlanta after left union with empty graph")

let result2 = UnweightedUniqueElementsGraph(unionOf: g, eg)
let result2 = UnweightedUniqueElementsGraph.unionOf(g, eg)

XCTAssertEqual(result2.vertices, g.vertices, "Expected same vertices after right union with empty graph")
XCTAssertEqual(result2.edgeCount, 1, "Expected same edge count after right union with empty graph")
Expand All @@ -122,7 +122,7 @@ class UnionTests: XCTestCase {
let g = UnweightedUniqueElementsGraph(vertices: ["Atlanta", "Boston"])
g.addEdge(from: "Atlanta", to: "Boston", directed: true)

let u = UnweightedUniqueElementsGraph(unionOf: g, g)
let u = UnweightedUniqueElementsGraph.unionOf(g, g)
XCTAssertEqual(u.vertices, g.vertices, "Expected same vertices after union with self")
XCTAssertEqual(u.edgeCount, 1, "Expected same edge count after union to self")
XCTAssertTrue(u.edgeExists(from: "Atlanta", to: "Boston"), "Expected an edge from Atlanta to Boston")
Expand All @@ -134,8 +134,8 @@ class UnionTests: XCTestCase {
let g2 = UnweightedUniqueElementsGraph(vertices: ["Boston", "Chicago"])
g2.addEdge(from: "Boston", to: "Chicago", directed: false)

let u12 = UnweightedUniqueElementsGraph(unionOf: g1, g2)
let u21 = UnweightedUniqueElementsGraph(unionOf: g2, g1)
let u12 = UnweightedUniqueElementsGraph.unionOf(g1, g2)
let u21 = UnweightedUniqueElementsGraph.unionOf(g2, g1)
// Both result graph must have the same vertices but they can be in different order.
XCTAssertTrue(arraysHaveSameElements(u12.vertices, u21.vertices), "Expected same vertices for g1 ∪ g2 and g2 ∪ g1")
XCTAssertTrue(arraysHaveSameElements(u12.neighborsForVertex("Atlanta")!, u21.neighborsForVertex("Atlanta")!), "Expected same neighbors of Atlanta in g1 ∪ g2 and g2 ∪ g1")
Expand All @@ -148,11 +148,11 @@ class UnionTests: XCTestCase {
let g2 = UnweightedUniqueElementsGraph(withPath:["B", "C"])
let g3 = UnweightedUniqueElementsGraph(withPath:["C", "A"])

let g12 = UnweightedUniqueElementsGraph(unionOf: g1, g2)
let g12_3 = UnweightedUniqueElementsGraph(unionOf: g12, g3)
let g12 = UnweightedUniqueElementsGraph.unionOf(g1, g2)
let g12_3 = UnweightedUniqueElementsGraph.unionOf(g12, g3)

let g23 = UnweightedUniqueElementsGraph(unionOf: g2, g3)
let g1_23 = UnweightedUniqueElementsGraph(unionOf: g1, g23)
let g23 = UnweightedUniqueElementsGraph.unionOf(g2, g3)
let g1_23 = UnweightedUniqueElementsGraph.unionOf(g1, g23)

XCTAssertTrue(arraysHaveSameElements(g12_3.vertices, g1_23.vertices), "Expected same vertices for (g1 ∪ g2) ∪ g3 and g1 ∪ (g2 ∪ g3)")

Expand All @@ -170,7 +170,7 @@ class UnionTests: XCTestCase {
let g2 = UnweightedUniqueElementsGraph(withPath:["B", "C"])
let g3 = UnweightedUniqueElementsGraph(withPath:["C", "A"])

let g = UnweightedUniqueElementsGraph(unionOf: g1, g2, g3)
let g = UnweightedUniqueElementsGraph.unionOf(g1, g2, g3)

XCTAssertEqual(g.vertices, ["A", "B", "C"], "g: Expected vertices to be A, B and C")
XCTAssertTrue(g.edgeExists(from: "A", to: "B"), "g: Expected an edge from A to B")
Expand Down

0 comments on commit a6c828a

Please sign in to comment.