Main4.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. package me.yoqi.servermanager;
  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.HashSet;
  13. import java.util.List;
  14. import java.util.Map;
  15. import java.util.Set;
  16. import org.apache.commons.lang3.tuple.ImmutablePair;
  17. import org.apache.commons.lang3.tuple.Pair;
  18. import com.aliyun.tianchi.mgr.evaluate.evaluate.file.evaluator.AlibabaSchedulerEvaluatorRun;
  19. import com.google.common.base.Charsets;
  20. public class Main4 {
  21. // 参数
  22. public static final double beta = 0.5;
  23. public static final int T2 = 98 * 15;
  24. public static final int EXEC_LIMIT = 3;
  25. private List<Problem> problems;
  26. public static void main(String[] args) throws IOException {
  27. InputStream problemIS;
  28. // 将赛题拼成评测数据
  29. StringBuffer sb = new StringBuffer();
  30. for (int i = 0; i < 5; i++) {
  31. List<String> lines = new ArrayList<String>();
  32. BufferedReader bs = new BufferedReader(new FileReader(new File(args[i])));
  33. for (String line = bs.readLine(); line != null; line = bs.readLine())
  34. lines.add(line);
  35. bs.close();
  36. sb.append("" + lines.size());
  37. for (String line : lines)
  38. sb.append("\n").append(line);
  39. if (i != 4)
  40. sb.append("\n");
  41. }
  42. String alldata = sb.toString();
  43. problemIS = new ByteArrayInputStream(alldata.getBytes());
  44. // 评测
  45. Main4 evaluator = new Main4();
  46. evaluator.init(new BufferedReader(new InputStreamReader(problemIS, Charsets.UTF_8)));
  47. List<Problem> problems=new ArrayList<Problem>();
  48. problems.get(0).run(null);
  49. }
  50. // 读取数据
  51. protected void init(BufferedReader bufferedReader) throws IOException {
  52. String firstLine = bufferedReader.readLine();
  53. Problem prob = new Problem();
  54. prob.init(firstLine, bufferedReader);
  55. problems.add(prob);
  56. System.out.println("init 成功");
  57. }
  58. class Problem {
  59. // 静态数据
  60. private int n; // app数
  61. private int N; // inst数
  62. private int m; // machine数
  63. private int k = 2 * T2 + 4; // 资源种类
  64. private Map<String, Integer> appIndex;
  65. private Map<String, Integer> machineIndex;
  66. private String[] apps;
  67. private String[] machines;
  68. private Map<String, Integer> inst2AppIndex;
  69. private double[][] appResources;
  70. private double[][] machineResources;
  71. private Map<Integer, Integer>[] appInterference;
  72. private String[] jobs;
  73. private int jobN;
  74. private Map<String, Integer> jobIndex;
  75. private double[][] jobResources;
  76. private int[] jobR;
  77. private int[] jobV;
  78. private Set<Integer>[] jobFa;
  79. // 动态数据
  80. private Map<String, Integer> inst2Machine;
  81. private double[][] machineResourcesUsed;
  82. private Map<Integer, Integer>[] machineHasApp;
  83. public void init(String firstLine, BufferedReader bufferedReader) throws IOException {
  84. /** Read app_resources */
  85. n = Integer.parseInt(firstLine);// 9338
  86. apps = new String[n];
  87. appIndex = new HashMap<String, Integer>();
  88. appResources = new double[n][k];
  89. for (int i = 0; i < n; i++) {
  90. // appId,resources
  91. String line = bufferedReader.readLine();
  92. String[] parts = line.split(",", -1);
  93. List<Double> resources = new ArrayList<Double>();
  94. for (String x : parts[1].split("\\|", -1)) {
  95. double cpu = Double.parseDouble(x);
  96. for (int tt = 0; tt < 15; tt++)
  97. resources.add(cpu);
  98. }
  99. for (String x : parts[2].split("\\|", -1)) {
  100. double mem = Double.parseDouble(x);
  101. for (int tt = 0; tt < 15; tt++)
  102. resources.add(mem);
  103. }
  104. for (int j = 3; j < parts.length; j++)
  105. resources.add(Double.parseDouble(parts[j]));
  106. if (k != resources.size())
  107. throw new IOException("[DEBUG 2]Invaild problem: " + k + ", " + resources.size());
  108. if (appIndex.containsKey(parts[0]))
  109. throw new IOException("[DEBUG 3]Invaild problem");
  110. appIndex.put(parts[0], i);
  111. apps[i] = parts[0];
  112. for (int j = 0; j < k; j++)
  113. appResources[i][j] = resources.get(j);
  114. }
  115. /** Read machine_resources */
  116. m = Integer.parseInt(bufferedReader.readLine());// 8000
  117. machineResources = new double[m][k];
  118. machineResourcesUsed = new double[m][k];
  119. machineIndex = new HashMap<String, Integer>();
  120. machineHasApp = new Map[m];
  121. machines = new String[m];
  122. for (int i = 0; i < m; i++) {
  123. // machineId,resources
  124. String line = bufferedReader.readLine();
  125. String[] parts = line.split(",", -1);
  126. if (machineIndex.containsKey(parts[0]))
  127. throw new IOException("[DEBUG 4]Invaild problem");
  128. machineIndex.put(parts[0], i);
  129. machines[i] = parts[0];
  130. machineHasApp[i] = new HashMap<Integer, Integer>();
  131. double cpu = Double.parseDouble(parts[1]);
  132. double mem = Double.parseDouble(parts[2]);
  133. for (int j = 0; j < T2; j++) {
  134. machineResources[i][j] = cpu;
  135. machineResources[i][T2 + j] = mem;
  136. }
  137. for (int j = 3; j < parts.length; j++)
  138. machineResources[i][2 * T2 + j - 3] = Double.parseDouble(parts[j]);
  139. for (int j = 0; j < k; j++)
  140. machineResourcesUsed[i][j] = 0.;
  141. }
  142. /** Read instance_deploy */
  143. N = Integer.parseInt(bufferedReader.readLine());
  144. inst2AppIndex = new HashMap<String, Integer>();
  145. inst2Machine = new HashMap<String, Integer>();
  146. for (int i = 0; i < N; i++) {
  147. String line = bufferedReader.readLine();
  148. String[] parts = line.split(",", -1);
  149. if (inst2AppIndex.containsKey(parts[0]))
  150. throw new IOException("[DEBUG 5]Invaild problem");
  151. if (!appIndex.containsKey(parts[1]))
  152. throw new IOException("[DEBUG 6]Invaild problem");
  153. inst2AppIndex.put(parts[0], appIndex.get(parts[1]));
  154. if (!"".equals(parts[2])) {
  155. if (!machineIndex.containsKey(parts[2]))
  156. throw new IOException("[DEBUG 7]Invaild problem");
  157. toMachine(parts[0], machineIndex.get(parts[2]), false);
  158. }
  159. }
  160. /** Read app_interference */
  161. int icnt = Integer.parseInt(bufferedReader.readLine());
  162. appInterference = new Map[n];
  163. for (int i = 0; i < n; i++)
  164. appInterference[i] = new HashMap<Integer, Integer>();
  165. for (int i = 0; i < icnt; i++) {
  166. String line = bufferedReader.readLine();
  167. String[] parts = line.split(",", -1);
  168. if (!appIndex.containsKey(parts[0]) || !appIndex.containsKey(parts[1]))
  169. throw new IOException("[DEBUG 8]Invaild problem");
  170. int app1 = appIndex.get(parts[0]);
  171. int app2 = appIndex.get(parts[1]);
  172. int limit = Integer.parseInt(parts[2]);
  173. Map<Integer, Integer> inter = appInterference[app1];
  174. if (inter.containsKey(app2))
  175. throw new IOException("[DEBUG 9]Invaild problem");
  176. if (app1 == app2)
  177. limit += 1; // self-interference +1 here
  178. inter.put(app2, limit);
  179. }
  180. /** Read job_info */
  181. jobN = Integer.parseInt(bufferedReader.readLine());
  182. jobs = new String[jobN];
  183. jobIndex = new HashMap<String, Integer>();
  184. jobResources = new double[jobN][2];
  185. jobV = new int[jobN];
  186. jobR = new int[jobN];
  187. jobFa = new Set[jobN];
  188. Set<String>[] tFa = new Set[jobN];
  189. for (int i = 0; i < jobN; i++) {
  190. tFa[i] = new HashSet<String>();
  191. String line = bufferedReader.readLine();
  192. String[] parts = line.split(",", -1);
  193. if (jobIndex.containsKey(parts[0]))
  194. throw new IOException("[DEBUG 10]Invaild problem");
  195. jobIndex.put(parts[0], i);
  196. jobs[i] = parts[0];
  197. jobResources[i][0] = Double.parseDouble(parts[1]);
  198. jobResources[i][1] = Double.parseDouble(parts[2]);
  199. jobV[i] = Integer.parseInt(parts[3]);
  200. jobR[i] = Integer.parseInt(parts[4]);
  201. if (jobV[i] <= 0 || jobR[i] <= 0)
  202. throw new IOException("[DEBUG 10.1]Invaild problem");
  203. for (int it = 5; it < parts.length; it++)
  204. tFa[i].add(parts[it]);
  205. }
  206. for (int i = 0; i < jobN; i++) {
  207. jobFa[i] = new HashSet<Integer>();
  208. for (String job : tFa[i]) {
  209. if (!jobIndex.containsKey(job))
  210. continue;
  211. jobFa[i].add(jobIndex.get(job));
  212. }
  213. }
  214. }
  215. public double run(BufferedReader bufferedReader) throws IOException {
  216. double costs = 0.;
  217. try {
  218. /** 读取执行数据 */
  219. List<Pair<String, Integer>>[] execs = new List[EXEC_LIMIT + 1];
  220. for (int i = 1; i <= EXEC_LIMIT; i++)// 3
  221. execs[i] = new ArrayList<Pair<String, Integer>>();
  222. List<Pair<Integer, Integer>> jobExec = new ArrayList<Pair<Integer, Integer>>();
  223. List<Pair<Integer, Integer>> jobExecDetail = new ArrayList<Pair<Integer, Integer>>();
  224. boolean readFail = false;
  225. boolean jobExecStart = false;
  226. for (String line = bufferedReader.readLine(); line != null
  227. && !line.equals("#"); line = bufferedReader.readLine()) {
  228. String[] pair = line.split(",", -1);
  229. if ((pair.length != 3 && pair.length != 4) || (pair.length == 3 && jobExecStart)) {
  230. System.out.println("Read failed: " + line);
  231. readFail = true;
  232. continue;
  233. }
  234. if (pair.length == 3) {
  235. int stage = Integer.parseInt(pair[0]);
  236. if (stage < 1 || stage > EXEC_LIMIT || !inst2AppIndex.containsKey(pair[1])
  237. || !machineIndex.containsKey(pair[2])) {
  238. System.out.println("" + (stage < 1) + ", " + (stage > EXEC_LIMIT) + ", "
  239. + (!inst2AppIndex.containsKey(pair[1])) + ", "
  240. + (!machineIndex.containsKey(pair[2])));
  241. readFail = true;
  242. continue;
  243. }
  244. execs[stage].add(new ImmutablePair(pair[1], machineIndex.get(pair[2])));
  245. } else {
  246. jobExecStart = true;
  247. if (!jobIndex.containsKey(pair[0]) || !machineIndex.containsKey(pair[1])) {
  248. System.out.println("" + (!jobIndex.containsKey(pair[0])) + ", "
  249. + (!machineIndex.containsKey(pair[1])));
  250. readFail = true;
  251. continue;
  252. }
  253. jobExec.add(new ImmutablePair(jobIndex.get(pair[0]), machineIndex.get(pair[1])));
  254. jobExecDetail.add(new ImmutablePair(Integer.parseInt(pair[2]), Integer.parseInt(pair[3])));
  255. }
  256. }
  257. if (readFail)
  258. throw new Exception("Invaild solution file");
  259. /** app exec */
  260. for (int stage = 1; stage <= EXEC_LIMIT; stage++) {
  261. /** 记录pickFrom */
  262. Map<String, Integer> pickFrom = new HashMap<String, Integer>();
  263. for (Pair<String, Integer> exec : execs[stage]) {
  264. String inst = exec.getLeft();
  265. if (!inst2Machine.containsKey(inst))
  266. continue;
  267. int fromMachine = inst2Machine.get(inst);
  268. if (pickFrom.containsKey(inst))
  269. throw new Exception("duplicate instance: " + inst);
  270. pickFrom.put(inst, fromMachine);
  271. }
  272. /** 执行 */
  273. for (Pair<String, Integer> exec : execs[stage]) {
  274. String inst = exec.getLeft();
  275. Integer machineIt = exec.getRight();
  276. String msg = toMachine(inst, machineIt);
  277. if (!msg.equals("success"))
  278. throw new Exception("执行失败, inst: " + inst + ", stage: " + stage + ", msg: " + msg);
  279. }
  280. /** 清理 */
  281. for (String inst : pickFrom.keySet()) {
  282. int machineIt = pickFrom.get(inst);
  283. pickInstance(inst, machineIt);
  284. }
  285. }
  286. /** job exec */
  287. int[] jobAsigned = new int[jobN];
  288. int[] jobFirstStart = new int[jobN];
  289. int[] jobLastEnd = new int[jobN];
  290. Set<Integer> hasJob = new HashSet<Integer>();
  291. for (int i = 0; i < jobN; i++) {
  292. jobAsigned[i] = 0;
  293. jobFirstStart[i] = T2;
  294. jobLastEnd[i] = -1;
  295. }
  296. for (int it = 0; it < jobExec.size(); it++) {
  297. int job = jobExec.get(it).getLeft();
  298. int machineIt = jobExec.get(it).getRight();
  299. int start = jobExecDetail.get(it).getLeft();
  300. int cnt = jobExecDetail.get(it).getRight();
  301. int end = start + jobR[job] - 1;
  302. if (end >= T2 || start < 0)
  303. throw new Exception("job TLE, job:" + jobs[job] + ", start:" + start);
  304. if (cnt <= 0)
  305. throw new Exception("job assignment <= 0");
  306. hasJob.add(machineIt);
  307. jobAsigned[job] += cnt;
  308. jobFirstStart[job] = Math.min(jobFirstStart[job], start);
  309. jobLastEnd[job] = Math.max(jobLastEnd[job], end);
  310. for (int i = start; i <= end; i++) {
  311. machineResourcesUsed[machineIt][i] += jobResources[job][0];
  312. machineResourcesUsed[machineIt][T2 + i] += jobResources[job][1];
  313. }
  314. }
  315. /** 计算终态得分 */
  316. // 检查inst是否全部放入machine
  317. for (String inst : inst2AppIndex.keySet())
  318. if (!inst2Machine.containsKey(inst))
  319. throw new Exception("instance未全部分配, " + inst);
  320. // 检查job是否全部放入machine
  321. for (int job = 0; job < jobN; job++)
  322. if (jobAsigned[job] != jobV[job])
  323. throw new Exception("job未全部分配, " + jobs[job]);
  324. // 检查job是否满足DAG
  325. for (int job = 0; job < jobN; job++)
  326. for (Integer fa : jobFa[job])
  327. if (jobFirstStart[job] <= jobLastEnd[fa])
  328. throw new Exception("DAG broken: " + jobs[fa] + ":" + jobLastEnd[fa] + " -> " + jobs[job]
  329. + ":" + jobFirstStart[job]);
  330. // 检查machine的终态
  331. for (int j = 0; j < m; j++) {
  332. Map<Integer, Integer> hasApp = machineHasApp[j];
  333. if (hasApp.size() == 0 && !hasJob.contains(j))
  334. continue;
  335. // 检查互斥条件
  336. int appCnt = 0;
  337. for (Integer conditionalApp : hasApp.keySet()) {
  338. if (hasApp.get(conditionalApp) <= 0)
  339. throw new Exception("[DEBUG 1]Stupid Judger.");
  340. appCnt += hasApp.get(conditionalApp);
  341. for (Integer checkApp : appInterference[conditionalApp].keySet()) {
  342. if (hasApp.containsKey(checkApp)) {
  343. if (hasApp.get(checkApp) > appInterference[conditionalApp].get(checkApp))
  344. throw new Exception("终态存在干扰冲突");
  345. }
  346. }
  347. }
  348. // 检查资源限制
  349. for (int i = 0; i < k; i++)
  350. if (dcmp(machineResourcesUsed[j][i] - machineResources[j][i]) > 0)
  351. throw new Exception("终态存在资源过载");
  352. // 技术得分
  353. for (int t = 0; t < T2; t++) {
  354. double usage = machineResourcesUsed[j][t] / machineResources[j][t];
  355. costs += 1. + (1. + appCnt) * (Math.exp(Math.max(0., usage - beta)) - 1.);
  356. }
  357. }
  358. costs /= T2;
  359. } catch (Exception e) {
  360. System.out.println(e.getMessage());
  361. // e.printStackTrace();
  362. costs = 1e9;
  363. }
  364. return costs;
  365. }
  366. private String toMachine(String inst, int machineIt) {
  367. return toMachine(inst, machineIt, true);
  368. }
  369. private String toMachine(String inst, int machineIt, boolean doCheck) {
  370. int appIt = inst2AppIndex.get(inst);
  371. Map<Integer, Integer> hasApp = machineHasApp[machineIt];
  372. if (doCheck) {
  373. // 检查互斥规则
  374. int nowHas = 0;
  375. if (hasApp.containsKey(appIt))
  376. nowHas = hasApp.get(appIt);
  377. for (Integer conditionalApp : hasApp.keySet()) {
  378. if (hasApp.get(conditionalApp) <= 0)
  379. continue;
  380. if (!appInterference[conditionalApp].containsKey(appIt))
  381. continue;
  382. if (nowHas + 1 > appInterference[conditionalApp].get(appIt)) {
  383. return "App Interference, inst: " + inst + ", " + apps[conditionalApp] + " -> " + apps[appIt]
  384. + ", " + (nowHas + 1) + " > " + appInterference[conditionalApp].get(appIt);
  385. }
  386. }
  387. for (Integer checkApp : hasApp.keySet()) {
  388. if (!appInterference[appIt].containsKey(checkApp))
  389. continue;
  390. if (hasApp.get(checkApp) > appInterference[appIt].get(checkApp)) {
  391. return "App Interference, inst: " + inst + ", " + apps[appIt] + " -> " + apps[checkApp] + ", "
  392. + (nowHas + 1) + " > " + appInterference[appIt].get(checkApp);
  393. }
  394. }
  395. // 检查资源限制
  396. for (int i = 0; i < k; i++)
  397. if (dcmp(machineResourcesUsed[machineIt][i] + appResources[appIt][i]
  398. - machineResources[machineIt][i]) > 0)
  399. return "Resource Limit: inst: " + inst + ", " + "machine: " + machines[machineIt] + ", app: "
  400. + apps[appIt] + ", resIter: " + i + ", " + machineResourcesUsed[machineIt][i] + " + "
  401. + appResources[appIt][i] + " > " + machineResources[machineIt][i];
  402. }
  403. // 将inst放入新的machine
  404. inst2Machine.put(inst, machineIt);
  405. if (!hasApp.containsKey(appIt))
  406. hasApp.put(appIt, 0);
  407. hasApp.put(appIt, hasApp.get(appIt) + 1);
  408. for (int i = 0; i < k; i++)
  409. machineResourcesUsed[machineIt][i] += appResources[appIt][i];
  410. return "success";
  411. }
  412. private void pickInstance(String inst, int fromMachine) throws Exception {
  413. int appIt = inst2AppIndex.get(inst);
  414. // 更新machineHasApp
  415. Map<Integer, Integer> fromHasApp = machineHasApp[fromMachine];
  416. if (!fromHasApp.containsKey(appIt))
  417. throw new Exception("[DEBUG 12] Stupid judger");
  418. fromHasApp.put(appIt, fromHasApp.get(appIt) - 1);
  419. if (fromHasApp.get(appIt) <= 0)
  420. fromHasApp.remove(appIt);
  421. // 更新machineResourcesUsed
  422. for (int i = 0; i < k; i++)
  423. machineResourcesUsed[fromMachine][i] -= appResources[appIt][i];
  424. }
  425. private int dcmp(double x) {
  426. if (Math.abs(x) < 1e-9)
  427. return 0;
  428. return x < 0. ? -1 : 1;
  429. }
  430. }
  431. }