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