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