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.

163 lines
4.9 KiB

12 years ago
12 years ago
12 years ago
  1. /*! read_tra_file.cpp
  2. * Provides functions for reading a *.tra file describing the transition
  3. * system of a Markov chain (DTMC) and saving it into a corresponding
  4. * matrix.
  5. *
  6. * Reuses code from the file "read_tra_file.c" from the old MRMC project.
  7. *
  8. * Created on: 15.08.2012
  9. * Author: Thomas Heinemann
  10. */
  11. #include "src/parser/read_tra_file.h"
  12. #include "src/exceptions/file_IO_exception.h"
  13. #include "src/exceptions/wrong_file_format.h"
  14. #include "boost/integer/integer_mask.hpp"
  15. #include <cstdlib>
  16. #include <cstdio>
  17. #include <pantheios/pantheios.hpp>
  18. #include <pantheios/inserters/integer.hpp>
  19. #include <pantheios/inserters/real.hpp>
  20. namespace mrmc {
  21. namespace parser{
  22. // Disable C4996 - This function or variable may be unsafe.
  23. #pragma warning(disable:4996)
  24. /*!
  25. * This method does the first pass through the .tra file and computes
  26. * the number of non zero elements that are not diagonal elements,
  27. * which correspondents to the number of transitions that are not
  28. * self-loops.
  29. * (Diagonal elements are treated in a special way).
  30. *
  31. * @return The number of non-zero elements that are not on the diagonal
  32. * @param p File stream to scan. Is expected to be opened, a NULL pointer will
  33. * be rejected!
  34. */
  35. static uint_fast32_t make_first_pass(FILE* p) {
  36. if(p==NULL) {
  37. pantheios::log_ERROR("make_first_pass was called with NULL! (SHOULD NEVER HAPPEN)");
  38. throw exceptions::file_IO_exception ("make_first_pass: File not readable (this should be checked before calling this function!)");
  39. }
  40. char s[1024]; //String buffer
  41. uint_fast32_t rows=0, non_zero=0;
  42. //Reading No. of states
  43. if (fgets(s, 1024, p) != NULL) {
  44. if (sscanf( s, "STATES %d", &rows) == 0) {
  45. pantheios::log_WARNING(pantheios::integer(rows));
  46. throw mrmc::exceptions::wrong_file_format();
  47. }
  48. }
  49. //Reading No. of transitions
  50. if (fgets(s, 1024, p) != NULL) {
  51. if (sscanf( s, "TRANSITIONS %d", &non_zero) == 0) {
  52. throw mrmc::exceptions::wrong_file_format();
  53. }
  54. }
  55. //Reading transitions (one per line)
  56. //And increase number of transitions
  57. while (NULL != fgets( s, 1024, p ))
  58. {
  59. uint_fast32_t row=0, col=0;
  60. double val=0.0;
  61. if (sscanf( s, "%d%d%lf", &row, &col, &val ) != 3) {
  62. throw mrmc::exceptions::wrong_file_format();
  63. }
  64. //Diagonal elements are not counted into the result!
  65. if(row == col) {
  66. --non_zero;
  67. }
  68. }
  69. return non_zero;
  70. }
  71. /*!Reads a .tra file and produces a sparse matrix representing the described Markov Chain.
  72. * @param *filename input .tra file's name.
  73. * @return a pointer to a sparse matrix.
  74. */
  75. sparse::StaticSparseMatrix<double> * read_tra_file(const char * filename) {
  76. FILE *p;
  77. char s[1024];
  78. uint_fast32_t rows, non_zero;
  79. sparse::StaticSparseMatrix<double> *sp = NULL;
  80. p = fopen(filename, "r");
  81. if(p==NULL) {
  82. pantheios::log_ERROR("File ", filename, " was not readable (Does it exist?)");
  83. throw exceptions::file_IO_exception("mrmc::read_tra_file: Error opening file! (Does it exist?)");
  84. }
  85. non_zero = make_first_pass(p);
  86. //Set file reader back to the beginning
  87. rewind(p);
  88. //Reading No. of states
  89. if (fgets(s, 1024, p) != NULL) {
  90. if (sscanf( s, "STATES %d", &rows) == 0) {
  91. pantheios::log_WARNING(pantheios::integer(rows));
  92. throw mrmc::exceptions::wrong_file_format();
  93. }
  94. }
  95. /* Reading No. of transitions
  96. * Note that the result is not used in this function as make_first_pass()
  97. * computes the relevant number (non_zero)
  98. */
  99. if (fgets(s, 1024, p) != NULL) {
  100. uint_fast32_t nnz=0;
  101. if (sscanf( s, "TRANSITIONS %d", &nnz) == 0) {
  102. throw mrmc::exceptions::wrong_file_format();
  103. }
  104. }
  105. pantheios::log_DEBUG("Creating matrix with ",
  106. pantheios::integer(rows), " rows and ",
  107. pantheios::integer(non_zero), " Non-Zero-Elements");
  108. /* Creating matrix
  109. * Variable non_zero does NOT count any diagonal element,
  110. * But all diagonal elements are allocated, so the number of allocated
  111. * elements is non_zero
  112. */
  113. sp = new sparse::StaticSparseMatrix<double>(rows,non_zero);
  114. sp->initialize();
  115. if ( NULL == sp ) {
  116. throw std::bad_alloc();
  117. return NULL;
  118. }
  119. //Reading transitions (one per line) and saving the results in the matrix
  120. while (NULL != fgets( s, 1024, p ))
  121. {
  122. uint_fast32_t row=0, col=0;
  123. double val = 0.0;
  124. if (sscanf( s, "%d%d%lf", &row, &col, &val) != 3) {
  125. throw mrmc::exceptions::wrong_file_format();
  126. }
  127. pantheios::log_DEBUG("Write value ",
  128. pantheios::real(val),
  129. " to position ",
  130. pantheios::integer(row), " x ",
  131. pantheios::integer(col));
  132. sp->addNextValue(row,col,val);
  133. }
  134. (void)fclose(p);
  135. pantheios::log_DEBUG("Finalizing Matrix");
  136. sp->finalize();
  137. return sp;
  138. }
  139. } //namespace parser
  140. } //namespace mrmc