latex_table.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. // =====================================================================================
  2. //
  3. // Filename: latex_table.cpp
  4. //
  5. // Description: generate latex table
  6. //
  7. // Version: 1.0
  8. // Created: 2018年 02月 19日 星期一 16:42:17 CST
  9. // Revision: none
  10. // Compiler: g++
  11. //
  12. // Author: Jinkun Lin, jkunlin@gmail.com
  13. // Organization: School of EECS, Peking University
  14. //
  15. // =====================================================================================
  16. #include <algorithm>
  17. #include <fstream>
  18. #include <iostream>
  19. #include <limits>
  20. #include <sstream>
  21. #include <vector>
  22. using namespace std;
  23. bool SMALL_BETTER = false;
  24. int FAILED_SIZE = numeric_limits<int>::min();
  25. double PENALTY_TIME = 100;
  26. double DELTA = 0.0001;
  27. string basename(string name) {
  28. size_t begin = name.find_last_of('/');
  29. return name.substr(begin + 1, name.size() - begin);
  30. }
  31. bool equal_for_double(double d1, double d2, double delta = DELTA) {
  32. return fabs(d1 - d2) < delta;
  33. }
  34. template <class T1, class T2> bool better(T1 a, T2 b) {
  35. return SMALL_BETTER ? a < b : a > b;
  36. }
  37. int main(int argc, char const *argv[]) {
  38. int solver_count = argc - 1;
  39. // =====================================================================================
  40. // read data from file
  41. // =====================================================================================
  42. vector<vector<int>> size_matrix(solver_count);
  43. vector<vector<double>> time_matrix(solver_count);
  44. vector<vector<char>> exact_matrix(solver_count);
  45. for (int i = 0; i < solver_count; ++i) {
  46. ifstream in_file(argv[i + 1]);
  47. in_file.seekg(0, in_file.end);
  48. int length = in_file.tellg();
  49. in_file.seekg(0, in_file.beg);
  50. if (!in_file || length == 0) {
  51. std::cout << argv[i + 1] << '\t' << i + 1 << " file error" << std::endl;
  52. for (int j = 0; j < 10; ++j) {
  53. size_matrix[i].push_back(FAILED_SIZE);
  54. time_matrix[i].push_back(PENALTY_TIME);
  55. exact_matrix[i].push_back('h');
  56. }
  57. continue;
  58. }
  59. int seed, size;
  60. double solver_time;
  61. char exact;
  62. while (in_file >> seed >> size >> solver_time >> exact) {
  63. if (size == 0) {
  64. size_matrix[i].push_back(FAILED_SIZE);
  65. time_matrix[i].push_back(PENALTY_TIME);
  66. exact_matrix[i].push_back('h');
  67. } else {
  68. size_matrix[i].push_back(size);
  69. time_matrix[i].push_back(solver_time);
  70. exact_matrix[i].push_back(exact);
  71. }
  72. }
  73. in_file.close();
  74. }
  75. // =====================================================================================
  76. // caculate data
  77. // =====================================================================================
  78. vector<int> best_size(solver_count);
  79. vector<double> avg_size(solver_count);
  80. vector<double> avg_time(solver_count);
  81. vector<int> is_exact(solver_count, 0);
  82. int g_best_size = FAILED_SIZE;
  83. double g_avg_best_size = FAILED_SIZE;
  84. double g_min_avg_t = std::numeric_limits<double>::max();
  85. for (int i = 0; i < solver_count; ++i) {
  86. int okay_count = 0;
  87. int best_s = FAILED_SIZE;
  88. double avg_s = 0;
  89. double avg_t = 0;
  90. for (int j = 0; j < size_matrix[i].size(); j++) {
  91. if (size_matrix[i][j] != FAILED_SIZE) {
  92. if (best_s == FAILED_SIZE || better(size_matrix[i][j], best_s)) {
  93. best_s = size_matrix[i][j];
  94. }
  95. avg_s += size_matrix[i][j];
  96. avg_t += time_matrix[i][j];
  97. if (exact_matrix[i][j] == 'x') {
  98. is_exact[i] = 1;
  99. }
  100. okay_count++;
  101. } else {
  102. avg_t += PENALTY_TIME;
  103. }
  104. }
  105. if (okay_count != 0) {
  106. best_size[i] = best_s;
  107. avg_size[i] = round(avg_s / okay_count * 100) / 100;
  108. avg_time[i] = round(avg_t / size_matrix[i].size() * 100) / 100;
  109. if (better(best_size[i], g_best_size)) {
  110. g_best_size = best_size[i];
  111. }
  112. if (better(avg_size[i], g_avg_best_size)) {
  113. g_avg_best_size = avg_size[i];
  114. }
  115. if (g_min_avg_t > avg_time[i]) {
  116. g_min_avg_t = avg_time[i];
  117. }
  118. } else {
  119. best_size[i] = FAILED_SIZE;
  120. avg_size[i] = FAILED_SIZE;
  121. avg_time[i] = PENALTY_TIME;
  122. }
  123. }
  124. // =====================================================================================
  125. // generate latex table
  126. // =====================================================================================
  127. ofstream out_latex("bold_table.tex", ios::app);
  128. if (!out_latex) {
  129. std::cout << "out file error" << std::endl;
  130. return 1;
  131. }
  132. auto bf_write = [&](double d, bool is_bf) {
  133. if (is_bf) {
  134. out_latex << "\\textbf{" << d << "}";
  135. } else {
  136. out_latex << d;
  137. }
  138. };
  139. auto bf_write_time = [&](double d, bool is_bf) {
  140. if (is_bf) {
  141. if (d < 0.01) {
  142. out_latex << "\\boldmath{$<$}\\textbf{0.01}";
  143. } else {
  144. out_latex << "\\textbf{" << d << "}";
  145. }
  146. } else {
  147. if (d < 0.01) {
  148. out_latex << "$<$0.01";
  149. } else {
  150. out_latex << d;
  151. }
  152. }
  153. };
  154. out_latex << basename(argv[1]) << " & ";
  155. bool has_double_winner = false;
  156. int s_win_count = 0;
  157. int avg_s_win_count = 0;
  158. int avg_t_win_count = 0;
  159. for (int i = 0; i < solver_count; ++i) {
  160. if (best_size[i] == g_best_size) {
  161. s_win_count++;
  162. }
  163. if (equal_for_double(avg_size[i], g_avg_best_size)) {
  164. avg_s_win_count++;
  165. }
  166. if (equal_for_double(avg_time[i], g_min_avg_t)) {
  167. avg_t_win_count++;
  168. }
  169. if (best_size[i] == g_best_size &&
  170. equal_for_double(avg_size[i], g_avg_best_size)) {
  171. has_double_winner = true;
  172. }
  173. }
  174. for (int i = 0; i < solver_count; ++i) {
  175. if (best_size[i] == FAILED_SIZE) {
  176. out_latex << "N/A"
  177. << " & "
  178. << "N/A";
  179. if (i == solver_count - 1) {
  180. out_latex << " \\\\" << std::endl;
  181. } else {
  182. out_latex << " & ";
  183. }
  184. continue;
  185. }
  186. // size
  187. if (equal_for_double(best_size[i], avg_size[i])) {
  188. if (has_double_winner) {
  189. if ((s_win_count != solver_count || avg_s_win_count != solver_count) &&
  190. best_size[i] == g_best_size &&
  191. equal_for_double(avg_size[i], g_avg_best_size)) {
  192. bf_write(best_size[i], true);
  193. } else {
  194. bf_write(best_size[i], false);
  195. }
  196. } else {
  197. bf_write(best_size[i],
  198. best_size[i] == g_best_size ||
  199. equal_for_double(avg_size[i], g_avg_best_size));
  200. }
  201. } else { // max size dosen't equal to avg size
  202. if (has_double_winner) {
  203. if ((s_win_count != solver_count || avg_s_win_count != solver_count) &&
  204. (best_size[i] == g_best_size &&
  205. equal_for_double(avg_size[i], g_avg_best_size))) {
  206. bf_write(best_size[i], true);
  207. out_latex << "(";
  208. bf_write(avg_size[i], true);
  209. out_latex << ")";
  210. } else {
  211. bf_write(best_size[i], false);
  212. out_latex << "(";
  213. bf_write(avg_size[i], false);
  214. out_latex << ")";
  215. }
  216. } else {
  217. if (s_win_count != solver_count) {
  218. bf_write(best_size[i], best_size[i] == g_best_size);
  219. } else {
  220. bf_write(best_size[i], false);
  221. }
  222. out_latex << "(";
  223. if (avg_s_win_count != solver_count) {
  224. bf_write(avg_size[i], equal_for_double(avg_size[i], g_avg_best_size));
  225. } else {
  226. bf_write(avg_size[i], false);
  227. }
  228. out_latex << ")";
  229. }
  230. }
  231. if (is_exact[i]) {
  232. out_latex << "$^*$";
  233. }
  234. out_latex << " & ";
  235. // time
  236. if (s_win_count == solver_count && avg_s_win_count == solver_count &&
  237. avg_t_win_count != solver_count) {
  238. bf_write_time(avg_time[i], equal_for_double(avg_time[i], g_min_avg_t));
  239. } else {
  240. bf_write_time(avg_time[i], false);
  241. }
  242. if (i == solver_count - 1) {
  243. out_latex << " \\\\" << std::endl;
  244. } else {
  245. out_latex << " & ";
  246. }
  247. }
  248. out_latex.close();
  249. // =====================================================================================
  250. // generate compare file
  251. // =====================================================================================
  252. vector<bool> win(solver_count, false);
  253. // if (s_win_count != solver_count || avg_s_win_count != solver_count) {
  254. for (int i = 0; i < solver_count; ++i) {
  255. if (best_size[i] == g_best_size &&
  256. equal_for_double(avg_size[i], g_avg_best_size)) {
  257. // if (best_size[i] == g_best_size) {
  258. win[i] = true;
  259. }
  260. }
  261. // }
  262. ofstream out_arch("arch.result", ios::app);
  263. if (!out_arch) {
  264. std::cout << "arch file error" << std::endl;
  265. return 1;
  266. }
  267. // win
  268. out_arch << (win[0] ? 1 : 0);
  269. for (int i = 1; i < solver_count; ++i) {
  270. out_arch << '\t' << (win[i] ? 1 : 0);
  271. }
  272. out_arch << std::endl;
  273. // time
  274. out_arch << avg_time[0];
  275. for (int i = 1; i < solver_count; ++i) {
  276. out_arch << '\t' << avg_time[i];
  277. }
  278. out_arch << std::endl;
  279. // okay solver
  280. out_arch << (best_size[0] != FAILED_SIZE ? 1 : 0);
  281. for (int i = 1; i < solver_count; ++i) {
  282. out_arch << '\t' << (best_size[i] != FAILED_SIZE ? 1 : 0);
  283. }
  284. out_arch << endl;
  285. // exact
  286. out_arch << (is_exact[0] != 0 ? 1 : 0);
  287. for (int i = 1; i < solver_count; ++i) {
  288. out_arch << '\t' << (is_exact[i] != 0 ? 1 : 0);
  289. }
  290. out_arch << endl;
  291. out_arch.close();
  292. return 0;
  293. }