#include "src/storage/dd/sylvan/InternalSylvanDdManager.h" #include #include "src/settings/SettingsManager.h" #include "src/settings/modules/SylvanSettings.h" #include "src/utility/constants.h" #include "src/utility/macros.h" #include "src/exceptions/NotSupportedException.h" #include "src/utility/sylvan.h" #include "storm-config.h" // TODO: Remove this later on. #ifndef STORM_HAVE_CARL #define STORM_HAVE_CARL 1 #endif namespace storm { namespace dd { uint_fast64_t InternalDdManager::numberOfInstances = 0; // It is important that the variable pairs start at an even offset, because sylvan assumes this to be true for // some operations. uint_fast64_t InternalDdManager::nextFreeVariableIndex = 0; uint_fast64_t findLargestPowerOfTwoFitting(uint_fast64_t number) { for (uint_fast64_t index = 0; index < 64; ++index) { if ((number & (1ull << (63 - index))) != 0) { return 63 - index; } } return 0; } InternalDdManager::InternalDdManager() { if (numberOfInstances == 0) { // Initialize lace: auto-detect number of workers. lace_init(storm::settings::getModule().getNumberOfThreads(), 1000000); lace_startup(0, 0, 0); // Each node takes 24 bytes and the maximal memory is specified in megabytes. uint_fast64_t totalNodesToStore = storm::settings::getModule().getMaximalMemory() * 1024 * 1024 / 24; // Compute the power of two that still fits within the total numbers to store. uint_fast64_t powerOfTwo = findLargestPowerOfTwoFitting(totalNodesToStore); sylvan::Sylvan::initPackage(1ull << std::max(16ull, powerOfTwo > 24 ? powerOfTwo - 8 : 0ull), 1ull << (powerOfTwo - 1), 1ull << std::max(16ull, powerOfTwo > 24 ? powerOfTwo - 12 : 0ull), 1ull << (powerOfTwo - 1)); sylvan::Sylvan::initBdd(1); sylvan::Sylvan::initMtbdd(); } ++numberOfInstances; } InternalDdManager::~InternalDdManager() { --numberOfInstances; if (numberOfInstances == 0) { // Enable this to print the sylvan statistics to a file. // FILE* filePointer = fopen("sylvan.stats", "w"); // sylvan_stats_report(filePointer, 0); // fclose(filePointer); sylvan::Sylvan::quitPackage(); lace_exit(); } } InternalBdd InternalDdManager::getBddOne() const { return InternalBdd(this, sylvan::Bdd::bddOne()); } template<> InternalAdd InternalDdManager::getAddOne() const { return InternalAdd(this, sylvan::Mtbdd::doubleTerminal(storm::utility::one())); } template<> InternalAdd InternalDdManager::getAddOne() const { return InternalAdd(this, sylvan::Mtbdd::int64Terminal(storm::utility::one())); } #ifdef STORM_HAVE_CARL template<> InternalAdd InternalDdManager::getAddOne() const { storm::RationalFunction rationalFunction = storm::utility::one(); storm_rational_function_ptr_struct helperStruct; helperStruct.storm_rational_function = static_cast(&rationalFunction); return InternalAdd(this, sylvan::Mtbdd::terminal(sylvan_storm_rational_function_get_type(), helperStruct)); } #endif InternalBdd InternalDdManager::getBddZero() const { return InternalBdd(this, sylvan::Bdd::bddZero()); } template<> InternalAdd InternalDdManager::getAddZero() const { return InternalAdd(this, sylvan::Mtbdd::doubleTerminal(storm::utility::zero())); } template<> InternalAdd InternalDdManager::getAddZero() const { return InternalAdd(this, sylvan::Mtbdd::int64Terminal(storm::utility::zero())); } #ifdef STORM_HAVE_CARL template<> InternalAdd InternalDdManager::getAddZero() const { storm::RationalFunction rationalFunction = storm::utility::zero(); storm_rational_function_ptr_struct helperStruct; helperStruct.storm_rational_function = static_cast(&rationalFunction); return InternalAdd(this, sylvan::Mtbdd::terminal(sylvan_storm_rational_function_get_type(), helperStruct)); } #endif template<> InternalAdd InternalDdManager::getConstant(double const& value) const { return InternalAdd(this, sylvan::Mtbdd::doubleTerminal(value)); } template<> InternalAdd InternalDdManager::getConstant(uint_fast64_t const& value) const { return InternalAdd(this, sylvan::Mtbdd::int64Terminal(value)); } #ifdef STORM_HAVE_CARL template<> InternalAdd InternalDdManager::getConstant(storm::RationalFunction const& value) const { storm::RationalFunction rationalFunction = value; storm_rational_function_ptr_struct helperStruct; helperStruct.storm_rational_function = static_cast(&rationalFunction); return InternalAdd(this, sylvan::Mtbdd::terminal(sylvan_storm_rational_function_get_type(), helperStruct)); } #endif std::pair, InternalBdd> InternalDdManager::createNewDdVariablePair() { InternalBdd first = InternalBdd(this, sylvan::Bdd::bddVar(nextFreeVariableIndex)); InternalBdd second = InternalBdd(this, sylvan::Bdd::bddVar(nextFreeVariableIndex + 1)); nextFreeVariableIndex += 2; return std::make_pair(first, second); } void InternalDdManager::allowDynamicReordering(bool value) { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan."); } bool InternalDdManager::isDynamicReorderingAllowed() const { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan."); } void InternalDdManager::triggerReordering() { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation is not supported by sylvan."); } template InternalAdd InternalDdManager::getAddOne() const; template InternalAdd InternalDdManager::getAddOne() const; #ifdef STORM_HAVE_CARL template InternalAdd InternalDdManager::getAddOne() const; #endif template InternalAdd InternalDdManager::getAddZero() const; template InternalAdd InternalDdManager::getAddZero() const; #ifdef STORM_HAVE_CARL template InternalAdd InternalDdManager::getAddZero() const; #endif template InternalAdd InternalDdManager::getConstant(double const& value) const; template InternalAdd InternalDdManager::getConstant(uint_fast64_t const& value) const; #ifdef STORM_HAVE_CARL template InternalAdd InternalDdManager::getConstant(storm::RationalFunction const& value) const; #endif } }