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