PageRenderTime 30ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/cmdp_collider_config.py

https://gitlab.com/dreval/bmdp-python-scripts
Python | 273 lines | 245 code | 15 blank | 13 comment | 8 complexity | 07f8c2fdf64d491f2eeeb60a2d09ec23 MD5 | raw file
  1. # -*- author: Dimitri Scheftelowitsch -*-
  2. # -*- coding:utf-8 -*-
  3. """
  4. A config file for collider
  5. Generates a sequence of CMDPs and runs some not very sophisticated analysis on
  6. them.
  7. """
  8. import numpy as np
  9. import pandas as pd
  10. import matplotlib
  11. from typing import Mapping, Any
  12. from scipy.stats import t
  13. matplotlib.use('PDF')
  14. from matplotlib import pyplot as plt
  15. experiment_name = 'CMDP'
  16. values = {
  17. 'scenarios': np.array([2, 3, 5]),
  18. 'states': np.array([2, 5, 10, 20, 50, 100, 200, 300]), # 10, 20, 50, 100, 200, 300
  19. 'actions': np.array([2, 3, 5]),
  20. 'run': np.arange(0, 30, 1), # np.arange(0, 30, 1),
  21. 'gamma': np.array([0.9, 0.999]),
  22. 'mode': ['deterministic', 'random'],
  23. }
  24. stages = [
  25. {
  26. 'name': 'generate',
  27. 'exe': 'python3',
  28. 'args': ['/home/scheftel/projects/bmdp-in-python/cmdp_generator.py',
  29. '--mode={mode}',
  30. '--scenarios={scenarios}',
  31. '--states={states}',
  32. '--actions={actions}']
  33. },
  34. {
  35. 'name': 'runIMGP',
  36. 'exe': '/home/scheftel/projects/BMDP/BMDPanalysis',
  37. 'args': ['{generate}', '901', '{gamma}'],
  38. 'timeout': 6050
  39. },
  40. {
  41. 'name': 'runIMPP',
  42. 'exe': '/home/scheftel/projects/BMDP/BMDPanalysis',
  43. 'args': ['{generate}', '902', '{gamma}'],
  44. 'timeout': 6050
  45. },
  46. {
  47. 'name': 'runMIP',
  48. 'exe': '/home/scheftel/projects/BMDP/BMDPanalysis',
  49. 'args': ['{generate}', '904', '{gamma}'],
  50. 'timeout': 6050
  51. },
  52. {
  53. 'name': 'runNLP',
  54. 'exe': '/home/scheftel/projects/BMDP/BMDPanalysis',
  55. 'args': ['{generate}', '905', '{gamma}'],
  56. 'timeout': 6050
  57. },
  58. {
  59. 'name': 'runQCLP',
  60. 'exe': '/home/scheftel/projects/BMDP/BMDPanalysis',
  61. 'args': ['{generate}', '903', '{gamma}'],
  62. 'timeout': 6010
  63. },
  64. {
  65. 'name': 'debug',
  66. 'exe': 'echo',
  67. 'args': ['mode: {mode}, scenarios: {scenarios}, states: {states}, actions: {actions}, run: {run}']
  68. },
  69. ]
  70. def postprocess(data: pd.DataFrame, values: Mapping[str, Any]):
  71. algorithms = ["IMGP", "IMPP", "QCLP", "MIP", "NLP"]
  72. major_tuples = ["scenarios", "states", "actions"]
  73. valid_run_filter = data['run'].map(lambda r: r in values['run'])
  74. data.loc[:, 'value'] = pd.Series(0.0, index=data.index)
  75. data.loc[:, 'relative_deviation'] = pd.Series(0.0, index=data.index)
  76. data.sort_values(by=major_tuples, inplace=True)
  77. models = values['mode']
  78. gammas = values['gamma']
  79. def filter_result(row):
  80. result = None
  81. run_stages = map("run{0}".format, algorithms)
  82. if row.Stage in run_stages:
  83. lines = row.output.decode('utf-8').split("\n")
  84. if len(lines) >= 2:
  85. try:
  86. result = float(lines[-2])
  87. except ValueError:
  88. result = None
  89. return result
  90. def compute_deviation(row):
  91. result = None
  92. run_stages = map("run{0}".format, algorithms)
  93. if (row.Stage in run_stages) and (not np.isnan(row.value)):
  94. query = (data.run == row.run) & (data.states == row.states) \
  95. & (data.actions == row.actions) & (data.scenarios == row.scenarios) \
  96. & (data['mode'] == row['mode']) & (data.gamma == row.gamma) \
  97. & ~np.isnan(data.value) & (data.value > 0.0)
  98. impp_value = data[query & (data.Stage == 'runIMPP')].value.iloc[0]
  99. cutoff = 2 * impp_value
  100. max_value = max(data[query & (data.value <= cutoff)].value)
  101. result = 1.0 - row.value / max_value
  102. return result
  103. data.loc[:, 'value'] = data.apply(filter_result, axis=1)
  104. # THIS CODE IS DUE TO A BUG IN GSL WHERE I HAD TO RERUN ONE SPECIFIC VALUE
  105. #data.loc[14051, 'value'] = 9.43569e+03
  106. #data.loc[14051, 'cpu_user'] = 184.74
  107. # END UGLY HACK
  108. data.loc[:, 'relative_deviation'] = data.apply(compute_deviation, axis=1)
  109. data_filtered = data[valid_run_filter]
  110. for model in models:
  111. for gamma in gammas:
  112. # tex_table_header = "\\begin{table}\\begin{tabular}"
  113. tex_code = ""
  114. tuples = data_filtered.loc[:, major_tuples].drop_duplicates()
  115. for _, tuple in tuples.iterrows():
  116. data_tuple = data_filtered[(data_filtered.scenarios == tuple.scenarios) &
  117. (data_filtered.states == tuple.states) &
  118. (data_filtered.actions == tuple.actions) &
  119. (data_filtered['mode'] == model) & (data_filtered.gamma == gamma)]
  120. avg_time = {}
  121. relative_deviation = {}
  122. errors = {}
  123. tex_code += "\\num{{{0}}} & \\num{{{1}}} & \\num{{{2}}} \n".format(tuple.scenarios, tuple.states,
  124. tuple.actions)
  125. # find all runs that can be compared
  126. for algorithm in algorithms:
  127. stage = "run{0}".format(algorithm)
  128. invalid_value_filter = (np.isnan(data_tuple.value) | (data_tuple.value == 0.0))
  129. successful_runs = data_tuple[~invalid_value_filter & (data_tuple.Stage == stage)]
  130. errors[algorithm] = len(data_tuple[invalid_value_filter & (data_tuple.Stage == stage)])
  131. avg_time[algorithm] = successful_runs.cpu_user.mean()
  132. for run in values['run']:
  133. data_run = data_tuple[data_tuple.run == run]
  134. # this is an ugly hack to ensure valid values.
  135. cutoff = data_run[data_run.Stage == 'runIMPP'].value.iloc[0]
  136. cutoff = 2 * cutoff
  137. validity_criterion = ~(np.isnan(data_run.value) | (data_run.value > cutoff))
  138. try:
  139. max_value = max(data_run[validity_criterion].value)
  140. except ValueError:
  141. max_value = None
  142. data_algorithm_program = data_run[data_run.Stage == stage]
  143. if len(data_algorithm_program) > 0:
  144. program_value = data_algorithm_program.value.iloc[0]
  145. if program_value > cutoff:
  146. errors[algorithm] += 1
  147. if not (np.isnan(program_value) or (program_value == 0.0) or (program_value > cutoff)):
  148. deviation = 1.0 - program_value / max_value
  149. if np.isnan(deviation):
  150. raise ArithmeticError
  151. relative_deviation[algorithm] = relative_deviation.get(algorithm, 0) + deviation
  152. data_query = (data.Stage == stage) & (data.run == run) \
  153. & (data.scenarios == tuple.scenarios) \
  154. & (data.states == tuple.states) \
  155. & (data.actions == tuple.actions) \
  156. & (data.gamma == gamma) \
  157. & (data['mode'] == model)
  158. #data[data_query].relative_deviation = deviation
  159. if algorithm in relative_deviation:
  160. relative_deviation[algorithm] /= len(successful_runs)
  161. if np.isnan(relative_deviation[algorithm]):
  162. raise ArithmeticError
  163. else:
  164. relative_deviation[algorithm] = None
  165. relative_deviation_string = "N/A"
  166. if relative_deviation[algorithm] not in [np.nan, None]:
  167. relative_deviation_string = "\\num{{{0:.2f}}}\%".format(relative_deviation[algorithm] * 100)
  168. average_time_string = "N/A"
  169. if not np.isnan(avg_time[algorithm]):
  170. average_time_string = "\\num{{{0:.3f}}}\\si{{s}}".format(avg_time[algorithm])
  171. tex_code += "& {0} & \\num{{{1}}} & {2} \n".format(average_time_string, errors[algorithm],
  172. relative_deviation_string)
  173. tex_code += "\\\\ \n"
  174. file = "CMDP_results_{0}_{1}.tex".format(model, gamma)
  175. f = open(file=file, mode='w+b')
  176. f.write(bytes(tex_code, 'utf-8'))
  177. f.close()
  178. pure_comparison = {
  179. 'exact': 'MIP',
  180. 'heuristic': 'IMPP',
  181. 'exact_color': 'c',
  182. 'heuristic_color': 'm',
  183. 'filename': 'pure'
  184. }
  185. stationary_comparison = {
  186. 'exact': 'NLP',
  187. 'heuristic': 'IMGP',
  188. 'exact_color': 'b',
  189. 'heuristic_color': 'k',
  190. 'filename': 'stationary'
  191. }
  192. plots = [pure_comparison, stationary_comparison]
  193. plot_axes = ['states', 'scenarios']
  194. subplots = ['cpu_user', 'relative_deviation']
  195. subplot_descriptions = {
  196. 'cpu_user': 'CPU time',
  197. 'relative_deviation': 'Deviation from optimum'
  198. }
  199. confidence_level = 0.99
  200. for plot in plots:
  201. for key in plot_axes:
  202. for subplot in subplots:
  203. filename = "plot_{0}_{1}_{2}.pdf".format(plot['filename'], key, subplot)
  204. x = values[key]
  205. heuristic_mean = np.zeros(values[key].shape)
  206. exact_mean = np.zeros(values[key].shape)
  207. heuristic_std = np.zeros(values[key].shape)
  208. exact_std = np.zeros(values[key].shape)
  209. for (i, value) in enumerate(values[key]):
  210. query_heuristic = (data_filtered.Stage == "run{0}".format(plot['heuristic']))
  211. query_exact = (data_filtered.Stage == "run{0}".format(plot['exact']))
  212. query_value = (data_filtered[key] == value) & ~np.isnan(data_filtered[subplot])
  213. data_key = data_filtered[query_value]
  214. exact_mean[i] = data_key[query_exact][subplot].mean()
  215. heuristic_mean[i] = data_key[query_heuristic][subplot].mean()
  216. num_samples = len(data_key[query_heuristic][subplot])
  217. t_star = t.isf((1 - confidence_level) / 2, num_samples - 1)
  218. factor = t_star / np.sqrt(num_samples)
  219. exact_std[i] = data_key[query_exact][subplot].std() * factor
  220. heuristic_std[i] = data_key[query_heuristic][subplot].std() * factor
  221. style = '{0}--'
  222. error_style = '{0}-.'
  223. plt.clf()
  224. matplotlib.rcParams['lines.linewidth'] = 1.0
  225. if subplot == 'cpu_user':
  226. plt.plot(x, exact_mean, style.format(plot['exact_color']))
  227. (_, caps, _) = plt.errorbar(x, exact_mean, yerr=[exact_std, exact_std], fmt='+',
  228. color=plot['exact_color'], label=plot['exact'], marker='.', capsize=5)
  229. #for cap in caps:
  230. # cap.set_markeredgewidth(5)
  231. #eb[-1][0].set_linestyle('-.')
  232. plt.plot(x, heuristic_mean, style.format(plot['heuristic_color']))
  233. (_, caps, _) = plt.errorbar(x, heuristic_mean, yerr=[heuristic_std, heuristic_std], fmt='+',
  234. color=plot['heuristic_color'], label='heuristic', marker='.', capsize=5)
  235. #for cap in caps:
  236. # cap.set_markeredgewidth(5)
  237. #eb[-1][0].set_linestyle('-.')
  238. plt.xlabel(key)
  239. plt.ylabel(subplot_descriptions[subplot])
  240. plt.legend()
  241. plt.savefig(filename)
  242. if __name__ == "__main__":
  243. data = pd.read_pickle("CMDP_results.pickle")
  244. postprocess(data, values)