490 lines
20 KiB

  1. /*
  2. * STORM - a C++ Rebuild of MRMC
  3. *
  4. * STORM (Stochastic Reward Model Checker) is a model checker for discrete-time and continuous-time Markov
  5. * reward models. It supports reward extensions of PCTL and CSL (PRCTL
  6. * and CSRL), and allows for the automated verification of properties
  7. * concerning long-run and instantaneous rewards as well as cumulative
  8. * rewards.
  9. *
  10. * Authors: Philipp Berger
  11. *
  12. * Description: Central part of the application containing the main() Method
  13. */
  14. #include "src/utility/OsDetection.h"
  15. #include <iostream>
  16. #include <cstdio>
  17. #include <sstream>
  18. #include <vector>
  19. #include "storm-config.h"
  20. #include "src/models/Dtmc.h"
  21. #include "src/storage/SparseMatrix.h"
  22. #include "src/models/AtomicPropositionsLabeling.h"
  23. #include "src/modelchecker/EigenDtmcPrctlModelChecker.h"
  24. #include "src/modelchecker/GmmxxDtmcPrctlModelChecker.h"
  25. #include "src/modelchecker/GmmxxMdpPrctlModelChecker.h"
  26. #include "src/parser/AutoParser.h"
  27. #include "src/parser/PrctlParser.h"
  28. #include "src/utility/Settings.h"
  29. #include "src/utility/ErrorHandling.h"
  30. #include "src/formula/Formulas.h"
  31. #include "log4cplus/logger.h"
  32. #include "log4cplus/loggingmacros.h"
  33. #include "log4cplus/consoleappender.h"
  34. #include "log4cplus/fileappender.h"
  35. #include "src/exceptions/InvalidSettingsException.h"
  36. log4cplus::Logger logger;
  37. /*!
  38. * Initializes the logging framework and sets up logging to console.
  39. */
  40. void initializeLogger() {
  41. logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main"));
  42. logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);
  43. log4cplus::SharedAppenderPtr consoleLogAppender(new log4cplus::ConsoleAppender());
  44. consoleLogAppender->setName("mainConsoleAppender");
  45. consoleLogAppender->setThreshold(log4cplus::WARN_LOG_LEVEL);
  46. consoleLogAppender->setLayout(std::auto_ptr<log4cplus::Layout>(new log4cplus::PatternLayout("%-5p - %D{%H:%M:%S} (%r ms) - %b:%L: %m%n")));
  47. logger.addAppender(consoleLogAppender);
  48. }
  49. /*!
  50. * Sets up the logging to file.
  51. */
  52. void setUpFileLogging() {
  53. storm::settings::Settings* s = storm::settings::instance();
  54. log4cplus::SharedAppenderPtr fileLogAppender(new log4cplus::FileAppender(s->getString("logfile")));
  55. fileLogAppender->setName("mainFileAppender");
  56. fileLogAppender->setLayout(std::auto_ptr<log4cplus::Layout>(new log4cplus::PatternLayout("%-5p - %D{%H:%M:%S} (%r ms) - %F:%L: %m%n")));
  57. logger.addAppender(fileLogAppender);
  58. }
  59. /*!
  60. * Prints the header.
  61. */
  62. void printHeader(const int argc, const char* argv[]) {
  63. std::cout << "StoRM" << std::endl;
  64. std::cout << "-----" << std::endl << std::endl;
  65. std::cout << "Version: 1.0 Alpha" << std::endl;
  66. // "Compute" the command line argument string with which STORM was invoked.
  67. std::stringstream commandStream;
  68. for (int i = 0; i < argc; ++i) {
  69. commandStream << argv[i] << " ";
  70. }
  71. std::cout << "Command line: " << commandStream.str() << std::endl << std::endl;
  72. }
  73. /*!
  74. * Prints the footer.
  75. */
  76. void printFooter() {
  77. std::cout << "Nothing more to do, exiting." << std::endl;
  78. }
  79. /*!
  80. * Function that parses the command line options.
  81. * @param argc The argc argument of main().
  82. * @param argv The argv argument of main().
  83. * @return True iff the program should continue to run after parsing the options.
  84. */
  85. bool parseOptions(const int argc, const char* argv[]) {
  86. storm::settings::Settings* s = nullptr;
  87. try {
  88. storm::settings::Settings::registerModule<storm::modelChecker::GmmxxDtmcPrctlModelChecker<double>>();
  89. s = storm::settings::newInstance(argc, argv, nullptr);
  90. } catch (storm::exceptions::InvalidSettingsException& e) {
  91. std::cout << "Could not recover from settings error: " << e.what() << "." << std::endl;
  92. std::cout << std::endl << storm::settings::help;
  93. return false;
  94. }
  95. if (s->isSet("help")) {
  96. std::cout << storm::settings::help;
  97. return false;
  98. }
  99. if (s->isSet("test-prctl")) {
  100. storm::parser::PrctlParser parser(s->getString("test-prctl").c_str());
  101. return false;
  102. }
  103. if (s->isSet("verbose")) {
  104. logger.getAppender("mainConsoleAppender")->setThreshold(log4cplus::INFO_LOG_LEVEL);
  105. LOG4CPLUS_INFO(logger, "Enable verbose mode, log output gets printed to console.");
  106. }
  107. if (s->isSet("debug")) {
  108. logger.setLogLevel(log4cplus::DEBUG_LOG_LEVEL);
  109. logger.getAppender("mainConsoleAppender")->setThreshold(log4cplus::DEBUG_LOG_LEVEL);
  110. LOG4CPLUS_DEBUG(logger, "Enable very verbose mode, log output gets printed to console.");
  111. }
  112. if (s->isSet("logfile")) {
  113. setUpFileLogging();
  114. }
  115. return true;
  116. }
  117. void setUp() {
  118. std::cout.precision(10);
  119. }
  120. /*!
  121. * Function to perform some cleanup.
  122. */
  123. void cleanUp() {
  124. // nothing here
  125. }
  126. void testCheckingDie(storm::models::Dtmc<double>& dtmc) {
  127. storm::modelChecker::GmmxxDtmcPrctlModelChecker<double>* mc = new storm::modelChecker::GmmxxDtmcPrctlModelChecker<double>(dtmc);
  128. storm::formula::Ap<double>* oneFormula = new storm::formula::Ap<double>("one");
  129. storm::formula::Eventually<double>* eventuallyFormula = new storm::formula::Eventually<double>(oneFormula);
  130. storm::formula::ProbabilisticNoBoundOperator<double>* probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
  131. mc->check(*probFormula);
  132. delete probFormula;
  133. oneFormula = new storm::formula::Ap<double>("two");
  134. eventuallyFormula = new storm::formula::Eventually<double>(oneFormula);
  135. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
  136. mc->check(*probFormula);
  137. delete probFormula;
  138. oneFormula = new storm::formula::Ap<double>("three");
  139. eventuallyFormula = new storm::formula::Eventually<double>(oneFormula);
  140. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
  141. mc->check(*probFormula);
  142. delete probFormula;
  143. storm::formula::Ap<double>* done = new storm::formula::Ap<double>("done");
  144. storm::formula::ReachabilityReward<double>* reachabilityRewardFormula = new storm::formula::ReachabilityReward<double>(done);
  145. storm::formula::RewardNoBoundOperator<double>* rewardFormula = new storm::formula::RewardNoBoundOperator<double>(reachabilityRewardFormula);
  146. mc->check(*rewardFormula);
  147. delete rewardFormula;
  148. delete mc;
  149. }
  150. void testCheckingCrowds(storm::models::Dtmc<double>& dtmc) {
  151. storm::formula::Ap<double>* observe0Greater1Formula = new storm::formula::Ap<double>("observe0Greater1");
  152. storm::formula::Eventually<double>* eventuallyFormula = new storm::formula::Eventually<double>(observe0Greater1Formula);
  153. storm::formula::ProbabilisticNoBoundOperator<double>* probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
  154. storm::modelChecker::GmmxxDtmcPrctlModelChecker<double>* mc = new storm::modelChecker::GmmxxDtmcPrctlModelChecker<double>(dtmc);
  155. mc->check(*probFormula);
  156. delete probFormula;
  157. storm::formula::Ap<double>* observeIGreater1Formula = new storm::formula::Ap<double>("observeIGreater1");
  158. eventuallyFormula = new storm::formula::Eventually<double>(observeIGreater1Formula);
  159. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
  160. mc->check(*probFormula);
  161. delete probFormula;
  162. storm::formula::Ap<double>* observeOnlyTrueSenderFormula = new storm::formula::Ap<double>("observeOnlyTrueSender");
  163. eventuallyFormula = new storm::formula::Eventually<double>(observeOnlyTrueSenderFormula);
  164. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
  165. mc->check(*probFormula);
  166. delete probFormula;
  167. delete mc;
  168. }
  169. void testCheckingSynchronousLeader(storm::models::Dtmc<double>& dtmc, uint_fast64_t n) {
  170. storm::formula::Ap<double>* electedFormula = new storm::formula::Ap<double>("elected");
  171. storm::formula::Eventually<double>* eventuallyFormula = new storm::formula::Eventually<double>(electedFormula);
  172. storm::formula::ProbabilisticNoBoundOperator<double>* probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
  173. storm::modelChecker::GmmxxDtmcPrctlModelChecker<double>* mc = new storm::modelChecker::GmmxxDtmcPrctlModelChecker<double>(dtmc);
  174. mc->check(*probFormula);
  175. delete probFormula;
  176. electedFormula = new storm::formula::Ap<double>("elected");
  177. storm::formula::BoundedUntil<double>* boundedUntilFormula = new storm::formula::BoundedUntil<double>(new storm::formula::Ap<double>("true"), electedFormula, n * 4);
  178. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(boundedUntilFormula);
  179. mc->check(*probFormula);
  180. delete probFormula;
  181. electedFormula = new storm::formula::Ap<double>("elected");
  182. storm::formula::ReachabilityReward<double>* reachabilityRewardFormula = new storm::formula::ReachabilityReward<double>(electedFormula);
  183. storm::formula::RewardNoBoundOperator<double>* rewardFormula = new storm::formula::RewardNoBoundOperator<double>(reachabilityRewardFormula);
  184. mc->check(*rewardFormula);
  185. delete rewardFormula;
  186. delete mc;
  187. }
  188. void testCheckingDice(storm::models::Mdp<double>& mdp) {
  189. storm::formula::Ap<double>* twoFormula = new storm::formula::Ap<double>("two");
  190. storm::formula::Eventually<double>* eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  191. storm::formula::ProbabilisticNoBoundOperator<double>* probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  192. storm::modelChecker::GmmxxMdpPrctlModelChecker<double>* mc = new storm::modelChecker::GmmxxMdpPrctlModelChecker<double>(mdp);
  193. mc->check(*probFormula);
  194. delete probFormula;
  195. twoFormula = new storm::formula::Ap<double>("two");
  196. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  197. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false);
  198. mc->check(*probFormula);
  199. delete probFormula;
  200. twoFormula = new storm::formula::Ap<double>("three");
  201. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  202. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  203. mc->check(*probFormula);
  204. delete probFormula;
  205. twoFormula = new storm::formula::Ap<double>("three");
  206. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  207. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false);
  208. mc->check(*probFormula);
  209. delete probFormula;
  210. twoFormula = new storm::formula::Ap<double>("four");
  211. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  212. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  213. mc->check(*probFormula);
  214. delete probFormula;
  215. twoFormula = new storm::formula::Ap<double>("four");
  216. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  217. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false);
  218. mc->check(*probFormula);
  219. delete probFormula;
  220. twoFormula = new storm::formula::Ap<double>("five");
  221. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  222. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  223. mc->check(*probFormula);
  224. delete probFormula;
  225. twoFormula = new storm::formula::Ap<double>("five");
  226. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  227. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false);
  228. mc->check(*probFormula);
  229. delete probFormula;
  230. twoFormula = new storm::formula::Ap<double>("six");
  231. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  232. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  233. mc->check(*probFormula);
  234. delete probFormula;
  235. twoFormula = new storm::formula::Ap<double>("six");
  236. eventuallyFormula = new storm::formula::Eventually<double>(twoFormula);
  237. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false);
  238. mc->check(*probFormula);
  239. delete probFormula;
  240. storm::formula::Ap<double>* doneFormula = new storm::formula::Ap<double>("done");
  241. storm::formula::ReachabilityReward<double>* reachabilityRewardFormula = new storm::formula::ReachabilityReward<double>(doneFormula);
  242. storm::formula::RewardNoBoundOperator<double>* rewardFormula = new storm::formula::RewardNoBoundOperator<double>(reachabilityRewardFormula, true);
  243. mc->check(*rewardFormula);
  244. delete rewardFormula;
  245. doneFormula = new storm::formula::Ap<double>("done");
  246. reachabilityRewardFormula = new storm::formula::ReachabilityReward<double>(doneFormula);
  247. rewardFormula = new storm::formula::RewardNoBoundOperator<double>(reachabilityRewardFormula, false);
  248. mc->check(*rewardFormula);
  249. delete rewardFormula;
  250. delete mc;
  251. }
  252. void testCheckingAsynchLeader(storm::models::Mdp<double>& mdp) {
  253. storm::formula::Ap<double>* electedFormula = new storm::formula::Ap<double>("elected");
  254. storm::formula::Eventually<double>* eventuallyFormula = new storm::formula::Eventually<double>(electedFormula);
  255. storm::formula::ProbabilisticNoBoundOperator<double>* probMinFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  256. storm::modelChecker::GmmxxMdpPrctlModelChecker<double>* mc = new storm::modelChecker::GmmxxMdpPrctlModelChecker<double>(mdp);
  257. mc->check(*probMinFormula);
  258. delete probMinFormula;
  259. electedFormula = new storm::formula::Ap<double>("elected");
  260. eventuallyFormula = new storm::formula::Eventually<double>(electedFormula);
  261. storm::formula::ProbabilisticNoBoundOperator<double>* probMaxFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false);
  262. mc->check(*probMaxFormula);
  263. delete probMaxFormula;
  264. electedFormula = new storm::formula::Ap<double>("elected");
  265. storm::formula::BoundedEventually<double>* boundedEventuallyFormula = new storm::formula::BoundedEventually<double>(electedFormula, 25);
  266. probMinFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, true);
  267. mc->check(*probMinFormula);
  268. delete probMinFormula;
  269. electedFormula = new storm::formula::Ap<double>("elected");
  270. boundedEventuallyFormula = new storm::formula::BoundedEventually<double>(electedFormula, 25);
  271. probMaxFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, false);
  272. mc->check(*probMaxFormula);
  273. delete probMaxFormula;
  274. electedFormula = new storm::formula::Ap<double>("elected");
  275. storm::formula::ReachabilityReward<double>* reachabilityRewardFormula = new storm::formula::ReachabilityReward<double>(electedFormula);
  276. storm::formula::RewardNoBoundOperator<double>* rewardFormula = new storm::formula::RewardNoBoundOperator<double>(reachabilityRewardFormula, true);
  277. mc->check(*rewardFormula);
  278. delete rewardFormula;
  279. electedFormula = new storm::formula::Ap<double>("elected");
  280. reachabilityRewardFormula = new storm::formula::ReachabilityReward<double>(electedFormula);
  281. rewardFormula = new storm::formula::RewardNoBoundOperator<double>(reachabilityRewardFormula, false);
  282. mc->check(*rewardFormula);
  283. delete rewardFormula;
  284. delete mc;
  285. }
  286. void testCheckingConsensus(storm::models::Mdp<double>& mdp) {
  287. storm::formula::Ap<double>* finishedFormula = new storm::formula::Ap<double>("finished");
  288. storm::formula::Eventually<double>* eventuallyFormula = new storm::formula::Eventually<double>(finishedFormula);
  289. storm::formula::ProbabilisticNoBoundOperator<double>* probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  290. storm::modelChecker::GmmxxMdpPrctlModelChecker<double>* mc = new storm::modelChecker::GmmxxMdpPrctlModelChecker<double>(mdp);
  291. mc->check(*probFormula);
  292. delete probFormula;
  293. finishedFormula = new storm::formula::Ap<double>("finished");
  294. storm::formula::Ap<double>* allCoinsEqual0Formula = new storm::formula::Ap<double>("all_coins_equal_0");
  295. storm::formula::And<double>* conjunctionFormula = new storm::formula::And<double>(finishedFormula, allCoinsEqual0Formula);
  296. eventuallyFormula = new storm::formula::Eventually<double>(conjunctionFormula);
  297. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  298. mc->check(*probFormula);
  299. delete probFormula;
  300. finishedFormula = new storm::formula::Ap<double>("finished");
  301. storm::formula::Ap<double>* allCoinsEqual1Formula = new storm::formula::Ap<double>("all_coins_equal_1");
  302. conjunctionFormula = new storm::formula::And<double>(finishedFormula, allCoinsEqual1Formula);
  303. eventuallyFormula = new storm::formula::Eventually<double>(conjunctionFormula);
  304. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true);
  305. mc->check(*probFormula);
  306. delete probFormula;
  307. finishedFormula = new storm::formula::Ap<double>("finished");
  308. storm::formula::Ap<double>* agree = new storm::formula::Ap<double>("agree");
  309. storm::formula::Not<double>* notAgree = new storm::formula::Not<double>(agree);
  310. conjunctionFormula = new storm::formula::And<double>(finishedFormula, notAgree);
  311. eventuallyFormula = new storm::formula::Eventually<double>(conjunctionFormula);
  312. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false);
  313. mc->check(*probFormula);
  314. delete probFormula;
  315. finishedFormula = new storm::formula::Ap<double>("finished");
  316. storm::formula::BoundedEventually<double>* boundedEventuallyFormula = new storm::formula::BoundedEventually<double>(finishedFormula, 50);
  317. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, true);
  318. mc->check(*probFormula);
  319. delete probFormula;
  320. finishedFormula = new storm::formula::Ap<double>("finished");
  321. boundedEventuallyFormula = new storm::formula::BoundedEventually<double>(finishedFormula, 50);
  322. probFormula = new storm::formula::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, false);
  323. mc->check(*probFormula);
  324. delete probFormula;
  325. finishedFormula = new storm::formula::Ap<double>("finished");
  326. storm::formula::ReachabilityReward<double>* reachabilityRewardFormula = new storm::formula::ReachabilityReward<double>(finishedFormula);
  327. storm::formula::RewardNoBoundOperator<double>* rewardFormula = new storm::formula::RewardNoBoundOperator<double>(reachabilityRewardFormula, true);
  328. mc->check(*rewardFormula);
  329. delete rewardFormula;
  330. finishedFormula = new storm::formula::Ap<double>("finished");
  331. reachabilityRewardFormula = new storm::formula::ReachabilityReward<double>(finishedFormula);
  332. rewardFormula = new storm::formula::RewardNoBoundOperator<double>(reachabilityRewardFormula, false);
  333. mc->check(*rewardFormula);
  334. delete rewardFormula;
  335. delete mc;
  336. }
  337. /*!
  338. * Simple testing procedure.
  339. */
  340. void testChecking() {
  341. storm::settings::Settings* s = storm::settings::instance();
  342. storm::parser::AutoParser<double> parser(s->getString("trafile"), s->getString("labfile"), s->getString("staterew"), s->getString("transrew"));
  343. if (parser.getType() == storm::models::DTMC) {
  344. std::shared_ptr<storm::models::Dtmc<double>> dtmc = parser.getModel<storm::models::Dtmc<double>>();
  345. dtmc->printModelInformationToStream(std::cout);
  346. // testCheckingDie(*dtmc);
  347. // testCheckingCrowds(*dtmc);
  348. // testCheckingSynchronousLeader(*dtmc, 6);
  349. } else if (parser.getType() == storm::models::MDP) {
  350. std::shared_ptr<storm::models::Mdp<double>> mdp = parser.getModel<storm::models::Mdp<double>>();
  351. mdp->printModelInformationToStream(std::cout);
  352. // testCheckingDice(*mdp);
  353. // testCheckingAsynchLeader(*mdp);
  354. // testCheckingConsensus(*mdp);
  355. } else {
  356. std::cout << "Input is neither a DTMC nor an MDP." << std::endl;
  357. }
  358. }
  359. /*!
  360. * Main entry point.
  361. */
  362. int main(const int argc, const char* argv[]) {
  363. // Catch segfaults and display a backtrace.
  364. installSignalHandler();
  365. printHeader(argc, argv);
  366. initializeLogger();
  367. if (!parseOptions(argc, argv)) {
  368. return 0;
  369. }
  370. setUp();
  371. try {
  372. LOG4CPLUS_INFO(logger, "StoRM was invoked.");
  373. testChecking();
  374. cleanUp();
  375. LOG4CPLUS_INFO(logger, "StoRM quit.");
  376. return 0;
  377. } catch (std::exception& e) {
  378. LOG4CPLUS_FATAL(logger, "An exception was thrown but not catched. All we can do now is show it to you and die in peace...");
  379. LOG4CPLUS_FATAL(logger, "\t" << e.what());
  380. }
  381. return 1;
  382. }