Browse Source
			
			
			first version of NonDeterministicSparseTransitionParser
			
				
		first version of NonDeterministicSparseTransitionParser
	
		
	
			
				This parser shall parse transition systems having transitions of the form <from> <choice> <to> <probability> Where every node <from> can first decide nondeterministically on a <choice>. Then, for every <choice> he has a given set of nodes <to> with assigned <probability>. While the parsing itself works and the number of non-zero non-diagonal entries for each choice class works, we have not decided on the exact way to store such transition systems in matrices...main
				 2 changed files with 244 additions and 0 deletions
			
			
		- 
					207src/parser/NonDeterministicSparseTransitionParser.cpp
- 
					37src/parser/NonDeterministicSparseTransitionParser.h
| @ -0,0 +1,207 @@ | |||||
|  | /*!
 | ||||
|  |  *	TraParser.cpp | ||||
|  |  * | ||||
|  |  *	Created on: 20.11.2012 | ||||
|  |  *		Author: Gereon Kremer | ||||
|  |  */ | ||||
|  | 
 | ||||
|  | #include "src/parser/NonDeterministicSparseTransitionParser.h"
 | ||||
|  | #include "src/exceptions/FileIoException.h"
 | ||||
|  | #include "src/exceptions/WrongFileFormatException.h"
 | ||||
|  | #include "boost/integer/integer_mask.hpp"
 | ||||
|  | #include <cstdlib>
 | ||||
|  | #include <cstdio>
 | ||||
|  | #include <cstring>
 | ||||
|  | #include <clocale>
 | ||||
|  | #include <iostream>
 | ||||
|  | #include <errno.h>
 | ||||
|  | #include <time.h>
 | ||||
|  | #include <sys/stat.h>
 | ||||
|  | #include <fcntl.h>
 | ||||
|  | #include <locale.h>
 | ||||
|  | 
 | ||||
|  | #include "log4cplus/logger.h"
 | ||||
|  | #include "log4cplus/loggingmacros.h"
 | ||||
|  | extern log4cplus::Logger logger; | ||||
|  | 
 | ||||
|  | namespace mrmc { | ||||
|  | namespace parser{ | ||||
|  | 
 | ||||
|  | /*!
 | ||||
|  |  *	@brief	Perform first pass through the file and obtain number of | ||||
|  |  *	non-zero cells and maximum node id. | ||||
|  |  * | ||||
|  |  *	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). | ||||
|  |  *	It also calculates the maximum node id and stores it in maxnode. | ||||
|  |  *	It also stores the maximum number of nondeterministic choices for a | ||||
|  |  *	single single node in maxchoices. | ||||
|  |  * | ||||
|  |  *	@return The number of non-zero elements that are not on the diagonal | ||||
|  |  *	@param buf Data to scan. Is expected to be some char array. | ||||
|  |  *	@param maxnode Is set to highest id of all nodes. | ||||
|  |  */ | ||||
|  | std::unique_ptr<std::vector<uint_fast64_t>> NonDeterministicSparseTransitionParser::firstPass(char* buf, uint_fast64_t &maxnode, uint_fast64_t &maxchoice) { | ||||
|  | 	std::unique_ptr<std::vector<uint_fast64_t>> non_zero = std::unique_ptr<std::vector<uint_fast64_t>>(new std::vector<uint_fast64_t>()); | ||||
|  | 	 | ||||
|  | 	/*
 | ||||
|  | 	 *	check file header and extract number of transitions | ||||
|  | 	 */ | ||||
|  | 	if (strncmp(buf, "STATES ", 7) != 0) { | ||||
|  | 		LOG4CPLUS_ERROR(logger, "Expected \"STATES\" but got \"" << std::string(buf, 0, 16) << "\"."); | ||||
|  | 		return nullptr; | ||||
|  | 	} | ||||
|  | 	buf += 7; // skip "STATES "
 | ||||
|  | 	if (strtol(buf, &buf, 10) == 0) return 0; | ||||
|  | 	buf = trimWhitespaces(buf); | ||||
|  | 	if (strncmp(buf, "TRANSITIONS ", 12) != 0) { | ||||
|  | 		LOG4CPLUS_ERROR(logger, "Expected \"TRANSITIONS\" but got \"" << std::string(buf, 0, 16) << "\"."); | ||||
|  | 		return 0; | ||||
|  | 	} | ||||
|  | 	buf += 12; // skip "TRANSITIONS "
 | ||||
|  | 	strtol(buf, &buf, 10); | ||||
|  | 	 | ||||
|  | 	/*
 | ||||
|  | 	 *	check all transitions for non-zero diagonal entrys | ||||
|  | 	 */ | ||||
|  | 	uint_fast64_t row, col, ndchoice; | ||||
|  | 	double val; | ||||
|  | 	maxnode = 0; | ||||
|  | 	maxchoice = 0; | ||||
|  | 	char* tmp; | ||||
|  | 	while (buf[0] != '\0') { | ||||
|  | 		/*
 | ||||
|  | 		 *	read row and column | ||||
|  | 		 */ | ||||
|  | 		row = checked_strtol(buf, &buf); | ||||
|  | 		ndchoice = checked_strtol(buf, &buf); | ||||
|  | 		col = checked_strtol(buf, &buf); | ||||
|  | 		/*
 | ||||
|  | 		 *	check if one is larger than the current maximum id | ||||
|  | 		 */ | ||||
|  | 		if (row > maxnode) maxnode = row; | ||||
|  | 		if (col > maxnode) maxnode = col; | ||||
|  | 		/*
 | ||||
|  | 		 *	check if nondeterministic choice is larger than current maximum | ||||
|  | 		 */ | ||||
|  | 		if (ndchoice > maxchoice) | ||||
|  | 		{ | ||||
|  | 			maxchoice = ndchoice; | ||||
|  | 			while (non_zero->size() < maxchoice) non_zero->push_back(0); | ||||
|  | 		} | ||||
|  | 		/*
 | ||||
|  | 		 *	read value. if value is 0.0, either strtod could not read a number or we encountered a probability of zero. | ||||
|  | 		 *	if row == col, we have a diagonal element which is treated separately and this non_zero must be decreased. | ||||
|  | 		 */ | ||||
|  | 		val = strtod(buf, &tmp); | ||||
|  | 		if (val == 0.0) { | ||||
|  | 			LOG4CPLUS_ERROR(logger, "Expected a positive probability but got \"" << std::string(buf, 0, 16) << "\"."); | ||||
|  | 			return 0; | ||||
|  | 		} | ||||
|  | 		if (row != col) (*non_zero)[ndchoice-1]++; | ||||
|  | 		buf = trimWhitespaces(tmp); | ||||
|  | 	} | ||||
|  | 
 | ||||
|  | 	return non_zero; | ||||
|  | } | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | /*!
 | ||||
|  |  *	Reads a .tra file and produces a sparse matrix representing the described Markov Chain. | ||||
|  |  * | ||||
|  |  *	Matrices created with this method have to be freed with the delete operator. | ||||
|  |  *	@param filename input .tra file's name. | ||||
|  |  *	@return a pointer to the created sparse matrix. | ||||
|  |  */ | ||||
|  | 
 | ||||
|  | NonDeterministicSparseTransitionParser::NonDeterministicSparseTransitionParser(std::string const &filename) | ||||
|  | 	: matrix(nullptr) | ||||
|  | { | ||||
|  | 	/*
 | ||||
|  | 	*	enforce locale where decimal point is '.' | ||||
|  | 	*/ | ||||
|  | 	setlocale( LC_NUMERIC, "C" ); | ||||
|  | 	 | ||||
|  | 	/*
 | ||||
|  | 	 *	open file | ||||
|  | 	 */ | ||||
|  | 	MappedFile file(filename.c_str()); | ||||
|  | 	char* buf = file.data; | ||||
|  | 	 | ||||
|  | 	/*
 | ||||
|  | 	 *	perform first pass, i.e. count entries that are not zero and not on the diagonal | ||||
|  | 	 */ | ||||
|  | 	uint_fast64_t maxnode, maxchoices; | ||||
|  | 	std::unique_ptr<std::vector<uint_fast64_t>> non_zero = this->firstPass(file.data, maxnode, maxchoices); | ||||
|  | 	 | ||||
|  | 	/*
 | ||||
|  | 	 *	if first pass returned zero, the file format was wrong | ||||
|  | 	 */ | ||||
|  | 	if (non_zero == nullptr) | ||||
|  | 	{ | ||||
|  | 		LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": erroneous file format."); | ||||
|  | 		throw mrmc::exceptions::WrongFileFormatException(); | ||||
|  | 	} | ||||
|  | 	 | ||||
|  | 	/*
 | ||||
|  | 	 *	perform second pass | ||||
|  | 	 *	 | ||||
|  | 	 *	from here on, we already know that the file header is correct | ||||
|  | 	 */ | ||||
|  | 
 | ||||
|  | 	/*
 | ||||
|  | 	 *	read file header, extract number of states | ||||
|  | 	 */ | ||||
|  | 	buf += 7; // skip "STATES "
 | ||||
|  | 	checked_strtol(buf, &buf); | ||||
|  | 	buf = trimWhitespaces(buf); | ||||
|  | 	buf += 12; // skip "TRANSITIONS "
 | ||||
|  | 	checked_strtol(buf, &buf); | ||||
|  | 	 | ||||
|  | 	/*
 | ||||
|  | 	 *	Creating matrix | ||||
|  | 	 *	Memory for diagonal elements is automatically allocated, hence only the number of non-diagonal | ||||
|  | 	 *	non-zero elements has to be specified (which is non_zero, computed by make_first_pass) | ||||
|  | 	 */ | ||||
|  | 	LOG4CPLUS_INFO(logger, "Attempting to create matrix of size " << (maxnode+1) << " x " << (maxnode+1) << "."); | ||||
|  | 	this->matrix = std::shared_ptr<mrmc::storage::SquareSparseMatrix<double>>(new mrmc::storage::SquareSparseMatrix<double>(maxnode + 1)); | ||||
|  | 	if (this->matrix == NULL) | ||||
|  | 	{ | ||||
|  | 		LOG4CPLUS_ERROR(logger, "Could not create matrix of size " << (maxnode+1) << " x " << (maxnode+1) << "."); | ||||
|  | 		throw std::bad_alloc(); | ||||
|  | 	} | ||||
|  | 	// TODO: put stuff in matrix / matrices.
 | ||||
|  | 	//this->matrix->initialize(*non_zero);
 | ||||
|  | 
 | ||||
|  | 	uint_fast64_t row, col, ndchoice; | ||||
|  | 	double val; | ||||
|  | 
 | ||||
|  | 	/*
 | ||||
|  | 	 *	read all transitions from file | ||||
|  | 	 */ | ||||
|  | 	while (buf[0] != '\0') | ||||
|  | 	{ | ||||
|  | 		/*
 | ||||
|  | 		 *	read row, col and value. | ||||
|  | 		 */ | ||||
|  | 		row = checked_strtol(buf, &buf); | ||||
|  | 		ndchoice = checked_strtol(buf, &buf); | ||||
|  | 		col = checked_strtol(buf, &buf); | ||||
|  | 		val = strtod(buf, &buf); | ||||
|  | 		 | ||||
|  | 		//this->matrix->addNextValue(row,col,val);
 | ||||
|  | 		buf = trimWhitespaces(buf); | ||||
|  | 	} | ||||
|  | 	 | ||||
|  | 	/*
 | ||||
|  | 	 * clean up | ||||
|  | 	 */	 | ||||
|  | 	//this->matrix->finalize();
 | ||||
|  | } | ||||
|  | 
 | ||||
|  | } //namespace parser
 | ||||
|  | } //namespace mrmc
 | ||||
| @ -0,0 +1,37 @@ | |||||
|  | #ifndef MRMC_PARSER_NONDETTRAPARSER_H_ | ||||
|  | #define MRMC_PARSER_NONDETTRAPARSER_H_ | ||||
|  | 
 | ||||
|  | #include "src/storage/SquareSparseMatrix.h" | ||||
|  | 
 | ||||
|  | #include "src/parser/Parser.h" | ||||
|  | #include "src/utility/OsDetection.h" | ||||
|  | 
 | ||||
|  | #include <memory> | ||||
|  | #include <vector> | ||||
|  | 
 | ||||
|  | namespace mrmc { | ||||
|  | namespace parser { | ||||
|  | 	 | ||||
|  | /*! | ||||
|  |  *	@brief	Load a nondeterministic transition system from file and create a | ||||
|  |  *	sparse adjacency matrix whose entries represent the weights of the edges | ||||
|  |  */ | ||||
|  | class NonDeterministicSparseTransitionParser : Parser { | ||||
|  | 	public: | ||||
|  | 		NonDeterministicSparseTransitionParser(std::string const &filename); | ||||
|  | 		 | ||||
|  | 		std::shared_ptr<mrmc::storage::SquareSparseMatrix<double>> getMatrix() { | ||||
|  | 			return this->matrix; | ||||
|  | 		} | ||||
|  | 	 | ||||
|  | 	private: | ||||
|  | 		std::shared_ptr<mrmc::storage::SquareSparseMatrix<double>> matrix; | ||||
|  | 		 | ||||
|  | 		std::unique_ptr<std::vector<uint_fast64_t>> firstPass(char* buf, uint_fast64_t &maxnode, uint_fast64_t &maxchoice); | ||||
|  | 	 | ||||
|  | }; | ||||
|  | 		 | ||||
|  | } // namespace parser | ||||
|  | } // namespace mrmc | ||||
|  | 
 | ||||
|  | #endif /* MRMC_PARSER_NONDETTRAPARSER_H_ */ | ||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue