Advertisement
Guest User

Untitled

a guest
May 3rd, 2016
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.00 KB | None | 0 0
  1.  
  2. import java.io.BufferedOutputStream;
  3. import java.io.BufferedReader;
  4. import java.io.BufferedWriter;
  5. import java.io.File;
  6. import java.io.FileNotFoundException;
  7. import java.io.FileOutputStream;
  8. import java.io.FileReader;
  9. import java.io.FileWriter;
  10. import java.io.IOException;
  11. import java.io.PrintStream;
  12. import java.util.LinkedList;
  13. import java.util.List;
  14. import java.util.Objects;
  15. import java.util.Set;
  16. import java.util.concurrent.ConcurrentHashMap;
  17. import java.util.concurrent.ConcurrentSkipListSet;
  18. import java.util.concurrent.ForkJoinPool;
  19. import java.util.concurrent.RecursiveAction;
  20. import java.util.concurrent.ThreadLocalRandom;
  21. import java.util.concurrent.atomic.AtomicBoolean;
  22. import java.util.logging.Level;
  23. import java.util.logging.Logger;
  24.  
  25. import org.apache.commons.cli.CommandLine;
  26. import org.apache.commons.cli.CommandLineParser;
  27. import org.apache.commons.cli.DefaultParser;
  28. import org.apache.commons.cli.Options;
  29. import org.apache.commons.cli.ParseException;
  30.  
  31.  
  32. /**
  33. *
  34. * @author Aleksandar
  35. */
  36. public class Graph {
  37.  
  38. /**
  39. * A map containing the node number and a boolean to decide if it is visited.
  40. */
  41. private ConcurrentHashMap<Integer, AtomicBoolean> visited = new ConcurrentHashMap<>();
  42.  
  43. /**
  44. * A map containing a list of neighbors for each node.
  45. */
  46. private ConcurrentHashMap<Integer, List<Integer>> adjacencyList = new ConcurrentHashMap<>();
  47. /**
  48. * A map containing a node number and a node object.
  49. */
  50. private ConcurrentHashMap<Integer,Node> treeNodes = new ConcurrentHashMap<>();
  51.  
  52. public static void main(String[] args) {
  53.  
  54. Options options = new Options();
  55.  
  56. setOptions(options);
  57. CommandLineParser parser = new DefaultParser();
  58. CommandLine cmd = null;
  59. try {
  60. cmd = parser.parse( options, args);
  61. } catch (ParseException e) {
  62. System.exit(-1);
  63. }
  64.  
  65. determinePrintLocation(cmd);
  66.  
  67. PrintStream originalStream = System.out;
  68.  
  69. Graph graph = new Graph();
  70.  
  71. determineGraphCreation(cmd, graph);
  72. doExecution(cmd, graph);
  73. shouldWriteTreeToFile(cmd, graph);
  74.  
  75. }
  76.  
  77. /**
  78. * Determines if the tree information from the program execution should be written to a file.
  79. * @param cmd
  80. * @param graph
  81. */
  82. protected static void shouldWriteTreeToFile(CommandLine cmd, Graph graph) {
  83. if(cmd.hasOption("gf")) {
  84. String outputFileName = cmd.getOptionValue("gf");
  85. graph.writeToFile(outputFileName);
  86. }
  87. }
  88.  
  89. /**
  90. * Determines with how many threads should the algorithm be executed.
  91. * @param cmd
  92. * @param graph
  93. */
  94. protected static void doExecution(CommandLine cmd, Graph graph) {
  95. if(cmd.hasOption("t")) {
  96. String threadCountString = cmd.getOptionValue("t");
  97. Integer threadCount = Integer.valueOf(threadCountString);
  98. graph.execute(threadCount);
  99. } else {
  100. graph.execute(1);
  101. }
  102. }
  103.  
  104. /**
  105. * Determines if the graph should be created from a file or on the go.
  106. * @param cmd
  107. * @param graph
  108. */
  109. protected static void determineGraphCreation(CommandLine cmd, Graph graph) {
  110. if(cmd.hasOption("n")) {
  111. String nodeCountString = cmd.getOptionValue("n", "1");
  112. Integer nodeCount = Integer.valueOf(nodeCountString);
  113. graph.generateGraph(nodeCount);
  114. } else if (cmd.hasOption("i")) {
  115. String fileName = cmd.getOptionValue("i");
  116. graph.constructGraphFromFile(fileName);
  117. }
  118. }
  119.  
  120. /**
  121. * Determines the location of the print file in which the
  122. * thread execution time and data should be written.
  123. * @param cmd
  124. */
  125. protected static void determinePrintLocation(CommandLine cmd) {
  126. if(cmd.hasOption("q")) {
  127. System.setOut(new NullPrintStream());
  128. } else if(cmd.hasOption("o")) {
  129. String fileName = cmd.getOptionValue("o", "output_file.txt");
  130. try {
  131. System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(fileName)), true));
  132. } catch (FileNotFoundException e) {
  133. Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "Failed to create output stream.", e);
  134. }
  135.  
  136. }
  137. }
  138.  
  139. /**
  140. * Sets the command line options.
  141. * @param options
  142. */
  143. protected static void setOptions(Options options) {
  144. options.addOption("n", true, "The number of nodes of the graph.");
  145. options.addOption("i", true, "The input file for the graph.");
  146. options.addOption("o", true, "The output file for the application");
  147. options.addOption("t", true, "The amount of threads to be used");
  148. options.addOption("q", false, "Determine if there should be output");
  149. options.addOption("gf",true, "File to which to write the graph information");
  150. }
  151.  
  152.  
  153. /**
  154. * Executes the parallel DFS.
  155. */
  156. private void execute(int threadCount) {
  157.  
  158. ForkJoinPool pool = new ForkJoinPool(threadCount);
  159. // check each node, because the graph may not be connected
  160. System.out.println("Algorithm execution started with " + threadCount + " threads");
  161. long startTime = System.nanoTime();
  162. for(Integer node : visited.keySet()) {
  163. if(visited.get(node).get()) {
  164. continue;
  165. }
  166. DFS dfs = new DFS(node);
  167. pool.invoke(dfs);
  168. }
  169.  
  170. long endTime = System.nanoTime();
  171. long elapsedTime = endTime - startTime;
  172. System.out.println("Algorithm execution took " + elapsedTime + " nanoseconds");
  173.  
  174. }
  175.  
  176. /**
  177. * Writes the graph data to a file.
  178. * @param fileName
  179. */
  180. public void writeToFile(String fileName) {
  181. File file = new File(fileName);
  182. try(BufferedWriter bwr = new BufferedWriter(new FileWriter(file))) {
  183.  
  184. for(Node node : treeNodes.values()) {
  185. bwr.write("Node number: " + node.getNode());
  186. bwr.newLine();
  187.  
  188. if(node.getParent() != null){
  189. bwr.write("Node parent: " + node.getParent().getNode());
  190. bwr.newLine();
  191. }
  192. }
  193.  
  194. } catch (IOException ex) {
  195. Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "Failed to create output stream for the graph data.", ex);
  196. }
  197.  
  198. }
  199.  
  200. /**
  201. * Generates a graph in memory.
  202. * @param nodeCount
  203. */
  204. private void generateGraph(int nodeCount) {
  205.  
  206. ThreadLocalRandom random = ThreadLocalRandom.current();
  207. visited = new ConcurrentHashMap<>(nodeCount);
  208.  
  209. System.out.println("Started graph creation.");
  210.  
  211. for(int i=0 ; i < nodeCount ; i++) {
  212.  
  213. List<Integer> neighbours = new LinkedList<>();
  214. for(int j=0; j < nodeCount ; j++) {
  215. int choice = random.nextInt(2);
  216. if(choice == 1) {
  217. neighbours.add(j);
  218. }
  219. }
  220.  
  221. adjacencyList.put(i, neighbours);
  222. visited.put(i, new AtomicBoolean(false));
  223. treeNodes.put(i, new Node(i));
  224. }
  225.  
  226. System.out.println("Graph created.");
  227. }
  228.  
  229. /**
  230. * Construct a graph from an adjacency matrix in a file.
  231. * @param fileName
  232. */
  233. public void constructGraphFromFile(String fileName) {
  234.  
  235. System.out.println("Construction of graph from file started");
  236.  
  237. File file = new File(fileName);
  238.  
  239. try(BufferedReader br = new BufferedReader(new FileReader(file))) {
  240.  
  241. String numberLine = br.readLine();
  242. int nodeCount = Integer.valueOf(numberLine);
  243.  
  244. visited = new ConcurrentHashMap<>(nodeCount);
  245. int count = 0;
  246. for(String line; (line = br.readLine()) != null; ) {
  247. String[] data = line.split("\\s+");
  248.  
  249. List<Integer> neighbours = new LinkedList<>();
  250.  
  251. for(int i = 0; i < data.length ; i++) {
  252. if(data[i].equals("1")) {
  253. neighbours.add(i);
  254. }
  255. }
  256.  
  257. adjacencyList.put(count, neighbours);
  258.  
  259. treeNodes.put(count, new Node(count));
  260. visited.put(count, new AtomicBoolean(false));
  261.  
  262. count++;
  263.  
  264. }
  265. } catch (IOException ex) {
  266. Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "Failed to construct graph from file.", ex);
  267. return;
  268. }
  269. System.out.println("Construction of graph from file finished");
  270. }
  271.  
  272. private void constructGraphFile(String fileName, int size) {
  273. System.out.println("Construction of graph file started.");
  274. File file = new File(fileName);
  275. try {
  276. file.createNewFile();
  277. } catch (IOException ex) {
  278. Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "Failed to create file with name: " + fileName, ex);
  279. }
  280. try(BufferedWriter bwr = new BufferedWriter(new FileWriter(file))){
  281. bwr.write(String.valueOf(size));
  282. bwr.newLine();
  283.  
  284. ThreadLocalRandom random = ThreadLocalRandom.current();
  285.  
  286. for(int i=0; i < size; i++) {
  287. StringBuilder builder = new StringBuilder();
  288. for(int j=0; j < size; j++) {
  289. builder.append(random.nextInt(2));
  290. builder.append(" ");
  291. }
  292. String trimed = builder.toString().trim();
  293. bwr.write(trimed);
  294. bwr.newLine();
  295. }
  296.  
  297. } catch (IOException ex) {
  298. Logger.getLogger(Graph.class.getName()).log(Level.SEVERE, "Failed to construct adjecancy matrix file.", ex);
  299. return;
  300. }
  301. System.out.println("Construction of graph file finished.");
  302.  
  303. }
  304.  
  305. /**
  306. * Class implementing {@link RecursiveAction} which does the actual computation.
  307. * @author aleksandar
  308. *
  309. */
  310. private class DFS extends RecursiveAction{
  311.  
  312. int node;
  313.  
  314. public DFS(int node) {
  315. this.node = node;
  316. }
  317.  
  318. @Override
  319. protected void compute() {
  320.  
  321. String threadName = Thread.currentThread().getName();
  322.  
  323. AtomicBoolean isVisited = visited.get(node);
  324. if(isVisited.getAndSet(true)) {
  325. return;
  326. }
  327.  
  328. //System.out.println("Executing thread " + threadName + ". For node " + node);
  329. List<Integer> adjList = adjacencyList.get(node);
  330. Node parent = treeNodes.get(node);
  331.  
  332. for(Integer neighbour : adjList) {
  333.  
  334. Node child = treeNodes.get(neighbour);
  335.  
  336. Integer childNode = child.getNode();
  337. if(visited.get(childNode).get()) {
  338. continue;
  339. }
  340.  
  341. child.setParent(parent);
  342.  
  343. DFS dfs = new DFS(neighbour);
  344. dfs.fork();
  345. }
  346.  
  347. // System.out.println("Thread " + threadName + ". Finished work on node " + node + " and returned to thread pool");
  348. }
  349.  
  350. }
  351.  
  352. /**
  353. * Class representing a node in the graph.
  354. * @author aleksandar
  355. *
  356. */
  357. private class Node {
  358. private Integer node;
  359. private Node parent;
  360.  
  361. public Node(int node) {
  362. this.node = node;
  363. }
  364.  
  365. @Override
  366. public int hashCode() {
  367. int hash = 5;
  368. hash = 79 * hash + Objects.hashCode(this.node);
  369. return hash;
  370. }
  371.  
  372. @Override
  373. public boolean equals(Object obj) {
  374. if (this == obj) {
  375. return true;
  376. }
  377. if (obj == null) {
  378. return false;
  379. }
  380. if (getClass() != obj.getClass()) {
  381. return false;
  382. }
  383. final Node other = (Node) obj;
  384. if (!Objects.equals(this.node, other.node)) {
  385. return false;
  386. }
  387. return true;
  388. }
  389.  
  390. public Integer getNode() {
  391. return node;
  392. }
  393.  
  394. public Node getParent() {
  395. return parent;
  396. }
  397.  
  398. public void setParent(Node parent) {
  399. this.parent = parent;
  400. }
  401.  
  402. }
  403.  
  404. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement