Skip to content

Commit 80dda2d

Browse files
committed
Introduces new workspace
1 parent d2911cf commit 80dda2d

File tree

16 files changed

+963
-0
lines changed

16 files changed

+963
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
var graph = AdjacencyListGraph<String>()
2+
3+
let v1 = graph.createVertex("Montreal")
4+
let v2 = graph.createVertex("New York")
5+
let v3 = graph.createVertex("Boston")
6+
let v4 = graph.createVertex("Portland")
7+
let v5 = graph.createVertex("Portsmouth")
8+
9+
graph.addDirectedEdge(v1, to: v2, withWeight: 3)
10+
graph.addDirectedEdge(v1, to: v5, withWeight: -4)
11+
graph.addDirectedEdge(v1, to: v3, withWeight: 8)
12+
13+
graph.addDirectedEdge(v2, to: v4, withWeight: 1)
14+
graph.addDirectedEdge(v2, to: v5, withWeight: 7)
15+
16+
graph.addDirectedEdge(v3, to: v2, withWeight: 4)
17+
18+
graph.addDirectedEdge(v4, to: v1, withWeight: 2)
19+
graph.addDirectedEdge(v4, to: v3, withWeight: -5)
20+
21+
graph.addDirectedEdge(v5, to: v4, withWeight: 6)
22+
23+
let result = FloydWarshall<String>.apply(graph)
24+
25+
let path = result.path(fromVertex: v1, toVertex: v4, inGraph: graph)
26+
27+
print(graph)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//
2+
// Base.swift
3+
// APSP
4+
//
5+
// Created by Andrew McKnight on 5/6/16.
6+
//
7+
8+
import Foundation
9+
10+
/**
11+
`APSPAlgorithm` is a protocol for encapsulating an All-Pairs Shortest Paths algorithm.
12+
It provides a single function `apply` that accepts a subclass of `AbstractGraph` and
13+
returns an object conforming to `APSPResult`.
14+
*/
15+
public protocol APSPAlgorithm {
16+
17+
associatedtype Q: Hashable
18+
associatedtype P: APSPResult
19+
20+
static func apply(_ graph: AbstractGraph<Q>) -> P
21+
22+
}
23+
24+
/**
25+
`APSPResult` is a protocol defining functions `distance` and `path`, allowing for opaque
26+
queries into the actual data structures that represent the APSP solution according to the algorithm used.
27+
*/
28+
public protocol APSPResult {
29+
30+
associatedtype T: Hashable
31+
32+
func distance(fromVertex from: Vertex<T>, toVertex to: Vertex<T>) -> Double?
33+
func path(fromVertex from: Vertex<T>, toVertex to: Vertex<T>, inGraph graph: AbstractGraph<T>) -> [T]?
34+
35+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//
2+
// AdjacencyListGraph.swift
3+
// Graph
4+
//
5+
// Created by Andrew McKnight on 5/13/16.
6+
//
7+
8+
import Foundation
9+
10+
private class EdgeList<T> where T: Hashable {
11+
var vertex: Vertex<T>
12+
var edges: [Edge<T>]?
13+
14+
init(vertex: Vertex<T>) {
15+
self.vertex = vertex
16+
}
17+
18+
func addEdge(_ edge: Edge<T>) {
19+
edges?.append(edge)
20+
}
21+
}
22+
23+
open class AdjacencyListGraph<T>: AbstractGraph<T> where T: Hashable {
24+
private var adjacencyList: [EdgeList<T>] = []
25+
26+
public required init() {
27+
super.init()
28+
}
29+
30+
public required init(fromGraph graph: AbstractGraph<T>) {
31+
super.init(fromGraph: graph)
32+
}
33+
34+
open override var vertices: [Vertex<T>] {
35+
adjacencyList.map { $0.vertex }
36+
}
37+
38+
open override var edges: [Edge<T>] {
39+
Array(adjacencyList.flatMap { $0.edges ?? [] }.reduce(into: Set<Edge<T>>()) { $0.insert($1) })
40+
}
41+
42+
open override func createVertex(_ data: T) -> Vertex<T> {
43+
if let match = vertices.first(where: { $0.data == data }) {
44+
return match
45+
}
46+
47+
// if the vertex doesn't exist, create a new one
48+
let vertex = Vertex(data: data, index: adjacencyList.count)
49+
adjacencyList.append(EdgeList(vertex: vertex))
50+
return vertex
51+
}
52+
53+
open override func addDirectedEdge(_ from: Vertex<T>, to: Vertex<T>, withWeight weight: Double?) {
54+
// works
55+
let edge = Edge(from: from, to: to, weight: weight)
56+
let edgeList = adjacencyList[from.index]
57+
if edgeList.edges != nil {
58+
edgeList.addEdge(edge)
59+
} else {
60+
edgeList.edges = [edge]
61+
}
62+
}
63+
64+
open override func addUndirectedEdge(_ vertices: (Vertex<T>, Vertex<T>), withWeight weight: Double?) {
65+
addDirectedEdge(vertices.0, to: vertices.1, withWeight: weight)
66+
addDirectedEdge(vertices.1, to: vertices.0, withWeight: weight)
67+
}
68+
69+
open override func weightFrom(_ sourceVertex: Vertex<T>, to destinationVertex: Vertex<T>) -> Double? {
70+
guard let edges = adjacencyList[sourceVertex.index].edges else {
71+
return nil
72+
}
73+
74+
for edge: Edge<T> in edges {
75+
if edge.to == destinationVertex {
76+
return edge.weight
77+
}
78+
}
79+
80+
return nil
81+
}
82+
83+
open override func edgesFrom(_ sourceVertex: Vertex<T>) -> [Edge<T>] {
84+
return adjacencyList[sourceVertex.index].edges ?? []
85+
}
86+
87+
open override var description: String {
88+
var rows = [String]()
89+
for edgeList in adjacencyList {
90+
91+
guard let edges = edgeList.edges else {
92+
continue
93+
}
94+
95+
var row = [String]()
96+
for edge in edges {
97+
var value = "\(edge.to.data)"
98+
if edge.weight != nil {
99+
value = "(\(value): \(edge.weight!))"
100+
}
101+
row.append(value)
102+
}
103+
104+
rows.append("\(edgeList.vertex.data) -> [\(row.joined(separator: ", "))]")
105+
}
106+
107+
return rows.joined(separator: "\n")
108+
}
109+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// Edge.swift
3+
// Graph
4+
//
5+
// Created by Andrew McKnight on 5/8/16.
6+
//
7+
8+
public struct Edge<T: Hashable> {
9+
public let from: Vertex<T>
10+
public let to: Vertex<T>
11+
public let weight: Double?
12+
}
13+
14+
extension Edge: CustomStringConvertible {
15+
public var description: String {
16+
guard let unwrappedWeight = weight else {
17+
return "\(from.description) -> \(to.description)"
18+
}
19+
return "\(from.description) -(\(unwrappedWeight))-> \(to.description)"
20+
}
21+
}
22+
23+
extension Edge: Hashable {}
24+
extension Edge: Equatable {}

0 commit comments

Comments
 (0)