/* * File: ParameterRegion.cpp * Author: tim * * Created on August 10, 2015, 1:51 PM */ #include "src/modelchecker/region/ParameterRegion.h" #include "src/utility/region.h" #include "src/utility/macros.h" #include "src/parser/MappedFile.h" #include "src/settings/SettingsManager.h" #include "src/settings/modules/RegionSettings.h" #include "src/exceptions/InvalidSettingsException.h" #include "src/exceptions/InvalidArgumentException.h" namespace storm { namespace modelchecker { namespace region { template ParameterRegion::ParameterRegion(VariableSubstitutionType const& lowerBoundaries, VariableSubstitutionType const& upperBoundaries) : lowerBoundaries(lowerBoundaries), upperBoundaries(upperBoundaries), checkResult(RegionCheckResult::UNKNOWN) { init(); } template ParameterRegion::ParameterRegion(VariableSubstitutionType&& lowerBoundaries, VariableSubstitutionType&& upperBoundaries) : lowerBoundaries(std::move(lowerBoundaries)), upperBoundaries(std::move(upperBoundaries)), checkResult(RegionCheckResult::UNKNOWN) { init(); } template void ParameterRegion::init() { //check whether both mappings map the same variables, check that lowerboundary <= upper boundary, and pre-compute the set of variables for (auto const& variableWithLowerBoundary : this->lowerBoundaries) { auto variableWithUpperBoundary = this->upperBoundaries.find(variableWithLowerBoundary.first); STORM_LOG_THROW((variableWithUpperBoundary != upperBoundaries.end()), storm::exceptions::InvalidArgumentException, "Couldn't create region. No upper boundary specified for Variable " << variableWithLowerBoundary.first); STORM_LOG_THROW((variableWithLowerBoundary.second<=variableWithUpperBoundary->second), storm::exceptions::InvalidArgumentException, "Couldn't create region. The lower boundary for " << variableWithLowerBoundary.first << " is larger then the upper boundary"); this->variables.insert(variableWithLowerBoundary.first); } for (auto const& variableWithBoundary : this->upperBoundaries) { STORM_LOG_THROW((this->variables.find(variableWithBoundary.first) != this->variables.end()), storm::exceptions::InvalidArgumentException, "Couldn't create region. No lower boundary specified for Variable " << variableWithBoundary.first); } } template ParameterRegion::~ParameterRegion() { //Intentionally left empty } template std::set::VariableType> ParameterRegion::getVariables() const { return this->variables; } template typename ParameterRegion::CoefficientType const& ParameterRegion::getLowerBoundary(VariableType const& variable) const { auto const& result = lowerBoundaries.find(variable); STORM_LOG_THROW(result != lowerBoundaries.end(), storm::exceptions::InvalidArgumentException, "tried to find a lower boundary of a variable that is not specified by this region"); return (*result).second; } template typename ParameterRegion::CoefficientType const& ParameterRegion::getUpperBoundary(VariableType const& variable) const { auto const& result = upperBoundaries.find(variable); STORM_LOG_THROW(result != upperBoundaries.end(), storm::exceptions::InvalidArgumentException, "tried to find an upper boundary of a variable that is not specified by this region"); return (*result).second; } template const typename ParameterRegion::VariableSubstitutionType ParameterRegion::getUpperBoundaries() const { return upperBoundaries; } template const typename ParameterRegion::VariableSubstitutionType ParameterRegion::getLowerBoundaries() const { return lowerBoundaries; } template std::vector::VariableSubstitutionType> ParameterRegion::getVerticesOfRegion(std::set const& consideredVariables) const { std::size_t const numOfVariables = consideredVariables.size(); std::size_t const numOfVertices = std::pow(2, numOfVariables); std::vector resultingVector(numOfVertices, VariableSubstitutionType()); if (numOfVertices == 1) { //no variables are given, the returned vector should still contain an empty map return resultingVector; } for (uint_fast64_t vertexId = 0; vertexId < numOfVertices; ++vertexId) { //interprete vertexId as a bit sequence //the consideredVariables.size() least significant bits of vertex will always represent the next vertex //(00...0 = lower boundaries for all variables, 11...1 = upper boundaries for all variables) std::size_t variableIndex = 0; for (auto const& variable : consideredVariables) { if ((vertexId >> variableIndex) % 2 == 0) { resultingVector[vertexId].insert(std::pair(variable, getLowerBoundary(variable))); } else { resultingVector[vertexId].insert(std::pair(variable, getUpperBoundary(variable))); } ++variableIndex; } } return resultingVector; } template typename ParameterRegion::VariableSubstitutionType ParameterRegion::getSomePoint() const { return this->getLowerBoundaries(); } template RegionCheckResult ParameterRegion::getCheckResult() const { return checkResult; } template void ParameterRegion::setCheckResult(RegionCheckResult checkResult) { //a few sanity checks STORM_LOG_THROW((this->checkResult == RegionCheckResult::UNKNOWN || checkResult != RegionCheckResult::UNKNOWN), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from something known to UNKNOWN "); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSSAT || checkResult != RegionCheckResult::EXISTSVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSSAT to EXISTSVIOLATED"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSSAT || checkResult != RegionCheckResult::ALLVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSSAT to ALLVIOLATED"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSVIOLATED || checkResult != RegionCheckResult::EXISTSSAT), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSVIOLATED to EXISTSSAT"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSVIOLATED || checkResult != RegionCheckResult::ALLSAT), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSVIOLATED to ALLSAT"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSBOTH || checkResult != RegionCheckResult::ALLSAT), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSBOTH to ALLSAT"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSBOTH || checkResult != RegionCheckResult::ALLVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSBOTH to ALLVIOLATED"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::ALLSAT || checkResult == RegionCheckResult::ALLSAT), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from ALLSAT to something else"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::ALLVIOLATED || checkResult == RegionCheckResult::ALLVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from ALLVIOLATED to something else"); this->checkResult = checkResult; } template typename ParameterRegion::VariableSubstitutionType ParameterRegion::getViolatedPoint() const { return violatedPoint; } template void ParameterRegion::setViolatedPoint(VariableSubstitutionType const& violatedPoint) { this->violatedPoint = violatedPoint; } template typename ParameterRegion::VariableSubstitutionType ParameterRegion::getSatPoint() const { return satPoint; } template void ParameterRegion::setSatPoint(VariableSubstitutionType const& satPoint) { this->satPoint = satPoint; } template void ParameterRegion::fixVariables(std::map const& fixedVariables) { this->fixedVariables = fixedVariables; } template std::map::VariableType, RegionBoundary> ParameterRegion::getFixedVariables() const { return fixedVariables; } template std::string ParameterRegion::toString() const { std::stringstream regionstringstream; for (auto var : this->getVariables()) { regionstringstream << storm::utility::region::convertNumber(this->getLowerBoundary(var)); regionstringstream << "<="; regionstringstream << storm::utility::region::getVariableName(var); regionstringstream << "<="; regionstringstream << storm::utility::region::convertNumber(this->getUpperBoundary(var)); regionstringstream << ","; } std::string regionstring = regionstringstream.str(); //the last comma should actually be a semicolon regionstring = regionstring.substr(0, regionstring.length() - 1) + ";"; return regionstring; } template void ParameterRegion::parseParameterBoundaries( VariableSubstitutionType& lowerBoundaries, VariableSubstitutionType& upperBoundaries, std::string const& parameterBoundariesString){ std::string::size_type positionOfFirstRelation = parameterBoundariesString.find("<="); STORM_LOG_THROW(positionOfFirstRelation!=std::string::npos, storm::exceptions::InvalidArgumentException, "When parsing the region" << parameterBoundariesString << " I could not find a '<=' after the first number"); std::string::size_type positionOfSecondRelation = parameterBoundariesString.find("<=", positionOfFirstRelation+2); STORM_LOG_THROW(positionOfSecondRelation!=std::string::npos, storm::exceptions::InvalidArgumentException, "When parsing the region" << parameterBoundariesString << " I could not find a '<=' after the parameter"); std::string parameter=parameterBoundariesString.substr(positionOfFirstRelation+2,positionOfSecondRelation-(positionOfFirstRelation+2)); //removes all whitespaces from the parameter string: parameter.erase(std::remove_if(parameter.begin(), parameter.end(), ::isspace), parameter.end()); STORM_LOG_THROW(parameter.length()>0, storm::exceptions::InvalidArgumentException, "When parsing the region" << parameterBoundariesString << " I could not find a parameter"); VariableType var = storm::utility::region::getVariableFromString(parameter); CoefficientType lb = storm::utility::region::convertNumber(parameterBoundariesString.substr(0,positionOfFirstRelation)); CoefficientType ub = storm::utility::region::convertNumber(parameterBoundariesString.substr(positionOfSecondRelation+2)); lowerBoundaries.emplace(std::make_pair(var, lb)); upperBoundaries.emplace(std::make_pair(var, ub)); } template ParameterRegion ParameterRegion::parseRegion( std::string const& regionString){ VariableSubstitutionType lowerBoundaries; VariableSubstitutionType upperBoundaries; std::vector parameterBoundaries; boost::split(parameterBoundaries, regionString, boost::is_any_of(",")); for(auto const& parameterBoundary : parameterBoundaries){ if(!std::all_of(parameterBoundary.begin(),parameterBoundary.end(), ::isspace)){ //skip this string if it only consists of space parseParameterBoundaries(lowerBoundaries, upperBoundaries, parameterBoundary); } } return ParameterRegion(std::move(lowerBoundaries), std::move(upperBoundaries)); } template std::vector> ParameterRegion::parseMultipleRegions( std::string const& regionsString){ std::vector result; std::vector regionsStrVec; boost::split(regionsStrVec, regionsString, boost::is_any_of(";")); for(auto const& regionStr : regionsStrVec){ if(!std::all_of(regionStr.begin(),regionStr.end(), ::isspace)){ //skip this string if it only consists of space result.emplace_back(parseRegion(regionStr)); } } return result; } template std::vector> ParameterRegion::getRegionsFromSettings(){ STORM_LOG_THROW(storm::settings::regionSettings().isRegionsSet() || storm::settings::regionSettings().isRegionFileSet(), storm::exceptions::InvalidSettingsException, "Tried to obtain regions from the settings but no regions are specified."); STORM_LOG_THROW(!(storm::settings::regionSettings().isRegionsSet() && storm::settings::regionSettings().isRegionFileSet()), storm::exceptions::InvalidSettingsException, "Regions are specified via file AND cmd line. Only one option is allowed."); std::string regionsString; if(storm::settings::regionSettings().isRegionsSet()){ regionsString = storm::settings::regionSettings().getRegionsFromCmdLine(); } else{ //if we reach this point we can assume that the region is given as a file. STORM_LOG_THROW(storm::parser::MappedFile::fileExistsAndIsReadable(storm::settings::regionSettings().getRegionFilePath().c_str()), storm::exceptions::InvalidSettingsException, "The path to the file in which the regions are specified is not valid."); storm::parser::MappedFile mf(storm::settings::regionSettings().getRegionFilePath().c_str()); regionsString = std::string(mf.getData(),mf.getDataSize()); } return parseMultipleRegions(regionsString); } #ifdef STORM_HAVE_CARL template class ParameterRegion; #endif } //namespace region } }