PlacementCostMetric.java 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package de.tu_darmstadt.informatik.tk.scopviz.metrics;
  2. import java.io.BufferedReader;
  3. import java.io.File;
  4. import java.io.FileReader;
  5. import java.util.Arrays;
  6. import java.util.LinkedList;
  7. import java.util.stream.Collectors;
  8. import de.tu_darmstadt.informatik.tk.scopviz.debug.Debug;
  9. import de.tu_darmstadt.informatik.tk.scopviz.graphs.MappingGraphManager;
  10. import de.tu_darmstadt.informatik.tk.scopviz.graphs.MyEdge;
  11. import de.tu_darmstadt.informatik.tk.scopviz.graphs.MyGraph;
  12. import de.tu_darmstadt.informatik.tk.scopviz.graphs.MyNode;
  13. import de.tu_darmstadt.informatik.tk.scopviz.main.Main;
  14. import de.tu_darmstadt.informatik.tk.scopviz.metrics.interfaces.ScopvizGraphMetric;
  15. import javafx.stage.FileChooser;
  16. import javafx.util.Pair;
  17. /**
  18. * Class to compute the placement cost Metric. Placement Cost is defined as the
  19. * sum of the costs of individual mapping placements. These Costs are specified
  20. * in operator node - underlay node pairs and are loaded from an external file
  21. * during setup.
  22. *
  23. * @author Jan Enders
  24. * @version 1.0
  25. *
  26. */
  27. public class PlacementCostMetric implements ScopvizGraphMetric {
  28. /**
  29. * The prefix used to mark the line containing all the relevant operator
  30. * node IDs.
  31. */
  32. private static final String OPERATOR_ID_PREFIX = "operatorIDs:";
  33. /**
  34. * The Prefix used to mark the line containing all the relevant underlay
  35. * node IDs.
  36. */
  37. private static final String UNDERLAY_ID_PREFIX = "underlayIDs:";
  38. /** The text to display in case of an error during computation. */
  39. private static final Pair<String, String> ERROR_MESSAGE = new Pair<String, String>("Error",
  40. "ERROR: check Debug logs");
  41. /** The text to display if the Setup has not yet been done. */
  42. private static final Pair<String, String> SETUP_NEEDED = new Pair<String, String>("Setup required!",
  43. "Setup required!");
  44. /** The Cost Matrix. */
  45. private double[][] costs;
  46. /** The operator node IDs specified in the cost data. */
  47. private LinkedList<String> operatorIDs = new LinkedList<String>();
  48. /** The underlay node IDs specified in the cost data. */
  49. private LinkedList<String> underlayIDs = new LinkedList<String>();
  50. /** Whether or not the Setup has been done yet. */
  51. private boolean setupDone = false;
  52. /** Flag for when an error occurs during computation */
  53. private boolean error = false;
  54. @Override
  55. public boolean isSetupRequired() {
  56. return true;
  57. }
  58. @Override
  59. public String getName() {
  60. return "Placement Cost";
  61. }
  62. @Override
  63. public void setup() {
  64. // Pick File from File Chooser
  65. FileChooser fileChooser = new FileChooser();
  66. fileChooser.setTitle("Select Placement Cost Data");
  67. File file = fileChooser.showOpenDialog(Main.getInstance().getPrimaryStage());
  68. if (file != null) {
  69. String fileName = file.getPath();
  70. try {
  71. // Read File Line by Line
  72. BufferedReader reader = new BufferedReader(new FileReader(fileName));
  73. String line;
  74. int lineCounter = 0;
  75. while ((line = reader.readLine()) != null) {
  76. lineCounter = processLine(line, lineCounter);
  77. }
  78. reader.close();
  79. setupDone = true;
  80. } catch (Exception e) {
  81. Debug.out("ERROR while trying to read File!");
  82. error = true;
  83. }
  84. }
  85. }
  86. @Override
  87. public LinkedList<Pair<String, String>> calculate(MyGraph g) {
  88. LinkedList<Pair<String, String>> results = new LinkedList<Pair<String, String>>();
  89. double placementCostSum = 0;
  90. // If an Error occurred, show error message
  91. if (error) {
  92. results.add(ERROR_MESSAGE);
  93. error = false;
  94. }
  95. // If Setup has not yet been successfully done, show error message
  96. if (!setupDone) {
  97. results.add(SETUP_NEEDED);
  98. } else {
  99. LinkedList<MyEdge> mappingEdges = new LinkedList<MyEdge>(g.<MyEdge>getEdgeSet().stream()
  100. .filter(e -> (((Boolean) e.getAttribute(MappingGraphManager.ATTRIBUTE_KEY_MAPPING)) == true))
  101. .collect(Collectors.toList()));
  102. for (MyEdge e : mappingEdges) {
  103. placementCostSum += placementCost(e.getNode0(), e.getNode1());
  104. }
  105. results.add(new Pair<String, String>("Overall Cost", "" + placementCostSum));
  106. }
  107. return results;
  108. }
  109. /**
  110. * Processes a single line of the input Data.
  111. *
  112. * @param line
  113. * The line to process
  114. * @param lineCounter
  115. * The counter of actual lines that has been read so far
  116. * @return the possibly increased line counter
  117. */
  118. private int processLine(String line, int lineCounter) {
  119. // Discard Comments and empty lines
  120. if (line.startsWith("%") || line.equals("")) {
  121. return lineCounter;
  122. }
  123. // Read Operator Node ID list
  124. if (line.startsWith(OPERATOR_ID_PREFIX)) {
  125. operatorIDs = new LinkedList<String>();
  126. String data = line.substring(OPERATOR_ID_PREFIX.length()).trim();
  127. String[] opIDs = data.split(",");
  128. for (String s : opIDs) {
  129. operatorIDs.add(s.trim());
  130. }
  131. // Read Underlay Node ID list
  132. } else if (line.startsWith(UNDERLAY_ID_PREFIX)) {
  133. underlayIDs = new LinkedList<String>();
  134. String data = line.substring(UNDERLAY_ID_PREFIX.length()).trim();
  135. String[] ulIDs = data.split(",");
  136. for (String s : ulIDs) {
  137. underlayIDs.add(s.trim());
  138. }
  139. } else {
  140. // When both lists have been read, create cost array with correct
  141. // size
  142. if (lineCounter == 2) {
  143. costs = new double[operatorIDs.size()][underlayIDs.size()];
  144. }
  145. // Parse comma separated data
  146. int dataRow = lineCounter - 2;
  147. String[] data = line.split(",");
  148. double[] convertedData = Arrays.asList(data).stream().mapToDouble(s -> Double.parseDouble(s)).toArray();
  149. costs[dataRow] = Arrays.copyOf(convertedData, costs[dataRow].length);
  150. }
  151. return lineCounter + 1;
  152. }
  153. /**
  154. * Fethes the placement cost of a specific Coupling of Operator node and
  155. * Underlay Node.
  156. *
  157. * @param operator
  158. * The Operator node
  159. * @param target
  160. * The Underlay node it is mapped to
  161. * @return The placement cost
  162. */
  163. private double placementCost(MyNode operator, MyNode target) {
  164. if (costs == null) {
  165. Debug.out(
  166. "Tried to read Costs from nonexistant Cost Matrix. Please run Setup before trying to Compute the Metric!");
  167. error = true;
  168. return 0;
  169. }
  170. String operatorID = operator.getId().substring(MappingGraphManager.OPERATOR.length()).trim();
  171. String underlayID = target.getId().substring(MappingGraphManager.UNDERLAY.length()).trim();
  172. int x = operatorIDs.indexOf(operatorID);
  173. int y = underlayIDs.indexOf(underlayID);
  174. if (x < 0 || y < 0) {
  175. Debug.out("Either operator node ID " + operatorID + " or underlay node ID " + underlayID
  176. + " do not exist in the cost data!");
  177. error = true;
  178. return 0;
  179. }
  180. return costs[x][y];
  181. }
  182. }