Guest User

Untitled

a guest
Jan 23rd, 2018
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.88 KB | None | 0 0
  1. import java.util.Scanner;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.Stack;
  5.  
  6. import java.io.File;
  7. import java.io.FileNotFoundException;
  8. import java.io.IOException;
  9.  
  10.  
  11.  
  12. class Oblig2V2 {
  13.    
  14.    
  15.     private static String   filename = "";
  16.     private static Scanner  sc;
  17.     private static Graph    graph;
  18.     private static int      cnt = 0;
  19.    
  20.    
  21.     public static void main (String [] args) throws IOException  {
  22.         if (args != null) {
  23.             if (args[0] != null)   
  24.                 filename = args[0];
  25.             if (!filename.equals("")) {
  26.                 try {
  27.                     // Create a scanner-instance based on the file specified:
  28.                     sc = new Scanner(new File(filename));
  29.                    
  30.                     // Get the number of vertices:
  31.                     cnt = Integer.parseInt(sc.next()); 
  32.  
  33.                     // Line feed:
  34.                     sc.nextLine();
  35.                     sc.nextLine();
  36.                    
  37.                     // Holds on to the vertices indegrees, where the KEY = VERTEX ID, and the VALUE = VERTEX IDS OF OUTDEGREES.
  38.                     HashMap<Integer, ArrayList<Integer>> edgesOverview = new HashMap<Integer, ArrayList<Integer>>();
  39.                    
  40.                     if (cnt > 0) {
  41.                         // Create a new graph:
  42.                         graph = new Graph(cnt);
  43.  
  44.  
  45.                         while (sc.hasNextLine()) {
  46.                             // Get vertex attributes:
  47.                             String [] line = sc.nextLine().split("[\t ]+");
  48.                            
  49.                             // If-statement to make sure the file corresponds to the input requirements.
  50.                             if (line.length < 4) {
  51.                                 break;
  52.                             }
  53.                            
  54.                             graph.addVertex(Integer.parseInt(line[0]), line[1], Integer.parseInt(line[2]), Integer.parseInt(line[3]));
  55.                        
  56.                             // Add the edge(s) to the graph:
  57.                             int newEdge = Integer.parseInt(line[4]);
  58.                            
  59.                             // For all edges:
  60.                             for (int i=4; newEdge > 0 && i < line.length; i++) {
  61.                                 // If startnode already exists in edgesOverview
  62.                                 if (edgesOverview.get(newEdge) != null) {
  63.                                     // Pull out nodeList, add the node, and put back into hashmap
  64.                                     ArrayList<Integer> nodeList = edgesOverview.get(newEdge);
  65.                                     nodeList.add(Integer.parseInt(line[0]));
  66.                                     edgesOverview.put(newEdge, nodeList);
  67.                                 } else {
  68.                                     // Create a new nodeList, add the node, and put into hashmap
  69.                                     ArrayList<Integer> nodeList = new ArrayList<Integer>();
  70.                                     nodeList.add(Integer.parseInt(line[0]));
  71.                                     edgesOverview.put(newEdge, nodeList);
  72.                                 }
  73.                                 // Get the next edge-ID:
  74.                                 newEdge = Integer.parseInt(line[i+1]);
  75.                             }
  76.                         }
  77.                        
  78.                         // Assign edges to all nodes:
  79.                         graph.setEdges(edgesOverview);
  80.                     }          
  81.                    
  82.                     // Check to see if the graph is acyclic.
  83.                     graph.topSort(edgesOverview);
  84.                    
  85.                 } catch (FileNotFoundException e) {
  86.                     System.out.println("File was not found.");
  87.                 }
  88.             } else {
  89.                 System.out.println("Vertex counter has to be a positive integer.");
  90.             }
  91.         }
  92.     }
  93. }
  94.  
  95. class Graph {
  96.  
  97.     // Contains the graph data structure.
  98.     protected HashMap<Integer, Vertex> graph;
  99.    
  100.     // Contains the number of vertices in the graph.
  101.     protected int numVertex;
  102.  
  103.     // Binary Heap storing vertices after topological sorting.
  104.     BinaryHeap heap;
  105.  
  106.     /**
  107.     * Default constructor
  108.     * @param numVertex      the number of vertices specified by the input file
  109.     */
  110.     public Graph (int numVertex) {
  111.         graph = new HashMap<Integer, Vertex>();
  112.         this.numVertex = numVertex;
  113.         heap = new BinaryHeap(numVertex);
  114.     }
  115.  
  116.     /**
  117.     * Adds a new Vertex instace to the graph.
  118.     * @param id id of vertex
  119.     * @param name   name of vertex
  120.     * @param est    estimated time of this vertex
  121.     * @param mp manpower required for this vertex      
  122.     */
  123.     public void addVertex(int id, String name, int est, int mp) {
  124.         graph.put(id, new Vertex(id, name, est, mp));
  125.     }
  126.  
  127.     /**
  128.     * Adds all edges in the graph based on input file
  129.     * @param edges      holds overview of all edges, where key identifies out-node, and value identifies a collection of in-nodes.
  130.     */
  131.     public void setEdges(HashMap<Integer, ArrayList<Integer>> edges) {
  132.         for ( Integer vtx_key : edges.keySet() ) {
  133.             for ( Integer edgesTo : edges.get(vtx_key) ) { 
  134.                 graph.get(vtx_key).addEdge(graph.get(edgesTo));
  135.             }
  136.         }
  137.     }
  138.    
  139.    
  140.     /**
  141.      * Topological search linear-time complexity function to ensure graph is acyclic from the beginning.
  142.      * @see findVertexWithIndegreeZero()
  143.      */
  144.     public void topSort(HashMap<Integer, ArrayList<Integer>> edgesOverview) {
  145.         Stack<Vertex> queue = new Stack<Vertex>();
  146.         int counter = 0;
  147.         findVertexWithIndegreeZero(queue);
  148.         System.out.println("Topological sort successfull! Graph was acyclic.");
  149.        
  150.         while (!queue.isEmpty()) {
  151.             Vertex v = queue.pop();
  152.             v.topNum = ++counter;
  153.             v.findEarliestStart();
  154.             heap.insert(v);
  155.            
  156.             for (Vertex w : v.getEdges()) {
  157.                 w.decrementIndegree(); 
  158.                 if (w.getIndegree() <= 0) {
  159.                     w.increaseCost(v.getCost());
  160.                     queue.add(w);
  161.                 }
  162.             }
  163.         }
  164.         // Resets the vertices back to original indegree build-up
  165.         setEdges(edgesOverview);
  166.        
  167.         // Prints the process
  168.         heap.printprocess();
  169.     }
  170.    
  171.     /**
  172.      * Finds all vertices with 0 indegree (no dependancies). Will end program if a cycle is found between 2 vertices.
  173.      * @param   queue   the queue to insert 0-indegree vertices
  174.      * @see     Vertex.isCyclic()
  175.      */
  176.     public void findVertexWithIndegreeZero(Stack<Vertex> queue) {
  177.         for ( Integer vKey : graph.keySet() ) {
  178.             // Will end program if the vertex is found to be cyclic.
  179.             graph.get(vKey).isCyclic();
  180.             if (graph.get(vKey).getIndegree() <= 0)
  181.                 queue.push(graph.get(vKey));
  182.         }
  183.     }
  184.    
  185.    
  186.     private class BinaryHeap {
  187.        
  188.         private int size;
  189.         private Vertex array [];
  190.         private int numElements;
  191.        
  192.         public BinaryHeap (int size) {
  193.             this.size = size;
  194.             array = new Vertex[size];
  195.             numElements = 0;
  196.         }
  197.        
  198.         public void insert(Vertex v) {
  199.             if (numElements == array.length-1)
  200.                 enlargeArray( array.length * 2 + 1 );
  201.            
  202.             int hole = ++numElements;
  203.             for ( ; hole > 1 && v.compareTo(array[hole/2]) < 0; hole /= 2)
  204.                 array[hole] = array[hole/2];
  205.            
  206.             array[hole] = v;
  207.         }
  208.        
  209.         public Vertex deleteMin() {
  210.             if (numElements == 0)
  211.                 return null;
  212.            
  213.             Vertex minItem = findMin();
  214.             array[1] = array[numElements--];
  215.             percolateDown(1);
  216.            
  217.             return minItem;
  218.         }
  219.        
  220.         public Vertex findMin() {
  221.             return array[1];
  222.         }
  223.        
  224.         private void percolateDown(int hole) {
  225.             int child;
  226.             Vertex tmp = array[hole];
  227.            
  228.             for ( ; hole * 2 <= numElements; hole = child) {
  229.                 child = hole * 2;
  230.                 if (child != numElements && array[child+1].compareTo(array[child]) < 0)
  231.                     child++;
  232.                 if (array[child].compareTo(tmp) < 0)
  233.                     array[hole] = array[child];
  234.                 else
  235.                     break;
  236.             }
  237.             array[hole] = tmp;
  238.         }
  239.        
  240.         public void enlargeArray(int newsize) {
  241.             Vertex [] tmp_array = new Vertex[newsize];
  242.            
  243.             for (int i=0; i<array.length; i++) {
  244.                 tmp_array[i] = array[i];
  245.             }
  246.            
  247.             array = tmp_array;
  248.         }
  249.        
  250.         public void printprocess() {
  251.             int totalCost = 0;
  252.             int timeCounter = 0;
  253.            
  254.             // Stores all vertices that already has been started.
  255.             ArrayList<Vertex> hasBeenStarted = new ArrayList<Vertex>();
  256.            
  257.             // Stores all vertices that are to be started at a later time.
  258.             Stack<Vertex> toBeStarted = new Stack<Vertex>();
  259.            
  260.             // Finds all vertices with indegree zero from priority heap.
  261.             Vertex vtx = deleteMin();
  262.             toBeStarted.add(vtx);
  263.             while (findMin().getIndegree() == 0) {
  264.                 toBeStarted.add(deleteMin());  
  265.             }
  266.                    
  267.             // Outputs the process.
  268.             while (!toBeStarted.isEmpty() || !hasBeenStarted.isEmpty()) {
  269.                 System.out.println("TIME: " + timeCounter);
  270.                
  271.                 // Prompts the next tasks at this TIME.
  272.                 while (toBeStarted.size() != 0 && timeCounter == toBeStarted.peek().earliestStart) {
  273.                     vtx = toBeStarted.pop();
  274.                     hasBeenStarted.add(vtx);
  275.                     System.out.println("\t\tStarting: " + vtx.getId() + ".");  
  276.                 }
  277.                
  278.            
  279.                 for (Vertex v : hasBeenStarted) {
  280.                     if (timeCounter == v.cost) {
  281.                         System.out.println("\t\tFinished: " + v.getId() + ".");
  282.                         hasBeenStarted.remove(v);
  283.                     }
  284.                 }
  285.            
  286.                
  287.                 vtx = deleteMin();
  288.                 int newNodeStart = vtx.cost - vtx.estimate;
  289.                 toBeStarted.push(vtx);
  290.                
  291.                 // Finds out whether any of the already started tasks is finished, if so, output info and remove from the list.
  292.                 for (Vertex v : hasBeenStarted) {
  293.                     if ((timeCounter + v.estimate) < newNodeStart)
  294.                         timeCounter = timeCounter + v.estimate;
  295.                     else
  296.                         timeCounter = newNodeStart;
  297.                 }
  298.             }
  299.             System.out.println("Total cost was: " + totalCost);
  300.         }
  301.     }
  302.  
  303.     private class Vertex {
  304.  
  305.         public int                      topNum;
  306.         public int                      dist;
  307.  
  308.         private int                     id, estimate, manpower;
  309.         private String                  name;
  310.         int                             earliestStart, latestStart, indegree, outdegree;
  311.         ArrayList<Vertex>               pointsTo, isPointedAt;
  312.         private int                     cost;
  313.  
  314.  
  315.         public Vertex(int id, String name, int estimate, int manpower) {
  316.             this.id = id;
  317.             this.name = name;
  318.             this.estimate = estimate;
  319.             this.manpower = manpower;
  320.             cost = estimate;
  321.             pointsTo = new ArrayList<Vertex>();
  322.             isPointedAt = new ArrayList<Vertex>();
  323.         }
  324.        
  325.        
  326.         public int getId() {
  327.             return id;
  328.         }
  329.  
  330.         public int getIndegree() {
  331.             return indegree;
  332.         }
  333.        
  334.         public int getEst() {
  335.             return estimate;
  336.         }
  337.        
  338.         public void incrementIndegree() {
  339.             indegree += 1;
  340.         }
  341.  
  342.         public void decrementIndegree() {
  343.             indegree--;
  344.         }
  345.        
  346.         public int getOutdegree() {
  347.             return outdegree;
  348.         }
  349.        
  350.         public void incrementOutdegree() {
  351.             outdegree++;
  352.         }
  353.        
  354.         public void decrementOutdegree() {
  355.             outdegree--;
  356.         }
  357.        
  358.         public void increaseCost(int num) {
  359.             cost += num;
  360.         }
  361.        
  362.         public int getCost() {
  363.             return cost;
  364.         }
  365.        
  366.         public void addEdge(Vertex w) {
  367.             pointsTo.add(w);
  368.             incrementOutdegree();
  369.             w.incrementIndegree();
  370.             w.isPointedAt.add(this);
  371.         }
  372.        
  373.         public void findEarliestStart() {
  374.             for ( Vertex v : pointsTo ) {
  375.                 v.earliestStart = cost;
  376.             }
  377.         }
  378.        
  379.         public void findLatestStart() {
  380.             int maxEarliestStart = 0;
  381.             for ( Vertex v : pointsTo ) {
  382.                 if (v.earliestStart > maxEarliestStart)
  383.                     maxEarliestStart = v.earliestStart;
  384.             }
  385.             latestStart = (maxEarliestStart - estimate) <= earliestStart ? earliestStart : (maxEarliestStart - estimate);
  386.            
  387.             for ( Vertex v : pointsTo ) {
  388.                 v.findLatestStart();
  389.             }
  390.         }
  391.        
  392.         public int getSlack() {
  393.             return latestStart - earliestStart;
  394.         }
  395.        
  396.         public ArrayList<Vertex> getEdges() {
  397.             return pointsTo;
  398.         }
  399.        
  400.         public boolean pointsAt(Vertex w) {
  401.             return pointsTo.contains(w);
  402.         }
  403.        
  404.         /**
  405.          * Checks to see if the vertex is part of a cyclic path; if this is the case, the program will be terminated.
  406.          */
  407.         public void isCyclic() {
  408.             for ( Vertex w : pointsTo) {
  409.                 if (this.pointsAt(w) && w.pointsAt(this)) {
  410.                     System.out.println("ERROR: Graph is cyclic! Occurs between " + w.getId() + " and " + getId() + ".");
  411.                     System.exit(0);
  412.                 }
  413.             }
  414.         }
  415.        
  416.         public int compareTo(Vertex v) {
  417.             if (v.getCost() > cost)
  418.                 return -1;
  419.             else if (v.getCost() < cost)
  420.                 return 1;
  421.             return 0;
  422.         }
  423.     }
  424. }
Add Comment
Please, Sign In to add comment