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.
 
 
 
 

231 lines
11 KiB

#include "storm/parser/DirectEncodingParser.h"
#include <iostream>
#include <string>
#include "storm/models/sparse/MarkovAutomaton.h"
#include "storm/models/sparse/Ctmc.h"
#include "storm/exceptions/FileIoException.h"
#include "storm/exceptions/WrongFormatException.h"
#include "storm/exceptions/InvalidArgumentException.h"
#include "storm/exceptions/NotSupportedException.h"
#include "storm/settings/SettingsManager.h"
#include "storm/adapters/CarlAdapter.h"
#include "storm/utility/constants.h"
#include "storm/utility/macros.h"
#include "storm/utility/file.h"
namespace storm {
namespace parser {
template<typename ValueType>
void ValueParser<ValueType>::addParameter(std::string const& parameter) {
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Parameters are not supported in this build.");
}
template<>
void ValueParser<storm::RationalFunction>::addParameter(std::string const& parameter) {
//STORM_LOG_THROW((std::is_same<ValueType, storm::RationalFunction>::value), storm::exceptions::NotSupportedException, "Parameters only allowed when using rational functions.");
storm::expressions::Variable var = manager->declareRationalVariable(parameter);
identifierMapping.emplace(var.getName(), var);
parser.setIdentifierMapping(identifierMapping);
STORM_LOG_TRACE("Added parameter: " << var.getName());
}
template<>
double ValueParser<double>::parseValue(std::string const& value) const {
return boost::lexical_cast<double>(value);
}
template<>
storm::RationalFunction ValueParser<storm::RationalFunction>::parseValue(std::string const& value) const {
storm::RationalFunction rationalFunction = evaluator.asRational(parser.parseFromString(value));
STORM_LOG_TRACE("Parsed expression: " << rationalFunction);
return rationalFunction;
}
template<typename ValueType, typename RewardModelType>
std::shared_ptr<storm::models::sparse::Model<ValueType, RewardModelType>> DirectEncodingParser<ValueType, RewardModelType>::parseModel(std::string const& filename) {
// Load file
STORM_LOG_INFO("Reading from file " << filename);
std::ifstream file;
storm::utility::openFile(filename, file);
std::string line;
// Initialize
ValueParser<ValueType> valueParser;
// Parse header
std::getline(file, line);
STORM_LOG_THROW(line == "// Exported by storm", storm::exceptions::WrongFormatException, "Expected header information.");
std::getline(file, line);
STORM_LOG_THROW(boost::starts_with(line, "// Original model type: "), storm::exceptions::WrongFormatException, "Expected header information.");
// Parse model type
std::getline(file, line);
STORM_LOG_THROW(boost::starts_with(line, "@type: "), storm::exceptions::WrongFormatException, "Expected model type.");
storm::models::ModelType type = storm::models::getModelType(line.substr(7));
STORM_LOG_TRACE("Model type: " << type);
// Parse parameters
std::getline(file, line);
STORM_LOG_THROW(line == "@parameters", storm::exceptions::WrongFormatException, "Expected parameter declaration.");
std::getline(file, line);
if (line != "") {
std::vector<std::string> parameters;
boost::split(parameters, line, boost::is_any_of(" "));
for (std::string parameter : parameters) {
STORM_LOG_TRACE("New parameter: " << parameter);
valueParser.addParameter(parameter);
}
}
// Parse no. states
std::getline(file, line);
STORM_LOG_THROW(line == "@nr_states", storm::exceptions::WrongFormatException, "Expected number of states.");
std::getline(file, line);
size_t nrStates = boost::lexical_cast<size_t>(line);
STORM_LOG_TRACE("Model type: " << type);
std::getline(file, line);
STORM_LOG_THROW(line == "@model", storm::exceptions::WrongFormatException, "Expected model declaration.");
// Construct transition matrix
std::shared_ptr<storm::storage::sparse::ModelComponents<ValueType, RewardModelType>> modelComponents = parseStates(file, type, nrStates, valueParser);
// Done parsing
storm::utility::closeFile(file);
// Build model
switch (type) {
case storm::models::ModelType::Dtmc:
{
STORM_LOG_THROW(false, storm::exceptions::FileIoException, "DTMC not supported.");
}
case storm::models::ModelType::Ctmc:
{
modelComponents->rateTransitions = true;
return std::make_shared<storm::models::sparse::Ctmc<ValueType, RewardModelType>>(std::move(*modelComponents));
}
case storm::models::ModelType::Mdp:
{
STORM_LOG_THROW(false, storm::exceptions::FileIoException, "MDP not supported.");
}
case storm::models::ModelType::MarkovAutomaton:
{
modelComponents->rateTransitions = true;
return std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType, RewardModelType>>(std::move(*modelComponents));
}
default:
STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Unknown/Unhandled model type " << type << " which cannot be parsed.");
}
}
template<typename ValueType, typename RewardModelType>
std::shared_ptr<storm::storage::sparse::ModelComponents<ValueType, RewardModelType>> DirectEncodingParser<ValueType, RewardModelType>::parseStates(std::istream& file, storm::models::ModelType type, size_t stateSize, ValueParser<ValueType> const& valueParser) {
// Initialize
auto modelComponents = std::make_shared<storm::storage::sparse::ModelComponents<ValueType, RewardModelType>>();
bool nonDeterministic = (type == storm::models::ModelType::Mdp || type == storm::models::ModelType::MarkovAutomaton);
storm::storage::SparseMatrixBuilder<ValueType> builder = storm::storage::SparseMatrixBuilder<ValueType>(0, 0, 0, false, nonDeterministic, 0);
modelComponents->stateLabeling = storm::models::sparse::StateLabeling(stateSize);
// Iterate over all lines
std::string line;
size_t row = 0;
size_t state = 0;
bool first = true;
while (std::getline(file, line)) {
STORM_LOG_TRACE("Parsing: " << line);
if (boost::starts_with(line, "state ")) {
// New state
if (first) {
first = false;
} else {
++state;
}
line = line.substr(6);
size_t parsedId;
size_t posId = line.find(" ");
if (posId != std::string::npos) {
parsedId = boost::lexical_cast<size_t>(line.substr(0, posId));
// Parse rewards and labels
line = line.substr(posId+1);
// Check for rewards
if (boost::starts_with(line, "[")) {
// Rewards found
size_t posEndReward = line.find(']');
STORM_LOG_THROW(posEndReward != std::string::npos, storm::exceptions::WrongFormatException, "] missing.");
std::string rewards = line.substr(1, posEndReward-1);
STORM_LOG_TRACE("State rewards: " << rewards);
// TODO import rewards
STORM_LOG_WARN("Rewards were not imported");
line = line.substr(posEndReward+1);
}
// Check for labels
std::vector<std::string> labels;
boost::split(labels, line, boost::is_any_of(" "));
for (std::string label : labels) {
if (!modelComponents->stateLabeling.containsLabel(label)) {
modelComponents->stateLabeling.addLabel(label);
}
modelComponents->stateLabeling.addLabelToState(label, state);
STORM_LOG_TRACE("New label: " << label);
}
} else {
// Only state id given
parsedId = boost::lexical_cast<size_t>(line);
}
STORM_LOG_TRACE("New state " << state);
STORM_LOG_ASSERT(state == parsedId, "State ids do not correspond.");
if (nonDeterministic) {
builder.newRowGroup(row);
}
} else if (boost::starts_with(line, "\taction ")) {
// New action
if (first) {
first = false;
} else {
++row;
}
line = line.substr(8);
STORM_LOG_TRACE("New action: " << row);
// Check for rewards
if (boost::starts_with(line, "[")) {
// Rewards found
size_t posEndReward = line.find(']');
STORM_LOG_THROW(posEndReward != std::string::npos, storm::exceptions::WrongFormatException, "] missing.");
std::string rewards = line.substr(1, posEndReward-1);
STORM_LOG_TRACE("Transition rewards: " << rewards);
// TODO save rewards
line = line.substr(posEndReward+1);
}
// TODO import choice labeling when the export works
} else {
// New transition
size_t posColon = line.find(":");
STORM_LOG_ASSERT(posColon != std::string::npos, "':' not found.");
size_t target = boost::lexical_cast<size_t>(line.substr(2, posColon-3));
std::string valueStr = line.substr(posColon+2);
ValueType value = valueParser.parseValue(valueStr);
STORM_LOG_TRACE("Transition " << state << " -> " << target << ": " << value);
builder.addNextValue(state, target, value);
}
}
STORM_LOG_TRACE("Finished parsing");
modelComponents->transitionMatrix = builder.build(stateSize, stateSize);
STORM_LOG_TRACE("Built matrix");
return modelComponents;
}
// Template instantiations.
template class DirectEncodingParser<double>;
#ifdef STORM_HAVE_CARL
template class DirectEncodingParser<storm::RationalFunction>;
#endif
} // namespace parser
} // namespace storm