AlibabaSchedulerEvaluatorRun.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. package com.aliyun.tianchi.mgr.evaluate.evaluate.file.evaluator;
  2. import java.io.BufferedReader;
  3. import java.io.ByteArrayInputStream;
  4. import java.io.File;
  5. import java.io.FileInputStream;
  6. import java.io.FileReader;
  7. import java.io.IOException;
  8. import java.io.InputStream;
  9. import java.io.InputStreamReader;
  10. import java.util.ArrayList;
  11. import java.util.HashMap;
  12. import java.util.List;
  13. import java.util.Map;
  14. import org.apache.commons.lang3.tuple.ImmutablePair;
  15. import org.apache.commons.lang3.tuple.Pair;
  16. import com.google.common.base.Charsets;
  17. /**
  18. * Created by mou.sunm on 2018/07/02.
  19. */
  20. public class AlibabaSchedulerEvaluatorRun {
  21. // 参数
  22. public static final double alpha = 10.;
  23. public static final double beta = 0.5;
  24. public static final int T = 98;
  25. public static final int EXEC_LIMIT = 100000;
  26. // 静态数据
  27. private int n; // app数
  28. private int N; // inst数
  29. private int m; // machine数
  30. private int k; // 资源种类
  31. private List<Integer> cpuIter; // T个时刻的cpu资源
  32. private Map<String, Integer> appIndex;
  33. private Map<String, Integer> machineIndex;
  34. private String[] apps;
  35. private String[] machines;
  36. private Map<String, Integer> inst2AppIndex;
  37. private double[][] appResources;//app
  38. private double[][] machineResources;//主机
  39. private Map<Integer, Integer>[] appInterference;//限制条件
  40. // 动态数据
  41. private Map<String, Integer> inst2Machine;
  42. private double[][] machineResourcesUsed;
  43. private Map<Integer, Integer>[] machineHasApp;
  44. protected double evaluate(BufferedReader bufferedReader) throws IOException {
  45. double costs = 0.;
  46. try {
  47. /** 读取执行数据 execs:[(inst_65379,5999), (inst_62243,5998)] */
  48. List<Pair<String, Integer>> execs = new ArrayList<Pair<String, Integer>>();
  49. for (String line = bufferedReader.readLine(); line != null; line = bufferedReader.readLine()) {
  50. String[] pair = line.split(",", -1);
  51. if (pair.length != 2) throw new Exception("Invaild solution file");
  52. if (!inst2AppIndex.containsKey(pair[0]) || !machineIndex.containsKey(pair[1]))
  53. throw new Exception("Invaild solution file");
  54. execs.add(new ImmutablePair(pair[0], machineIndex.get(pair[1])));
  55. }
  56. /** 逐行执行 */
  57. int iter = 0;
  58. for (Pair<String, Integer> exec : execs) {
  59. iter++;
  60. //if (iter > EXEC_LIMIT) {
  61. //System.out.println("超过EXECUTION LIMIT(" + EXEC_LIMIT+"), 执行中断");
  62. //break;
  63. //}
  64. String inst = exec.getLeft();//key:inst_65379
  65. Integer machineIt = exec.getRight();//value:5999
  66. pickInstance(inst); // 先将inst从当前所属的machine删除
  67. String msg = toMachine(inst, machineIt);
  68. if (!msg.equals("success")) {
  69. System.out.println("执行中断于第" + iter + "行: " + msg);
  70. break; // 执行失败立即退出
  71. }
  72. }
  73. /** 计算终态得分 */
  74. // 检查inst是否全部放入machine
  75. for (String inst : inst2AppIndex.keySet())
  76. if (!inst2Machine.containsKey(inst)) throw new Exception("instance未全部分配");
  77. // 检查machine的终态
  78. for (int j = 0; j < m; j++) {
  79. Map<Integer, Integer> hasApp = machineHasApp[j];
  80. if (hasApp.size() == 0) continue;
  81. // 检查互斥条件
  82. for (Integer conditionalApp : hasApp.keySet()) {
  83. if (hasApp.get(conditionalApp) <= 0) throw new Exception("[DEBUG 1]Stupid Judger.");
  84. for (Integer checkApp : appInterference[conditionalApp].keySet()) {
  85. if (hasApp.containsKey(checkApp)) {
  86. if (hasApp.get(checkApp) > appInterference[conditionalApp].get(checkApp))
  87. throw new Exception("终态存在干扰冲突");
  88. }
  89. }
  90. }
  91. // 检查资源限制
  92. for (int i = 0; i < k; i++)
  93. if (dcmp(machineResourcesUsed[j][i] - machineResources[j][i]) > 0)
  94. throw new Exception("终态存在资源过载");
  95. // 技术得分
  96. for (Integer t : cpuIter) {
  97. double usage = machineResourcesUsed[j][t] / machineResources[j][t];
  98. costs += 1. + alpha*(Math.exp(Math.max(0., usage - beta)) - 1.);
  99. }
  100. }
  101. costs /= T;
  102. } catch (Exception e) {
  103. System.out.println(e.getMessage());
  104. //e.printStackTrace();
  105. costs = 1e9;
  106. }
  107. return costs;
  108. }
  109. // 读取数据
  110. protected void init(BufferedReader bufferedReader) throws IOException {
  111. /* Preprocessing: cat *.csv to one file as:
  112. n
  113. app_resources.csv
  114. m
  115. machine_resources.csv
  116. N
  117. instance_deploy.csv
  118. iterference_cnt
  119. app_interference.csv
  120. judge framework
  121. */
  122. /** cpuIter */
  123. cpuIter = new ArrayList<Integer>();//1,2,3....98
  124. for (int i = 0; i < T; i++)
  125. cpuIter.add(i);
  126. /** Read app_resources */
  127. n = Integer.parseInt(bufferedReader.readLine());//9338
  128. apps = new String[n];
  129. for (int i = 0; i < n; i++) {//循环app表每一行
  130. // appId,resources
  131. String line = bufferedReader.readLine();
  132. String[] parts = line.split(",", -1);
  133. List<Double> resources = new ArrayList<Double>();
  134. for (String x : parts[1].split("\\|", -1))//cpu
  135. resources.add(Double.parseDouble(x));
  136. for (String x : parts[2].split("\\|", -1))//mem
  137. resources.add(Double.parseDouble(x));
  138. for (int j = 3; j < parts.length; j++) //disk/P/M/PM
  139. resources.add(Double.parseDouble(parts[j]));
  140. if (i == 0) {
  141. k = resources.size();//200
  142. appIndex = new HashMap<String, Integer>();
  143. appResources = new double[n][k];//9338*200
  144. }
  145. if (k != resources.size())
  146. throw new IOException("[DEBUG 2]Invaild problem");
  147. if (appIndex.containsKey(parts[0]))
  148. throw new IOException("[DEBUG 3]Invaild problem");
  149. appIndex.put(parts[0], i+1);//{app_5269=5268, app_5267=5266, app_6598=6597}
  150. apps[i] = parts[0];//appid [app_1, app_2, app_3, app_4]
  151. for (int j = 0; j < k; j++)
  152. appResources[i][j] = resources.get(j);
  153. }
  154. /** Read machine_resources*/
  155. m = Integer.parseInt(bufferedReader.readLine());//6000
  156. machineResources = new double[m][k];
  157. machineResourcesUsed = new double[m][k];
  158. machineIndex = new HashMap<String, Integer>();//{machine_3791=3790, machine_3792=3791}
  159. machineHasApp = new Map[m];
  160. machines = new String[m];
  161. for (int i = 0; i < m; i++) {
  162. // machineId,resources
  163. String line = bufferedReader.readLine();
  164. String[] parts = line.split(",", -1);
  165. if (machineIndex.containsKey(parts[0]))
  166. throw new IOException("[DEBUG 4]Invaild problem");
  167. machineIndex.put(parts[0], i+1);
  168. machines[i] = parts[0];
  169. machineHasApp[i] = new HashMap<Integer, Integer>();
  170. double cpu = Double.parseDouble(parts[1]);
  171. double mem = Double.parseDouble(parts[2]);
  172. for (int j = 0; j < T; j++) {
  173. machineResources[i][j] = cpu;
  174. machineResources[i][T+j] = mem;
  175. }
  176. for (int j = 3; j < parts.length; j++)
  177. machineResources[i][2*T + j - 3] = Double.parseDouble(parts[j]);
  178. for (int j = 0; j < k; j++)
  179. machineResourcesUsed[i][j] = 0.;
  180. }
  181. /** Read instance_deploy */
  182. N = Integer.parseInt(bufferedReader.readLine());//68219
  183. inst2AppIndex = new HashMap<String, Integer>();
  184. inst2Machine = new HashMap<String, Integer>();
  185. for (int i = 0; i < N; i++) {
  186. String line = bufferedReader.readLine();
  187. String[] parts = line.split(",", -1);
  188. if (inst2AppIndex.containsKey(parts[0]))
  189. throw new IOException("[DEBUG 5]Invaild problem");
  190. if (!appIndex.containsKey(parts[1]))
  191. throw new IOException("[DEBUG 6]Invaild problem");
  192. inst2AppIndex.put(parts[0], appIndex.get(parts[1]));
  193. if (!"".equals(parts[2])) {
  194. if (!machineIndex.containsKey(parts[2]))
  195. throw new IOException("[DEBUG 7]Invaild problem");
  196. toMachine(parts[0], machineIndex.get(parts[2]), false);
  197. }
  198. }
  199. /** Read app_interference */
  200. int icnt = Integer.parseInt(bufferedReader.readLine());//35242
  201. appInterference = new Map[n];
  202. for (int i = 0; i < n; i++)
  203. appInterference[i] = new HashMap<Integer, Integer>();
  204. for (int i = 0; i < icnt; i++) {
  205. String line = bufferedReader.readLine();
  206. String[] parts = line.split(",", -1);
  207. if (!appIndex.containsKey(parts[0]) || !appIndex.containsKey(parts[1]))
  208. throw new IOException("[DEBUG 8]Invaild problem");
  209. int app1 = appIndex.get(parts[0]);
  210. int app2 = appIndex.get(parts[1]);
  211. int limit = Integer.parseInt(parts[2]);
  212. Map<Integer, Integer> inter = appInterference[app1];
  213. if (inter.containsKey(app2))
  214. throw new IOException("[DEBUG 9]Invaild problem");
  215. if (app1 == app2) limit += 1; //self-interference +1 here
  216. inter.put(app2, limit);
  217. }
  218. }
  219. private String toMachine(String inst, int machineIt)
  220. {
  221. return toMachine(inst, machineIt, true);
  222. }
  223. private String toMachine(String inst, int machineIt, boolean doCheck)
  224. {
  225. int appIt = inst2AppIndex.get(inst);
  226. Map<Integer, Integer> hasApp = machineHasApp[machineIt];
  227. if (doCheck) {
  228. // 检查互斥规则
  229. int nowHas = 0;
  230. if (hasApp.containsKey(appIt))
  231. nowHas = hasApp.get(appIt);
  232. for (Integer conditionalApp : hasApp.keySet()) {
  233. if (hasApp.get(conditionalApp) <= 0) continue;
  234. if (!appInterference[conditionalApp].containsKey(appIt)) continue;
  235. if (nowHas + 1 > appInterference[conditionalApp].get(appIt)) {
  236. return "App Interference, inst: " + inst + ", "
  237. + apps[conditionalApp] + " -> " + apps[appIt] + ", "
  238. + (nowHas + 1) + " > " + appInterference[conditionalApp].get(appIt);
  239. }
  240. }
  241. for (Integer checkApp : hasApp.keySet()) {
  242. if (!appInterference[appIt].containsKey(checkApp)) continue;
  243. if (hasApp.get(checkApp) > appInterference[appIt].get(checkApp)) {
  244. return "App Interference, inst: " + inst + ", "
  245. + apps[appIt] + " -> " + apps[checkApp] + ", "
  246. + (nowHas + 1) + " > " + appInterference[appIt].get(checkApp);
  247. }
  248. }
  249. // 检查资源限制
  250. for (int i = 0; i < k; i++)
  251. if (dcmp(machineResourcesUsed[machineIt][i] + appResources[appIt][i] - machineResources[machineIt][i]) > 0)
  252. return "Resource Limit: inst: " + inst + ", "
  253. + "machine: " + machines[machineIt] + ", app: " + apps[appIt] + ", resIter: " + i + ", "
  254. + machineResourcesUsed[machineIt][i] + " + " + appResources[appIt][i] + " > " + machineResources[machineIt][i];
  255. }
  256. // 将inst放入新的machine
  257. inst2Machine.put(inst, machineIt);
  258. if (!hasApp.containsKey(appIt))
  259. hasApp.put(appIt, 0);
  260. hasApp.put(appIt, hasApp.get(appIt) + 1);
  261. for (int i = 0; i < k; i++)
  262. machineResourcesUsed[machineIt][i] += appResources[appIt][i];
  263. return "success";
  264. }
  265. private void pickInstance(String inst)
  266. {
  267. if (!inst2Machine.containsKey(inst)) return;
  268. int appIt = inst2AppIndex.get(inst);
  269. int fromMachine = inst2Machine.get(inst);
  270. // 更新machineHasApp
  271. Map<Integer, Integer> fromHasApp = machineHasApp[fromMachine];
  272. fromHasApp.put(appIt, fromHasApp.get(appIt) - 1);
  273. if (fromHasApp.get(appIt) <= 0)
  274. fromHasApp.remove(appIt);
  275. // 更新machineResourcesUsed
  276. for (int i = 0; i < k; i++)
  277. machineResourcesUsed[fromMachine][i] -= appResources[appIt][i];
  278. // 更新inst2Machine
  279. inst2Machine.remove(inst);
  280. }
  281. private int dcmp(double x) {
  282. if (Math.abs(x) < 1e-9) return 0;
  283. return x < 0. ? -1 : 1;
  284. }
  285. public static void main(String[] args) throws Exception {
  286. if (args.length != 5 && args.length != 2){
  287. System.err.println("传入参数有误,使用方式为:java -cp xxx.jar com.aliyun.tianchi.mgr.evaluate.evaluate.file.evaluator.AlibabaSchedulerEvaluatorRun app_resources.csv machine_resources.csv instance_deploy.csv app_interference.csv result.csv");
  288. return;
  289. }
  290. InputStream problem;
  291. InputStream result;
  292. // app_resources.csv
  293. // machine_resources.csv
  294. // instance_deploy.csv
  295. // app_interference.csv
  296. // result.csv
  297. if (args.length == 5) {
  298. // 将赛题拼成评测数据
  299. StringBuffer sb = new StringBuffer();
  300. for (int i = 0; i < 4; i++) {
  301. List<String> lines = new ArrayList<String>();
  302. BufferedReader bs = new BufferedReader(new FileReader(new File(args[i])));
  303. for (String line = bs.readLine(); line != null; line = bs.readLine())
  304. lines.add(line);
  305. sb.append(""+lines.size()).append("\n");
  306. for (String line : lines)
  307. sb.append(line).append("\n");
  308. }
  309. String alldata = sb.toString();
  310. problem = new ByteArrayInputStream(alldata.getBytes());
  311. result = new FileInputStream(args[4]);
  312. }
  313. else {
  314. problem = new FileInputStream(args[0]);
  315. result = new FileInputStream(args[1]);
  316. }
  317. // 评测
  318. AlibabaSchedulerEvaluatorRun evaluator = new AlibabaSchedulerEvaluatorRun();
  319. evaluator.init(new BufferedReader(new InputStreamReader(problem, Charsets.UTF_8)));
  320. double score = evaluator.evaluate(new BufferedReader(new InputStreamReader(result, Charsets.UTF_8)));
  321. System.out.println("选手所得分数为:" + score);
  322. }
  323. }