You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
5.0 KiB

  1. import os
  2. import os.path
  3. import sys
  4. import subprocess
  5. import re
  6. import time
  7. import argparse
  8. DIR=os.getcwd()
  9. STORM_PATH=os.path.join(DIR, "build/src/storm-dft")
  10. EXAMPLE_DIR=os.path.join(DIR, "examples/dft/")
  11. benchmarks = [
  12. ("and", False, [3, 1]),
  13. ("and_param", True, ["(4*x^2+2*x+1)/((x) * (2*x+1))", "1"]),
  14. ("cardiac", False, [8597.360004, 1]),
  15. ("cas", False, [0.859736, 1]),
  16. ("cm2", False, [0.256272, 1]),
  17. #("cm4", False, [0.338225, 1]), # big
  18. ("cps", False, ["inf", 0.333333]),
  19. #("deathegg", False, [24.642857, 1]), # contains fdep to gate
  20. #("fdep", False, [0.666667, 1]), # contains fdep to two elements
  21. ("fdep2", False, [2, 1]),
  22. ("fdep3", False, [2.5, 1]),
  23. #("ftpp_complex", False, [0, 1]), # Compute
  24. #("ftpp_large", False, [0, 1]), # Compute
  25. #("ftpp_standard", False, [0, 1]), # Compute
  26. ("mdcs", False, [2.85414, 1]),
  27. ("mdcs2", False, [2.85414, 1]),
  28. ("mp", False, [1.66667, 1]),
  29. ("or", False, [1, 1]),
  30. ("pand", False, ["inf", 0.666667]),
  31. ("pand_param", True, ["-1", "(x)/(y+x)"]),
  32. ("pdep", False, [2.66667, 1]),
  33. #("pdep2", False, [0, 1]), #Compute # contains pdep to two elements
  34. ("pdep3", False, [2.79167, 1]),
  35. ("spare", False, [3.53846, 1]),
  36. ("spare2", False, [1.86957, 1]),
  37. ("spare3", False, [1.27273, 1]),
  38. ("spare4", False, [4.8459, 1]),
  39. ("spare5", False, [2.66667, 1]),
  40. ("spare6", False, [1.4, 1]),
  41. ("spare7", False, [3.67333, 1]),
  42. ("symmetry", False, [4.16667, 1]),
  43. ("symmetry2", False, [3.06111, 1]),
  44. ("tripple_and1", False, [4.16667, 1]),
  45. ("tripple_and2", False, [3.66667, 1]),
  46. ("tripple_and2_c", False, [3.6667, 1]),
  47. ("tripple_and_c", False, [4.16667, 1]),
  48. ("tripple_or", False, [0.5, 1]),
  49. ("tripple_or2", False, [0.666667, 1]),
  50. ("tripple_or2_c", False, [0.66667, 1]),
  51. ("tripple_or_c", False, [0.5, 1]),
  52. ("tripple_pand", False, ["inf", 0.0416667]),
  53. ("tripple_pand2", False, ["inf", 0.166667]),
  54. ("tripple_pand2_c", False, ["inf", 0.166667]),
  55. ("tripple_pand_c", False, ["inf", 0.0416667]),
  56. ("voting", False, [1.66667, 1]),
  57. ("voting2", False, [0.588235, 1])
  58. ]
  59. def run_storm_dft(filename, prop, parametric, quiet):
  60. # Run storm-dft on filename and return result
  61. dft_file = os.path.join(EXAMPLE_DIR, filename + ".dft")
  62. args = [STORM_PATH,
  63. dft_file,
  64. prop]
  65. if parametric:
  66. args.append('--parametric')
  67. output = run_tool(args, quiet)
  68. # Get result
  69. match = re.search(r'Result: \[(.*)\]', output)
  70. if not match:
  71. return None
  72. result = match.group(1)
  73. return result
  74. def run_tool(args, quiet=False):
  75. """
  76. Executes a process,
  77. :returns: the `stdout`
  78. """
  79. pipe = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  80. result = "";
  81. for line in iter(pipe.stdout.readline, ""):
  82. if not line and pipe.poll() is not None:
  83. break
  84. output = line.decode(encoding='UTF-8').rstrip()
  85. if output != "":
  86. if not quiet:
  87. print("\t * " + output)
  88. result = output
  89. return result
  90. def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
  91. if a == b:
  92. return True
  93. return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
  94. if __name__ == "__main__":
  95. parser = argparse.ArgumentParser(description='Benchmarking DFTs via Storm')
  96. parser.add_argument('--debuglevel', type=int, default=0, help='the debug level (0=silent, 1=print benchmarks, 2=print output from storm')
  97. args = parser.parse_args()
  98. count = 0
  99. correct = 0
  100. properties = ['--expectedtime', '--probability']
  101. start = time.time()
  102. for index, prop in enumerate(properties):
  103. for (benchmark, parametric, result_original) in benchmarks:
  104. expected_result = result_original[index]
  105. # Run benchmark and check result
  106. count += 1;
  107. if args.debuglevel > 0:
  108. print("Running '{}' with property '{}'".format(benchmark, prop))
  109. result = run_storm_dft(benchmark, prop, parametric, args.debuglevel<2)
  110. if result is None:
  111. print("Error occurred on example '{}' with property '{}'".format(benchmark, prop))
  112. continue
  113. if not parametric:
  114. # Float
  115. result = float(result)
  116. if not isclose(result, float(expected_result), rel_tol=1e-05):
  117. print("Wrong result on example '{}' with property '{}': result: {}, Expected: {}".format(benchmark, prop, result, expected_result))
  118. else:
  119. correct += 1
  120. else:
  121. # Parametric
  122. if result != expected_result:
  123. print("Wrong result on example '{}' with property '{}': result: {}, Expected: {}".format(benchmark, prop, result, expected_result))
  124. else:
  125. correct += 1
  126. end = time.time()
  127. print("Correct results for {} of {} DFT checks in {}s".format(correct, count, end-start))