aboutsummaryrefslogtreecommitdiff
path: root/com/example/portfolio3/GraphAlgorithms.java
blob: 823e2b1283b13f4f1936c080fce7b60fff0796e2 (plain)
  1. package com.example.portfolio3;
  2. // origin: <https://moodle.ruc.dk/course/section.php?id=211877>
  3. import java.io.*;
  4. import java.util.*;
  5. public class GraphAlgorithms {
  6. public static int pathLength(Collection<Edge> edges){
  7. // Calculates the length of a path or any other collection of edes
  8. // does not require the edges to form a path
  9. return edges.stream().mapToInt(e-> e.weight()).sum();
  10. }
  11. public static boolean isPath(List<Edge> edges){
  12. // checks whether a list of edges form a path so that
  13. // the to-vertex in one edge is the from-vertex of the next
  14. for(int i=1;i<edges.size();i++){
  15. if(edges.get(i-1).to()!=edges.get(i).from())return false;
  16. }
  17. return true;
  18. }
  19. public static Integer pathLength(Graph g,List<Vertex> path){
  20. //Calculates the length of a path vertices in a graph
  21. // return null if vertices are not connected as a path
  22. int length=0;
  23. for(int i=1;i<path.size();i++){
  24. Integer w=g.getWeight(path.get(i-1),path.get(i));
  25. if(w==null)return null;
  26. length+=w;
  27. }
  28. return length;
  29. }
  30. //------------------------------------------------------------
  31. //
  32. // Comparators and sorting methods
  33. static int cmpEdgeWeight(Edge e1,Edge e2) {
  34. // Comparator of edges based on weight
  35. // can be used for sorting a list of edges
  36. int w1=e1.weight(),w2=e2.weight();
  37. if(w1!=w2)return w1-w2;
  38. if(e1.from()!=e2.from())return e1.from().name().compareTo(e2.from().name());
  39. return e1.to().name().compareTo(e2.to().name());
  40. }
  41. static int cmpEdgeFrom(Edge e1,Edge e2) {
  42. // Comparator of edges based on from-vertex
  43. // can be used for sorting a list of edges
  44. if(e1.from()!=e2.from())return e1.from().name().compareTo(e2.from().name());
  45. int w1=e1.weight(),w2=e2.weight();
  46. if(w1!=w2)return w1-w2;
  47. return e1.to().name().compareTo(e2.to().name());
  48. }
  49. static int cmpEdgeTo(Edge e1,Edge e2) {
  50. // Comparator of edges based on from-vertex
  51. // can be used for sorting a list of edges
  52. if(e1.to()!=e2.to())return e1.to().name().compareTo(e2.to().name());
  53. if(e1.from()!=e2.from())return e1.from().name().compareTo(e2.from().name());
  54. int w1=e1.weight(),w2=e2.weight();
  55. return w1-w2;
  56. }
  57. static List<Edge> sortEdges(Collection<Edge> edges){
  58. // sort a collection of edges based on their weights
  59. ArrayList<Edge> list=new ArrayList<>(edges);
  60. Collections.sort(list,GraphAlgorithms::cmpEdgeWeight);
  61. return list;
  62. }
  63. static List<Edge> sortEdgesFrom(Collection<Edge> edges){
  64. // sort a collection of edges based on from-vertex
  65. ArrayList<Edge> list=new ArrayList<>(edges);
  66. Collections.sort(list,GraphAlgorithms::cmpEdgeFrom);
  67. return list;
  68. }
  69. static List<Edge> sortEdgesTo(Collection<Edge> edges){
  70. // sort a collection of edges based on to-vertex
  71. ArrayList<Edge> list=new ArrayList<>(edges);
  72. Collections.sort(list,GraphAlgorithms::cmpEdgeTo);
  73. return list;
  74. }
  75. static List<Vertex> sortVertex(Collection<Vertex> vertices){
  76. // sort a collection of vertices based on their name
  77. ArrayList<Vertex> list=new ArrayList<>(vertices);
  78. Collections.sort(list,(Vertex v1,Vertex v2)-> v1.name().compareTo(v2.name()));
  79. return list;
  80. }
  81. //------------------------------------------------------------
  82. //
  83. // Algorithms for traverse and minimum spanning tree
  84. public static Set<Vertex> visitBreadthFirst(Graph g,Vertex v){
  85. // traverse a graph depth first from a given vertex
  86. // return the set of visited vertices
  87. HashSet<Vertex> thisLevel=new HashSet<>();
  88. HashSet<Vertex> nextLevel=new HashSet<>();
  89. HashSet<Vertex> visited=new HashSet<>();
  90. thisLevel.add(v);
  91. while(thisLevel.size()>0){
  92. System.out.println("level "+thisLevel);
  93. for(Vertex w:thisLevel){
  94. //System.out.println("visited "+w);
  95. visited.add(w);
  96. Collection<Edge> outedge=g.outEdge(w);
  97. if(outedge==null)continue;
  98. for(Edge e: outedge){
  99. if(visited.contains(e.to()))continue;
  100. if(thisLevel.contains(e.to()))continue;
  101. nextLevel.add(e.to());
  102. }
  103. }
  104. thisLevel=nextLevel;
  105. nextLevel=new HashSet<Vertex>();
  106. }
  107. return visited;
  108. }
  109. public static Set<Vertex> visitDepthFirst(Graph g,Vertex v){
  110. // traverse a graph depth first from a given vertex
  111. // return the set of visited vertices
  112. HashSet<Vertex> visit=new HashSet<>();
  113. visitDepthFirst(g, v,visit);
  114. return visit;
  115. }
  116. private static void visitDepthFirst(Graph g,Vertex v,Set<Vertex> visited){
  117. if(visited.contains(v))return;
  118. //System.out.println("visited "+v);
  119. visited.add(v);
  120. for(Edge e: g.outEdge(v))
  121. visitDepthFirst(g,e.to(),visited);
  122. }
  123. public static Set<Edge> minimumSpanningTree(Graph g){
  124. // an implementation of Prim's algorithm
  125. // naive implementation without priorityqueue
  126. Collection<Edge> edges=g.edges();
  127. HashSet<Edge> mst=new HashSet<>();
  128. HashSet<Vertex> frontier=new HashSet<>();
  129. for(Edge e:edges){frontier.add(e.from());break;}
  130. while(true) {
  131. Edge nearest = null;
  132. for (Edge e : edges) {
  133. if (!frontier.contains(e.from())) continue;
  134. if (frontier.contains(e.to())) continue;
  135. if (nearest == null || nearest.weight() > e.weight())
  136. nearest = e;
  137. }
  138. if(nearest==null)break;
  139. mst.add(nearest);
  140. frontier.add(nearest.to());
  141. }
  142. return mst;
  143. }
  144. public static Set<Edge> dijkstra(Graph g, Vertex start){
  145. // returns the tree of shortest paths from start to
  146. // all vertices in the graph
  147. // naive implementation without a prorityqueue
  148. // create table for done, prev and weight from start
  149. int maxint =Integer.MAX_VALUE;
  150. HashSet<Vertex> done=new HashSet<>();
  151. HashMap<Vertex,Edge> prev=new HashMap<>();
  152. HashMap<Vertex,Integer> weight=new HashMap<>();
  153. for(Vertex w:g.vertices())weight.put(w,maxint);
  154. // start node is done, distance 0 from start
  155. weight.put(start,0);
  156. done.add(start);
  157. while(true){
  158. // find nearest from a done vertex
  159. Vertex nearest = null;
  160. int neardist = maxint;
  161. Edge done2near=null;
  162. for(Vertex w1:done){
  163. for (Edge e : g.outEdge(w1)) {
  164. Vertex w2 = e.to();
  165. if (done.contains(w2)) continue;
  166. if ((weight.get(w1) + e.weight()) < neardist) {
  167. nearest = e.to();
  168. neardist = weight.get(w1) + e.weight();
  169. done2near = e;
  170. }
  171. }
  172. }
  173. // System.out.println("find nearest "+done2near);
  174. // if no more, then we are done
  175. if (nearest == null) break;
  176. // update distance from this node to other nodes
  177. for (Edge e1 : g.outEdge(nearest)) {
  178. Vertex w3 = e1.to();
  179. int wght = e1.weight();
  180. if (weight.get(w3) > (neardist + wght)) {
  181. weight.put(w3, neardist + wght);
  182. }
  183. }
  184. done.add(nearest);
  185. prev.put(nearest,done2near);
  186. weight.put(nearest,neardist);
  187. }
  188. return new HashSet<Edge>(prev.values());
  189. }
  190. //------------------------------------------------------------
  191. //
  192. // IO operations
  193. public static void readGraph(Graph g, String file) {
  194. // read a comma-separated file in the format
  195. // stores file as bidirectional graph
  196. // <vertex> , <vertex> , <weight>
  197. try{
  198. BufferedReader in = new BufferedReader(new FileReader(file));
  199. for(String line=in.readLine(); line!=null; line=in.readLine()) {
  200. if(line.length()==0) continue;
  201. String[] arr = line.split(",");
  202. if(arr.length!=3) throw new RuntimeException("CSV file format error: "+line);
  203. g.insertEdge(arr[0].trim(), arr[1].trim(), Integer.parseInt(arr[2].trim()));
  204. g.insertEdge(arr[1].trim(), arr[0].trim(), Integer.parseInt(arr[2].trim()));
  205. }
  206. in.close();
  207. }catch(IOException e){
  208. throw new RuntimeException(e);
  209. }
  210. }
  211. static void printGraph(Graph g) {
  212. for(Vertex v: sortVertex(g.vertices())) {
  213. System.out.println(v.toString());
  214. for(Edge e:sortEdgesTo(g.outEdge(v)))
  215. System.out.println(" "+e.toString());
  216. }
  217. }
  218. public static void storeStrings(List<String> list,String f){
  219. // store a list of lines as a file
  220. try{
  221. PrintWriter out=new PrintWriter(new FileWriter(f));
  222. for(String s:list){
  223. out.println(s);
  224. }
  225. out.close();
  226. }catch(IOException e){
  227. throw new RuntimeException(e);
  228. }
  229. }
  230. public static ArrayList<String> loadStrings(String f){
  231. // read a file a returns a list of lines
  232. ArrayList<String> list=new ArrayList<>();
  233. try{
  234. BufferedReader in=new BufferedReader(new FileReader(f));
  235. while(true){
  236. String s=in.readLine();
  237. if(s==null)break;
  238. list.add(s);
  239. }
  240. in.close();
  241. }catch(IOException e){
  242. throw new RuntimeException(e);
  243. }
  244. return list;
  245. }
  246. }