| class Edge { | |
| Integer v1 | |
| Integer v2 | |
| Integer weight | |
| Edge(Integer v1, Integer v2, Integer w) { | |
| this.v1 = v1 | |
| this.v2 = v2 | |
| this.weight = w | |
| } | |
| boolean contains(Integer v) { v1 == v || v2 == v } | |
| Integer otherThan(Integer v) { v1 == v ? v2 : v1 } | |
| } | |
| class Graph { | |
| List<Integer> V | |
| Collection<Edge> E | |
| // Dumbest implementation | |
| List<Integer> getIncident(Integer v) { E.findAll{ it.contains(v) }.collect{ it.otherThan(v) } } | |
| Edge findEdge(Integer v1, Integer v2) { E.find{ it.contains(v1) && it.contains(v2) } } | |
| Number weight(Integer v1, Integer v2) { findEdge(v1, v2)?.weight ?: Double.POSITIVE_INFINITY } | |
| } | |
| Collection<Edge> prim(Graph G) { | |
| Set<Edge> T = [] | |
| Map<Integer, Number> d = [:] + G.V.collect { new MapEntry(it, Double.POSITIVE_INFINITY) } | |
| Map<Integer, Integer> p = [:] + G.V.collect { new MapEntry(it, null) } | |
| d[G.V[0]] = 0 | |
| List<Integer> Q = G.V.collect{it} | |
| Q.metaClass.extractMin = { -> | |
| // Dumbest implementation | |
| int minimum = Q.min { d[it] } | |
| int indexOfMinimum = Q.indexOf(minimum) // here Groovy fails to make a shortcut. | |
| return Q.remove(indexOfMinimum) | |
| } | |
| Integer v = Q.extractMin() | |
| while (!Q.isEmpty()) { | |
| G.getIncident(v).each { Integer u -> | |
| if(Q.contains(u) && G.weight(u, v) < d[u]) { | |
| d[u] = G.weight(u, v) | |
| p[u] = v | |
| } | |
| } | |
| v = Q.extractMin() | |
| T << G.findEdge(p[v], v) | |
| } | |
| T | |
| } | |
| void testPrim() { | |
| Set<Edge> expected = [ | |
| new Edge(1, 2, 1), | |
| new Edge(2, 3, 1), | |
| new Edge(3, 4, 1), | |
| new Edge(4, 5, 1), | |
| ] | |
| Set<Edge> edges = [ | |
| new Edge(1, 3, 2), | |
| new Edge(1, 4, 3), | |
| new Edge(1, 5, 2), | |
| new Edge(2, 4, 7), | |
| new Edge(3, 5, 2), | |
| ] | |
| Graph G = new Graph(V: 1..5, E: expected + edges) | |
| Set<Edge> T = prim(G) | |
| assert expected.equals(T) | |
| println "it worked!" | |
| } | |
| testPrim() |