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
163 lines
4.9 KiB
/*! read_tra_file.cpp
|
|
* Provides functions for reading a *.tra file describing the transition
|
|
* system of a Markov chain (DTMC) and saving it into a corresponding
|
|
* matrix.
|
|
*
|
|
* Reuses code from the file "read_tra_file.c" from the old MRMC project.
|
|
*
|
|
* Created on: 15.08.2012
|
|
* Author: Thomas Heinemann
|
|
*/
|
|
|
|
#include "src/parser/read_tra_file.h"
|
|
#include "src/exceptions/file_IO_exception.h"
|
|
#include "src/exceptions/wrong_file_format.h"
|
|
#include "boost/integer/integer_mask.hpp"
|
|
#include <cstdlib>
|
|
#include <cstdio>
|
|
|
|
#include <pantheios/pantheios.hpp>
|
|
#include <pantheios/inserters/integer.hpp>
|
|
#include <pantheios/inserters/real.hpp>
|
|
|
|
namespace mrmc {
|
|
|
|
namespace parser{
|
|
|
|
// Disable C4996 - This function or variable may be unsafe.
|
|
#pragma warning(disable:4996)
|
|
|
|
/*!
|
|
* This method does the first pass through the .tra file and computes
|
|
* the number of non zero elements that are not diagonal elements,
|
|
* which correspondents to the number of transitions that are not
|
|
* self-loops.
|
|
* (Diagonal elements are treated in a special way).
|
|
*
|
|
* @return The number of non-zero elements that are not on the diagonal
|
|
* @param p File stream to scan. Is expected to be opened, a NULL pointer will
|
|
* be rejected!
|
|
*/
|
|
static uint_fast32_t make_first_pass(FILE* p) {
|
|
if(p==NULL) {
|
|
pantheios::log_ERROR("make_first_pass was called with NULL! (SHOULD NEVER HAPPEN)");
|
|
throw exceptions::file_IO_exception ("make_first_pass: File not readable (this should be checked before calling this function!)");
|
|
}
|
|
char s[1024]; //String buffer
|
|
uint_fast32_t rows=0, non_zero=0;
|
|
|
|
//Reading No. of states
|
|
if (fgets(s, 1024, p) != NULL) {
|
|
if (sscanf( s, "STATES %d", &rows) == 0) {
|
|
pantheios::log_WARNING(pantheios::integer(rows));
|
|
throw mrmc::exceptions::wrong_file_format();
|
|
}
|
|
}
|
|
|
|
//Reading No. of transitions
|
|
if (fgets(s, 1024, p) != NULL) {
|
|
if (sscanf( s, "TRANSITIONS %d", &non_zero) == 0) {
|
|
throw mrmc::exceptions::wrong_file_format();
|
|
}
|
|
}
|
|
|
|
//Reading transitions (one per line)
|
|
//And increase number of transitions
|
|
while (NULL != fgets( s, 1024, p ))
|
|
{
|
|
uint_fast32_t row=0, col=0;
|
|
double val=0.0;
|
|
if (sscanf( s, "%d%d%lf", &row, &col, &val ) != 3) {
|
|
throw mrmc::exceptions::wrong_file_format();
|
|
}
|
|
//Diagonal elements are not counted into the result!
|
|
if(row == col) {
|
|
--non_zero;
|
|
}
|
|
}
|
|
return non_zero;
|
|
}
|
|
|
|
|
|
|
|
/*!Reads a .tra file and produces a sparse matrix representing the described Markov Chain.
|
|
* @param *filename input .tra file's name.
|
|
* @return a pointer to a sparse matrix.
|
|
*/
|
|
|
|
sparse::StaticSparseMatrix<double> * read_tra_file(const char * filename) {
|
|
FILE *p;
|
|
char s[1024];
|
|
uint_fast32_t rows, non_zero;
|
|
sparse::StaticSparseMatrix<double> *sp = NULL;
|
|
|
|
p = fopen(filename, "r");
|
|
if(p==NULL) {
|
|
pantheios::log_ERROR("File ", filename, " was not readable (Does it exist?)");
|
|
throw exceptions::file_IO_exception("mrmc::read_tra_file: Error opening file! (Does it exist?)");
|
|
}
|
|
non_zero = make_first_pass(p);
|
|
|
|
//Set file reader back to the beginning
|
|
rewind(p);
|
|
|
|
//Reading No. of states
|
|
if (fgets(s, 1024, p) != NULL) {
|
|
if (sscanf( s, "STATES %d", &rows) == 0) {
|
|
pantheios::log_WARNING(pantheios::integer(rows));
|
|
throw mrmc::exceptions::wrong_file_format();
|
|
}
|
|
}
|
|
|
|
/* Reading No. of transitions
|
|
* Note that the result is not used in this function as make_first_pass()
|
|
* computes the relevant number (non_zero)
|
|
*/
|
|
if (fgets(s, 1024, p) != NULL) {
|
|
uint_fast32_t nnz=0;
|
|
if (sscanf( s, "TRANSITIONS %d", &nnz) == 0) {
|
|
throw mrmc::exceptions::wrong_file_format();
|
|
}
|
|
}
|
|
|
|
pantheios::log_DEBUG("Creating matrix with ",
|
|
pantheios::integer(rows), " rows and ",
|
|
pantheios::integer(non_zero), " Non-Zero-Elements");
|
|
/* Creating matrix
|
|
* Variable non_zero does NOT count any diagonal element,
|
|
* But all diagonal elements are allocated, so the number of allocated
|
|
* elements is non_zero
|
|
*/
|
|
sp = new sparse::StaticSparseMatrix<double>(rows,non_zero);
|
|
sp->initialize();
|
|
if ( NULL == sp ) {
|
|
throw std::bad_alloc();
|
|
return NULL;
|
|
}
|
|
|
|
//Reading transitions (one per line) and saving the results in the matrix
|
|
while (NULL != fgets( s, 1024, p ))
|
|
{
|
|
uint_fast32_t row=0, col=0;
|
|
double val = 0.0;
|
|
if (sscanf( s, "%d%d%lf", &row, &col, &val) != 3) {
|
|
throw mrmc::exceptions::wrong_file_format();
|
|
}
|
|
pantheios::log_DEBUG("Write value ",
|
|
pantheios::real(val),
|
|
" to position ",
|
|
pantheios::integer(row), " x ",
|
|
pantheios::integer(col));
|
|
sp->addNextValue(row,col,val);
|
|
}
|
|
|
|
(void)fclose(p);
|
|
|
|
pantheios::log_DEBUG("Finalizing Matrix");
|
|
sp->finalize();
|
|
return sp;
|
|
}
|
|
|
|
} //namespace parser
|
|
|
|
} //namespace mrmc
|