diff --git a/.gitignore b/.gitignore index d4d4d6429..a4327b775 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ resources/3rdparty/gtest-1.7.0/ resources/3rdparty/eigen/ resources/3rdparty/gmm-4.2/ resources/3rdparty/cudd-3.0.0/ -resources/3rdparty/carl/ resources/3rdparty/xercesc-3.1.2/ #Visual Studio files *.[Oo]bj diff --git a/CMakeLists.txt b/CMakeLists.txt index e512bc945..1ab7c6888 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/resources/cmak include(ExternalProject) include(RegisterSourceGroup) +include(imported) + ############################################################# ## @@ -34,7 +36,6 @@ option(USE_HYPRO "Sets whether HyPro should be included." OFF) option(XML_SUPPORT "Sets whether xml based format parsing should be included." ON) option(FORCE_COLOR "Force color output" OFF) mark_as_advanced(FORCE_COLOR) -option(STORM_PYTHON "Build the API for Python" OFF) option(STORM_COMPILE_WITH_CCACHE "Compile using CCache [if found]" ON) mark_as_advanced(STORM_COMPILE_WITH_CCACHE) option(STORM_LOG_DISABLE_DEBUG "Disable log and trace message support" OFF) @@ -55,10 +56,22 @@ mark_as_advanced(CMAKE_OSX_ARCHITECTURES) mark_as_advanced(CMAKE_OSX_SYSROOT) mark_as_advanced(CMAKE_OSX_DEPLOYMENT_TARGET) +# Offer the user the choice of overriding the installation directories +set(INCLUDE_INSTALL_DIR include/ CACHE PATH "Installation directory for header files" ) +set(LIB_INSTALL_DIR lib/ CACHE PATH "Installation directory for libraries") +#set(SYSCONFIG_INSTALL_DIR etc/carl/ CACHE PATH "Installation for system configuration files) +set(BIN_INSTALL_DIR lib/ CACHE PATH "Installation directory for executables") + + # By default, we build a release version. if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RELEASE") endif() +# Install dir for cmake files (info for other libraries that include storm) +set(DEF_INSTALL_CMAKE_DIR "lib/CMake/storm") +set(CMAKE_INSTALL_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") + +message("CMAKE_INSTALL_DIR: ${CMAKE_INSTALL_DIR}") # If the STORM_DEVELOPER option was turned on, we target a debug version. if (STORM_DEVELOPER) @@ -118,11 +131,6 @@ endif() message(STATUS "Assuming extension for shared libraries: ${DYNAMIC_EXT}") message(STATUS "Assuming extension for static libraries: ${STATIC_EXT}") -# Python bindings need shared library -if(STORM_PYTHON) - set(BUILD_SHARED_LIBS ON CACHE BOOL "Build the Storm library dynamically" FORCE) -endif() - if(BUILD_SHARED_LIBS) set(LIB_EXT ${DYNAMIC_EXT}) message(STATUS "Build dynamic libraries.") @@ -346,12 +354,14 @@ set(STORM_GENERATED_SOURCES "${PROJECT_BINARY_DIR}/src/storm/utility/storm-versi include_directories("${PROJECT_BINARY_DIR}/include") include(CTest) +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) +set(CMAKE_CTEST_COMMAND_VERBOSE ${CMAKE_CTEST_COMMAND} -V) +add_custom_target(check-verbose COMMAND ${CMAKE_CTEST_COMMAND_VERBOSE}) -# Python bindings for storm -if(STORM_PYTHON) - add_subdirectory(stormpy) -endif() +set(STORM_TARGETS "") add_subdirectory(src) +include(export) + include(StormCPackConfig.cmake) diff --git a/doc/build.md b/doc/build.md index 703f6ca0f..725794034 100644 --- a/doc/build.md +++ b/doc/build.md @@ -23,9 +23,11 @@ Prerequisites: ## Instructions ### General - -> mkdir build +```bash +mkdir build +cd build +``` It is recommended to make an out-of-source build, meaning that the folder in which CMake generates its Cache, Makefiles and output files should not be the Project Root nor its Source Directory. A typical build layout is to create a folder "build" in the project root alongside the CMakeLists.txt file, change into this folder and execute "cmake .." as this will leave all source files untouched diff --git a/resources/3rdparty/CMakeLists.txt b/resources/3rdparty/CMakeLists.txt index 8d414ea64..e6bd1c6f5 100644 --- a/resources/3rdparty/CMakeLists.txt +++ b/resources/3rdparty/CMakeLists.txt @@ -4,14 +4,6 @@ add_custom_target(test-resources) set(STORM_3RDPARTY_SOURCE_DIR ${PROJECT_SOURCE_DIR}/resources/3rdparty) set(STORM_3RDPARTY_BINARY_DIR ${PROJECT_BINARY_DIR}/resources/3rdparty) -if (STORM_PYTHON) - find_package(PythonInterp 3 REQUIRED QUIET) - find_package(PythonLibs 3 REQUIRED QUIET) - - message(STATUS "Python executable: ${PYTHON_EXECUTABLE}") - message(STATUS "Python include: ${PYTHON_INCLUDE_DIRS}") - message(STATUS "Python include: ${PYTHON_LIBRARIES}") -endif() ############################################################# ## @@ -21,7 +13,7 @@ endif() # Do not take a branch, needs internet connection. ExternalProject_Add( - l3pp + l3pp_ext GIT_REPOSITORY https://github.com/hbruintjes/l3pp.git GIT_TAG e4f8d7fe6c328849aff34d2dfd6fd592c14070d5 SOURCE_DIR ${STORM_3RDPARTY_SOURCE_DIR}/l3pp @@ -31,10 +23,10 @@ ExternalProject_Add( INSTALL_COMMAND "" LOG_INSTALL ON ) -ExternalProject_Get_Property(l3pp source_dir) +ExternalProject_Get_Property(l3pp_ext source_dir) set(l3pp_INCLUDE "${source_dir}/") -include_directories(${l3pp_INCLUDE}) -add_dependencies(resources l3pp) +add_imported_library_interface(l3pp "${l3pp_INCLUDE}") +list(APPEND STORM_DEP_TARGETS l3pp) ############################################################# ## @@ -42,9 +34,8 @@ add_dependencies(resources l3pp) ## ############################################################# -# Add the shipped version of GMM to the include pathes -set(GMMXX_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/resources/3rdparty/gmm-5.0/include") -include_directories(${GMMXX_INCLUDE_DIR}) +add_imported_library_interface(gmm "${PROJECT_SOURCE_DIR}/resources/3rdparty/gmm-5.0/include") +list(APPEND STORM_DEP_TARGETS gmm) ############################################################# ## @@ -52,9 +43,8 @@ include_directories(${GMMXX_INCLUDE_DIR}) ## ############################################################# -# Add the shipped version of Eigen to the include pathes -set(EIGEN_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/resources/3rdparty/eigen-3.3-beta1") -include_directories(${EIGEN_INCLUDE_DIR}) +add_imported_library_interface(Eigen33 "${PROJECT_SOURCE_DIR}/resources/3rdparty/eigen-3.3-beta1") +list(APPEND STORM_DEP_TARGETS Eigen33) ############################################################# @@ -95,7 +85,8 @@ set(STORM_BOOST_INCLUDE_DIR "${Boost_INCLUDE_DIRS}") # Use the shipped version of ExprTK message (STATUS "Storm - Including ExprTk.") -include_directories("${PROJECT_SOURCE_DIR}/resources/3rdparty/exprtk") +add_imported_library_interface(ExprTk "${PROJECT_SOURCE_DIR}/resources/3rdparty/exprtk") +list(APPEND STORM_DEP_TARGETS ExprTk) ############################################################# ## @@ -124,7 +115,8 @@ list(APPEND STORM_RESOURCES_HEADERS "${CMAKE_BINARY_DIR}/include/resources/3rdpa #use the shipped version of modernjson message (STATUS "Storm - Including ModernJSON.") -include_directories("${PROJECT_SOURCE_DIR}/resources/3rdparty/modernjson/src/") +add_imported_library_interface(ModernJSON "${PROJECT_SOURCE_DIR}/resources/3rdparty/modernjson/src/") +list(APPEND STORM_DEP_TARGETS ModernJSON) ############################################################# ## @@ -162,9 +154,8 @@ if (STORM_USE_GUROBI) set(STORM_HAVE_GUROBI ${GUROBI_FOUND}) if (GUROBI_FOUND) message (STATUS "Storm - Linking with Gurobi.") - include_directories(${GUROBI_INCLUDE_DIRS}) - list(APPEND STORM_LINK_LIBRARIES ${GUROBI_LIBRARY}) - #link_directories("${GUROBI_ROOT}/lib") + add_imported_library(Gurobi "" ${GUROBI_LIBRARY} ${GUROBI_INCLUDE_DIRS}) + list(APPEND STORM_DEP_TARGETS Gurobi) endif() else() set(STORM_HAVE_GUROBI OFF) @@ -184,25 +175,7 @@ include(${STORM_3RDPARTY_SOURCE_DIR}/include_cudd.cmake) ############################################################# include(${STORM_3RDPARTY_SOURCE_DIR}/include_cpptemplate.cmake) -############################################################# -## -## CLN -## -############################################################# -find_package(CLN QUIET) - -if(CLN_FOUND) - set(STORM_HAVE_CLN ON) - message(STATUS "Storm - Linking with CLN ${CLN_VERSION_STRING}.") - include_directories("${CLN_INCLUDE_DIR}") - list(APPEND STORM_LINK_LIBRARIES ${CLN_LIBRARIES}) -else() - set(STORM_HAVE_CLN OFF) - if(NOT GMP_FOUND) - message(FATAL_ERROR "Storm - Neither CLN nor GMP found.") - endif() -endif() ############################################################# ## @@ -216,39 +189,60 @@ if(USE_CARL) if(carl_FOUND) set(STORM_HAVE_CARL ON) message(STATUS "Storm - Use system version of carl.") - message(STATUS "Storm - Linking with carl ${carl_VERSION_STRING}.") - include_directories("${carl_INCLUDE_DIR}") - list(APPEND STORM_LINK_LIBRARIES ${carl_LIBRARIES}) + message(STATUS "Storm - Linking with carl ${carl_VERSION} (CARL_USE_CLN_NUMBERS: ${CARL_USE_CLN_NUMBERS}).") + set(STORM_HAVE_CLN ${CARL_USE_CLN_NUMBERS}) else() + # The first external project will be built at *configure stage* + message("START CARL CONFIG PROCESS") + file(MAKE_DIRECTORY ${STORM_3RDPARTY_BINARY_DIR}/carl_download) + execute_process( + COMMAND ${CMAKE_COMMAND} ${STORM_3RDPARTY_SOURCE_DIR}/carl "-DSTORM_3RDPARTY_BINARY_DIR=${STORM_3RDPARTY_BINARY_DIR}" + WORKING_DIRECTORY ${STORM_3RDPARTY_BINARY_DIR}/carl_download + OUTPUT_VARIABLE carlconfig_out + RESULT_VARIABLE carlconfig_result + ) + + + if(NOT carlconfig_result) + message("${carlconfig_out}") + endif() + execute_process( + COMMAND ${CMAKE_COMMAND} --build . --target carl-config + WORKING_DIRECTORY ${STORM_3RDPARTY_BINARY_DIR}/carl_download + OUTPUT_VARIABLE carlconfig_out + RESULT_VARIABLE carlconfig_result + ) + if(NOT carlconfig_result) + message("${carlconfig_out}") + endif() + message("END CARL CONFIG PROCESS") + message(STATUS "Storm - Using shipped version of carl.") set(CARL_BUILD_COMMAND make lib_carl) - if(STORM_PYTHON) - set(CARL_BUILD_COMMAND ${CARL_BUILD_COMMAND} PythonBindingsDevelop) - endif() ExternalProject_Add( carl - GIT_REPOSITORY https://github.com/smtrat/carl - GIT_TAG master - INSTALL_DIR ${STORM_3RDPARTY_BINARY_DIR}/carl - SOURCE_DIR ${STORM_3RDPARTY_SOURCE_DIR}/carl - CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DBOOST_INCLUDEDIR=${Boost_INCLUDE_DIRS} -DBOOST_LIBRARYDIR=${Boost_LIBRARY_DIRS} -DBoost_NO_SYSTEM_PATHS=1 -DEXPORT_TO_CMAKE=0 -DUSE_CLN_NUMBERS=1 -DCMAKE_SKIP_INSTALL_ALL_DEPENDENCY=1 -DCMAKE_INSTALL_PREFIX:PATH=${STORM_3RDPARTY_BINARY_DIR}/carl -DBINDINGS_PYTHON=${STORM_PYTHON} -DPYTHON_LIBRARY=${PYTHON_LIBRARY} -DPYTHON_INCLUDE_DIR=${PYTHON_INCLUDE_DIR} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} - BUILD_IN_SOURCE 0 - BUILD_COMMAND ${CARL_BUILD_COMMAND} + SOURCE_DIR ${STORM_3RDPARTY_BINARY_DIR}/carl + CONFIGURE_COMMAND "" + BUILD_IN_SOURCE 1 + BUILD_COMMAND make lib_carl INSTALL_COMMAND "" - LOG_UPDATE ON - LOG_CONFIGURE ON LOG_BUILD ON BUILD_BYPRODUCTS ${STORM_3RDPARTY_BINARY_DIR}/carl/lib/libcarl${DYNAMIC_EXT} ) - - add_dependencies(resources carl) - set(carl_INCLUDE_DIR "${STORM_3RDPARTY_BINARY_DIR}/carl/include") - include_directories("${carl_INCLUDE_DIR}") - list(APPEND STORM_LINK_LIBRARIES ${STORM_3RDPARTY_BINARY_DIR}/carl/lib/libcarl${DYNAMIC_EXT}) + include(${STORM_3RDPARTY_BINARY_DIR}/carl/carlConfig.cmake) + message("CARL_USE_CLN_NUMBERS: ${CARL_USE_CLN_NUMBERS}") + set(STORM_HAVE_CLN ${CARL_USE_CLN_NUMBERS}) + add_dependencies(resources carl) + set(carl_INCLUDE_DIR "${STORM_3RDPARTY_BINARY_DIR}/carl/build/include") set(STORM_HAVE_CARL ON) endif() + if(STORM_USE_CLN_NUMBERS AND NOT STORM_HAVE_CLN) + message(FATAL_ERROR "Cannot use CLN numbers if carl is build without") + endif() + + list(APPEND STORM_DEP_IMP_TARGETS lib_carl) + endif() -set(STORM_CARL_INCLUDE_DIR "${carl_INCLUDE_DIR}") ############################################################# @@ -293,26 +287,6 @@ endif() -############################################################# -## -## GiNaC -## -############################################################# - -find_package(GiNaC QUIET) - -if(GINAC_FOUND) - set(STORM_HAVE_GINAC ON) - message(STATUS "Storm - Linking with GiNaC ${GINAC_VERSION_STRING}.") - # Right now only link with GiNaC for carl - #include_directories("${GINAC_INCLUDE_DIR}") - list(APPEND STORM_LINK_LIBRARIES ${GINAC_LIBRARIES}) -else() - set(STORM_HAVE_GINAC OFF) - #TODO: Check if CARL actually requires the use of GiNaC -endif() - - ############################################################# ## ## gmp @@ -372,13 +346,13 @@ ExternalProject_Add( PREFIX "sylvan" SOURCE_DIR ${STORM_3RDPARTY_SOURCE_DIR}/sylvan CMAKE_ARGS -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DSYLVAN_BUILD_TEST=Off -DSYLVAN_BUILD_EXAMPLES=Off -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON - BINARY_DIR ${PROJECT_BINARY_DIR}/sylvan + BINARY_DIR ${STORM_3RDPARTY_BINARY_DIR}/sylvan BUILD_IN_SOURCE 0 INSTALL_COMMAND "" INSTALL_DIR ${STORM_3RDPARTY_BINARY_DIR}/sylvan LOG_CONFIGURE ON LOG_BUILD ON - BUILD_BYPRODUCTS ${PROJECT_BINARY_DIR}/sylvan/src/libsylvan${STATIC_EXT} + BUILD_BYPRODUCTS ${STORM_3RDPARTY_BINARY_DIR}/sylvan/src/libsylvan${STATIC_EXT} ) ExternalProject_Get_Property(sylvan source_dir) ExternalProject_Get_Property(sylvan binary_dir) @@ -386,15 +360,16 @@ set(Sylvan_INCLUDE_DIR "${source_dir}/src") set(Sylvan_LIBRARY "${binary_dir}/src/libsylvan${STATIC_EXT}") message(STATUS "Storm - Using shipped version of sylvan.") message(STATUS "Storm - Linking with sylvan.") -include_directories("${Sylvan_INCLUDE_DIR}") -list(APPEND STORM_LINK_LIBRARIES ${Sylvan_LIBRARY}) -add_dependencies(resources sylvan) +add_imported_library(sylvan STATIC ${Sylvan_LIBRARY} ${Sylvan_INCLUDE_DIR}) +add_dependencies(sylvan_STATIC sylvan) +list(APPEND STORM_DEP_TARGETS sylvan_STATIC) if(${OPERATING_SYSTEM} MATCHES "Linux") find_package(Hwloc QUIET REQUIRED) if(HWLOC_FOUND) message(STATUS "Storm - Linking with hwloc ${HWLOC_VERSION}.") - list(APPEND STORM_LINK_LIBRARIES ${HWLOC_LIBRARIES}) + add_imported_library(hwloc STATIC ${HWLOC_LIBRARIES} "") + list(APPEND STORM_DEP_TARGETS hwloc_STATIC) else() message(FATAL_ERROR "HWLOC is required but was not found.") endif() diff --git a/resources/3rdparty/carl/CMakeLists.txt b/resources/3rdparty/carl/CMakeLists.txt new file mode 100644 index 000000000..749b561aa --- /dev/null +++ b/resources/3rdparty/carl/CMakeLists.txt @@ -0,0 +1,25 @@ +project(carlext) +cmake_minimum_required(VERSION 3.3) +include(ExternalProject) + +option(STORM_3RDPARTY_BINARY_DIR "3rd party bin dir") + +message(STORM_3RDPARTY_BINARY_DIR: ${STORM_3RDPARTY_BINARY_DIR}) + +ExternalProject_Add(carl-config + GIT_REPOSITORY https://github.com/smtrat/carl + GIT_TAG master + PREFIX here + SOURCE_DIR source_dir + BINARY_DIR ${STORM_3RDPARTY_BINARY_DIR}/carl + CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DBOOST_INCLUDEDIR=${Boost_INCLUDE_DIRS} -DBOOST_LIBRARYDIR=${Boost_LIBRARY_DIRS} -DBoost_NO_SYSTEM_PATHS=1 -DEXPORT_TO_CMAKE=0 -DUSE_CLN_NUMBERS=1 -DCMAKE_SKIP_INSTALL_ALL_DEPENDENCY=1 -DCMAKE_INSTALL_PREFIX:PATH=${STORM_3RDPARTY_BINARY_DIR}/carl + BUILD_IN_SOURCE 0 + LOG_UPDATE OFF + LOG_CONFIGURE OFF + BUILD_COMMAND "" # Disable build step. + INSTALL_COMMAND "" # Disable install step too. +) +add_custom_target(build-carl) +add_dependencies(build-carl carl-config) + +message("done") diff --git a/resources/3rdparty/include_cpptemplate.cmake b/resources/3rdparty/include_cpptemplate.cmake index 138965f15..e6f341b31 100644 --- a/resources/3rdparty/include_cpptemplate.cmake +++ b/resources/3rdparty/include_cpptemplate.cmake @@ -22,8 +22,8 @@ ExternalProject_Add( set(CPPTEMPLATE_INCLUDE_DIR ${STORM_3RDPARTY_SOURCE_DIR}/cpptemplate) set(CPPTEMPLATE_STATIC_LIBRARY ${STORM_3RDPARTY_BINARY_DIR}/cpptemplate/cpptemplate${STATIC_EXT}) -list(APPEND STORM_LINK_LIBRARIES ${CPPTEMPLATE_STATIC_LIBRARY}) add_dependencies(resources cpptemplate) message(STATUS "Storm - Linking with cpptemplate.") -include_directories(${CPPTEMPLATE_INCLUDE_DIR}) +add_imported_library(cpptempl STATIC ${CPPTEMPLATE_STATIC_LIBRARY} ${CPPTEMPLATE_INCLUDE_DIR}) +list(APPEND STORM_DEP_TARGETS cpptempl_STATIC) \ No newline at end of file diff --git a/resources/3rdparty/include_cudd.cmake b/resources/3rdparty/include_cudd.cmake index 79edfc071..731758830 100644 --- a/resources/3rdparty/include_cudd.cmake +++ b/resources/3rdparty/include_cudd.cmake @@ -37,12 +37,16 @@ set(CUDD_INCLUDE_DIR ${STORM_3RDPARTY_BINARY_DIR}/cudd-3.0.0/include) set(CUDD_SHARED_LIBRARY ${CUDD_LIB_DIR}/libcudd${DYNAMIC_EXT}) set(CUDD_STATIC_LIBRARY ${CUDD_LIB_DIR}/libcudd${STATIC_EXT}) set(CUDD_VERSION_STRING 3.0.0) + +add_imported_library(cudd SHARED ${CUDD_SHARED_LIBRARY} ${CUDD_INCLUDE_DIR}) +add_imported_library(cudd STATIC ${CUDD_STATIC_LIBRARY} ${CUDD_INCLUDE_DIR}) + +add_dependencies(resources cudd3) + if(BUILD_SHARED_LIBS) - list(APPEND STORM_LINK_LIBRARIES ${CUDD_SHARED_LIBRARY}) + list(APPEND STORM_DEP_TARGETS cudd_SHARED) else() - list(APPEND STORM_LINK_LIBRARIES ${CUDD_STATIC_LIBRARY}) + list(APPEND STORM_DEP_TARGETS cudd_STATIC) endif() -add_dependencies(resources cudd3) -message(STATUS "Storm - Linking with CUDD ${CUDD_VERSION_STRING}.") -include_directories(${CUDD_INCLUDE_DIR}) +message(STATUS "Storm - Linking with CUDD ${CUDD_VERSION_STRING}.") \ No newline at end of file diff --git a/resources/3rdparty/include_glpk.cmake b/resources/3rdparty/include_glpk.cmake index 7d75e89b9..e7dc55149 100644 --- a/resources/3rdparty/include_glpk.cmake +++ b/resources/3rdparty/include_glpk.cmake @@ -4,7 +4,7 @@ if(GLPK_FOUND) else() message (STATUS "Storm - Using shipped version of glpk.") set(GLPK_LIB_DIR ${STORM_3RDPARTY_BINARY_DIR}/glpk-4.57/lib) - ExternalProject_Add(glpk + ExternalProject_Add(glpk_ext DOWNLOAD_COMMAND "" PREFIX ${STORM_3RDPARTY_BINARY_DIR}/glpk-4.57 SOURCE_DIR ${STORM_3RDPARTY_SOURCE_DIR}/glpk-4.57 @@ -20,11 +20,12 @@ else() set(GLPK_LIBRARIES ${GLPK_LIB_DIR}/libglpk${DYNAMIC_EXT}) set(GLPK_INCLUDE_DIR ${STORM_3RDPARTY_BINARY_DIR}/glpk-4.57/include) set(GLPK_VERSION_STRING 4.57) - add_dependencies(resources glpk) + add_dependencies(resources glpk_ext) endif() # Since there is a shipped version, always use GLPK set(STORM_HAVE_GLPK ON) message (STATUS "Storm - Linking with glpk ${GLPK_VERSION_STRING}") -include_directories(${GLPK_INCLUDE_DIR}) -list(APPEND STORM_LINK_LIBRARIES ${GLPK_LIBRARIES}) + +add_imported_library(glpk SHARED ${GLPK_LIBRARIES} ${GLPK_INCLUDE_DIR}) +list(APPEND STORM_DEP_TARGETS glpk_SHARED) \ No newline at end of file diff --git a/resources/3rdparty/include_xerces.cmake.save b/resources/3rdparty/include_xerces.cmake.save new file mode 100644 index 000000000..e69de29bb diff --git a/resources/3rdparty/include_xerces.cmake.save.1 b/resources/3rdparty/include_xerces.cmake.save.1 new file mode 100644 index 000000000..4480844f5 --- /dev/null +++ b/resources/3rdparty/include_xerces.cmake.save.1 @@ -0,0 +1,49 @@ +if(USE_XERCESC) + set(XERCESC_FIND_QUIETLY ON) + set(XERCESC_STATIC OFF) + find_package(XercesC QUIET REQUIRED) + if(XERCESC_FOUND) + message(STATUS "Storm - Use system version of xerces.") + else() + message(STATUS "Storm - Use shipped version of xerces.") + set(XERCESC_LIB_DIR ${STORM_3RDPARTY_BINARY_DIR}/xercesc-3.1.2/lib) + ExternalProject_Add( + xercesc + SOURCE_DIR ${STORM_3RDPARTY_SOURCE_DIR}/xercesc-3.1.2 + CONFIGURE_COMMAND ${STORM_3RDPARTY_SOURCE_DIR}/xercesc-3.1.2/configure --prefix=${STORM_3RDPARTY_BINARY_DIR}/xercesc-3.1.2 --libdir=${XERCESC_LIB_DIR} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} CFLAGS=-O3 CXXFLAGS=-O3 + PREFIX ${STORM_3RDPARTY_BINARY_DIR}/xercesc-3.1.2 + BUILD_COMMAND make + BUILD_IN_SOURCE 0 + LOG_CONFIGURE ON + LOG_BUILD ON + LOG_INSTALL ON + BUILD_BYPRODUCTS ${XERCESC_LIB_DIR}/libxerces-c${DYNAMIC_EXT} ${XERCESC_LIB_DIR}/libxerces-c${STATIC_EXT} + ) + + set(XERCESC_ROOT ${STORM_3RDPARTY_BINARY_DIR}/xercesc-3.1.2) + set(XERCESC_INCLUDE ${XERCESC_ROOT}/include) + set(XERCESC_LIBRARY_PATH ${XERCESC_LIB_DIR}) + + if(BUILD_STATIC) + set(XERCESC_LIBRARIES ${XERCESC_LIBRARY_PATH}/libxerces-c${STATIC_EXT}) + else() + set(XERCESC_LIBRARIES ${XERCESC_LIBRARY_PATH}/libxerces-c${DYNAMIC_EXT}) + endif() + + add_dependencies(resources xercesc) + endif() + + message (STATUS "Storm - Linking with xercesc.") + set(STORM_HAVE_XERCES ON) + include_directories(${XERCESC_INCLUDE}) + if(APPLE) + FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation ) + FIND_LIBRARY(CORESERVICES_LIBRARY CoreServices ) + mark_as_advanced(COREFOUNDATION_LIBRARY) + mark_as_advanced(CORESERVICES_LIBRARY) + endif() + find_package(CURL) + list(APPEND STORM_GSPN_LINK_LIBRARIES ${XERCESC_LIBRARIES} ${COREFOUNDATION_LIBRARY} ${CORESERVICES_LIBRARY} ${CURL_LIBRARIES}) +else() + message (WARNING "Storm - Building without Xerces disables parsing XML formats (for GSPNs)") +endif(USE_XERCESC) diff --git a/resources/cmake/find_modules/FindCLN.cmake b/resources/cmake/find_modules/FindCLN.cmake deleted file mode 100644 index 2bb284648..000000000 --- a/resources/cmake/find_modules/FindCLN.cmake +++ /dev/null @@ -1,43 +0,0 @@ -# - Try to find libcln -# Once done this will define -# CLN_FOUND - System has cln -# CLN_INCLUDE_DIR - The cln include directory -# CLN_LIBRARIES - The libraries needed to use cln -# CLN_VERSION_STRING - The version of cln ("major.minor.patch") - -# use pkg-config to get the directories and then use these values -# in the find_path() and find_library() calls -find_package(PkgConfig QUIET) -PKG_CHECK_MODULES(PC_CLN QUIET cln) - -find_path(CLN_INCLUDE_DIR NAMES cln/cln.h - HINTS - ${PC_CLN_INCLUDEDIR} - ${PC_CLN_INCLUDE_DIRS} - PATH_SUFFIXES cln - ) - -find_library(CLN_LIBRARIES NAMES cln - HINTS - ${PC_CLN_LIBDIR} - ${PC_CLN_LIBRARY_DIRS} - ) - -if(PC_CLN_VERSION) - set(CLN_VERSION_STRING ${PC_CLN_VERSION}) -elseif(CLN_INCLUDE_DIR AND EXISTS "${CLN_INCLUDE_DIR}/version.h") - file(STRINGS "${CLN_INCLUDE_DIR}/version.h" cln_version - REGEX "^#define[\t ]+CL_VERSION[\t ]+.+") - string(REGEX REPLACE "^#define[\t ]+CL_VERSION[\t ]+(.+)" "\\1" - CLN_VERSION_STRING "${cln_version}") - unset(cln_version) -endif() - -# handle the QUIETLY and REQUIRED arguments and set LIBXML2_FOUND to TRUE if -# all listed variables are TRUE -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(CLN - REQUIRED_VARS CLN_LIBRARIES CLN_INCLUDE_DIR - VERSION_VAR CLN_VERSION_STRING) - -mark_as_advanced(CLN_INCLUDE_DIR CLN_LIBRARIES) diff --git a/resources/cmake/find_modules/FindGiNaC.cmake b/resources/cmake/find_modules/FindGiNaC.cmake deleted file mode 100644 index 13e8ea59e..000000000 --- a/resources/cmake/find_modules/FindGiNaC.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# - Try to find libginac -# Once done this will define -# GINAC_FOUND - System has ginac -# GINAC_INCLUDE_DIR - The ginac include directory -# GINAC_LIBRARIES - The libraries needed to use ginac -# GINAC_VERSION_STRING - The version of ginac ("major.minor.micro") - -# use pkg-config to get the directories and then use these values -# in the find_path() and find_library() calls -find_package(PkgConfig QUIET) -PKG_CHECK_MODULES(PC_GINAC QUIET ginac) - -find_path(GINAC_INCLUDE_DIR NAMES ginac.h - HINTS - ${PC_GINAC_INCLUDEDIR} - ${PC_GINAC_INCLUDE_DIRS} - PATH_SUFFIXES ginac - ) - -find_library(GINAC_LIBRARIES NAMES ginac - HINTS - ${PC_GINAC_LIBDIR} - ${PC_GINAC_LIBRARY_DIRS} - ) - -if(PC_GINAC_VERSION) - set(GINAC_VERSION_STRING ${PC_GINAC_VERSION}) -elseif(GINAC_INCLUDE_DIR AND EXISTS "${GINAC_INCLUDE_DIR}/ginac.h") - file(STRINGS "${GINAC_INCLUDE_DIR}/ginac.h" ginac_major_version - REGEX "^#define[\t ]+GINACLIB_MAJOR_VERSION[\t ]+.+") - file(STRINGS "${GINAC_INCLUDE_DIR}/ginac.h" ginac_minor_version - REGEX "^#define[\t ]+GINACLIB_MINOR_VERSION[\t ]+.+") - file(STRINGS "${GINAC_INCLUDE_DIR}/ginac.h" ginac_micro_version - REGEX "^#define[\t ]+GINACLIB_MICRO_VERSION[\t ]+.+") - string(REGEX REPLACE "^#define[\t ]+GINACLIB_MAJOR_VERSION[\t ]+(.+)" "\\1" - ginac_major_version "${ginac_major_version}") - string(REGEX REPLACE "^#define[\t ]+GINACLIB_MINOR_VERSION[\t ]+(.+)" "\\1" - ginac_minor_version "${ginac_minor_version}") - string(REGEX REPLACE "^#define[\t ]+GINACLIB_MICRO_VERSION[\t ]+(.+)" "\\1" - ginac_micro_version "${ginac_micro_version}") - set(GINAC_VERSION_STRING "${ginac_major_version}.${ginac_minor_version}.${ginac_micro_version}") - unset(ginac_major_version) - unset(ginac_minor_version) - unset(ginac_micro_version) -endif() - -# handle the QUIETLY and REQUIRED arguments and set GINAC_FOUND to TRUE if -# all listed variables are TRUE -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(GINAC - REQUIRED_VARS GINAC_LIBRARIES GINAC_INCLUDE_DIR - VERSION_VAR GINAC_VERSION_STRING) - -mark_as_advanced(GINAC_INCLUDE_DIR GINAC_LIBRARIES) diff --git a/resources/cmake/macros/export.cmake b/resources/cmake/macros/export.cmake new file mode 100644 index 000000000..eb2e8fa84 --- /dev/null +++ b/resources/cmake/macros/export.cmake @@ -0,0 +1,28 @@ + +# Add all targets to the build-tree export set +export(TARGETS ${STORM_TARGETS} FILE "${PROJECT_BINARY_DIR}/stormTargets.cmake") + +message(STATUS "Registered with cmake") +# Export the package for use from the build-tree +# (this registers the build-tree with a global CMake-registry) +export(PACKAGE storm) + +set(DEP_TARGETS "") +foreach(dt ${STORM_DEP_TARGETS}) + export_target(DEP_TARGETS ${dt}) +endforeach() + +set(EXP_OPTIONS "") +foreach(option ${EXPORTED_OPTIONS}) + set(EXP_OPTIONS "${EXP_OPTIONS}\nset(${option} \"${${option}}\")") +endforeach() + +include(CMakePackageConfigHelpers) + +set(CONF_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/include/") +configure_package_config_file( + resources/cmake/stormConfig.cmake.in + ${PROJECT_BINARY_DIR}/stormConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_DIR} + PATH_VARS INCLUDE_INSTALL_DIR #SYSCONFIG_INSTALL_DIR +) diff --git a/resources/cmake/macros/imported.cmake b/resources/cmake/macros/imported.cmake new file mode 100644 index 000000000..ef25990c3 --- /dev/null +++ b/resources/cmake/macros/imported.cmake @@ -0,0 +1,59 @@ +# copied from CARL + + +macro(add_imported_library_interface name include) + add_library(${name} INTERFACE IMPORTED) + set_target_properties(${name} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include}") +endmacro(add_imported_library_interface) + +macro(add_imported_library name type lib include) +# Workaround from https://cmake.org/Bug/view.php?id=15052 + file(MAKE_DIRECTORY "${include}") + if("${lib}" STREQUAL "") + if("${type}" STREQUAL "SHARED") + add_library(${name} INTERFACE IMPORTED) + set_target_properties(${name} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include}") + endif() + else() + add_library(${name}_${type} ${type} IMPORTED) + set_target_properties(${name}_${type} PROPERTIES IMPORTED_LOCATION "${lib}") + set_target_properties(${name}_${type} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include}") + endif() +endmacro(add_imported_library) + +macro(export_option name) + list(APPEND EXPORTED_OPTIONS "${name}") +endmacro(export_option) + +macro(export_target output TARGET) + get_target_property(TYPE ${TARGET} TYPE) + if(TYPE STREQUAL "SHARED_LIBRARY") + get_target_property(LOCATION ${TARGET} IMPORTED_LOCATION) + get_target_property(INCLUDE ${TARGET} INTERFACE_INCLUDE_DIRECTORIES) + set(${output} "${${output}} +add_library(${TARGET} SHARED IMPORTED) +set_target_properties(${TARGET} PROPERTIES IMPORTED_LOCATION \"${LOCATION}\") +set_target_properties(${TARGET} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES \"${INCLUDE}\") +") + elseif(TYPE STREQUAL "STATIC_LIBRARY") + get_target_property(LOCATION ${TARGET} IMPORTED_LOCATION) + get_target_property(INCLUDE ${TARGET} INTERFACE_INCLUDE_DIRECTORIES) + set(${output} "${${output}} +add_library(${TARGET} STATIC IMPORTED) +set_target_properties(${TARGET} PROPERTIES IMPORTED_LOCATION \"${LOCATION}\") +set_target_properties(${TARGET} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES \"${INCLUDE}\") +") + if(NOT "${ARGN}" STREQUAL "") + set(${output} "${${output}}set_target_properties(${TARGET} PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES \"${ARGN}\") +") + endif() + elseif(TYPE STREQUAL "INTERFACE_LIBRARY") + get_target_property(INCLUDE ${TARGET} INTERFACE_INCLUDE_DIRECTORIES) + set(${output} "${${output}} +add_library(${TARGET} INTERFACE IMPORTED) +set_target_properties(${TARGET} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES \"${INCLUDE}\") +") + else() + message(STATUS "Unknown type ${TYPE}") + endif() +endmacro(export_target) diff --git a/resources/cmake/stormConfig.cmake.in b/resources/cmake/stormConfig.cmake.in new file mode 100644 index 000000000..d8f08533f --- /dev/null +++ b/resources/cmake/stormConfig.cmake.in @@ -0,0 +1,21 @@ +set(storm_VERSION @storm_VERSION@) + +get_filename_component(storm_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +include("@carl_CMAKE_DIR@/carlConfig.cmake") + +@DEP_TARGETS@ + +@EXP_OPTIONS@ + +# Our library dependencies (contains definitions for IMPORTED targets) +if(NOT TARGET storm) + include("${storm_CMAKE_DIR}/stormTargets.cmake") +endif() + +@PACKAGE_INIT@ + +set(storm_INCLUDE_DIR "@CONF_INCLUDE_DIRS@") + +set(storm_LIBRARIES storm) +check_required_components(storm) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 80f7bd9b7..a3056d870 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,3 +6,5 @@ add_subdirectory(storm-gspn-cli) add_subdirectory(storm-dft) add_subdirectory(storm-dft-cli) add_subdirectory(test) + +set(STORM_TARGETS ${STORM_TARGETS} PARENT_SCOPE) \ No newline at end of file diff --git a/src/storm-dft-cli/storm-dyftee.cpp b/src/storm-dft-cli/storm-dyftee.cpp index fe5c1ad47..f246438fe 100644 --- a/src/storm-dft-cli/storm-dyftee.cpp +++ b/src/storm-dft-cli/storm-dyftee.cpp @@ -1,33 +1,36 @@ #include "storm/logic/Formula.h" #include "storm/utility/initialize.h" #include "storm/utility/storm.h" -#include "storm-dft/parser/DFTGalileoParser.h" -#include "storm-dft/modelchecker/dft/DFTModelChecker.h" - -#include "storm-dft/modelchecker/dft/DFTASFChecker.h" #include "storm/cli/cli.h" #include "storm/exceptions/BaseException.h" -#include "storm/utility/macros.h" +#include "storm/logic/Formula.h" #include "storm/settings/modules/GeneralSettings.h" -#include "storm-dft/settings/modules/DFTSettings.h" #include "storm/settings/modules/CoreSettings.h" #include "storm/settings/modules/DebugSettings.h" -//#include "storm/settings/modules/CounterexampleGeneratorSettings.h" -//#include "storm/settings/modules/CuddSettings.h" -//#include "storm/settings/modules/SylvanSettings.h" #include "storm/settings/modules/GmmxxEquationSolverSettings.h" #include "storm/settings/modules/MinMaxEquationSolverSettings.h" #include "storm/settings/modules/NativeEquationSolverSettings.h" -//#include "storm/settings/modules/BisimulationSettings.h" -//#include "storm/settings/modules/GlpkSettings.h" -//#include "storm/settings/modules/GurobiSettings.h" -//#include "storm/settings/modules/TopologicalValueIterationEquationSolverSettings.h" -//#include "storm/settings/modules/ParametricSettings.h" #include "storm/settings/modules/EliminationSettings.h" +#include "storm-dft/parser/DFTGalileoParser.h" +#include "storm-dft/parser/DFTJsonParser.h" +#include "storm-dft/modelchecker/dft/DFTModelChecker.h" +#include "storm-dft/modelchecker/dft/DFTASFChecker.h" +#include "storm-dft/transformations/DftToGspnTransformator.h" + + +#include "storm-dft/settings/modules/DFTSettings.h" + +#include "storm-gspn/storage/gspn/GSPN.h" +#include "storm-gspn/storm-gspn.h" +#include "storm/settings/modules/GSPNSettings.h" +#include "storm/settings/modules/GSPNExportSettings.h" + + #include +#include /*! * Load DFT from filename, build corresponding Model and check against given property. @@ -71,21 +74,6 @@ void analyzeWithSMT(std::string filename) { //std::cout << "SMT result: " << sat << std::endl; } -/*! - * Load DFT from filename and transform into a GSPN. - * - * @param filename Path to DFT file in Galileo format. - * - */ -template -void transformDFT(std::string filename) { - std::cout << "Transforming DFT from file " << filename << std::endl; - storm::parser::DFTGalileoParser parser; - storm::storage::DFT dft = parser.parseDFT(filename); - // TODO: activate again - //storm::transformations::dft::DftToGspnTransformator gspnTransformator(dft); - //gspnTransformator.transform(); -} /*! * Initialize the settings manager. @@ -110,6 +98,11 @@ void initializeSettings() { //storm::settings::addModule(); //storm::settings::addModule(); storm::settings::addModule(); + + // For translation into JANI via GSPN. + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); } /*! @@ -132,13 +125,48 @@ int main(const int argc, const char** argv) { storm::settings::modules::DFTSettings const& dftSettings = storm::settings::getModule(); storm::settings::modules::GeneralSettings const& generalSettings = storm::settings::getModule(); - if (!dftSettings.isDftFileSet()) { + if (!dftSettings.isDftFileSet() && !dftSettings.isDftJsonFileSet()) { STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "No input model."); } + if (dftSettings.isTransformToGspn()) { - // For now we only transform the DFT to a GSPN and then exit - transformDFT(dftSettings.getDftFilename()); + std::shared_ptr> dft; + if (dftSettings.isDftJsonFileSet()) { + storm::parser::DFTJsonParser parser; + dft = std::make_shared>(parser.parseJson(dftSettings.getDftJsonFilename())); + } else { + storm::parser::DFTGalileoParser parser(true, false); + dft = std::make_shared>(parser.parseDFT(dftSettings.getDftFilename())); + } + storm::transformations::dft::DftToGspnTransformator gspnTransformator(*dft); + gspnTransformator.transform(); + storm::gspn::GSPN* gspn = gspnTransformator.obtainGSPN(); + uint64_t toplevelFailedPlace = gspnTransformator.toplevelFailedPlaceId(); + + storm::handleGSPNExportSettings(*gspn); + + std::shared_ptr exprManager(new storm::expressions::ExpressionManager()); + storm::builder::JaniGSPNBuilder builder(*gspn, exprManager); + storm::jani::Model* model = builder.build(); + storm::jani::Variable const& topfailedVar = builder.getPlaceVariable(toplevelFailedPlace); + + + storm::expressions::Expression targetExpression = exprManager->integer(1) == topfailedVar.getExpressionVariable().getExpression(); + auto evtlFormula = std::make_shared(targetExpression); + auto tbFormula = std::make_shared(std::make_shared(true), evtlFormula, 0.0, 10.0); + auto tbUntil = std::make_shared(tbFormula); + + auto evFormula = std::make_shared(evtlFormula, storm::logic::FormulaContext::Time); + auto rewFormula = std::make_shared(evFormula, storm::logic::OperatorInformation(), storm::logic::RewardMeasureType::Expectation); + + storm::settings::modules::JaniExportSettings const& janiSettings = storm::settings::getModule(); + if (janiSettings.isJaniFileSet()) { + storm::exportJaniModel(*model, {storm::jani::Property("time-bounded", tbUntil), storm::jani::Property("mttf", rewFormula)}, janiSettings.getJaniFilename()); + } + + delete model; + delete gspn; storm::utility::cleanUp(); return 0; } diff --git a/src/storm-dft/CMakeLists.txt b/src/storm-dft/CMakeLists.txt index df0c067e0..10d9b8508 100644 --- a/src/storm-dft/CMakeLists.txt +++ b/src/storm-dft/CMakeLists.txt @@ -10,4 +10,4 @@ file(GLOB_RECURSE STORM_DFT_HEADERS ${PROJECT_SOURCE_DIR}/src/storm-dft/*/*.h) # Create storm-pgcl. add_library(storm-dft SHARED ${STORM_DFT_SOURCES} ${STORM_DFT_HEADERS}) -target_link_libraries(storm-dft storm ${STORM_DFT_LINK_LIBRARIES}) +target_link_libraries(storm-dft storm storm-gspn ${STORM_DFT_LINK_LIBRARIES}) diff --git a/src/storm-dft/modelchecker/dft/DFTModelChecker.cpp b/src/storm-dft/modelchecker/dft/DFTModelChecker.cpp index ae4144ee7..2de46e599 100644 --- a/src/storm-dft/modelchecker/dft/DFTModelChecker.cpp +++ b/src/storm-dft/modelchecker/dft/DFTModelChecker.cpp @@ -8,6 +8,7 @@ #include "storm-dft/storage/dft/DFTIsomorphism.h" #include "storm-dft/settings/modules/DFTSettings.h" + namespace storm { namespace modelchecker { diff --git a/src/storm-dft/parser/DFTGalileoParser.cpp b/src/storm-dft/parser/DFTGalileoParser.cpp index 776eb64d9..f872f4526 100644 --- a/src/storm-dft/parser/DFTGalileoParser.cpp +++ b/src/storm-dft/parser/DFTGalileoParser.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "storm/storage/expressions/ExpressionManager.h" #include "storm/exceptions/NotImplementedException.h" #include "storm/exceptions/FileIoException.h" @@ -34,6 +35,11 @@ namespace storm { return name.substr(firstQuots+1,secondQuots-1); } } + + template + std::string DFTGalileoParser::parseNodeIdentifier(std::string const& name) { + return boost::replace_all_copy(name, "'", "__prime__"); + } template void DFTGalileoParser::readFile(const std::string& filename) { @@ -84,11 +90,11 @@ namespace storm { } else { std::vector tokens; boost::split(tokens, line, boost::is_any_of(" ")); - std::string name(stripQuotsFromName(tokens[0])); + std::string name(parseNodeIdentifier(stripQuotsFromName(tokens[0]))); std::vector childNames; for(unsigned i = 2; i < tokens.size(); ++i) { - childNames.push_back(stripQuotsFromName(tokens[i])); + childNames.push_back(parseNodeIdentifier(stripQuotsFromName(tokens[i]))); } if(tokens[1] == "and") { success = builder.addAndElement(name, childNames); @@ -104,8 +110,16 @@ namespace storm { success = builder.addVotElement(name, threshold, childNames); } else if (tokens[1] == "pand") { success = builder.addPandElement(name, childNames); + } else if (tokens[1] == "pand-inc") { + success = builder.addPandElement(name, childNames, true); + } else if (tokens[1] == "pand-ex") { + success = builder.addPandElement(name, childNames, false); } else if (tokens[1] == "por") { success = builder.addPorElement(name, childNames); + } else if (tokens[1] == "por-ex") { + success = builder.addPorElement(name, childNames, false); + } else if (tokens[1] == "por-inc") { + success = builder.addPorElement(name, childNames, true); } else if (tokens[1] == "wsp" || tokens[1] == "csp") { success = builder.addSpareElement(name, childNames); } else if (tokens[1] == "seq") { diff --git a/src/storm-dft/parser/DFTGalileoParser.h b/src/storm-dft/parser/DFTGalileoParser.h index 3f19683ff..c2a35bc50 100644 --- a/src/storm-dft/parser/DFTGalileoParser.h +++ b/src/storm-dft/parser/DFTGalileoParser.h @@ -26,7 +26,7 @@ namespace storm { std::unordered_map identifierMapping; public: - DFTGalileoParser() : manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) { + DFTGalileoParser(bool defaultInclusive = true, bool binaryDependencies = true) : builder(defaultInclusive, binaryDependencies), manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) { } storm::storage::DFT parseDFT(std::string const& filename); @@ -35,8 +35,11 @@ namespace storm { void readFile(std::string const& filename); std::string stripQuotsFromName(std::string const& name); + std::string parseNodeIdentifier(std::string const& name); ValueType parseRationalExpression(std::string const& expr); + + bool defaultInclusive; }; } } diff --git a/src/storm-dft/parser/DFTJsonParser.cpp b/src/storm-dft/parser/DFTJsonParser.cpp new file mode 100644 index 000000000..9a5c5d047 --- /dev/null +++ b/src/storm-dft/parser/DFTJsonParser.cpp @@ -0,0 +1,167 @@ +#include "DFTJsonParser.h" + +#include +#include +#include +#include +#include +#include "storm/storage/expressions/ExpressionManager.h" +#include "storm/exceptions/NotImplementedException.h" +#include "storm/exceptions/FileIoException.h" +#include "storm/exceptions/NotSupportedException.h" +#include "storm/utility/macros.h" + +namespace storm { + namespace parser { + + template + storm::storage::DFT DFTJsonParser::parseJson(const std::string& filename) { + readFile(filename); + storm::storage::DFT dft = builder.build(); + STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString()); + STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString()); + return dft; + } + + template + std::string DFTJsonParser::stripQuotsFromName(std::string const& name) { + size_t firstQuots = name.find("\""); + size_t secondQuots = name.find("\"", firstQuots+1); + + if(firstQuots == std::string::npos) { + return name; + } else { + STORM_LOG_THROW(secondQuots != std::string::npos, storm::exceptions::FileIoException, "No ending quotation mark found in " << name); + return name.substr(firstQuots+1,secondQuots-1); + } + } + + template + std::string DFTJsonParser::getString(json const& structure, std::string const& errorInfo) { + STORM_LOG_THROW(structure.is_string(), storm::exceptions::FileIoException, "Expected a string in " << errorInfo << ", got '" << structure.dump() << "'"); + return structure.front(); + } + + template + std::string DFTJsonParser::parseNodeIdentifier(std::string const& name) { + return boost::replace_all_copy(name, "'", "__prime__"); + } + + template + void DFTJsonParser::readFile(const std::string& filename) { + STORM_LOG_DEBUG("Parsing from JSON"); + + std::ifstream file; + file.exceptions ( std::ifstream::failbit ); + try { + file.open(filename); + } + catch (std::ifstream::failure e) { + STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Exception during file opening on " << filename << "."); + return; + } + file.exceptions( std::ifstream::goodbit ); + + json parsedJson; + parsedJson << file; + file.close(); + + // Start by building mapping from ids to names + std::map nameMapping; + for (auto& element: parsedJson) { + if (element.at("classes") != "") { + json data = element.at("data"); + std::string id = data.at("id"); + std::string name = data.at("name"); + nameMapping[id] = name; + } + } + + // TODO: avoid hack + std::string toplevelId = nameMapping["1"]; + + for (auto& element : parsedJson) { + bool success = true; + if (element.at("classes") == "") { + continue; + } + json data = element.at("data"); + std::string name = data.at("name"); + std::vector childNames; + if (data.count("children") > 0) { + for (auto& child : data.at("children")) { + childNames.push_back(nameMapping[child]); + } + } + + std::string type = getString(element.at("classes"), "classes"); + + if(type == "and") { + success = builder.addAndElement(name, childNames); + } else if (type == "or") { + success = builder.addOrElement(name, childNames); + } else if (type == "pand") { + success = builder.addPandElement(name, childNames); + } else if (type == "por") { + success = builder.addPorElement(name, childNames); + } else if (type == "spare") { + success = builder.addSpareElement(name, childNames); + } else if (type == "seq") { + success = builder.addSequenceEnforcer(name, childNames); + } else if (type== "fdep") { + success = builder.addDepElement(name, childNames, storm::utility::one()); + } else if (type== "pdep") { + ValueType probability = parseRationalExpression(data.at("prob")); + success = builder.addDepElement(name, childNames, probability); + } else if (type == "be") { + ValueType failureRate = parseRationalExpression(data.at("rate")); + ValueType dormancyFactor = parseRationalExpression(data.at("dorm")); + success = builder.addBasicElement(name, failureRate, dormancyFactor); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " << type << " not recognized."); + success = false; + } + + // Set layout positions + json position = element.at("position"); + double x = position.at("x"); + double y = position.at("y"); + builder.addLayoutInfo(name, x / 7, y / 7); + STORM_LOG_THROW(success, storm::exceptions::FileIoException, "Error while adding element '" << element << "'."); + } + + if(!builder.setTopLevel(toplevelId)) { + STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Top level id unknown."); + } + } + + template + ValueType DFTJsonParser::parseRationalExpression(std::string const& expr) { + STORM_LOG_ASSERT(false, "Specialized method should be called."); + return 0; + } + + template<> + double DFTJsonParser::parseRationalExpression(std::string const& expr) { + return boost::lexical_cast(expr); + } + + // Explicitly instantiate the class. + template class DFTJsonParser; + +#ifdef STORM_HAVE_CARL + template<> + storm::RationalFunction DFTJsonParser::parseRationalExpression(std::string const& expr) { + STORM_LOG_TRACE("Translating expression: " << expr); + storm::expressions::Expression expression = parser.parseFromString(expr); + STORM_LOG_TRACE("Expression: " << expression); + storm::RationalFunction rationalFunction = evaluator.asRational(expression); + STORM_LOG_TRACE("Parsed expression: " << rationalFunction); + return rationalFunction; + } + + template class DFTJsonParser; +#endif + + } +} diff --git a/src/storm-dft/parser/DFTJsonParser.h b/src/storm-dft/parser/DFTJsonParser.h new file mode 100644 index 000000000..cf2e83826 --- /dev/null +++ b/src/storm-dft/parser/DFTJsonParser.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#include "storm/storage/expressions/ExpressionManager.h" +#include "storm/parser/ExpressionParser.h" +#include "storm/storage/expressions/ExpressionEvaluator.h" + +#include "storm-dft/storage/dft/DFT.h" +#include "storm-dft/storage/dft/DFTBuilder.h" + +// JSON parser +#include "json.hpp" + +using json = nlohmann::json; + +namespace storm { + namespace parser { + + template + class DFTJsonParser { + storm::storage::DFTBuilder builder; + + std::shared_ptr manager; + + storm::parser::ExpressionParser parser; + + storm::expressions::ExpressionEvaluator evaluator; + + std::unordered_map identifierMapping; + + public: + DFTJsonParser() : manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) { + } + + storm::storage::DFT parseJson(std::string const& filename); + + private: + void readFile(std::string const& filename); + + std::string stripQuotsFromName(std::string const& name); + std::string parseNodeIdentifier(std::string const& name); + std::string getString(json const& structure, std::string const& errorInfo); + + ValueType parseRationalExpression(std::string const& expr); + }; + } +} diff --git a/src/storm-dft/settings/modules/DFTSettings.cpp b/src/storm-dft/settings/modules/DFTSettings.cpp index 5bf705d8a..898360c4b 100644 --- a/src/storm-dft/settings/modules/DFTSettings.cpp +++ b/src/storm-dft/settings/modules/DFTSettings.cpp @@ -16,6 +16,8 @@ namespace storm { const std::string DFTSettings::moduleName = "dft"; const std::string DFTSettings::dftFileOptionName = "dftfile"; const std::string DFTSettings::dftFileOptionShortName = "dft"; + const std::string DFTSettings::dftJsonFileOptionName = "dftfile-json"; + const std::string DFTSettings::dftJsonFileOptionShortName = "dftjson"; const std::string DFTSettings::symmetryReductionOptionName = "symmetryreduction"; const std::string DFTSettings::symmetryReductionOptionShortName = "symred"; const std::string DFTSettings::modularisationOptionName = "modularisation"; @@ -37,6 +39,8 @@ namespace storm { DFTSettings::DFTSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, dftFileOptionName, false, "Parses the model given in the Galileo format.").setShortName(dftFileOptionShortName) .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file from which to read the DFT model.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, dftJsonFileOptionName, false, "Parses the model given in the Cytoscape JSON format.").setShortName(dftJsonFileOptionShortName) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the JSON file from which to read the DFT model.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, symmetryReductionOptionName, false, "Exploit symmetric structure of model.").setShortName(symmetryReductionOptionShortName).build()); this->addOption(storm::settings::OptionBuilder(moduleName, modularisationOptionName, false, "Use modularisation (not applicable for expected time).").build()); this->addOption(storm::settings::OptionBuilder(moduleName, disableDCOptionName, false, "Disable Dont Care propagation.").build()); @@ -60,7 +64,15 @@ namespace storm { std::string DFTSettings::getDftFilename() const { return this->getOption(dftFileOptionName).getArgumentByName("filename").getValueAsString(); } - + + bool DFTSettings::isDftJsonFileSet() const { + return this->getOption(dftJsonFileOptionName).getHasOptionBeenSet(); + } + + std::string DFTSettings::getDftJsonFilename() const { + return this->getOption(dftJsonFileOptionName).getArgumentByName("filename").getValueAsString(); + } + bool DFTSettings::useSymmetryReduction() const { return this->getOption(symmetryReductionOptionName).getHasOptionBeenSet(); } diff --git a/src/storm-dft/settings/modules/DFTSettings.h b/src/storm-dft/settings/modules/DFTSettings.h index 1b1b097f9..c1a9df7e5 100644 --- a/src/storm-dft/settings/modules/DFTSettings.h +++ b/src/storm-dft/settings/modules/DFTSettings.h @@ -34,6 +34,20 @@ namespace storm { */ std::string getDftFilename() const; + /*! + * Retrieves whether the dft file option for Json was set. + * + * @return True if the dft file option was set. + */ + bool isDftJsonFileSet() const; + + /*! + * Retrieves the name of the json file that contains the dft specification. + * + * @return The name of the json file that contains the dft specification. + */ + std::string getDftJsonFilename() const; + /*! * Retrieves whether the option to use symmetry reduction is set. * @@ -144,6 +158,8 @@ namespace storm { // Define the string names of the options as constants. static const std::string dftFileOptionName; static const std::string dftFileOptionShortName; + static const std::string dftJsonFileOptionName; + static const std::string dftJsonFileOptionShortName; static const std::string symmetryReductionOptionName; static const std::string symmetryReductionOptionShortName; static const std::string modularisationOptionName; diff --git a/src/storm-dft/storage/dft/DFT.cpp b/src/storm-dft/storage/dft/DFT.cpp index 8f19119a2..e38c40ce1 100644 --- a/src/storm-dft/storage/dft/DFT.cpp +++ b/src/storm-dft/storage/dft/DFT.cpp @@ -174,7 +174,8 @@ namespace storm { std::shared_ptr const> dependency = getDependency(idDependency); visitQueue.push(dependency->id()); visitQueue.push(dependency->triggerEvent()->id()); - visitQueue.push(dependency->dependentEvent()->id()); + STORM_LOG_THROW(dependency->dependentEvents().size() == 1, storm::exceptions::NotSupportedException, "Direct state generation does not support n-ary dependencies. Consider rewriting them by setting the binary dependency flag."); + visitQueue.push(dependency->dependentEvents()[0]->id()); } stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); @@ -284,7 +285,13 @@ namespace storm { template uint64_t DFT::maxRank() const { - return mElements.back()->rank(); + uint64_t max = 0; + for (auto const& e : mElements) { + if(e->rank() > max) { + max = e->rank(); + } + } + return max; } template diff --git a/src/storm-dft/storage/dft/DFT.h b/src/storm-dft/storage/dft/DFT.h index 9ef232a65..4c904ec5c 100644 --- a/src/storm-dft/storage/dft/DFT.h +++ b/src/storm-dft/storage/dft/DFT.h @@ -15,7 +15,7 @@ #include "storm-dft/storage/dft/DFTElements.h" #include "storm-dft/storage/dft/SymmetricUnits.h" #include "storm-dft/storage/dft/DFTStateGenerationInfo.h" - +#include "storm-dft/storage/dft/DFTLayoutInfo.h" namespace storm { namespace storage { @@ -63,7 +63,8 @@ namespace storm { std::vector mTopModule; std::map mRepresentants; // id element -> id representative std::vector> mSymmetries; - + std::map mLayoutInfo; + public: DFT(DFTElementVector const& elements, DFTElementPointer const& tle); @@ -263,7 +264,19 @@ namespace storm { std::vector immediateFailureCauses(size_t index) const; std::vector findModularisationRewrite() const; - + + void setElementLayoutInfo(size_t id, DFTLayoutInfo const& layoutInfo) { + mLayoutInfo[id] = layoutInfo; + } + + DFTLayoutInfo const& getElementLayoutInfo(size_t id) const { + if(mLayoutInfo.count(id) == 0) { + STORM_LOG_WARN("Layout info for element with id " << id << " not found"); + return DFTLayoutInfo(); + } + return mLayoutInfo.at(id); + } + private: std::pair, std::vector> getSortedParentAndOutDepIds(size_t index) const; diff --git a/src/storm-dft/storage/dft/DFTBuilder.cpp b/src/storm-dft/storage/dft/DFTBuilder.cpp index 612008226..70df810cf 100644 --- a/src/storm-dft/storage/dft/DFTBuilder.cpp +++ b/src/storm-dft/storage/dft/DFTBuilder.cpp @@ -25,9 +25,11 @@ namespace storm { if (itFind != mElements.end()) { // Child found DFTElementPointer childElement = itFind->second; - STORM_LOG_ASSERT(!childElement->isDependency(), "Child is dependency."); - gate->pushBackChild(childElement); - childElement->addParent(gate); + STORM_LOG_TRACE("Ignore functional dependency " << child << " in gate " << gate->name()); + if(!childElement->isDependency()) { + gate->pushBackChild(childElement); + childElement->addParent(gate); + } } else { // Child not found -> find first dependent event to assure that child is dependency // TODO: Not sure whether this is the intended behaviour? @@ -50,17 +52,31 @@ namespace storm { } } - // Initialize dependencies - for (auto& dependency : mDependencies) { - DFTGatePointer triggerEvent = std::static_pointer_cast>(mElements[dependency->nameTrigger()]); - STORM_LOG_ASSERT(mElements[dependency->nameDependent()]->isBasicElement(), "Dependent element is not BE."); - std::shared_ptr> dependentEvent = std::static_pointer_cast>(mElements[dependency->nameDependent()]); - dependency->initialize(triggerEvent, dependentEvent); - triggerEvent->addOutgoingDependency(dependency); - dependentEvent->addIngoingDependency(dependency); + for(auto& elem : mDependencyChildNames) { + bool first = true; + std::vector>> dependencies; + for(auto const& childName : elem.second) { + auto itFind = mElements.find(childName); + STORM_LOG_ASSERT(itFind != mElements.end(), "Child '" << childName << "' not found"); + DFTElementPointer childElement = itFind->second; + if (!first) { + dependencies.push_back(std::static_pointer_cast>(childElement)); + } else { + elem.first->setTriggerElement(std::static_pointer_cast>(childElement)); + childElement->addOutgoingDependency(elem.first); + } + first = false; + } + if (binaryDependencies) { + assert(dependencies.size() == 1); + } + elem.first->setDependentEvents(dependencies); + for (auto& dependency : dependencies) { + dependency->addIngoingDependency(elem.first); + } + } - - + // Sort elements topologically // compute rank @@ -73,8 +89,18 @@ namespace storm { for(DFTElementPointer e : elems) { e->setId(id++); } + STORM_LOG_ASSERT(!mTopLevelIdentifier.empty(), "No top level element."); - return DFT(elems, mElements[mTopLevelIdentifier]); + DFT dft(elems, mElements[mTopLevelIdentifier]); + + // Set layout info + for (auto& elem : mElements) { + if(mLayoutInfo.count(elem.first) > 0) { + dft.setElementLayoutInfo(elem.second->id(), mLayoutInfo.at(elem.first)); + } + } + + return dft; } template @@ -144,10 +170,10 @@ namespace storm { element = std::make_shared>(mNextId++, name); break; case DFTElementType::PAND: - element = std::make_shared>(mNextId++, name); + element = std::make_shared>(mNextId++, name, pandDefaultInclusive); break; case DFTElementType::POR: - element = std::make_shared>(mNextId++, name); + element = std::make_shared>(mNextId++, name, porDefaultInclusive); break; case DFTElementType::SPARE: element = std::make_shared>(mNextId++, name); @@ -175,10 +201,24 @@ namespace storm { } else if(visited[n] == topoSortColour::WHITE) { if(n->isGate()) { visited[n] = topoSortColour::GREY; - for(DFTElementPointer const& c : std::static_pointer_cast>(n)->children()) { + for (DFTElementPointer const& c : std::static_pointer_cast>(n)->children()) { + topoVisit(c, visited, L); + } + } + // TODO restrictions and dependencies have no parents, so this can be done more efficiently. + if(n->isRestriction()) { + visited[n] = topoSortColour::GREY; + for (DFTElementPointer const& c : std::static_pointer_cast>(n)->children()) { topoVisit(c, visited, L); } } + if(n->isDependency()) { + visited[n] = topoSortColour::GREY; + for (DFTElementPointer const& c : std::static_pointer_cast>(n)->dependentEvents()) { + topoVisit(c, visited, L); + } + topoVisit(std::static_pointer_cast>(n)->triggerEvent(), visited, L); + } visited[n] = topoSortColour::BLACK; L.push_back(n); } @@ -240,7 +280,9 @@ namespace storm { { DFTDependencyPointer dependency = std::static_pointer_cast>(element); children.push_back(dependency->triggerEvent()->name()); - children.push_back(dependency->dependentEvent()->name()); + for(auto const& depEv : dependency->dependentEvents()) { + children.push_back(depEv->name()); + } addDepElement(element->name(), children, dependency->probability()); break; } diff --git a/src/storm-dft/storage/dft/DFTBuilder.h b/src/storm-dft/storage/dft/DFTBuilder.h index f9a11d52b..636b5e5a1 100644 --- a/src/storm-dft/storage/dft/DFTBuilder.h +++ b/src/storm-dft/storage/dft/DFTBuilder.h @@ -7,7 +7,7 @@ #include "storm-dft/storage/dft/DFTElements.h" #include "storm-dft/storage/dft/elements/DFTRestriction.h" - +#include "storm-dft/storage/dft/DFTLayoutInfo.h" namespace storm { namespace storage { @@ -31,11 +31,13 @@ namespace storm { std::unordered_map mElements; std::unordered_map> mChildNames; std::unordered_map> mRestrictionChildNames; + std::unordered_map> mDependencyChildNames; std::vector mDependencies; std::vector mRestrictions; + std::unordered_map mLayoutInfo; public: - DFTBuilder() { + DFTBuilder(bool defaultInclusive = true, bool binaryDependencies = true) : pandDefaultInclusive(defaultInclusive), porDefaultInclusive(defaultInclusive), binaryDependencies(binaryDependencies) { } @@ -51,10 +53,26 @@ namespace storm { return addStandardGate(name, children, DFTElementType::PAND); } + bool addPandElement(std::string const& name, std::vector const& children, bool inclusive) { + bool tmpDefault = pandDefaultInclusive; + pandDefaultInclusive = inclusive; + bool result = addStandardGate(name, children, DFTElementType::PAND); + pandDefaultInclusive = tmpDefault; + return result; + } + bool addPorElement(std::string const& name, std::vector const& children) { return addStandardGate(name, children, DFTElementType::POR); } + bool addPorElement(std::string const& name, std::vector const& children, bool inclusive) { + bool tmpDefault = porDefaultInclusive; + porDefaultInclusive = inclusive; + bool result = addStandardGate(name, children, DFTElementType::POR); + pandDefaultInclusive = tmpDefault; + return result; + } + bool addSpareElement(std::string const& name, std::vector const& children) { return addStandardGate(name, children, DFTElementType::SPARE); } @@ -84,7 +102,7 @@ namespace storm { //TODO Matthias: collect constraints for SMT solving //0 <= probability <= 1 - if (!storm::utility::isOne(probability) && children.size() > 2) { + if (binaryDependencies && !storm::utility::isOne(probability) && children.size() > 2) { // Introduce additional element for first capturing the proabilistic dependency std::string nameAdditional = name + "_additional"; addBasicElement(nameAdditional, storm::utility::zero(), storm::utility::zero()); @@ -97,16 +115,27 @@ namespace storm { return true; } else { // Add dependencies - for (size_t i = 1; i < children.size(); ++i) { - std::string nameDep = name + "_" + std::to_string(i); - if(mElements.count(nameDep) != 0) { - // Element with that name already exists. - STORM_LOG_ERROR("Element with name: " << nameDep << " already exists."); - return false; + if(binaryDependencies) { + for (size_t i = 1; i < children.size(); ++i) { + std::string nameDep = name + "_" + std::to_string(i); + if (mElements.count(nameDep) != 0) { + // Element with that name already exists. + STORM_LOG_ERROR("Element with name: " << nameDep << " already exists."); + return false; + } + STORM_LOG_ASSERT(storm::utility::isOne(probability) || children.size() == 2, + "PDep with multiple children supported."); + DFTDependencyPointer element = std::make_shared>(mNextId++, + nameDep, + probability); + mElements[element->name()] = element; + mDependencyChildNames[element] = {trigger, children[i]}; + mDependencies.push_back(element); } - STORM_LOG_ASSERT(storm::utility::isOne(probability) || children.size() == 2, "PDep with multiple children supported."); - DFTDependencyPointer element = std::make_shared>(mNextId++, nameDep, trigger, children[i], probability); + } else { + DFTDependencyPointer element = std::make_shared>(mNextId++, name, probability); mElements[element->name()] = element; + mDependencyChildNames[element] = children; mDependencies.push_back(element); } return true; @@ -147,6 +176,11 @@ namespace storm { mElements[name] = std::make_shared>(mNextId++, name, failureRate, dormancyFactor); return true; } + + void addLayoutInfo(std::string const& name, double x, double y) { + STORM_LOG_ASSERT(mElements.count(name) > 0, "Element '" << name << "' not found."); + mLayoutInfo[name] = storm::storage::DFTLayoutInfo(x, y); + } bool setTopLevel(std::string const& tle) { mTopLevelIdentifier = tle; @@ -187,6 +221,13 @@ namespace storm { DFTElementVector topoSort(); + // If true, the standard gate adders make a pand inclusive, and exclusive otherwise. + bool pandDefaultInclusive; + // If true, the standard gate adders make a pand inclusive, and exclusive otherwise. + bool porDefaultInclusive; + + bool binaryDependencies; + }; } } diff --git a/src/storm-dft/storage/dft/DFTIsomorphism.h b/src/storm-dft/storage/dft/DFTIsomorphism.h index 86625c975..081b76f0b 100644 --- a/src/storm-dft/storage/dft/DFTIsomorphism.h +++ b/src/storm-dft/storage/dft/DFTIsomorphism.h @@ -258,7 +258,8 @@ namespace storage { } void colourize(std::shared_ptr> const& dep) { - depColour[dep->id()] = std::pair(dep->probability(), dep->dependentEvent()->activeFailureRate()); + // TODO this can be improved for n-ary dependencies. + depColour[dep->id()] = std::pair(dep->probability(), dep->dependentEvents()[0]->activeFailureRate()); } void colourize(std::shared_ptr> const& restr) { @@ -486,10 +487,26 @@ namespace storage { STORM_LOG_ASSERT(dft.isDependency(indexpair.second), "Element is no dependency."); auto const& lDep = dft.getDependency(indexpair.first); auto const& rDep = dft.getDependency(indexpair.second); + if(bijection.at(lDep->triggerEvent()->id()) != rDep->triggerEvent()->id()) { return false; - } - if(bijection.at(lDep->dependentEvent()->id()) != rDep->dependentEvent()->id()) { + } + + std::set dependenciesLeftMapped; + for (auto const& depEv : lDep->dependentEvents()) { + if (bleft.has(depEv->id())) { + dependenciesLeftMapped.insert(bijection.at(depEv->id())); + } + } + + std::set dependenciesRight; + for (auto const& depEv : rDep->dependentEvents()) { + if (bright.has(depEv->id())) { + dependenciesRight.insert(depEv->id()); + } + } + + if (dependenciesLeftMapped != dependenciesRight) { return false; } } else if(dft.isRestriction(indexpair.first)) { diff --git a/src/storm-dft/storage/dft/DFTLayoutInfo.h b/src/storm-dft/storage/dft/DFTLayoutInfo.h new file mode 100644 index 000000000..c61de0f6d --- /dev/null +++ b/src/storm-dft/storage/dft/DFTLayoutInfo.h @@ -0,0 +1,15 @@ +#pragma once + +namespace storm { + namespace storage { + struct DFTLayoutInfo { + DFTLayoutInfo() {}; + DFTLayoutInfo(double x, double y) : x(x), y(y) {}; + + // x location + double x = 0.0; + // y location + double y = 0.0; + }; + } +} diff --git a/src/storm-dft/storage/dft/DFTState.cpp b/src/storm-dft/storage/dft/DFTState.cpp index 78c0937d8..ec6509944 100644 --- a/src/storm-dft/storage/dft/DFTState.cpp +++ b/src/storm-dft/storage/dft/DFTState.cpp @@ -57,7 +57,8 @@ namespace storm { for (size_t dependencyId : mDft.getDependencies()) { std::shared_ptr const> dependency = mDft.getDependency(dependencyId); STORM_LOG_ASSERT(dependencyId == dependency->id(), "Ids do not match."); - if (hasFailed(dependency->triggerEvent()->id()) && getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) { + assert(dependency->dependentEvents().size() == 1); + if (hasFailed(dependency->triggerEvent()->id()) && getElementState(dependency->dependentEvents()[0]->id()) == DFTElementState::Operational) { mFailableDependencies.push_back(dependencyId); STORM_LOG_TRACE("New dependency failure: " << dependency->toString()); } @@ -198,8 +199,9 @@ namespace storm { for (auto dependency : mDft.getElement(id)->outgoingDependencies()) { STORM_LOG_ASSERT(dependency->triggerEvent()->id() == id, "Ids do not match."); - if (getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) { - STORM_LOG_ASSERT(!isFailsafe(dependency->dependentEvent()->id()), "Dependent event is failsafe."); + assert(dependency->dependentEvents().size() == 1); + if (getElementState(dependency->dependentEvents()[0]->id()) == DFTElementState::Operational) { + STORM_LOG_ASSERT(!isFailsafe(dependency->dependentEvents()[0]->id()), "Dependent event is failsafe."); mFailableDependencies.push_back(dependency->id()); STORM_LOG_TRACE("New dependency failure: " << dependency->toString()); } @@ -213,7 +215,8 @@ namespace storm { STORM_LOG_ASSERT(hasFailed(id), "Element has not failed."); for (auto dependency : mDft.getBasicElement(id)->ingoingDependencies()) { - STORM_LOG_ASSERT(dependency->dependentEvent()->id() == id, "Ids do not match."); + assert(dependency->dependentEvents().size() == 1); + STORM_LOG_ASSERT(dependency->dependentEvents()[0]->id() == id, "Ids do not match."); setDependencyDontCare(dependency->id()); } } @@ -244,7 +247,8 @@ namespace storm { // Consider failure due to dependency STORM_LOG_ASSERT(index < nrFailableDependencies(), "Index invalid."); std::shared_ptr const> dependency = mDft.getDependency(mFailableDependencies[index]); - std::pair const>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true); + assert(dependency->dependentEvents().size() == 1); + std::pair const>,bool> res(mDft.getBasicElement(dependency->dependentEvents()[0]->id()), true); mFailableDependencies.erase(mFailableDependencies.begin() + index); setFailed(res.first->id()); setDependencySuccessful(dependency->id()); diff --git a/src/storm-dft/storage/dft/elements/DFTBE.h b/src/storm-dft/storage/dft/elements/DFTBE.h index 216227af6..3be82d9f1 100644 --- a/src/storm-dft/storage/dft/elements/DFTBE.h +++ b/src/storm-dft/storage/dft/elements/DFTBE.h @@ -38,7 +38,8 @@ namespace storm { } bool addIngoingDependency(DFTDependencyPointer const& e) { - STORM_LOG_ASSERT(e->dependentEvent()->id() == this->id(), "Ids do not match."); + // TODO write this assertion for n-ary dependencies, probably by addign a method to the dependencies to support this. + //STORM_LOG_ASSERT(e->dependentEvent()->id() == this->id(), "Ids do not match."); if(std::find(mIngoingDependencies.begin(), mIngoingDependencies.end(), e) != mIngoingDependencies.end()) { return false; } diff --git a/src/storm-dft/storage/dft/elements/DFTDependency.h b/src/storm-dft/storage/dft/elements/DFTDependency.h index 2c5b7d0cc..7d11bae2a 100644 --- a/src/storm-dft/storage/dft/elements/DFTDependency.h +++ b/src/storm-dft/storage/dft/elements/DFTDependency.h @@ -12,35 +12,28 @@ namespace storm { using DFTBEPointer = std::shared_ptr>; protected: - std::string mNameTrigger; - std::string mNameDependent; ValueType mProbability; DFTGatePointer mTriggerEvent; - DFTBEPointer mDependentEvent; + std::vector mDependentEvents; public: - DFTDependency(size_t id, std::string const& name, std::string const& trigger, std::string const& dependent, ValueType probability) : - DFTElement(id, name), mNameTrigger(trigger), mNameDependent(dependent), mProbability(probability) + DFTDependency(size_t id, std::string const& name, ValueType probability) : + DFTElement(id, name), mProbability(probability) { } virtual ~DFTDependency() {} - void initialize(DFTGatePointer triggerEvent, DFTBEPointer dependentEvent) { - STORM_LOG_ASSERT(triggerEvent->name() == mNameTrigger, "Name does not match."); - STORM_LOG_ASSERT(dependentEvent->name() == mNameDependent, "Name does not match."); + void setTriggerElement(DFTGatePointer const& triggerEvent) { mTriggerEvent = triggerEvent; - mDependentEvent = dependentEvent; - } - std::string nameTrigger() const { - return mNameTrigger; } - std::string nameDependent() const { - return mNameDependent; + void setDependentEvents(std::vector const& dependentEvents) { + mDependentEvents = dependentEvents; } + ValueType const& probability() const { return mProbability; } @@ -50,9 +43,9 @@ namespace storm { return mTriggerEvent; } - DFTBEPointer const& dependentEvent() const { - STORM_LOG_ASSERT(mDependentEvent, "Dependent element does not exists."); - return mDependentEvent; + std::vector const& dependentEvents() const { + STORM_LOG_ASSERT(mDependentEvents.size() > 0, "Dependent element does not exists."); + return mDependentEvents; } DFTElementType type() const override { @@ -76,9 +69,11 @@ namespace storm { virtual std::vector independentUnit() const override { std::set unit = {this->mId}; - mDependentEvent->extendUnit(unit); - if(unit.count(mTriggerEvent->id()) != 0) { - return {}; + for(auto const& depEv : mDependentEvents) { + depEv->extendUnit(unit); + if(unit.count(mTriggerEvent->id()) != 0) { + return {}; + } } return std::vector(unit.begin(), unit.end()); } @@ -90,7 +85,10 @@ namespace storm { // Parent in the subdft, ie it is *not* a subdft return; } - mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); + for (auto const& depEv : mDependentEvents) { + depEv->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); + if (elemsInSubtree.empty()) return; + } if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; @@ -102,7 +100,11 @@ namespace storm { virtual std::string toString() const override { std::stringstream stream; bool fdep = storm::utility::isOne(mProbability); - stream << "{" << this->name() << "} " << (fdep ? "FDEP" : "PDEP") << "(" << mTriggerEvent->name() << " => " << mDependentEvent->name() << ")"; + stream << "{" << this->name() << "} " << (fdep ? "FDEP" : "PDEP") << "(" << mTriggerEvent->name() << " => { "; + for(auto const& depEv : mDependentEvents) { + stream << depEv->name() << " "; + } + stream << "}"; if (!fdep) { stream << " with probability " << mProbability; } diff --git a/src/storm-dft/storage/dft/elements/DFTElement.cpp b/src/storm-dft/storage/dft/elements/DFTElement.cpp index 61a087bdb..287af8e98 100644 --- a/src/storm-dft/storage/dft/elements/DFTElement.cpp +++ b/src/storm-dft/storage/dft/elements/DFTElement.cpp @@ -14,8 +14,10 @@ namespace storm { } // Check that no outgoing dependencies can be triggered anymore + // Notice that n-ary dependencies are supported via rewriting them during build-time for (DFTDependencyPointer dependency : mOutgoingDependencies) { - if (state.isOperational(dependency->dependentEvent()->id()) && state.isOperational(dependency->triggerEvent()->id())) { + assert(dependency->dependentEvents().size() == 1); + if (state.isOperational(dependency->dependentEvents()[0]->id()) && state.isOperational(dependency->triggerEvent()->id())) { return false; } } diff --git a/src/storm-dft/storage/dft/elements/DFTPand.h b/src/storm-dft/storage/dft/elements/DFTPand.h index bb18efe72..21cda29a9 100644 --- a/src/storm-dft/storage/dft/elements/DFTPand.h +++ b/src/storm-dft/storage/dft/elements/DFTPand.h @@ -7,11 +7,13 @@ namespace storm { class DFTPand : public DFTGate { public: - DFTPand(size_t id, std::string const& name, std::vector>> const& children = {}) : - DFTGate(id, name, children) + DFTPand(size_t id, std::string const& name, bool inclusive, std::vector>> const& children = {}) : + DFTGate(id, name, children), + inclusive(inclusive) {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(inclusive); if(state.isOperational(this->mId)) { bool childOperationalBefore = false; for(auto const& child : this->mChildren) @@ -31,6 +33,7 @@ namespace storm { } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(inclusive); STORM_LOG_ASSERT(this->hasFailsafeChild(state), "No failsafe child."); if(state.isOperational(this->mId)) { this->failsafe(state, queues); @@ -42,9 +45,15 @@ namespace storm { return DFTElementType::PAND; } + bool isInclusive() const { + return inclusive; + } + std::string typestring() const override { - return "PAND"; + return inclusive ? "PAND-inc" : "PAND-ex"; } + protected: + bool inclusive; }; template diff --git a/src/storm-dft/storage/dft/elements/DFTPor.h b/src/storm-dft/storage/dft/elements/DFTPor.h index 6e2fe731c..857e19714 100644 --- a/src/storm-dft/storage/dft/elements/DFTPor.h +++ b/src/storm-dft/storage/dft/elements/DFTPor.h @@ -6,12 +6,14 @@ namespace storm { template class DFTPor : public DFTGate { public: - DFTPor(size_t id, std::string const& name, std::vector>> const& children = {}) : - DFTGate(id, name, children) + DFTPor(size_t id, std::string const& name, bool inclusive, std::vector>> const& children = {}) : + DFTGate(id, name, children), + inclusive(inclusive) {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(state.isOperational(this->mId)) { + assert(inclusive); + if(state.isOperational(this->mId)) { if (state.hasFailed(this->mChildren.front()->id())) { // First child has failed before others this->fail(state, queues); @@ -28,6 +30,7 @@ namespace storm { } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(inclusive); if (state.isFailsafe(this->mChildren.front()->id())) { this->failsafe(state, queues); this->childrenDontCare(state, queues); @@ -39,8 +42,14 @@ namespace storm { } std::string typestring() const override { - return "POR"; + return inclusive ? "POR-inc" : "POR-ex"; } + + bool isInclusive() const { + return inclusive; + } + protected: + bool inclusive; }; template diff --git a/src/storm-dft/storage/dft/elements/DFTRestriction.h b/src/storm-dft/storage/dft/elements/DFTRestriction.h index f4a03f688..195a217bb 100644 --- a/src/storm-dft/storage/dft/elements/DFTRestriction.h +++ b/src/storm-dft/storage/dft/elements/DFTRestriction.h @@ -36,6 +36,15 @@ namespace storm { virtual bool isSeqEnforcer() const { return false; } + + bool allChildrenBEs() const { + for(auto const& elem : mChildren) { + if (!elem->isBasicElement()) { + return false; + } + } + return true; + } virtual std::string typestring() const = 0; diff --git a/src/storm-dft/transformations/DftToGspnTransformator.cpp b/src/storm-dft/transformations/DftToGspnTransformator.cpp new file mode 100644 index 000000000..8c3ef0448 --- /dev/null +++ b/src/storm-dft/transformations/DftToGspnTransformator.cpp @@ -0,0 +1,629 @@ +#include "DftToGspnTransformator.h" +#include "storm/exceptions/NotImplementedException.h" +#include + +namespace storm { + namespace transformations { + namespace dft { + + // Prevent some magic constants + static constexpr const uint64_t defaultPriority = 1; + static constexpr const uint64_t defaultCapacity = 1; + + template + DftToGspnTransformator::DftToGspnTransformator(storm::storage::DFT const& dft) : mDft(dft) { + // Intentionally left empty. + } + + template + void DftToGspnTransformator::transform() { + + builder.setGspnName("DftToGspnTransformation"); + + // Loop through every DFT element and draw them as a GSPN. + drawGSPNElements(); + + // Draw restrictions into the GSPN (i.e. SEQ or MUTEX). + //drawGSPNRestrictions(); + } + + template + uint64_t DftToGspnTransformator::toplevelFailedPlaceId() { + assert(failedNodes.size() > mDft.getTopLevelIndex()); + return failedNodes[mDft.getTopLevelIndex()]; + } + + template + void DftToGspnTransformator::drawGSPNElements() { + + + // Loop through every DFT element and draw them as a GSPN. + for (std::size_t i = 0; i < mDft.nrElements(); i++) { + auto dftElement = mDft.getElement(i); + bool isRepresentative = mDft.isRepresentative(i); + + // Check which type the element is and call the corresponding drawing-function. + switch (dftElement->type()) { + case storm::storage::DFTElementType::AND: + drawAND(std::static_pointer_cast const>(dftElement), isRepresentative); + break; + case storm::storage::DFTElementType::OR: + drawOR(std::static_pointer_cast const>(dftElement), isRepresentative); + break; + case storm::storage::DFTElementType::VOT: + drawVOT(std::static_pointer_cast const>(dftElement), isRepresentative); + break; + case storm::storage::DFTElementType::PAND: + drawPAND(std::static_pointer_cast const>(dftElement), isRepresentative); + break; + case storm::storage::DFTElementType::SPARE: + drawSPARE(std::static_pointer_cast const>(dftElement), isRepresentative); + break; + case storm::storage::DFTElementType::POR: + drawPOR(std::static_pointer_cast const>(dftElement), isRepresentative); + break; + case storm::storage::DFTElementType::SEQ: + drawSeq(std::static_pointer_cast const>(dftElement)); + break; + case storm::storage::DFTElementType::MUTEX: + // No method call needed here. MUTEX only consists of restrictions, which are handled later. + break; + case storm::storage::DFTElementType::BE: + drawBE(std::static_pointer_cast const>(dftElement), isRepresentative); + break; + case storm::storage::DFTElementType::CONSTF: + drawCONSTF(dftElement, isRepresentative); + break; + case storm::storage::DFTElementType::CONSTS: + drawCONSTS(dftElement, isRepresentative); + break; + case storm::storage::DFTElementType::PDEP: + drawPDEP(std::static_pointer_cast const>(dftElement)); + break; + default: + STORM_LOG_ASSERT(false, "DFT type unknown."); + break; + } + } + + } + + template + void DftToGspnTransformator::drawBE(std::shared_ptr const> dftBE, bool isRepresentative) { + uint64_t beActive = builder.addPlace(defaultCapacity, isBEActive(dftBE) ? 1 : 0, dftBE->name() + STR_ACTIVATED); + activeNodes.emplace(dftBE->id(), beActive); + uint64_t beFailed = builder.addPlace(defaultCapacity, 0, dftBE->name() + STR_FAILED); + + double xcenter = mDft.getElementLayoutInfo(dftBE->id()).x; + double ycenter = mDft.getElementLayoutInfo(dftBE->id()).y; + builder.setPlaceLayoutInfo(beActive, storm::gspn::LayoutInfo(xcenter - 3.0, ycenter)); + builder.setPlaceLayoutInfo(beFailed, storm::gspn::LayoutInfo(xcenter + 3.0, ycenter)); + + + uint64_t disabledNode = 0; + if (!smart || dftBE->nrRestrictions() > 0) { + disabledNode = addDisabledPlace(dftBE); + } + + uint64_t unavailableNode = 0; + if (!smart || isRepresentative) { + unavailableNode = addUnavailableNode(dftBE, storm::gspn::LayoutInfo(xcenter+9.0, ycenter)); + } + + assert(failedNodes.size() == dftBE->id()); + failedNodes.push_back(beFailed); + uint64_t tActive = builder.addTimedTransition(defaultPriority, dftBE->activeFailureRate(), dftBE->name() + "_activeFailing"); + builder.setTransitionLayoutInfo(tActive, storm::gspn::LayoutInfo(xcenter, ycenter + 3.0)); + builder.addInputArc(beActive, tActive); + builder.addInhibitionArc(beFailed, tActive); + builder.addOutputArc(tActive, beActive); + builder.addOutputArc(tActive, beFailed); + uint64_t tPassive = builder.addTimedTransition(defaultPriority, dftBE->passiveFailureRate(), dftBE->name() + "_passiveFailing"); + builder.setTransitionLayoutInfo(tPassive, storm::gspn::LayoutInfo(xcenter, ycenter - 3.0)); + builder.addInhibitionArc(beActive, tPassive); + builder.addInhibitionArc(beFailed, tPassive); + builder.addOutputArc(tPassive, beFailed); + + if (!smart || dftBE->nrRestrictions() > 0) { + builder.addInhibitionArc(disabledNode, tActive); + builder.addInhibitionArc(disabledNode, tPassive); + } + + if (!smart || isRepresentative) { + builder.addOutputArc(tActive, unavailableNode); + builder.addOutputArc(tPassive, unavailableNode); + } + } + + template + void DftToGspnTransformator::drawAND(std::shared_ptr const> dftAnd, bool isRepresentative) { + uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftAnd->name() + STR_FAILED); + assert(failedNodes.size() == dftAnd->id()); + failedNodes.push_back(nodeFailed); + + double xcenter = mDft.getElementLayoutInfo(dftAnd->id()).x; + double ycenter = mDft.getElementLayoutInfo(dftAnd->id()).y; + builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter, ycenter-3.0)); + + uint64_t unavailableNode = 0; + if (isRepresentative) { + unavailableNode = addUnavailableNode(dftAnd, storm::gspn::LayoutInfo(xcenter+6.0, ycenter-3.0)); + } + + + uint64_t tAndFailed = builder.addImmediateTransition( getFailPriority(dftAnd) , 0.0, dftAnd->name() + STR_FAILING ); + builder.setTransitionLayoutInfo(tAndFailed, storm::gspn::LayoutInfo(xcenter, ycenter+3.0)); + builder.addInhibitionArc(nodeFailed, tAndFailed); + builder.addOutputArc(tAndFailed, nodeFailed); + if (isRepresentative) { + builder.addOutputArc(tAndFailed, unavailableNode); + } + for(auto const& child : dftAnd->children()) { + assert(failedNodes.size() > child->id()); + builder.addInputArc(failedNodes[child->id()], tAndFailed); + builder.addOutputArc(tAndFailed, failedNodes[child->id()]); + } + } + + template + void DftToGspnTransformator::drawOR(std::shared_ptr const> dftOr, bool isRepresentative) { + uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftOr->name() + STR_FAILED); + assert(failedNodes.size() == dftOr->id()); + failedNodes.push_back(nodeFailed); + + double xcenter = mDft.getElementLayoutInfo(dftOr->id()).x; + double ycenter = mDft.getElementLayoutInfo(dftOr->id()).y; + builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter, ycenter-3.0)); + + uint64_t unavailableNode = 0; + if (isRepresentative) { + unavailableNode = addUnavailableNode(dftOr, storm::gspn::LayoutInfo(xcenter+6.0, ycenter-3.0)); + } + + uint64_t i = 0; + for (auto const& child : dftOr->children()) { + uint64_t tNodeFailed = builder.addImmediateTransition( getFailPriority(dftOr), 0.0, dftOr->name() + STR_FAILING + std::to_string(i) ); + builder.setTransitionLayoutInfo(tNodeFailed, storm::gspn::LayoutInfo(xcenter-5.0+i*3.0, ycenter+3.0)); + builder.addInhibitionArc(nodeFailed, tNodeFailed); + builder.addOutputArc(tNodeFailed, nodeFailed); + if (isRepresentative) { + builder.addOutputArc(tNodeFailed, unavailableNode); + } + assert(failedNodes.size() > child->id()); + builder.addInputArc(failedNodes[child->id()], tNodeFailed); + builder.addOutputArc(tNodeFailed, failedNodes[child->id()]); + ++i; + } + } + + template + void DftToGspnTransformator::drawVOT(std::shared_ptr const> dftVot, bool isRepresentative) { + // TODO: finish layouting + uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftVot->name() + STR_FAILED); + assert(failedNodes.size() == dftVot->id()); + failedNodes.push_back(nodeFailed); + + double xcenter = mDft.getElementLayoutInfo(dftVot->id()).x; + double ycenter = mDft.getElementLayoutInfo(dftVot->id()).y; + builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter, ycenter-3.0)); + + uint64_t unavailableNode = 0; + if (isRepresentative) { + unavailableNode = addUnavailableNode(dftVot, storm::gspn::LayoutInfo(xcenter+6.0, ycenter-3.0)); + } + + uint64_t nodeCollector = builder.addPlace(dftVot->nrChildren(), 0, dftVot->name() + "_collector"); + builder.setPlaceLayoutInfo(nodeCollector, storm::gspn::LayoutInfo(xcenter, ycenter)); + + uint64_t tNodeFailed = builder.addImmediateTransition(getFailPriority(dftVot), 0.0, dftVot->name() + STR_FAILING); + builder.addOutputArc(tNodeFailed, nodeFailed); + if (isRepresentative) { + builder.addOutputArc(tNodeFailed, unavailableNode); + } + builder.addInhibitionArc(nodeFailed, tNodeFailed); + builder.addInputArc(nodeCollector, tNodeFailed, dftVot->threshold()); + builder.addOutputArc(tNodeFailed, nodeCollector, dftVot->threshold()); + uint64_t i = 0; + for (auto const& child : dftVot->children()) { + uint64_t childInhibPlace = builder.addPlace(1, 0, dftVot->name() + "_child_fail_inhib" + std::to_string(i)); + uint64_t tCollect = builder.addImmediateTransition(getFailPriority(dftVot), 0.0, dftVot->name() + "_child_collect" + std::to_string(i)); + builder.addOutputArc(tCollect, nodeCollector); + builder.addOutputArc(tCollect, childInhibPlace); + builder.addInhibitionArc(childInhibPlace, tCollect); + builder.addInputArc(failedNodes[child->id()], tCollect); + builder.addOutputArc(tCollect, failedNodes[child->id()]); + ++i; + } + } + + template + void DftToGspnTransformator::drawPAND(std::shared_ptr const> dftPand, bool isRepresentative) { + uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftPand->name() + STR_FAILED); + assert(failedNodes.size() == dftPand->id()); + failedNodes.push_back(nodeFailed); + + double xcenter = mDft.getElementLayoutInfo(dftPand->id()).x; + double ycenter = mDft.getElementLayoutInfo(dftPand->id()).y; + builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter+3.0, ycenter-3.0)); + + uint64_t unavailableNode = 0; + if (!smart || isRepresentative) { + unavailableNode = addUnavailableNode(dftPand, storm::gspn::LayoutInfo(xcenter+9.0, ycenter-3.0)); + } + + uint64_t tNodeFailed = builder.addImmediateTransition(getFailPriority(dftPand), 0.0, dftPand->name() + STR_FAILING); + builder.setTransitionLayoutInfo(tNodeFailed, storm::gspn::LayoutInfo(xcenter+3.0, ycenter+3.0)); + builder.addInhibitionArc(nodeFailed, tNodeFailed); + builder.addOutputArc(tNodeFailed, nodeFailed); + if (!smart || isRepresentative) { + builder.addOutputArc(tNodeFailed, nodeFailed); + } + + if(dftPand->isInclusive()) { + // Inclusive PAND + uint64_t nodeFS = builder.addPlace(defaultCapacity, 0, dftPand->name() + STR_FAILSAVE); + builder.setPlaceLayoutInfo(nodeFS, storm::gspn::LayoutInfo(xcenter-3.0, ycenter-3.0)); + + builder.addInhibitionArc(nodeFS, tNodeFailed); + for(auto const& child : dftPand->children()) { + builder.addInputArc(failedNodes[child->id()], tNodeFailed); + builder.addOutputArc(tNodeFailed, failedNodes[child->id()]); + } + for (uint64_t j = 1; j < dftPand->nrChildren(); ++j) { + uint64_t tfs = builder.addImmediateTransition(getFailPriority(dftPand), 0.0, dftPand->name() + STR_FAILSAVING + std::to_string(j)); + builder.setTransitionLayoutInfo(tfs, storm::gspn::LayoutInfo(xcenter-6.0+j*3.0, ycenter+3.0)); + + builder.addInputArc(failedNodes[dftPand->children().at(j)->id()], tfs); + builder.addOutputArc(tfs, failedNodes[dftPand->children().at(j)->id()]); + builder.addInhibitionArc(failedNodes[dftPand->children().at(j-1)->id()], tfs); + builder.addOutputArc(tfs, nodeFS); + builder.addInhibitionArc(nodeFS, tfs); + + } + } else { + // Exclusive PAND + uint64_t fi = 0; + uint64_t tn = 0; + for(uint64_t j = 0; j < dftPand->nrChildren(); ++j) { + auto const& child = dftPand->children()[j]; + if (j > 0) { + builder.addInhibitionArc(failedNodes.at(child->id()), tn); + } + if (j != dftPand->nrChildren() - 1) { + tn = builder.addImmediateTransition(getFailPriority(dftPand), 0.0, dftPand->name() + STR_FAILING + "_" +std::to_string(j)); + builder.setTransitionLayoutInfo(tn, storm::gspn::LayoutInfo(xcenter-3.0, ycenter+3.0)); + } else { + tn = tNodeFailed; + } + builder.addInputArc(failedNodes.at(child->id()), tn); + builder.addOutputArc(tn, failedNodes.at(child->id())); + if (j > 0) { + builder.addInputArc(fi, tn); + } + if (j != dftPand->nrChildren() - 1) { + fi = builder.addPlace(defaultCapacity, 0, dftPand->name() + "_F_" + std::to_string(j)); + builder.setPlaceLayoutInfo(fi, storm::gspn::LayoutInfo(xcenter-3.0+j*3.0, ycenter)); + builder.addOutputArc(tn, fi); + } + + } + } + } + + template + void DftToGspnTransformator::drawPOR(std::shared_ptr const> dftPor, bool isRepresentative) { + uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftPor->name() + STR_FAILED); + failedNodes.push_back(nodeFailed); + + double xcenter = mDft.getElementLayoutInfo(dftPor->id()).x; + double ycenter = mDft.getElementLayoutInfo(dftPor->id()).y; + builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter+3.0, ycenter-3.0)); + + uint64_t unavailableNode = 0; + if (!smart || isRepresentative) { + unavailableNode = addUnavailableNode(dftPor, storm::gspn::LayoutInfo(xcenter+9.0, ycenter-3.0)); + } + + uint64_t tfail = builder.addImmediateTransition(getFailPriority(dftPor), 0.0, dftPor->name() + STR_FAILING); + builder.setTransitionLayoutInfo(tfail, storm::gspn::LayoutInfo(xcenter+3.0, ycenter+3.0)); + builder.addOutputArc(tfail, nodeFailed); + builder.addInhibitionArc(nodeFailed, tfail); + + builder.addInputArc(failedNodes.at(dftPor->children().front()->id()), tfail); + builder.addOutputArc(tfail, failedNodes.at(dftPor->children().front()->id())); + + if(!smart || isRepresentative) { + builder.addOutputArc(tfail, unavailableNode); + } + + if(dftPor->isInclusive()) { + // Inclusive POR + uint64_t nodeFS = builder.addPlace(defaultCapacity, 0, dftPor->name() + STR_FAILSAVE); + builder.setPlaceLayoutInfo(nodeFS, storm::gspn::LayoutInfo(xcenter-3.0, ycenter-3.0)); + + builder.addInhibitionArc(nodeFS, tfail); + uint64_t j = 0; + for (auto const& child : dftPor->children()) { + if(j > 0) { + uint64_t tfailsf = builder.addImmediateTransition(getFailPriority(dftPor), 0.0, dftPor->name() + STR_FAILSAVING + std::to_string(j)); + builder.setTransitionLayoutInfo(tfailsf, storm::gspn::LayoutInfo(xcenter-3.0+j*3.0, ycenter+3.0)); + builder.addInputArc(failedNodes.at(child->id()), tfailsf); + builder.addOutputArc(tfailsf, failedNodes.at(child->id())); + builder.addOutputArc(tfailsf, nodeFS); + builder.addInhibitionArc(nodeFS, tfailsf); + builder.addInhibitionArc(failedNodes.at(dftPor->children().front()->id()), tfailsf); + } + + ++j; + } + } else { + // Exclusive POR + uint64_t j = 0; + for (auto const& child : dftPor->children()) { + if(j > 0) { + builder.addInhibitionArc(failedNodes.at(child->id()), tfail); + } + ++j; + } + + } + + } + + template + void DftToGspnTransformator::drawSPARE(std::shared_ptr const> dftSpare, bool isRepresentative) { + + uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftSpare->name() + STR_FAILED); + failedNodes.push_back(nodeFailed); + + double xcenter = mDft.getElementLayoutInfo(dftSpare->id()).x; + double ycenter = mDft.getElementLayoutInfo(dftSpare->id()).y; + builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter+10.0, ycenter-8.0)); + + uint64_t unavailableNode = 0; + if (isRepresentative) { + unavailableNode = addUnavailableNode(dftSpare, storm::gspn::LayoutInfo(xcenter+16.0, ycenter-8.0)); + } + uint64_t spareActive = builder.addPlace(defaultCapacity, isBEActive(dftSpare) ? 1 : 0, dftSpare->name() + STR_ACTIVATED); + builder.setPlaceLayoutInfo(spareActive, storm::gspn::LayoutInfo(xcenter-20.0, ycenter-8.0)); + activeNodes.emplace(dftSpare->id(), spareActive); + + + std::vector cucNodes; + std::vector considerNodes; + std::vector nextclTransitions; + std::vector nextconsiderTransitions; + uint64_t j = 0; + for(auto const& child : dftSpare->children()) { + if (j > 0) { + size_t nodeConsider = builder.addPlace(defaultCapacity, 0, dftSpare->name()+ "_consider_" + child->name()); + considerNodes.push_back(nodeConsider); + builder.setPlaceLayoutInfo(nodeConsider, storm::gspn::LayoutInfo(xcenter-15.0+j*14.0, ycenter-8.0)); + + builder.addOutputArc(nextclTransitions.back(), considerNodes.back(), 1); + if (j > 1) { + builder.addOutputArc(nextconsiderTransitions.back(), considerNodes.back()); + } + + uint64_t tnextconsider = builder.addImmediateTransition(getFailPriority(dftSpare), 0.0, dftSpare->name() + "_cannot_claim_" + child->name()); + builder.setTransitionLayoutInfo(tnextconsider, storm::gspn::LayoutInfo(xcenter-7.0+j*14.0, ycenter-8.0)); + builder.addInputArc(considerNodes.back(), tnextconsider); + builder.addInputArc(unavailableNodes.at(child->id()), tnextconsider); + nextconsiderTransitions.push_back(tnextconsider); + + } + size_t nodeCUC = builder.addPlace(defaultCapacity, j == 0 ? 1 : 0, dftSpare->name() + "_claimed_" + child->name()); + cucNodes.push_back(nodeCUC); + builder.setPlaceLayoutInfo(nodeCUC, storm::gspn::LayoutInfo(xcenter-9.0+j*14.0, ycenter+5.0)); + if (j > 0) { + uint64 tclaim = builder.addImmediateTransition(getFailPriority(dftSpare), 0.0, dftSpare->name() + "_claim_" + child->name()); + builder.setTransitionLayoutInfo(tclaim, storm::gspn::LayoutInfo(xcenter-9.0+j*14.0, ycenter)); + builder.addInhibitionArc(unavailableNodes.at(child->id()), tclaim); + builder.addInputArc(considerNodes.back(), tclaim); + builder.addOutputArc(tclaim, cucNodes.back()); + } + uint64_t tnextcl = builder.addImmediateTransition(getFailPriority(dftSpare), 0.0, dftSpare->name() + "_next_claim_" + std::to_string(j)); + builder.setTransitionLayoutInfo(tnextcl, storm::gspn::LayoutInfo(xcenter-3.0+j*14.0, ycenter+5.0)); + builder.addInputArc(cucNodes.back(), tnextcl); + builder.addInputArc(failedNodes.at(child->id()), tnextcl); + builder.addOutputArc(tnextcl, failedNodes.at(child->id())); + nextclTransitions.push_back(tnextcl); + ++j; + for (uint64_t k : mDft.module(child->id())) { + + uint64_t tactive = builder.addImmediateTransition(defaultPriority+1, 0.0, dftSpare->name() + "_activate_" + std::to_string(j) + "_" + std::to_string(k)); + builder.addInputArc(cucNodes.back(), tactive); + builder.addOutputArc(tactive, cucNodes.back()); + builder.addInputArc(spareActive, tactive); + builder.addOutputArc(tactive, activeNodes.at(k)); + builder.addInhibitionArc(activeNodes.at(k), tactive); + } + + + } + builder.addOutputArc(nextconsiderTransitions.back(), nodeFailed); + builder.addOutputArc(nextclTransitions.back(), nodeFailed); + + if (isRepresentative) { + builder.addOutputArc(nextconsiderTransitions.back(), unavailableNode); + builder.addOutputArc(nextclTransitions.back(), unavailableNode); + } + + + + } + + template + void DftToGspnTransformator::drawCONSTF(std::shared_ptr const> dftConstF, bool isRepresentative) { + failedNodes.push_back(builder.addPlace(defaultCapacity, 1, dftConstF->name() + STR_FAILED)); + uint64_t unavailableNode = 0; + if (isRepresentative) { + // TODO set position + unavailableNode = addUnavailableNode(dftConstF, storm::gspn::LayoutInfo(0, 0), false); + } + + } +// + template + void DftToGspnTransformator::drawCONSTS(std::shared_ptr const> dftConstS, bool isRepresentative) { +// storm::gspn::Place placeCONSTSFailed; +// placeCONSTSFailed.setName(dftConstS->name() + STR_FAILED); +// placeCONSTSFailed.setNumberOfInitialTokens(0); +// placeCONSTSFailed.setCapacity(0); // It cannot contain a token, because it cannot fail. +// mGspn.addPlace(placeCONSTSFailed); + } +// + template + void DftToGspnTransformator::drawPDEP(std::shared_ptr const> dftDependency) { + double xcenter = mDft.getElementLayoutInfo(dftDependency->id()).x;; + double ycenter = mDft.getElementLayoutInfo(dftDependency->id()).y;; + + uint64_t coinPlace = builder.addPlace(defaultCapacity, 1, dftDependency->name() + "_coin"); + builder.setPlaceLayoutInfo(coinPlace, storm::gspn::LayoutInfo(xcenter-5.0, ycenter+2.0)); + uint64_t t1 = builder.addImmediateTransition(defaultPriority, 0.0, dftDependency->name() + "_start_flip"); + + builder.addInputArc(coinPlace, t1); + builder.addInputArc(failedNodes.at(dftDependency->triggerEvent()->id()), t1); + builder.addOutputArc(t1, failedNodes.at(dftDependency->triggerEvent()->id())); + uint64_t forwardPlace = builder.addPlace(defaultCapacity, 0, dftDependency->name() + "_forward"); + builder.setPlaceLayoutInfo(forwardPlace, storm::gspn::LayoutInfo(xcenter+1.0, ycenter+2.0)); + + if (!smart || dftDependency->probability() < 1.0) { + uint64_t flipPlace = builder.addPlace(defaultCapacity, 0, dftDependency->name() + "_flip"); + builder.addOutputArc(t1, flipPlace); + + builder.setPlaceLayoutInfo(flipPlace, storm::gspn::LayoutInfo(xcenter-2.0, ycenter+2.0)); + uint64_t t2 = builder.addImmediateTransition(defaultPriority + 1, dftDependency->probability(), "_win_flip"); + builder.addInputArc(flipPlace, t2); + builder.addOutputArc(t2, forwardPlace); + if (dftDependency->probability() < 1.0) { + uint64_t t3 = builder.addImmediateTransition(defaultPriority + 1, 1 - dftDependency->probability(), "_loose_flip"); + builder.addInputArc(flipPlace, t3); + } + } else { + builder.addOutputArc(t1, forwardPlace); + } + for(auto const& depEv : dftDependency->dependentEvents()) { + uint64_t tx = builder.addImmediateTransition(defaultPriority, 0.0, dftDependency->name() + "_propagate_" + depEv->name()); + builder.addInputArc(forwardPlace, tx); + builder.addOutputArc(tx, forwardPlace); + builder.addOutputArc(tx, failedNodes.at(depEv->id())); + builder.addInhibitionArc(failedNodes.at(depEv->id()), tx); + if (!smart || depEv->nrRestrictions() > 0) { + builder.addInhibitionArc(disabledNodes.at(depEv->id()), tx); + } + if (!smart || mDft.isRepresentative(depEv->id())) { + builder.addOutputArc(tx, unavailableNodes.at(depEv->id())); + } + + } + + + + + + } + + template + void DftToGspnTransformator::drawSeq(std::shared_ptr const> dftSeq) { + STORM_LOG_THROW(dftSeq->allChildrenBEs(), storm::exceptions::NotImplementedException, "Sequence enforcers with gates as children are currently not supported"); + uint64_t j = 0; + uint64_t tEnable = 0; + uint64_t nextPlace = 0; + for(auto const& child : dftSeq->children()) { + nextPlace = builder.addPlace(defaultCapacity, j==0 ? 1 : 0, dftSeq->name() + "_next_" + child->name()); + if (j>0) { + builder.addOutputArc(tEnable, nextPlace); + } + tEnable = builder.addImmediateTransition(defaultPriority + 1, 0.0, dftSeq->name() + "_unblock_" +child->name() ); + builder.addInputArc(nextPlace, tEnable); + builder.addInputArc(disabledNodes.at(child->id()), tEnable); + if (j>0) { + builder.addInputArc(failedNodes.at(dftSeq->children().at(j-1)->id()), tEnable); + } + ++j; + } + + } + + template + uint64_t DftToGspnTransformator::addUnavailableNode(std::shared_ptr const> dftElement, storm::gspn::LayoutInfo const& layoutInfo, bool initialAvailable) { + uint64_t unavailableNode = builder.addPlace(defaultCapacity, initialAvailable ? 0 : 1, dftElement->name() + "_unavailable"); + assert(unavailableNode != 0); + unavailableNodes.emplace(dftElement->id(), unavailableNode); + builder.setPlaceLayoutInfo(unavailableNode, layoutInfo); + return unavailableNode; + } + + template + uint64_t DftToGspnTransformator::addDisabledPlace(std::shared_ptr > dftBe) { + uint64_t disabledNode = builder.addPlace(dftBe->nrRestrictions(), dftBe->nrRestrictions(), dftBe->name() + "_dabled"); + disabledNodes.emplace(dftBe->id(), disabledNode); + return disabledNode; + } +// + + template + bool DftToGspnTransformator::isBEActive(std::shared_ptr const> dftElement) + { + // If element is the top element, return true. + if (dftElement->id() == mDft.getTopLevelIndex()) { + return true; + } + else { // Else look at all parents. + auto parents = dftElement->parents(); + std::vector pathValidities; + + for (std::size_t i = 0; i < parents.size(); i++) { + // Add all parents to the vector, except if the parent is a SPARE and the current element is an inactive child of the SPARE. + if (parents[i]->type() == storm::storage::DFTElementType::SPARE) { + auto children = std::static_pointer_cast const>(parents[i])->children(); + if (children[0]->id() != dftElement->id()) { + continue; + } + } + + pathValidities.push_back(isBEActive(parents[i])); + } + + // Check all vector entries. If one is true, a "valid" path has been found. + for (std::size_t i = 0; i < pathValidities.size(); i++) { + if (pathValidities[i]) { + return true; + } + } + } + + // No "valid" path found. BE is inactive. + return false; + } + + template + uint64_t DftToGspnTransformator::getFailPriority(std::shared_ptr const> dftElement) + { + return mDft.maxRank() - dftElement->rank() + 2; + } + + + template + void DftToGspnTransformator::drawGSPNRestrictions() { + } + + template + gspn::GSPN* DftToGspnTransformator::obtainGSPN() { + return builder.buildGspn(); + } + + // Explicitly instantiate the class. + template class DftToGspnTransformator; + + + #ifdef STORM_HAVE_CARL + // template class DftToGspnTransformator; + #endif + + } // namespace dft + } // namespace transformations +} // namespace storm + + diff --git a/src/storm-dft/transformations/DftToGspnTransformator.h b/src/storm-dft/transformations/DftToGspnTransformator.h new file mode 100644 index 000000000..4ec911b23 --- /dev/null +++ b/src/storm-dft/transformations/DftToGspnTransformator.h @@ -0,0 +1,163 @@ +#pragma once + +#include "storm-dft/storage/dft/DFT.h" +#include "storm-gspn/storage/gspn/GSPN.h" +#include "storm-gspn/storage/gspn/GspnBuilder.h" + +namespace storm { + namespace transformations { + namespace dft { + + /*! + * Transformator for DFT -> GSPN. + */ + template + class DftToGspnTransformator { + + public: + /*! + * Constructor. + * + * @param dft DFT + */ + DftToGspnTransformator(storm::storage::DFT const& dft); + + /*! + * Transform the DFT to a GSPN. + */ + void transform(); + + /*! + * Extract Gspn by building + * + */ + gspn::GSPN* obtainGSPN(); + + + uint64_t toplevelFailedPlaceId(); + + private: + /* + * Draw all elements of the GSPN. + */ + void drawGSPNElements(); + /* + * Draw restrictions between the elements of the GSPN (i.e. SEQ or MUTEX). + */ + void drawGSPNRestrictions(); + + /* + * Draw a Petri net Basic Event. + * + * @param dftBE The Basic Event. + */ + void drawBE(std::shared_ptr const> dftBE, bool isRepresentative); + + /* + * Draw a Petri net AND. + * + * @param dftAnd The AND gate. + */ + void drawAND(std::shared_ptr const> dftAnd, bool isRepresentative); + + /* + * Draw a Petri net OR. + * + * @param dftOr The OR gate. + */ + void drawOR(std::shared_ptr const> dftOr, bool isRepresentative); + + /* + * Draw a Petri net VOT. + * + * @param dftVot The VOT gate. + */ + void drawVOT(std::shared_ptr const> dftVot, bool isRepresentative); + + /* + * Draw a Petri net PAND. + * This PAND is inklusive (children are allowed to fail simultaneously and the PAND will fail nevertheless). + * + * @param dftPand The PAND gate. + */ + void drawPAND(std::shared_ptr const> dftPand, bool isRepresentative); + + /* + * Draw a Petri net SPARE. + * + * @param dftSpare The SPARE gate. + */ + void drawSPARE(std::shared_ptr const> dftSpare, bool isRepresentative); + + /* + * Draw a Petri net POR. + * This POR is inklusive (children are allowed to fail simultaneously and the POR will fail nevertheless). + * + * @param dftPor The POR gate. + */ + void drawPOR(std::shared_ptr const> dftPor, bool isRepresentative); + + /* + * Draw a Petri net CONSTF (Constant Failure, a Basic Event that has already failed). + * + * @param dftPor The CONSTF Basic Event. + */ + void drawCONSTF(std::shared_ptr const> dftConstF, bool isRepresentative); + + /* + * Draw a Petri net CONSTS (Constant Save, a Basic Event that cannot fail). + * + * @param dftPor The CONSTS Basic Event. + */ + void drawCONSTS(std::shared_ptr const> dftConstS, bool isRepresentative); + + /* + * Draw a Petri net PDEP (FDEP is included with a firerate of 1). + */ + void drawPDEP(std::shared_ptr const> dftDependency); + + + void drawSeq(std::shared_ptr const> dftSeq); + /* + * Return true if BE is active (corresponding place contains one initial token) or false if BE is inactive (corresponding place contains no initial token). + * + * @param dFTElement DFT element. + */ + bool isBEActive(std::shared_ptr const> dFTElement); + + /* + * Get the priority of the element. + * The priority is two times the length of the shortest path to the top event. + * + * @param priority The priority of the gate. Top Event has priority 0, its children 2, its grandchildren 4, ... + * + * @param dftElement The element whose priority shall be determined. + */ + uint64_t getFailPriority(std::shared_ptr const> dFTElement); + + + uint64_t addUnavailableNode(std::shared_ptr const> dftElement, storm::gspn::LayoutInfo const& layoutInfo, bool initialAvailable = true); + + uint64_t addDisabledPlace(std::shared_ptr const> dftBe); + + storm::storage::DFT const& mDft; + storm::gspn::GspnBuilder builder; + std::vector failedNodes; + std::map unavailableNodes; + std::map activeNodes; + std::map disabledNodes; + bool smart = true; + + static constexpr const char* STR_FAILING = "_failing"; // Name standard for transitions that point towards a place, which in turn indicates the failure of a gate. + static constexpr const char* STR_FAILED = "_failed"; // Name standard for place which indicates the failure of a gate. + static constexpr const char* STR_FAILSAVING = "_failsaving"; // Name standard for transition that point towards a place, which in turn indicates the failsave state of a gate. + static constexpr const char* STR_FAILSAVE = "_failsave"; // Name standard for place which indicates the failsave state of a gate. + static constexpr const char* STR_ACTIVATED = "_activated"; // Name standard for place which indicates the activity. + static constexpr const char* STR_ACTIVATING = "_activating"; // Name standard for transition that point towards a place, which in turn indicates its activity. + + + }; + } + } +} + diff --git a/src/storm-gspn-cli/storm-gspn.cpp b/src/storm-gspn-cli/storm-gspn.cpp index b973d046d..4caa46485 100644 --- a/src/storm-gspn-cli/storm-gspn.cpp +++ b/src/storm-gspn-cli/storm-gspn.cpp @@ -3,6 +3,7 @@ #include "storm-gspn/storage/gspn/GSPN.h" #include "storm-gspn/storage/gspn/GspnBuilder.h" #include "storm-gspn/builder/JaniGSPNBuilder.h" +#include "storm-gspn/storm-gspn.h" #include "storm/exceptions/BaseException.h" #include "storm/exceptions/WrongFormatException.h" @@ -65,13 +66,6 @@ std::unordered_map parseCapacitiesList(std::string const& } -void handleJani(storm::gspn::GSPN const& gspn) { - std::shared_ptr exprManager(new storm::expressions::ExpressionManager()); - storm::builder::JaniGSPNBuilder builder(gspn, exprManager); - storm::jani::Model* model = builder.build(); - storm::jani::JsonExporter::toFile(*model, {}, storm::settings::getModule().getJaniFilename()); - delete model; -} int main(const int argc, const char **argv) { try { @@ -109,7 +103,9 @@ int main(const int argc, const char **argv) { } if(storm::settings::getModule().isJaniFileSet()) { - handleJani(*gspn); + storm::jani::Model* model = storm::buildJani(*gspn); + storm::exportJaniModel(*model, {}, storm::settings::getModule().getJaniFilename()); + delete model; } diff --git a/src/storm-gspn/builder/JaniGSPNBuilder.h b/src/storm-gspn/builder/JaniGSPNBuilder.h index 4fcb19f16..196d29562 100644 --- a/src/storm-gspn/builder/JaniGSPNBuilder.h +++ b/src/storm-gspn/builder/JaniGSPNBuilder.h @@ -9,17 +9,11 @@ namespace storm { class JaniGSPNBuilder { public: JaniGSPNBuilder(storm::gspn::GSPN const& gspn, std::shared_ptr const& expManager) : gspn(gspn), expressionManager(expManager) { - gspn.writeDotToStream(std::cout); + } virtual ~JaniGSPNBuilder() { - for (auto const& varEntry : vars) { - delete varEntry.second; - } - } - - void setIgnoreWeights(bool ignore = true) { - ignoreWeights = ignore; + } @@ -34,6 +28,10 @@ namespace storm { return model; } + storm::jani::Variable const& getPlaceVariable(uint64_t placeId) { + return *vars.at(placeId); + } + void addVariables(storm::jani::Model* model) { for (auto const& place : gspn.getPlaces()) { storm::jani::Variable* janiVar = nullptr; @@ -46,8 +44,8 @@ namespace storm { } assert(janiVar != nullptr); assert(vars.count(place.getID()) == 0); - vars[place.getID()] = janiVar; - model->addVariable(*janiVar); + vars[place.getID()] = &model->addVariable(*janiVar); + delete janiVar; } } @@ -59,66 +57,66 @@ namespace storm { void addEdges(storm::jani::Automaton& automaton, uint64_t locId) { - storm::expressions::Expression guard = expressionManager->boolean(true); - for (auto const& trans : gspn.getImmediateTransitions()) { - if (ignoreWeights || trans.noWeightAttached()) { - std::vector assignments; - for (auto const& inPlaceEntry : trans.getInputPlaces()) { - guard = guard && (vars[inPlaceEntry.first]->getExpressionVariable() > inPlaceEntry.second); - assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first])->getExpressionVariable() - inPlaceEntry.second); - } - for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) { - guard = guard && (vars[inhibPlaceEntry.first]->getExpressionVariable() > inhibPlaceEntry.second); - } - for (auto const& outputPlaceEntry : trans.getOutputPlaces()) { - assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second ); - } - storm::jani::OrderedAssignments oa(assignments); - storm::jani::EdgeDestination dest(locId, expressionManager->integer(1), oa); - storm::jani::Edge e(locId, storm::jani::Model::SILENT_ACTION_INDEX, boost::none, guard, {dest}); - automaton.addEdge(e); - } - - } - if(!ignoreWeights) { + uint64_t lastPriority = -1; + storm::expressions::Expression lastPriorityGuard = expressionManager->boolean(false); + storm::expressions::Expression priorityGuard = expressionManager->boolean(true); + // TODO here there is something to fix if we add transition partitions. - // TODO here there is something to fix if we add transition partitions. + for (auto const& partition : gspn.getPartitions()) { storm::expressions::Expression guard = expressionManager->boolean(false); std::vector weightedDestinations; + assert(lastPriority >= partition.priority); + if (lastPriority > partition.priority) { + priorityGuard = priorityGuard && !lastPriorityGuard; + lastPriority = partition.priority; + } else { + assert(lastPriority == partition.priority); + } + // Compute enabled weight expression. storm::expressions::Expression totalWeight = expressionManager->rational(0.0); - for (auto const& trans : gspn.getImmediateTransitions()) { + for (auto const& transId : partition.transitions) { + auto const& trans = gspn.getImmediateTransitions()[transId]; if (trans.noWeightAttached()) { continue; } storm::expressions::Expression destguard = expressionManager->boolean(true); for (auto const& inPlaceEntry : trans.getInputPlaces()) { - destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() > inPlaceEntry.second); + destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second); } for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) { - destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() > inhibPlaceEntry.second); + destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second); } totalWeight = totalWeight + storm::expressions::ite(destguard, expressionManager->rational(trans.getWeight()), expressionManager->rational(0.0)); } totalWeight = totalWeight.simplify(); - for (auto const& trans : gspn.getImmediateTransitions()) { + + for (auto const& transId : partition.transitions) { + auto const& trans = gspn.getImmediateTransitions()[transId]; if (trans.noWeightAttached()) { + std::cout << "ERROR -- no weights attached at transition" << std::endl; continue; } storm::expressions::Expression destguard = expressionManager->boolean(true); std::vector assignments; for (auto const& inPlaceEntry : trans.getInputPlaces()) { - destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() > inPlaceEntry.second); - assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first]->getExpressionVariable() - inPlaceEntry.second) ); + destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second); + if (trans.getOutputPlaces().count(inPlaceEntry.first) == 0) { + assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first])->getExpressionVariable() - inPlaceEntry.second); + } } for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) { - destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() > inhibPlaceEntry.second); + destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second); } for (auto const& outputPlaceEntry : trans.getOutputPlaces()) { - assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first]->getExpressionVariable() + outputPlaceEntry.second) ); + if (trans.getInputPlaces().count(outputPlaceEntry.first) == 0) { + assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second ); + } else { + assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second - trans.getInputPlaces().at(outputPlaceEntry.first)); + } } destguard = destguard.simplify(); guard = guard || destguard; @@ -126,35 +124,43 @@ namespace storm { storm::jani::EdgeDestination dest(locId, storm::expressions::ite(destguard, (expressionManager->rational(trans.getWeight()) / totalWeight), expressionManager->rational(0.0)), oa); weightedDestinations.push_back(dest); } - storm::jani::Edge e(locId, storm::jani::Model::SILENT_ACTION_INDEX, boost::none, guard.simplify(), weightedDestinations); + storm::jani::Edge e(locId, storm::jani::Model::SILENT_ACTION_INDEX, boost::none, (priorityGuard && guard).simplify(), weightedDestinations); automaton.addEdge(e); + lastPriorityGuard = lastPriorityGuard || guard; + } for (auto const& trans : gspn.getTimedTransitions()) { storm::expressions::Expression guard = expressionManager->boolean(true); std::vector assignments; for (auto const& inPlaceEntry : trans.getInputPlaces()) { - guard = guard && (vars[inPlaceEntry.first]->getExpressionVariable() > inPlaceEntry.second); - assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first]->getExpressionVariable() - inPlaceEntry.second) ); + guard = guard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second); + if (trans.getOutputPlaces().count(inPlaceEntry.first) == 0) { + assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first])->getExpressionVariable() - inPlaceEntry.second); + } } for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) { - guard = guard && (vars[inhibPlaceEntry.first]->getExpressionVariable() > inhibPlaceEntry.second); + guard = guard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second); } for (auto const& outputPlaceEntry : trans.getOutputPlaces()) { - assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first]->getExpressionVariable() + outputPlaceEntry.second) ); + if (trans.getInputPlaces().count(outputPlaceEntry.first) == 0) { + assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second ); + } else { + assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second - trans.getInputPlaces().at(outputPlaceEntry.first)); + } } storm::jani::OrderedAssignments oa(assignments); storm::jani::EdgeDestination dest(locId, expressionManager->integer(1), oa); storm::jani::Edge e(locId, storm::jani::Model::SILENT_ACTION_INDEX, expressionManager->rational(trans.getRate()), guard, {dest}); automaton.addEdge(e); + } } private: - bool ignoreWeights; const uint64_t janiVersion = 1; storm::gspn::GSPN const& gspn; - std::map vars; + std::map vars; std::shared_ptr expressionManager; }; diff --git a/src/storm-gspn/storage/gspn/GSPN.cpp b/src/storm-gspn/storage/gspn/GSPN.cpp index 8377f2f8e..ce0d47d44 100644 --- a/src/storm-gspn/storage/gspn/GSPN.cpp +++ b/src/storm-gspn/storage/gspn/GSPN.cpp @@ -27,8 +27,8 @@ namespace storm { return tId; } - GSPN::GSPN(std::string const& name, std::vector const& places, std::vector> const& itransitions, std::vector> const& ttransitions) - : name(name), places(places), immediateTransitions(itransitions), timedTransitions(ttransitions) + GSPN::GSPN(std::string const& name, std::vector const& places, std::vector> const& itransitions, std::vector> const& ttransitions, std::vector const& partitions) + : name(name), places(places), immediateTransitions(itransitions), timedTransitions(ttransitions), partitions(partitions) { } @@ -36,6 +36,14 @@ namespace storm { uint64_t GSPN::getNumberOfPlaces() const { return places.size(); } + + uint64_t GSPN::getNumberOfImmediateTransitions() const { + return immediateTransitions.size(); + } + + uint64_t GSPN::getNumberOfTimedTransitions() const { + return timedTransitions.size(); + } std::vector> const& GSPN::getTimedTransitions() const { return this->timedTransitions; @@ -57,6 +65,10 @@ namespace storm { return m; } + std::vector const& GSPN::getPartitions() const { + return partitions; + } + storm::gspn::Place const* GSPN::getPlace(uint64_t id) const { if(id < places.size()) { @@ -364,6 +376,20 @@ namespace storm { return result; } + + void GSPN::setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layout) const { + placeLayout[placeId] = layout; + } + void GSPN::setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layout) const { + transitionLayout[transitionId] = layout; + } + + void GSPN::setPlaceLayoutInfo(std::map const& placeLayout) const { + this->placeLayout = placeLayout; + } + void GSPN::setTransitionLayoutInfo(std::map const& transitionLayout) const { + this->transitionLayout = transitionLayout; + } void GSPN::toPnpro(std::ostream &stream) const { auto space = " "; @@ -378,8 +404,14 @@ namespace storm { for (auto& place : places) { stream << space3 << " 0) { + stream << "x=\"" << placeLayout.at(place.getID()).x << "\" "; + stream << "y=\"" << placeLayout.at(place.getID()).y << "\" "; + } else { + stream << "x=\"" << x << "\" "; + stream << "y=\"1\" "; + + } stream << "/>" << std::endl; x = x + 3; } @@ -388,16 +420,28 @@ namespace storm { stream << space3 << " 0) { + stream << "x=\"" << transitionLayout.at(trans.getID()).x << "\" "; + stream << "y=\"" << transitionLayout.at(trans.getID()).y << "\" "; + } else { + stream << "x=\"" << x << "\" "; + stream << "y=\"4\" "; + + } stream << "/>" << std::endl; x = x + 3; } for (auto& trans : immediateTransitions) { stream << space3 << " 0) { + stream << "x=\"" << transitionLayout.at(trans.getID()).x << "\" "; + stream << "y=\"" << transitionLayout.at(trans.getID()).y << "\" "; + } else { + stream << "x=\"" << x << "\" "; + stream << "y=\"4\" "; + } stream << "/>" << std::endl; x = x + 3; } @@ -561,6 +605,12 @@ namespace storm { stream << space << "" << std::endl; stream << "" << std::endl; } + + void GSPN::writeStatsToStream(std::ostream& stream) const { + stream << "Number of places: " << getNumberOfPlaces() << std::endl; + stream << "Number of timed transitions: " << getNumberOfTimedTransitions() << std::endl; + stream << "Number of immediate transitions: " << getNumberOfImmediateTransitions() << std::endl; + } } } diff --git a/src/storm-gspn/storage/gspn/GSPN.h b/src/storm-gspn/storage/gspn/GSPN.h index 17448bc8b..947769af3 100644 --- a/src/storm-gspn/storage/gspn/GSPN.h +++ b/src/storm-gspn/storage/gspn/GSPN.h @@ -10,6 +10,8 @@ #include "storm-gspn/storage/gspn/Marking.h" #include "storm-gspn/storage/gspn/Place.h" #include "storm-gspn/storage/gspn/TimedTransition.h" +#include "storm-gspn/storage/gspn/TransitionPartition.h" +#include "storm-gspn/storage/gspn/PlacementInfo.h" namespace storm { namespace gspn { @@ -27,7 +29,8 @@ namespace storm { typedef double WeightType; - GSPN(std::string const& name, std::vector const& places, std::vector> const& itransitions, std::vector> const& ttransitions); + GSPN(std::string const& name, std::vector const& places, std::vector> const& itransitions, + std::vector> const& ttransitions, std::vector const& partitions); /*! * Returns the number of places in this gspn. @@ -35,7 +38,16 @@ namespace storm { * @return The number of places. */ uint64_t getNumberOfPlaces() const; + + uint64_t getNumberOfImmediateTransitions() const; + + uint64_t getNumberOfTimedTransitions() const; + /*! + * + */ + std::vector const& getPartitions() const; + /*! * Returns the vector of timed transitions in this gspn. * @@ -63,7 +75,6 @@ namespace storm { */ std::shared_ptr getInitialMarking(std::map& numberOfBits, uint64_t const& numberOfTotalBits) const; - /*! * Returns the place with the corresponding id. * @@ -84,6 +95,7 @@ namespace storm { * Returns the timed transition with the corresponding name. * * @param name The ID of the timed transition. + * @return A pointer to the transition, and nullptr otherwise */ storm::gspn::TimedTransition const* getTimedTransition(std::string const& name) const; @@ -129,7 +141,13 @@ namespace storm { * Set Capacities according to name->capacity map. */ void setCapacities(std::unordered_map const& mapping); - + + void setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layout) const; + void setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layout) const; + void setPlaceLayoutInfo(std::map const& placeLayout) const; + void setTransitionLayoutInfo(std::map const& transitionLayout) const; + + /*! * Performe some checks * - testPlaces() @@ -139,9 +157,11 @@ namespace storm { */ bool isValid() const; // TODO doc - void toPnpro(std::ostream &stream) const; + void toPnpro(std::ostream& stream) const; // TODO doc - void toPnml(std::ostream &stream) const; + void toPnml(std::ostream& stream) const; + + void writeStatsToStream(std::ostream& stream) const; private: storm::gspn::Place* getPlace(uint64_t id); storm::gspn::Place* getPlace(std::string const& name); @@ -176,7 +196,12 @@ namespace storm { // set containing all timed transitions std::vector> timedTransitions; - + std::vector partitions; + + mutable std::map placeLayout; + mutable std::map transitionLayout; + + }; } } diff --git a/src/storm-gspn/storage/gspn/GspnBuilder.cpp b/src/storm-gspn/storage/gspn/GspnBuilder.cpp index cbea96b6a..e0bbd76fd 100644 --- a/src/storm-gspn/storage/gspn/GspnBuilder.cpp +++ b/src/storm-gspn/storage/gspn/GspnBuilder.cpp @@ -23,14 +23,42 @@ namespace storm { places.push_back(place); return newId; } + + + void GspnBuilder::setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layoutInfo) { + placeLayout[placeId] = layoutInfo; + } + + void GspnBuilder::setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layoutInfo) { + transitionLayout[transitionId] = layoutInfo; + } uint_fast64_t GspnBuilder::addImmediateTransition(uint_fast64_t const& priority, double const& weight, std::string const& name) { auto trans = storm::gspn::ImmediateTransition(); auto newId = GSPN::immediateTransitionIdToTransitionId(immediateTransitions.size()); trans.setName(name); trans.setPriority(priority); - trans.setWeight(weight); trans.setID(newId); + + // ensure that the first partition is for the 'general/weighted' transitions + if(partitions.count(priority) == 0) { + TransitionPartition newPart; + newPart.priority = priority; + partitions[priority].push_back(newPart); + } + + if(storm::utility::isZero(weight)) { + trans.setWeight(storm::utility::one()); + TransitionPartition newPart; + newPart.priority = priority; + newPart.transitions = {newId}; + partitions.at(priority).push_back(newPart); + } else { + trans.setWeight(weight); + partitions.at(priority).front().transitions.push_back(newId); + + + } immediateTransitions.push_back(trans); return newId; @@ -131,7 +159,24 @@ namespace storm { storm::gspn::GSPN* GspnBuilder::buildGspn() const { - return new GSPN(gspnName, places, immediateTransitions, timedTransitions); + std::vector orderedPartitions; + for(auto const& priorityPartitions : partitions) { + for (auto const& partition : priorityPartitions.second) { + // sanity check + assert(partition.priority == priorityPartitions.first); + + if(partition.nrTransitions() > 0) { + orderedPartitions.push_back(partition); + } + } + + } + std::reverse(orderedPartitions.begin(), orderedPartitions.end()); + + GSPN* result = new GSPN(gspnName, places, immediateTransitions, timedTransitions, orderedPartitions); + result->setTransitionLayoutInfo(transitionLayout); + result->setPlaceLayoutInfo(placeLayout); + return result; } } } diff --git a/src/storm-gspn/storage/gspn/GspnBuilder.h b/src/storm-gspn/storage/gspn/GspnBuilder.h index 59f098a82..79fb2e712 100644 --- a/src/storm-gspn/storage/gspn/GspnBuilder.h +++ b/src/storm-gspn/storage/gspn/GspnBuilder.h @@ -20,29 +20,32 @@ namespace storm { /** * Add a place to the gspn. - * @param id The id must be unique for the gspn. * @param name The name must be unique for the gspn. * @param capacity The capacity is the limit of tokens in the place. * A capacity of -1 indicates an unbounded place. * @param initialTokens The number of inital tokens in the place. */ uint_fast64_t addPlace(int_fast64_t const& capacity = 1, uint_fast64_t const& initialTokens = 0, std::string const& name = ""); + + void setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layoutInfo); /** * Adds an immediate transition to the gspn. - * @param id The id must be unique for the gspn. * @param priority The priority for the transtion. * @param weight The weight for the transition. */ uint_fast64_t addImmediateTransition(uint_fast64_t const& priority = 0, WeightType const& weight = 0, std::string const& name = ""); - + + /** * Adds an timed transition to the gspn. - * @param id The name id be unique for the gspn. * @param priority The priority for the transtion. * @param weight The weight for the transition. */ uint_fast64_t addTimedTransition(uint_fast64_t const &priority, RateType const& rate, std::string const& name = ""); + + void setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layoutInfo); + /** * Adds an new input arc from a place to an transition. @@ -102,6 +105,8 @@ namespace storm { std::string gspnName = "_gspn_"; + std::map> partitions; + // set containing all immediate transitions std::vector> immediateTransitions; @@ -110,6 +115,9 @@ namespace storm { // set containing all places std::vector places; + + std::map placeLayout; + std::map transitionLayout; }; } } diff --git a/src/storm-gspn/storage/gspn/PlacementInfo.h b/src/storm-gspn/storage/gspn/PlacementInfo.h new file mode 100644 index 000000000..e59218686 --- /dev/null +++ b/src/storm-gspn/storage/gspn/PlacementInfo.h @@ -0,0 +1,17 @@ +#pragma once + +namespace storm { + namespace gspn { + struct LayoutInfo { + LayoutInfo() {}; + LayoutInfo(double x, double y, double rotation = 0.0) : x(x), y(y), rotation(rotation) {}; + + // x location + double x = 0.0; + // y location + double y = 0.0; + // degrees + double rotation = 0.0; + }; + } +} \ No newline at end of file diff --git a/src/storm-gspn/storage/gspn/Transition.h b/src/storm-gspn/storage/gspn/Transition.h index d61affaea..9deab2fb0 100644 --- a/src/storm-gspn/storage/gspn/Transition.h +++ b/src/storm-gspn/storage/gspn/Transition.h @@ -168,6 +168,9 @@ namespace storm { void setID(uint64_t const& id) { this->id = id; } + + + uint64_t getID() const { return id; } private: // maps place ids connected to this transition with an input arc to the corresponding multiplicity diff --git a/src/storm-gspn/storage/gspn/TransitionPartition.h b/src/storm-gspn/storage/gspn/TransitionPartition.h new file mode 100644 index 000000000..128a87641 --- /dev/null +++ b/src/storm-gspn/storage/gspn/TransitionPartition.h @@ -0,0 +1,18 @@ +#pragma once +#include + +namespace storm { + namespace gspn { + + struct TransitionPartition { + std::vector transitions; + uint64_t priority; + + + uint64_t nrTransitions() const { + return transitions.size(); + } + }; + + } +} \ No newline at end of file diff --git a/src/storm-gspn/storm-gspn.h b/src/storm-gspn/storm-gspn.h new file mode 100644 index 000000000..095b82aca --- /dev/null +++ b/src/storm-gspn/storm-gspn.h @@ -0,0 +1,61 @@ +#pragma once + +#include "storm/storage/jani/Model.h" + +#include "storm-gspn/builder/JaniGSPNBuilder.h" +#include "storm-gspn/storage/gspn/GSPN.h" + +#include "storm/settings/SettingsManager.h" +#include "storm/settings/modules/GSPNExportSettings.h" + +namespace storm { + /** + * Builds JANI model from GSPN. + */ + storm::jani::Model* buildJani(storm::gspn::GSPN const& gspn) { + std::shared_ptr exprManager(new storm::expressions::ExpressionManager()); + storm::builder::JaniGSPNBuilder builder(gspn, exprManager); + return builder.build(); + } + + void handleGSPNExportSettings(storm::gspn::GSPN const& gspn) { + storm::settings::modules::GSPNExportSettings const& exportSettings = storm::settings::getModule(); + if (exportSettings.isWriteToDotSet()) { + std::ofstream fs; + fs.open(exportSettings.getWriteToDotFilename()); + gspn.writeDotToStream(fs); + fs.close(); + } + + if (exportSettings.isWriteToPnproSet()) { + std::ofstream fs; + fs.open(exportSettings.getWriteToPnproFilename()); + gspn.toPnpro(fs); + fs.close(); + } + + if (exportSettings.isWriteToPnmlSet()) { + std::ofstream fs; + fs.open(exportSettings.getWriteToPnmlFilename()); + gspn.toPnml(fs); + fs.close(); + } + + if (exportSettings.isDisplayStatsSet()) { + std::cout << "============GSPN Statistics==============" << std::endl; + gspn.writeStatsToStream(std::cout); + std::cout << "=========================================" << std::endl; + } + + if (exportSettings.isWriteStatsToFileSet()) { + std::ofstream fs; + fs.open(exportSettings.getWriteStatsFilename()); + gspn.writeStatsToStream(fs); + fs.close(); + } + + + + } + +} \ No newline at end of file diff --git a/src/storm-pgcl-cli/storm-pgcl.cpp b/src/storm-pgcl-cli/storm-pgcl.cpp index bf5dc1c1e..b849cb264 100644 --- a/src/storm-pgcl-cli/storm-pgcl.cpp +++ b/src/storm-pgcl-cli/storm-pgcl.cpp @@ -76,13 +76,16 @@ int main(const int argc, const char** argv) { programGraphToDotFile(*progGraph); } if (storm::settings::getModule().isToJaniSet()) { + storm::builder::JaniProgramGraphBuilderSetting settings; + // To disable reward detection, uncomment the following line + // TODO add a setting for this. + // settings.filterRewardVariables = false; storm::builder::JaniProgramGraphBuilder builder(*progGraph); if (storm::settings::getModule().isProgramVariableRestrictionSet()) { // TODO More fine grained control storm::storage::IntegerInterval restr = storm::storage::parseIntegerInterval(storm::settings::getModule().getProgramVariableRestrictions()); builder.restrictAllVariables(restr); } - builder.restrictAllVariables(0, 120); storm::jani::Model* model = builder.build(); delete progGraph; handleJani(*model); diff --git a/src/storm-pgcl/builder/JaniProgramGraphBuilder.h b/src/storm-pgcl/builder/JaniProgramGraphBuilder.h index 34b5dd5d7..beb6c1aed 100644 --- a/src/storm-pgcl/builder/JaniProgramGraphBuilder.h +++ b/src/storm-pgcl/builder/JaniProgramGraphBuilder.h @@ -19,15 +19,21 @@ namespace storm { }; struct JaniProgramGraphBuilderSetting { + /// Method how to obtain domain for the variables; currently only unrestricted is supported JaniProgramGraphVariableDomainMethod variableDomainMethod = JaniProgramGraphVariableDomainMethod::Unrestricted; + /// If this is true, reward variables will be given special treatment, effectively removing them from the state space. + /// Disable in order to obtain full state space. + bool filterRewardVariables = true; }; class JaniProgramGraphBuilder { public: static unsigned janiVersion; - JaniProgramGraphBuilder(storm::ppg::ProgramGraph const& pg) : programGraph(pg) { - rewards = programGraph.rewardVariables(); + JaniProgramGraphBuilder(storm::ppg::ProgramGraph const& pg, JaniProgramGraphBuilderSetting const& pgbs = JaniProgramGraphBuilderSetting()) : programGraph(pg), pgbs(pgbs) { + if (pgbs.filterRewardVariables) { + rewards = programGraph.rewardVariables(); + } constants = programGraph.constants(); auto boundedVars = programGraph.constantAssigned(); for(auto const& v : boundedVars) { @@ -41,10 +47,6 @@ namespace storm { } } - //void addVariableRestriction(storm::expressions::Variable const& var, storm::IntegerInterval const& interval ) { - - //} - void restrictAllVariables(int64_t from, int64_t to) { restrictAllVariables(storm::storage::IntegerInterval(from, to)); @@ -167,7 +169,7 @@ namespace storm { /// Restrictions on variables (provided by users) std::map userVariableRestrictions; - /// Locations for variables that would have gone ot o + /// Locations for variables that would have gone out of bounds std::map varOutOfBoundsLocations; std::map janiLocId; std::map variables; @@ -176,6 +178,8 @@ namespace storm { std::shared_ptr expManager; /// The program graph to be translated storm::ppg::ProgramGraph const& programGraph; + /// Settings + JaniProgramGraphBuilderSetting pgbs; }; diff --git a/src/storm/CMakeLists.txt b/src/storm/CMakeLists.txt index f0d64ab0c..363fbc0ab 100644 --- a/src/storm/CMakeLists.txt +++ b/src/storm/CMakeLists.txt @@ -28,6 +28,9 @@ if (ADDITIONAL_LINK_DIRS) link_directories(${ADDITIONAL_LINK_DIRS}) endif(ADDITIONAL_LINK_DIRS) +# Disable Debug compiler flags for PrismParser to lessen memory consumption during compilation +SET_SOURCE_FILES_PROPERTIES(${PROJECT_SOURCE_DIR}/src/storm/parser/PrismParser.cpp PROPERTIES COMPILE_FLAGS -g0) + ############################################################################### ## ## Binary creation (All link_directories() calls must be made before this point.) @@ -39,7 +42,9 @@ add_library(storm SHARED ${STORM_LIB_SOURCES} ${STORM_LIB_HEADERS}) # Remove define symbol for shared libstorm. set_target_properties(storm PROPERTIES DEFINE_SYMBOL "") add_dependencies(storm resources) -target_link_libraries(storm ${STORM_LINK_LIBRARIES}) +target_link_libraries(storm PUBLIC ${STORM_DEP_TARGETS} ${STORM_DEP_IMP_TARGETS} ${STORM_LINK_LIBRARIES}) +list(APPEND STORM_TARGETS storm) +set(STORM_TARGETS ${STORM_TARGETS} PARENT_SCOPE) # Create storm. add_executable(storm-main ${STORM_MAIN_SOURCES} ${STORM_MAIN_HEADERS}) diff --git a/src/storm/cli/cli.cpp b/src/storm/cli/cli.cpp index 7d43e0d8b..aaa601d15 100644 --- a/src/storm/cli/cli.cpp +++ b/src/storm/cli/cli.cpp @@ -14,7 +14,7 @@ #include "storm/utility/resources.h" #include "storm/utility/storm-version.h" -#include "storm/storage/jani/JSONExporter.h" + // Includes for the linked libraries and versions header. #ifdef STORM_HAVE_INTELTBB @@ -262,14 +262,7 @@ namespace storm { } if (model.isJaniModel() && storm::settings::getModule().isJaniFileSet()) { - STORM_LOG_TRACE("Exporting JANI model."); - if (storm::settings::getModule().isExportAsStandardJaniSet()) { - storm::jani::Model normalisedModel = storm::jani::Model(model.asJaniModel()); - normalisedModel.makeStandardJaniCompliant(); - storm::jani::JsonExporter::toFile(normalisedModel, formulasInProperties(properties), storm::settings::getModule().getJaniFilename()); - } else { - storm::jani::JsonExporter::toFile(model.asJaniModel(), formulasInProperties(properties), storm::settings::getModule().getJaniFilename()); - } + exportJaniModel(model.asJaniModel(), properties, storm::settings::getModule().getJaniFilename()); } if (ioSettings.isNoBuildModelSet()) { diff --git a/src/storm/generator/NextStateGenerator.cpp b/src/storm/generator/NextStateGenerator.cpp index 588edb70a..7f931051f 100644 --- a/src/storm/generator/NextStateGenerator.cpp +++ b/src/storm/generator/NextStateGenerator.cpp @@ -119,7 +119,7 @@ namespace storm { result.getChoices().front().add(choice); // Swap the choice to the end to indicate it can be removed (if it's not already there). - if (index != result.getNumberOfChoices() - 1) { + if (index != result.getNumberOfChoices() - 1 - numberOfChoicesToDelete) { choice = std::move(result.getChoices()[result.getNumberOfChoices() - 1 - numberOfChoicesToDelete]); } ++numberOfChoicesToDelete; diff --git a/src/storm/logic/Formula.h b/src/storm/logic/Formula.h index e381e9d1b..80f31203f 100644 --- a/src/storm/logic/Formula.h +++ b/src/storm/logic/Formula.h @@ -25,7 +25,7 @@ namespace storm { // Forward-declare formula information class for info() method. class FormulaInformation; - class Formula : public std::enable_shared_from_this { + class Formula : public std::enable_shared_from_this { public: // Make the destructor virtual to allow deletion of objects of subclasses via a pointer to this class. virtual ~Formula() { diff --git a/src/storm/settings/modules/GSPNExportSettings.cpp b/src/storm/settings/modules/GSPNExportSettings.cpp index 9be15c75e..8a5c315dc 100644 --- a/src/storm/settings/modules/GSPNExportSettings.cpp +++ b/src/storm/settings/modules/GSPNExportSettings.cpp @@ -19,6 +19,8 @@ namespace storm { const std::string GSPNExportSettings::writeToPnmlOptionName = "to-pnml"; const std::string GSPNExportSettings::writeToPnproOptionName = "to-pnpro"; + const std::string GSPNExportSettings::writeStatsOptionName = "to-stats"; + const std::string GSPNExportSettings::displayStatsOptionName = "show-stats"; //const std::string GSPNExportSettings::janiFileOptionShortName = "dotoutput"; @@ -27,6 +29,8 @@ namespace storm { this->addOption(storm::settings::OptionBuilder(moduleName, writeToDotOptionName, false, "Destination for the dot output.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "path to file").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, writeToPnmlOptionName, false, "Destination for the pnml output").addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "path to file").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, writeToPnproOptionName, false, "Destination for the pnpro output").addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "path to file").build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, writeStatsOptionName, false, "Destination for the stats file").addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "path to file").build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, displayStatsOptionName, false, "Print stats to stdout").build()); } bool GSPNExportSettings::isWriteToDotSet() const { @@ -54,6 +58,18 @@ namespace storm { } + bool GSPNExportSettings::isDisplayStatsSet() const { + return this->getOption(displayStatsOptionName).getHasOptionBeenSet(); + } + + bool GSPNExportSettings::isWriteStatsToFileSet() const { + return this->getOption(writeStatsOptionName).getHasOptionBeenSet(); + } + + std::string GSPNExportSettings::getWriteStatsFilename() const { + return this->getOption(writeStatsOptionName).getArgumentByName("filename").getValueAsString(); + } + void GSPNExportSettings::finalize() { } diff --git a/src/storm/settings/modules/GSPNExportSettings.h b/src/storm/settings/modules/GSPNExportSettings.h index 3db836cf7..554cce223 100644 --- a/src/storm/settings/modules/GSPNExportSettings.h +++ b/src/storm/settings/modules/GSPNExportSettings.h @@ -15,7 +15,7 @@ namespace storm { GSPNExportSettings(); /** - * Retrievew whether the pgcl file option was set + * Retrieve whether the pgcl file option was set */ bool isWriteToDotSet() const; @@ -38,6 +38,12 @@ namespace storm { */ std::string getWriteToPnproFilename() const; + bool isDisplayStatsSet() const; + + bool isWriteStatsToFileSet() const; + + std::string getWriteStatsFilename() const; + bool check() const override; void finalize() override; @@ -48,6 +54,9 @@ namespace storm { static const std::string writeToDotOptionName; static const std::string writeToPnmlOptionName; static const std::string writeToPnproOptionName; + static const std::string displayStatsOptionName; + static const std::string writeStatsOptionName; + //static const std::string writeToDotOptionShortName; }; diff --git a/src/storm/storage/BitVector.cpp b/src/storm/storage/BitVector.cpp index 89113d718..a0004263a 100644 --- a/src/storm/storage/BitVector.cpp +++ b/src/storm/storage/BitVector.cpp @@ -486,7 +486,7 @@ namespace storm { void BitVector::setFromInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits, uint64_t value) { STORM_LOG_ASSERT(numberOfBits <= 64, "Number of bits must be <= 64."); - STORM_LOG_ASSERT(numberOfBits == 64 || (value >> numberOfBits) == 0, "Integer value too large to fit in the given number of bits."); + STORM_LOG_ASSERT(numberOfBits == 64 || (value >> numberOfBits) == 0, "Integer value ("<< value << ") too large to fit in the given number of bits (" << numberOfBits << ")."); uint64_t bucket = bitIndex >> 6; uint64_t bitIndexInBucket = bitIndex & mod64mask; diff --git a/src/storm/storage/expressions/Expression.cpp b/src/storm/storage/expressions/Expression.cpp index 0a2f200e3..b980cab0a 100644 --- a/src/storm/storage/expressions/Expression.cpp +++ b/src/storm/storage/expressions/Expression.cpp @@ -245,6 +245,12 @@ namespace storm { Expression operator&&(Expression const& first, Expression const& second) { assertSameManager(first.getBaseExpression(), second.getBaseExpression()); + if (first.isTrue()) { + return second; + } + if (second.isTrue()) { + return first; + } return Expression(std::shared_ptr(new BinaryBooleanFunctionExpression(first.getBaseExpression().getManager(), first.getType().logicalConnective(second.getType()), first.getBaseExpressionPointer(), second.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::And))); } diff --git a/src/storm/storage/jani/JSONExporter.cpp b/src/storm/storage/jani/JSONExporter.cpp index 037222fe5..889496265 100644 --- a/src/storm/storage/jani/JSONExporter.cpp +++ b/src/storm/storage/jani/JSONExporter.cpp @@ -516,7 +516,7 @@ namespace storm { - void JsonExporter::toFile(storm::jani::Model const& janiModel, std::vector> const& formulas, std::string const& filepath, bool checkValid) { + void JsonExporter::toFile(storm::jani::Model const& janiModel, std::vector const& formulas, std::string const& filepath, bool checkValid) { std::ofstream ofs; ofs.open (filepath, std::ofstream::out ); if(ofs.is_open()) { @@ -526,7 +526,7 @@ namespace storm { } } - void JsonExporter::toStream(storm::jani::Model const& janiModel, std::vector> const& formulas, std::ostream& os, bool checkValid) { + void JsonExporter::toStream(storm::jani::Model const& janiModel, std::vector const& formulas, std::ostream& os, bool checkValid) { if(checkValid) { janiModel.checkValid(); } @@ -650,6 +650,7 @@ namespace storm { } modernjson::json buildDestinations(std::vector const& destinations, std::map const& locationNames) { + assert(destinations.size() > 0); std::vector destDeclarations; for(auto const& destination : destinations) { modernjson::json destEntry; @@ -664,6 +665,10 @@ namespace storm { modernjson::json buildEdges(std::vector const& edges , std::map const& actionNames, std::map const& locationNames) { std::vector edgeDeclarations; for(auto const& edge : edges) { + if (edge.getGuard().isFalse()) { + continue; + } + STORM_LOG_THROW(edge.getDestinations().size() > 0, storm::exceptions::InvalidJaniException, "An edge without destinations is not allowed."); modernjson::json edgeEntry; edgeEntry["location"] = locationNames.at(edge.getSourceLocationIndex()); if(!edge.hasSilentAction()) { @@ -754,13 +759,13 @@ namespace storm { } - void JsonExporter::convertProperties( std::vector> const& formulas, storm::jani::Model const& model) { + void JsonExporter::convertProperties( std::vector const& formulas, storm::jani::Model const& model) { std::vector properties; uint64_t index = 0; for(auto const& f : formulas) { modernjson::json propDecl; - propDecl["name"] = "prop" + std::to_string(index); - propDecl["expression"] = convertFilterExpression(storm::jani::FilterExpression(f), model); + propDecl["name"] = f.getName(); + propDecl["expression"] = convertFilterExpression(f.getFilter(), model); ++index; properties.push_back(propDecl); } diff --git a/src/storm/storage/jani/JSONExporter.h b/src/storm/storage/jani/JSONExporter.h index 1008ec097..1eceb5d2e 100644 --- a/src/storm/storage/jani/JSONExporter.h +++ b/src/storm/storage/jani/JSONExporter.h @@ -4,6 +4,7 @@ #include "storm/storage/expressions/ExpressionVisitor.h" #include "storm/logic/FormulaVisitor.h" #include "Model.h" +#include "storm/storage/jani/Property.h" #include "storm/adapters/NumberAdapter.h" // JSON parser #include "json.hpp" @@ -66,12 +67,13 @@ namespace storm { JsonExporter() = default; public: - static void toFile(storm::jani::Model const& janiModel, std::vector> const& formulas, std::string const& filepath, bool checkValid = true); - static void toStream(storm::jani::Model const& janiModel, std::vector> const& formulas, std::ostream& ostream, bool checkValid = false); + static void toFile(storm::jani::Model const& janiModel, std::vector const& formulas, std::string const& filepath, bool checkValid = true); + static void toStream(storm::jani::Model const& janiModel, std::vector const& formulas, std::ostream& ostream, bool checkValid = false); + private: void convertModel(storm::jani::Model const& model); - void convertProperties(std::vector> const& formulas, storm::jani::Model const& model); + void convertProperties(std::vector const& formulas, storm::jani::Model const& model); void appendVariableDeclaration(storm::jani::Variable const& variable); modernjson::json finalize() { diff --git a/src/storm/storage/jani/OrderedAssignments.cpp b/src/storm/storage/jani/OrderedAssignments.cpp index 00358b417..24ebf4b03 100644 --- a/src/storm/storage/jani/OrderedAssignments.cpp +++ b/src/storm/storage/jani/OrderedAssignments.cpp @@ -153,5 +153,14 @@ namespace storm { return std::lower_bound(assignments.begin(), assignments.end(), assignment, storm::jani::AssignmentPartialOrderByLevelAndVariable()); } + std::ostream& operator<<(std::ostream& stream, OrderedAssignments const& assignments) { + stream << "["; + for(auto const& e : assignments.allAssignments) { + stream << *e << std::endl; + } + stream << "]"; + return stream; + } + } } diff --git a/src/storm/storage/jani/OrderedAssignments.h b/src/storm/storage/jani/OrderedAssignments.h index 5c2dd36f8..1cd9df215 100644 --- a/src/storm/storage/jani/OrderedAssignments.h +++ b/src/storm/storage/jani/OrderedAssignments.h @@ -119,6 +119,8 @@ namespace storm { */ void changeAssignmentVariables(std::map> const& remapping); + friend std::ostream& operator<<(std::ostream& stream, OrderedAssignments const& assignments); + private: static std::vector>::const_iterator lowerBound(Assignment const& assignment, std::vector> const& assignments); diff --git a/src/storm/utility/storm.cpp b/src/storm/utility/storm.cpp index 40ab41b91..9a0e6faba 100644 --- a/src/storm/utility/storm.cpp +++ b/src/storm/utility/storm.cpp @@ -30,6 +30,17 @@ namespace storm{ modelAndFormulae.first.checkValid(); return modelAndFormulae; } + + void exportJaniModel(storm::jani::Model const& model, std::vector const& properties, std::string const& filepath) { + STORM_LOG_TRACE("Exporting JANI model."); + if (storm::settings::getModule().isExportAsStandardJaniSet()) { + storm::jani::Model normalisedModel = model; + normalisedModel.makeStandardJaniCompliant(); + storm::jani::JsonExporter::toFile(normalisedModel, properties, filepath); + } else { + storm::jani::JsonExporter::toFile(model, properties, filepath); + } + } /** * Helper diff --git a/src/storm/utility/storm.h b/src/storm/utility/storm.h index d5be5ed9c..1784e44c7 100644 --- a/src/storm/utility/storm.h +++ b/src/storm/utility/storm.h @@ -23,6 +23,7 @@ #include "storm/settings/modules/RegionSettings.h" #include "storm/settings/modules/EliminationSettings.h" #include "storm/settings/modules/JitBuilderSettings.h" +#include "storm/settings/modules/JaniExportSettings.h" // Formula headers. #include "storm/logic/Formulas.h" @@ -55,6 +56,7 @@ #include "storm/storage/bisimulation/NondeterministicModelBisimulationDecomposition.h" #include "storm/storage/ModelFormulasPair.h" #include "storm/storage/SymbolicModelDescription.h" +#include "storm/storage/jani/JSONExporter.h" // Headers for model checking. #include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h" @@ -228,6 +230,7 @@ namespace storm { std::shared_ptr preprocessModel(std::shared_ptr model, std::vector> const& formulas) { if (model->getType() == storm::models::ModelType::MarkovAutomaton && model->isSparseModel()) { std::shared_ptr> ma = model->template as>(); + ma->close(); if (ma->hasOnlyTrivialNondeterminism()) { // Markov automaton can be converted into CTMC. model = ma->convertToCTMC(); @@ -593,7 +596,12 @@ namespace storm { return modelchecker.check(task); } } - + + /** + * + */ + void exportJaniModel(storm::jani::Model const& model, std::vector const& properties, std::string const& filepath); + template void exportMatrixToFile(std::shared_ptr> model, std::string const& filepath) { STORM_LOG_THROW(model->getType() != storm::models::ModelType::Ctmc, storm::exceptions::NotImplementedException, "This functionality is not yet implemented." ); diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index fde489754..4a389019a 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -18,5 +18,7 @@ foreach (testsuite abstraction adapter builder logic modelchecker parser permiss add_dependencies(test-${testsuite} test-resources) add_test(run-test-${testsuite} test-${testsuite}) + add_dependencies(check test-${testsuite}) + add_dependencies(check-verbose test-${testsuite}) endforeach () diff --git a/stormpy/CMakeLists.txt b/stormpy/CMakeLists.txt deleted file mode 100644 index afd91d57e..000000000 --- a/stormpy/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -set(STORMPY_OUTPUT_DIR "${PROJECT_BINARY_DIR}/stormpy") -set(STORMPY_SOURCE_DIR "${PROJECT_SOURCE_DIR}/stormpy") - -if(STORM_HAVE_CLN) - set(STORMPY_USE_CLN 1) -else() - set(STORMPY_USE_CLN 0) -endif() - -# Set configuration file -get_directory_property(STORMPY_INCLUDE_DIRS_PROP INCLUDE_DIRECTORIES) -foreach(arg ${STORMPY_INCLUDE_DIRS_PROP}) - set(STORMPY_INCLUDE_DIRS "${STORMPY_INCLUDE_DIRS}${sep}${arg}") - set(sep ":") -endforeach() -set(STORMPY_COMPILE_ARGS ${CMAKE_CXX_FLAGS}) -set(STORMPY_LIBRARY_DIRS "${PROJECT_BINARY_DIR}/src/storm") -set(STORMPY_RPATH "${PROJECT_BINARY_DIR}/src/storm") -configure_file ( - "${PROJECT_SOURCE_DIR}/stormpy/setup.cfg.in" - "${PROJECT_SOURCE_DIR}/stormpy/setup.cfg" -) - -# Add targets -add_custom_target(PythonBindingsBuild - COMMAND ${PYTHON_EXECUTABLE} setup.py build - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS storm -) -add_custom_target(PythonBindingsDevelop - COMMAND ${PYTHON_EXECUTABLE} setup.py develop - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS storm -) -add_custom_target(PythonBindingsInstall - COMMAND ${PYTHON_EXECUTABLE} setup.py install --user - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS storm -) diff --git a/stormpy/MANIFEST.in b/stormpy/MANIFEST.in deleted file mode 100644 index 0e6f51f28..000000000 --- a/stormpy/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -recursive-include src *.h diff --git a/stormpy/lib/.gitignore b/stormpy/lib/.gitignore deleted file mode 100644 index c70bcf8ef..000000000 --- a/stormpy/lib/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.so -__pycache__/ -stormpy.egg-info/ diff --git a/stormpy/lib/stormpy/__init__.py b/stormpy/lib/stormpy/__init__.py deleted file mode 100644 index 3dee81dd7..000000000 --- a/stormpy/lib/stormpy/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -It looks like you want to know about 'stormpy'. - - _.-;:q=._ - .' j=""^k;:\. - ; .F ";`Y - ,;.J_ ;'j - ,-;"^7F : .F _________________ - ,-'-_<. ;gj. _.,---""'' .' - ; _,._`\. : `T"5, ; - : `?8w7 `J ,-'" -^q. ` ; - \;._ _,=' ; n58L Y. .' - F;"; .' k_ `^' j' ; - J;:: ; "y:-=' ; - L;;== |:; jT\ ; - L;:;J J:L 7:;' _ ; - I;|:.L |:k J:.' , ' . ; - |;J:.| ;.I F.: . : - ;J;:L:: |.| |.J , ' ` ; ; - .' J:`J.`. :.J |. L . ; ; - ; L :k:`._ ,',j J; | ` , ; ; - .' I :`=.:."_".' L J `.' - .' |.: `"-=-' |.J ; - _.-' `: : ;:; _ ; - _.-'" J: : /.;' ; ; - ='_ k;.\. _.;:Y' , .' - `"---..__ `Y;."-=';:=' , .' - `""--..__ `"==="' - .' - ``""---...__ itz .-' - ``""---' -""" - -from . import core -from .core import * -from . import storage -from .storage import * - -core.set_up("") - -def build_model(program, formulae): - intermediate = core._build_model(program, formulae) - assert not intermediate.supports_parameters - if intermediate.model_type == ModelType.DTMC: - return intermediate.as_dtmc() - elif intermediate.model_type == ModelType.MDP: - return intermediate.as_mdp() - else: - raise RuntimeError("Not supported non-parametric model constructed") - -def build_parametric_model(program, formulae): - intermediate = core._build_parametric_model(program, formulae) - assert intermediate.supports_parameters - if intermediate.model_type == ModelType.DTMC: - return intermediate.as_pdtmc() - elif intermediate.model_type == ModelType.MDP: - return intermediate.as_pmdp() - else: - raise RuntimeError("Not supported parametric model constructed") - -def perform_bisimulation(model, formula, bisimulation_type): - if model.supports_parameters: - return core._perform_parametric_bisimulation(model, formula, bisimulation_type) - else: - return core._perform_bisimulation(model, formula, bisimulation_type) - -def model_checking(model, formula): - if model.supports_parameters: - return core._parametric_model_checking(model, formula) - else: - return core._model_checking(model, formula) diff --git a/stormpy/lib/stormpy/expressions/__init__.py b/stormpy/lib/stormpy/expressions/__init__.py deleted file mode 100644 index b185f368c..000000000 --- a/stormpy/lib/stormpy/expressions/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import expressions -from .expressions import * diff --git a/stormpy/lib/stormpy/info/__init__.py b/stormpy/lib/stormpy/info/__init__.py deleted file mode 100644 index d8e3cfa68..000000000 --- a/stormpy/lib/stormpy/info/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import info -from .info import * diff --git a/stormpy/lib/stormpy/logic/__init__.py b/stormpy/lib/stormpy/logic/__init__.py deleted file mode 100644 index 9ab762097..000000000 --- a/stormpy/lib/stormpy/logic/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import logic -from .logic import * diff --git a/stormpy/lib/stormpy/storage/__init__.py b/stormpy/lib/stormpy/storage/__init__.py deleted file mode 100644 index c68800f3a..000000000 --- a/stormpy/lib/stormpy/storage/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import storage -from .storage import * -from . import state,action diff --git a/stormpy/lib/stormpy/storage/action.py b/stormpy/lib/stormpy/storage/action.py deleted file mode 100644 index 420f5b3ba..000000000 --- a/stormpy/lib/stormpy/storage/action.py +++ /dev/null @@ -1,36 +0,0 @@ -class Action: - """ Represents an action in the model """ - - def __init__(self, row_group_start, row_group_end, row, model): - """ Initialize - :param row_group_start: Start index of the row group in the matrix - :param row_group_end: End index of the row group in the matrix - :param row: Index of the corresponding row in the matrix - :param model: Corresponding model - """ - self.row_group_start = row_group_start - self.row_group_end = row_group_end - self.row = row - 1 - self.model = model - assert row >= -1 and row + row_group_start <= row_group_end - - def __iter__(self): - return self - - def __next__(self): - if self.row + self.row_group_start >= self.row_group_end - 1: - raise StopIteration - else: - self.row += 1 - return self - - def __str__(self): - return "{}".format(self.row) - - def transitions(self): - """ Get transitions associated with the action - :return List of tranistions - """ - row = self.row_group_start + self.row - #return self.model.transition_matrix().get_row(self.row_group_start + self.row) - return self.model.transition_matrix.row_iter(row, row) diff --git a/stormpy/lib/stormpy/storage/state.py b/stormpy/lib/stormpy/storage/state.py deleted file mode 100644 index 6a315e76d..000000000 --- a/stormpy/lib/stormpy/storage/state.py +++ /dev/null @@ -1,34 +0,0 @@ -from . import action - -class State: - """ Represents a state in the model """ - - def __init__(self, id, model): - """ Initialize - :param id: Id of the state - :param model: Corresponding model - """ - self.id = id - 1 - self.model = model - - def __iter__(self): - return self - - def __next__(self): - if self.id >= self.model.nr_states - 1: - raise StopIteration - else: - self.id += 1 - return self - - def __str__(self): - return "{}".format(self.id) - - def actions(self): - """ Get actions associated with the state - :return List of actions - """ - row_group_indices = self.model.transition_matrix._row_group_indices - start = row_group_indices[self.id] - end = row_group_indices[self.id+1] - return action.Action(start, end, 0, self.model) diff --git a/stormpy/resources/pybind11/.appveyor.yml b/stormpy/resources/pybind11/.appveyor.yml deleted file mode 100644 index 80e02f4f4..000000000 --- a/stormpy/resources/pybind11/.appveyor.yml +++ /dev/null @@ -1,24 +0,0 @@ -version: 1.0.{build} -os: Visual Studio 2015 -clone_folder: C:\projects\pybind11 -test: off -configuration: - - Release - - Debug -branches: - only: - - master -environment: - matrix: - - CMAKE_PLATFORM: "Visual Studio 14 2015" - PYTHON_DIR: "C:\\Python34" - - CMAKE_PLATFORM: "Visual Studio 14 2015 Win64" - PYTHON_DIR: "C:\\Python34-x64" -install: - - cinstall: python -build_script: - - echo Running cmake... - - cd c:\projects\pybind11 - - cmake -G "%CMAKE_PLATFORM%" -DPYTHON_EXECUTABLE:FILEPATH=%PYTHON_DIR%/python.exe - - set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - - cmake --build . --config %Configuration% --target check -- /v:m /logger:%MSBuildLogger% diff --git a/stormpy/resources/pybind11/.gitignore b/stormpy/resources/pybind11/.gitignore deleted file mode 100644 index 16701940f..000000000 --- a/stormpy/resources/pybind11/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -CMakeCache.txt -CMakeFiles -Makefile -cmake_install.cmake -.DS_Store -/example/example.so -/example/example.cpython*.so -/example/example.pyd -/example/example*.dll -*.sln -*.sdf -*.opensdf -*.vcxproj -*.filters -example.dir -Win32 -x64 -Release -Debug -.vs -CTestTestfile.cmake -Testing -autogen -MANIFEST -/.ninja_* -/*.ninja -/docs/.build -*.py[co] -*.egg-info -*~ -.DS_Store -/dist -/build diff --git a/stormpy/resources/pybind11/.gitmodules b/stormpy/resources/pybind11/.gitmodules deleted file mode 100644 index 5191885e7..000000000 --- a/stormpy/resources/pybind11/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "tools/clang"] - path = tools/clang - url = https://github.com/wjakob/clang-cindex-python3 diff --git a/stormpy/resources/pybind11/.travis.yml b/stormpy/resources/pybind11/.travis.yml deleted file mode 100644 index 3f9cb501c..000000000 --- a/stormpy/resources/pybind11/.travis.yml +++ /dev/null @@ -1,44 +0,0 @@ -language: cpp -sudo: false -cache: - directories: - - $HOME/.cache/pip - - ccache -addons: - apt: - sources: - - ubuntu-toolchain-r-test - - deadsnakes - - kubuntu-backports # cmake 2.8.12 - packages: - - g++-4.8 - - g++-4.8-multilib - - g++-multilib - - python3.5 - - python3.5-dev - - python3.5-venv - - python3.5-dev:i386 - - cmake -matrix: - include: - - os: linux - compiler: gcc-4.8 - install: - - pyvenv-3.5 venv - - source venv/bin/activate - - pip install -U pip wheel - - pip install numpy - script: - - CXX=g++-4.8 cmake -DPYBIND11_PYTHON_VERSION=3.5 - - CTEST_OUTPUT_ON_FAILURE=TRUE make check -j 2 - - os: osx - compiler: clang - script: - - cmake -DPYBIND11_PYTHON_VERSION=2.7 - - CTEST_OUTPUT_ON_FAILURE=TRUE make check -j 2 - #- os: linux - #compiler: gcc-4.8 - #script: - #- pyvenv-3.5 venv - #- cmake -DPYBIND11_PYTHON_VERSION=3.5 -DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.5m -DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.5m.so -DPYTHON_EXECUTABLE:FILEPATH=`pwd`/venv/bin/python3.5 -DCMAKE_CXX_COMPILER=g++-4.8 -DCMAKE_CXX_FLAGS=-m32 - #- make -j 2 diff --git a/stormpy/resources/pybind11/CMakeLists.txt b/stormpy/resources/pybind11/CMakeLists.txt deleted file mode 100644 index 7d2c991ab..000000000 --- a/stormpy/resources/pybind11/CMakeLists.txt +++ /dev/null @@ -1,170 +0,0 @@ -# CMakeLists.txt -- Build system for the pybind11 examples -# -# Copyright (c) 2015 Wenzel Jakob -# -# All rights reserved. Use of this source code is governed by a -# BSD-style license that can be found in the LICENSE file. - -cmake_minimum_required(VERSION 2.8.12) - -project(pybind11) - -# Check if pybind11 is being used directly or via add_subdirectory -set(PYBIND11_MASTER_PROJECT OFF) -if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - set(PYBIND11_MASTER_PROJECT ON) -endif() - -option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT}) -option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT}) - -# Add a CMake parameter for choosing a desired Python version -set(PYBIND11_PYTHON_VERSION "" CACHE STRING "Python version to use for compiling the example application") - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/tools") -set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6 3.7) -find_package(PythonLibsNew ${PYBIND11_PYTHON_VERSION} REQUIRED) - -include(CheckCXXCompilerFlag) - -if(NOT MSVC AND NOT PYBIND11_CPP_STANDARD) - check_cxx_compiler_flag("-std=c++14" HAS_CPP14_FLAG) - check_cxx_compiler_flag("-std=c++11" HAS_CPP11_FLAG) - - if (HAS_CPP14_FLAG) - set(PYBIND11_CPP_STANDARD -std=c++14) - elseif (HAS_CPP11_FLAG) - set(PYBIND11_CPP_STANDARD -std=c++11) - else() - message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!") - endif() - - set(PYBIND11_CPP_STANDARD ${PYBIND11_CPP_STANDARD} CACHE STRING - "C++ standard flag, e.g. -std=c++11 or -std=c++14. Defaults to latest available.") -endif() - -# Cache variables so pybind11_add_module can be used in parent projects -set(PYBIND11_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include" CACHE INTERNAL "") -set(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS} CACHE INTERNAL "") -set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} CACHE INTERNAL "") -set(PYTHON_MODULE_PREFIX ${PYTHON_MODULE_PREFIX} CACHE INTERNAL "") -set(PYTHON_MODULE_EXTENSION ${PYTHON_MODULE_EXTENSION} CACHE INTERNAL "") - -# Build a Python extension module: -# pybind11_add_module( source1 [source2 ...]) -# -function(pybind11_add_module target_name) - add_library(${target_name} MODULE ${ARGN}) - target_include_directories(${target_name} PUBLIC ${PYBIND11_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS}) - - # The prefix and extension are provided by FindPythonLibsNew.cmake - set_target_properties(${target_name} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}") - set_target_properties(${target_name} PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}") - - if(WIN32 OR CYGWIN) - # Link against the Python shared library on Windows - target_link_libraries(${target_name} PRIVATE ${PYTHON_LIBRARIES}) - elseif(APPLE) - # It's quite common to have multiple copies of the same Python version - # installed on one's system. E.g.: one copy from the OS and another copy - # that's statically linked into an application like Blender or Maya. - # If we link our plugin library against the OS Python here and import it - # into Blender or Maya later on, this will cause segfaults when multiple - # conflicting Python instances are active at the same time (even when they - # are of the same version). - - # Windows is not affected by this issue since it handles DLL imports - # differently. The solution for Linux and Mac OS is simple: we just don't - # link against the Python library. The resulting shared library will have - # missing symbols, but that's perfectly fine -- they will be resolved at - # import time. - - target_link_libraries(${target_name} PRIVATE "-undefined dynamic_lookup") - endif() - - if(NOT MSVC) - # Make sure C++11/14 are enabled - target_compile_options(${target_name} PUBLIC ${PYBIND11_CPP_STANDARD}) - - # Enable link time optimization and set the default symbol - # visibility to hidden (very important to obtain small binaries) - string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) - if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) - # Check for Link Time Optimization support (GCC/Clang) - check_cxx_compiler_flag("-flto" HAS_LTO_FLAG) - if(HAS_LTO_FLAG AND NOT CYGWIN) - target_compile_options(${target_name} PRIVATE -flto) - endif() - - # Intel equivalent to LTO is called IPO - if(CMAKE_CXX_COMPILER_ID MATCHES "Intel") - check_cxx_compiler_flag("-ipo" HAS_IPO_FLAG) - if(HAS_IPO_FLAG) - target_compile_options(${target_name} PRIVATE -ipo) - endif() - endif() - - # Default symbol visibility - target_compile_options(${target_name} PRIVATE "-fvisibility=hidden") - - # Strip unnecessary sections of the binary on Linux/Mac OS - if(CMAKE_STRIP) - if(APPLE) - add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND ${CMAKE_STRIP} -u -r $) - else() - add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND ${CMAKE_STRIP} $) - endif() - endif() - endif() - elseif(MSVC) - # /MP enables multithreaded builds (relevant when there are many files), /bigobj is - # needed for bigger binding projects due to the limit to 64k addressable sections - target_compile_options(${target_name} PRIVATE /MP /bigobj) - - # Enforce link time code generation on MSVC, except in debug mode - target_compile_options(${target_name} PRIVATE $<$>:/GL>) - - # Fancy generator expressions don't work with linker flags, for reasons unknown - set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE /LTCG) - set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL /LTCG) - set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS_RELWITHDEBINFO /LTCG) - endif() -endfunction() - -# Compile with compiler warnings turned on -function(pybind11_enable_warnings target_name) - if(MSVC) - target_compile_options(${target_name} PRIVATE /W4) - else() - target_compile_options(${target_name} PRIVATE -Wall -Wextra -Wconversion) - endif() -endfunction() - -if (PYBIND11_TEST) - enable_testing() - add_subdirectory(example) - add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C $ DEPENDS example) -endif() - -if (PYBIND11_INSTALL) - set(PYBIND11_HEADERS - include/pybind11/attr.h - include/pybind11/cast.h - include/pybind11/common.h - include/pybind11/complex.h - include/pybind11/descr.h - include/pybind11/eigen.h - include/pybind11/functional.h - include/pybind11/numpy.h - include/pybind11/operators.h - include/pybind11/pybind11.h - include/pybind11/pytypes.h - include/pybind11/stl.h - include/pybind11/stl_bind.h - include/pybind11/typeid.h - ) - - install(FILES ${PYBIND11_HEADERS} DESTINATION include/pybind11) -endif() diff --git a/stormpy/resources/pybind11/CONTRIBUTING.md b/stormpy/resources/pybind11/CONTRIBUTING.md deleted file mode 100644 index d700c4ae7..000000000 --- a/stormpy/resources/pybind11/CONTRIBUTING.md +++ /dev/null @@ -1,37 +0,0 @@ -Thank you for your interest in this project! Please refer to the following -sections on how to contribute code and bug reports. - -### Reporting bugs - -At the moment, this project is run in the spare time of a single person -([Wenzel Jakob](http://rgl.epfl.ch/people/wjakob)) with very limited resources -for issue tracker tickets. Thus, before submitting a question or bug report, -please take a moment of your time and ensure that your issue isn't already -discussed in the project documentation provided at -[http://pybind11.readthedocs.org/en/latest](http://pybind11.readthedocs.org/en/latest). - -Assuming that you have identified a previously unknown problem or an important -question, it's essential that you submit a self-contained and minimal piece of -code that reproduces the problem. In other words: no external dependencies, -isolate the function(s) that cause breakage, submit matched and complete C++ -and Python snippets that can be easily compiled and run on my end. - -## Pull requests -Contributions are submitted, reviewed, and accepted using Github pull requests. -Please refer to [this -article](https://help.github.com/articles/using-pull-requests) for details and -adhere to the following rules to make the process as smooth as possible: - -* Make a new branch for every feature you're working on. -* Make small and clean pull requests that are easy to review but make sure they - do add value by themselves. -* Add tests for any new functionality and run the test suite (``make test``) to - ensure that no existing features break. -* This project has a strong focus on providing general solutions using a - minimal amount of code, thus small pull requests are greatly preferred. - -### License - -pybind11 is provided under a BSD-style license that can be found in the -``LICENSE`` file. By using, distributing, or contributing to this project, you -agree to the terms and conditions of this license. diff --git a/stormpy/resources/pybind11/LICENSE b/stormpy/resources/pybind11/LICENSE deleted file mode 100644 index ccf4e9787..000000000 --- a/stormpy/resources/pybind11/LICENSE +++ /dev/null @@ -1,36 +0,0 @@ -Copyright (c) 2016 Wenzel Jakob , All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You are under no obligation whatsoever to provide any bug fixes, patches, or -upgrades to the features, functionality or performance of the source code -("Enhancements") to anyone; however, if you choose to make your Enhancements -available either publicly, or directly to the author of this software, without -imposing a separate written license agreement for such Enhancements, then you -hereby grant the following license: a non-exclusive, royalty-free perpetual -license to install, use, modify, prepare derivative works, incorporate into -other computer software, distribute, and sublicense such enhancements or -derivative works thereof, in binary and source code form. diff --git a/stormpy/resources/pybind11/MANIFEST.in b/stormpy/resources/pybind11/MANIFEST.in deleted file mode 100644 index 33c22c84c..000000000 --- a/stormpy/resources/pybind11/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include include/pybind11/*.h diff --git a/stormpy/resources/pybind11/README.md b/stormpy/resources/pybind11/README.md deleted file mode 100644 index a313c6f54..000000000 --- a/stormpy/resources/pybind11/README.md +++ /dev/null @@ -1,114 +0,0 @@ -![pybind11 logo](https://github.com/pybind/pybind11/raw/master/docs/pybind11-logo.png) - -# pybind11 — Seamless operability between C++11 and Python - -[![Documentation Status](https://readthedocs.org/projects/pybind11/badge/?version=latest)](http://pybind11.readthedocs.org/en/latest/?badge=latest) -[![Build Status](https://travis-ci.org/pybind/pybind11.svg?branch=master)](https://travis-ci.org/pybind/pybind11) -[![Build status](https://ci.appveyor.com/api/projects/status/riaj54pn4h08xy40?svg=true)](https://ci.appveyor.com/project/wjakob/pybind11) - -**pybind11** is a lightweight header-only library that exposes C++ types in Python -and vice versa, mainly to create Python bindings of existing C++ code. Its -goals and syntax are similar to the excellent -[Boost.Python](http://www.boost.org/doc/libs/1_58_0/libs/python/doc/) library -by David Abrahams: to minimize boilerplate code in traditional extension -modules by inferring type information using compile-time introspection. - -The main issue with Boost.Python—and the reason for creating such a similar -project—is Boost. Boost is an enormously large and complex suite of utility -libraries that works with almost every C++ compiler in existence. This -compatibility has its cost: arcane template tricks and workarounds are -necessary to support the oldest and buggiest of compiler specimens. Now that -C++11-compatible compilers are widely available, this heavy machinery has -become an excessively large and unnecessary dependency. - -Think of this library as a tiny self-contained version of Boost.Python with -everything stripped away that isn't relevant for binding generation. Without -comments, the core header files only require ~2.5K lines of code and depend on -Python (2.7 or 3.x) and the C++ standard library. This compact implementation -was possible thanks to some of the new C++11 language features (specifically: -tuples, lambda functions and variadic templates). Since its creation, this -library has grown beyond Boost.Python in many ways, leading to dramatically -simpler binding code in many common situations. - -Tutorial and reference documentation is provided at -[http://pybind11.readthedocs.org/en/latest](http://pybind11.readthedocs.org/en/latest). -A PDF version of the manual is available -[here](https://media.readthedocs.org/pdf/pybind11/latest/pybind11.pdf). - -## Core features -pybind11 can map the following core C++ features to Python - -- Functions accepting and returning custom data structures per value, reference, or pointer -- Instance methods and static methods -- Overloaded functions -- Instance attributes and static attributes -- Exceptions -- Enumerations -- Callbacks -- Custom operators -- STL data structures -- Iterators and ranges -- Smart pointers with reference counting like `std::shared_ptr` -- Internal references with correct reference counting -- C++ classes with virtual (and pure virtual) methods can be extended in Python - -## Goodies -In addition to the core functionality, pybind11 provides some extra goodies: - -- pybind11 uses C++11 move constructors and move assignment operators whenever - possible to efficiently transfer custom data types. - -- It is possible to bind C++11 lambda functions with captured variables. The - lambda capture data is stored inside the resulting Python function object. - -- It's easy to expose the internal storage of custom data types through - Pythons' buffer protocols. This is handy e.g. for fast conversion between - C++ matrix classes like Eigen and NumPy without expensive copy operations. - -- pybind11 can automatically vectorize functions so that they are transparently - applied to all entries of one or more NumPy array arguments. - -- Python's slice-based access and assignment operations can be supported with - just a few lines of code. - -- Everything is contained in just a few header files; there is no need to link - against any additional libraries. - -- Binaries are generally smaller by a factor of 2 or more compared to - equivalent bindings generated by Boost.Python. - -- When supported by the compiler, two new C++14 features (relaxed constexpr and - return value deduction) are used to precompute function signatures at compile - time, leading to smaller binaries. - -- With little extra effort, C++ types can be pickled and unpickled similar to - regular Python objects. - -## Supported compilers - -1. Clang/LLVM (any non-ancient version with C++11 support) -2. GCC (any non-ancient version with C++11 support) -3. Microsoft Visual Studio 2015 or newer -4. Intel C++ compiler v15 or newer -5. Cygwin/GCC (tested on 2.5.1) - -## About - -This project was created by [Wenzel Jakob](https://www.mitsuba-renderer.org/~wenzel/). -Significant features and/or improvements to the code were contributed by -Jonas Adler, -Sylvain Corlay, -Axel Huebl, -@hulucc, -Sergey Lyskov -Johan Mabille, -Tomasz MiÄ…sko, -Dean Moldovan, -Ben Pritchard, and -Boris Schäling. - -### License - -pybind11 is provided under a BSD-style license that can be found in the -``LICENSE`` file. By using, distributing, or contributing to this project, -you agree to the terms and conditions of this license. diff --git a/stormpy/resources/pybind11/docs/_static/theme_overrides.css b/stormpy/resources/pybind11/docs/_static/theme_overrides.css deleted file mode 100644 index 1071809fa..000000000 --- a/stormpy/resources/pybind11/docs/_static/theme_overrides.css +++ /dev/null @@ -1,11 +0,0 @@ -.wy-table-responsive table td, -.wy-table-responsive table th { - white-space: initial !important; -} -.rst-content table.docutils td { - vertical-align: top !important; -} -div[class^='highlight'] pre { - white-space: pre; - white-space: pre-wrap; -} diff --git a/stormpy/resources/pybind11/docs/advanced.rst b/stormpy/resources/pybind11/docs/advanced.rst deleted file mode 100644 index c257fa2d4..000000000 --- a/stormpy/resources/pybind11/docs/advanced.rst +++ /dev/null @@ -1,1613 +0,0 @@ -.. _advanced: - -Advanced topics -############### - -For brevity, the rest of this chapter assumes that the following two lines are -present: - -.. code-block:: cpp - - #include - - namespace py = pybind11; - -Exporting constants and mutable objects -======================================= - -To expose a C++ constant, use the ``attr`` function to register it in a module -as shown below. The ``int_`` class is one of many small wrapper objects defined -in ``pybind11/pytypes.h``. General objects (including integers) can also be -converted using the function ``cast``. - -.. code-block:: cpp - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - m.attr("MY_CONSTANT") = py::int_(123); - m.attr("MY_CONSTANT_2") = py::cast(new MyObject()); - } - -Operator overloading -==================== - -Suppose that we're given the following ``Vector2`` class with a vector addition -and scalar multiplication operation, all implemented using overloaded operators -in C++. - -.. code-block:: cpp - - class Vector2 { - public: - Vector2(float x, float y) : x(x), y(y) { } - - Vector2 operator+(const Vector2 &v) const { return Vector2(x + v.x, y + v.y); } - Vector2 operator*(float value) const { return Vector2(x * value, y * value); } - Vector2& operator+=(const Vector2 &v) { x += v.x; y += v.y; return *this; } - Vector2& operator*=(float v) { x *= v; y *= v; return *this; } - - friend Vector2 operator*(float f, const Vector2 &v) { - return Vector2(f * v.x, f * v.y); - } - - std::string toString() const { - return "[" + std::to_string(x) + ", " + std::to_string(y) + "]"; - } - private: - float x, y; - }; - -The following snippet shows how the above operators can be conveniently exposed -to Python. - -.. code-block:: cpp - - #include - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - - py::class_(m, "Vector2") - .def(py::init()) - .def(py::self + py::self) - .def(py::self += py::self) - .def(py::self *= float()) - .def(float() * py::self) - .def("__repr__", &Vector2::toString); - - return m.ptr(); - } - -Note that a line like - -.. code-block:: cpp - - .def(py::self * float()) - -is really just short hand notation for - -.. code-block:: cpp - - .def("__mul__", [](const Vector2 &a, float b) { - return a * b; - }) - -This can be useful for exposing additional operators that don't exist on the -C++ side, or to perform other types of customization. - -.. note:: - - To use the more convenient ``py::self`` notation, the additional - header file :file:`pybind11/operators.h` must be included. - -.. seealso:: - - The file :file:`example/example3.cpp` contains a complete example that - demonstrates how to work with overloaded operators in more detail. - -Callbacks and passing anonymous functions -========================================= - -The C++11 standard brought lambda functions and the generic polymorphic -function wrapper ``std::function<>`` to the C++ programming language, which -enable powerful new ways of working with functions. Lambda functions come in -two flavors: stateless lambda function resemble classic function pointers that -link to an anonymous piece of code, while stateful lambda functions -additionally depend on captured variables that are stored in an anonymous -*lambda closure object*. - -Here is a simple example of a C++ function that takes an arbitrary function -(stateful or stateless) with signature ``int -> int`` as an argument and runs -it with the value 10. - -.. code-block:: cpp - - int func_arg(const std::function &f) { - return f(10); - } - -The example below is more involved: it takes a function of signature ``int -> int`` -and returns another function of the same kind. The return value is a stateful -lambda function, which stores the value ``f`` in the capture object and adds 1 to -its return value upon execution. - -.. code-block:: cpp - - std::function func_ret(const std::function &f) { - return [f](int i) { - return f(i) + 1; - }; - } - -This example demonstrates using python named parameters in C++ callbacks which -requires using ``py::cpp_function`` as a wrapper. Usage is similar to defining -methods of classes: - -.. code-block:: cpp - - py::cpp_function func_cpp() { - return py::cpp_function([](int i) { return i+1; }, - py::arg("number")); - } - -After including the extra header file :file:`pybind11/functional.h`, it is almost -trivial to generate binding code for all of these functions. - -.. code-block:: cpp - - #include - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - - m.def("func_arg", &func_arg); - m.def("func_ret", &func_ret); - m.def("func_cpp", &func_cpp); - - return m.ptr(); - } - -The following interactive session shows how to call them from Python. - -.. code-block:: pycon - - $ python - >>> import example - >>> def square(i): - ... return i * i - ... - >>> example.func_arg(square) - 100L - >>> square_plus_1 = example.func_ret(square) - >>> square_plus_1(4) - 17L - >>> plus_1 = func_cpp() - >>> plus_1(number=43) - 44L - -.. note:: - - This functionality is very useful when generating bindings for callbacks in - C++ libraries (e.g. a graphical user interface library). - - The file :file:`example/example5.cpp` contains a complete example that - demonstrates how to work with callbacks and anonymous functions in more detail. - -.. warning:: - - Keep in mind that passing a function from C++ to Python (or vice versa) - will instantiate a piece of wrapper code that translates function - invocations between the two languages. Copying the same function back and - forth between Python and C++ many times in a row will cause these wrappers - to accumulate, which can decrease performance. - -Overriding virtual functions in Python -====================================== - -Suppose that a C++ class or interface has a virtual function that we'd like to -to override from within Python (we'll focus on the class ``Animal``; ``Dog`` is -given as a specific example of how one would do this with traditional C++ -code). - -.. code-block:: cpp - - class Animal { - public: - virtual ~Animal() { } - virtual std::string go(int n_times) = 0; - }; - - class Dog : public Animal { - public: - std::string go(int n_times) { - std::string result; - for (int i=0; igo(3); - } - -Normally, the binding code for these classes would look as follows: - -.. code-block:: cpp - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - - py::class_ animal(m, "Animal"); - animal - .def("go", &Animal::go); - - py::class_(m, "Dog", animal) - .def(py::init<>()); - - m.def("call_go", &call_go); - - return m.ptr(); - } - -However, these bindings are impossible to extend: ``Animal`` is not -constructible, and we clearly require some kind of "trampoline" that -redirects virtual calls back to Python. - -Defining a new type of ``Animal`` from within Python is possible but requires a -helper class that is defined as follows: - -.. code-block:: cpp - - class PyAnimal : public Animal { - public: - /* Inherit the constructors */ - using Animal::Animal; - - /* Trampoline (need one for each virtual function) */ - std::string go(int n_times) { - PYBIND11_OVERLOAD_PURE( - std::string, /* Return type */ - Animal, /* Parent class */ - go, /* Name of function */ - n_times /* Argument(s) */ - ); - } - }; - -The macro :func:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual -functions, and :func:`PYBIND11_OVERLOAD` should be used for functions which have -a default implementation. - -There are also two alternate macros :func:`PYBIND11_OVERLOAD_PURE_NAME` and -:func:`PYBIND11_OVERLOAD_NAME` which take a string-valued name argument -after the *Name of the function* slot. This is useful when the C++ and Python -versions of the function have different names, e.g. ``operator()`` vs ``__call__``. - -The binding code also needs a few minor adaptations (highlighted): - -.. code-block:: cpp - :emphasize-lines: 4,6,7 - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - - py::class_, PyAnimal /* <--- trampoline*/> animal(m, "Animal"); - animal - .def(py::init<>()) - .def("go", &Animal::go); - - py::class_(m, "Dog", animal) - .def(py::init<>()); - - m.def("call_go", &call_go); - - return m.ptr(); - } - -Importantly, pybind11 is made aware of the trampoline trampoline helper class -by specifying it as the *third* template argument to :class:`class_`. The -second argument with the unique pointer is simply the default holder type used -by pybind11. Following this, we are able to define a constructor as usual. - -The Python session below shows how to override ``Animal::go`` and invoke it via -a virtual method call. - -.. code-block:: pycon - - >>> from example import * - >>> d = Dog() - >>> call_go(d) - u'woof! woof! woof! ' - >>> class Cat(Animal): - ... def go(self, n_times): - ... return "meow! " * n_times - ... - >>> c = Cat() - >>> call_go(c) - u'meow! meow! meow! ' - -Please take a look at the :ref:`macro_notes` before using this feature. - -.. seealso:: - - The file :file:`example/example12.cpp` contains a complete example that - demonstrates how to override virtual functions using pybind11 in more - detail. - - -.. _macro_notes: - -General notes regarding convenience macros -========================================== - -pybind11 provides a few convenience macros such as -:func:`PYBIND11_MAKE_OPAQUE` and :func:`PYBIND11_DECLARE_HOLDER_TYPE`, and -``PYBIND11_OVERLOAD_*``. Since these are "just" macros that are evaluated -in the preprocessor (which has no concept of types), they *will* get confused -by commas in a template argument such as ``PYBIND11_OVERLOAD(MyReturnValue, myFunc)``. In this case, the preprocessor assumes that the comma indicates -the beginnning of the next parameter. Use a ``typedef`` to bind the template to -another name and use it in the macro to avoid this problem. - - -Global Interpreter Lock (GIL) -============================= - -The classes :class:`gil_scoped_release` and :class:`gil_scoped_acquire` can be -used to acquire and release the global interpreter lock in the body of a C++ -function call. In this way, long-running C++ code can be parallelized using -multiple Python threads. Taking the previous section as an example, this could -be realized as follows (important changes highlighted): - -.. code-block:: cpp - :emphasize-lines: 8,9,33,34 - - class PyAnimal : public Animal { - public: - /* Inherit the constructors */ - using Animal::Animal; - - /* Trampoline (need one for each virtual function) */ - std::string go(int n_times) { - /* Acquire GIL before calling Python code */ - py::gil_scoped_acquire acquire; - - PYBIND11_OVERLOAD_PURE( - std::string, /* Return type */ - Animal, /* Parent class */ - go, /* Name of function */ - n_times /* Argument(s) */ - ); - } - }; - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - - py::class_, PyAnimal> animal(m, "Animal"); - animal - .def(py::init<>()) - .def("go", &Animal::go); - - py::class_(m, "Dog", animal) - .def(py::init<>()); - - m.def("call_go", [](Animal *animal) -> std::string { - /* Release GIL before calling into (potentially long-running) C++ code */ - py::gil_scoped_release release; - return call_go(animal); - }); - - return m.ptr(); - } - -Passing STL data structures -=========================== - -When including the additional header file :file:`pybind11/stl.h`, conversions -between ``std::vector<>``, ``std::list<>``, ``std::set<>``, and ``std::map<>`` -and the Python ``list``, ``set`` and ``dict`` data structures are automatically -enabled. The types ``std::pair<>`` and ``std::tuple<>`` are already supported -out of the box with just the core :file:`pybind11/pybind11.h` header. - -.. note:: - - Arbitrary nesting of any of these types is supported. - -.. seealso:: - - The file :file:`example/example2.cpp` contains a complete example that - demonstrates how to pass STL data types in more detail. - -Binding sequence data types, iterators, the slicing protocol, etc. -================================================================== - -Please refer to the supplemental example for details. - -.. seealso:: - - The file :file:`example/example6.cpp` contains a complete example that - shows how to bind a sequence data type, including length queries - (``__len__``), iterators (``__iter__``), the slicing protocol and other - kinds of useful operations. - -Return value policies -===================== - -Python and C++ use wildly different ways of managing the memory and lifetime of -objects managed by them. This can lead to issues when creating bindings for -functions that return a non-trivial type. Just by looking at the type -information, it is not clear whether Python should take charge of the returned -value and eventually free its resources, or if this is handled on the C++ side. -For this reason, pybind11 provides a several `return value policy` annotations -that can be passed to the :func:`module::def` and :func:`class_::def` -functions. The default policy is :enum:`return_value_policy::automatic`. - -.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}| - -+--------------------------------------------------+----------------------------------------------------------------------------+ -| Return value policy | Description | -+==================================================+============================================================================+ -| :enum:`return_value_policy::automatic` | This is the default return value policy, which falls back to the policy | -| | :enum:`return_value_policy::take_ownership` when the return value is a | -| | pointer. Otherwise, it uses :enum:`return_value::move` or | -| | :enum:`return_value::copy` for rvalue and lvalue references, respectively. | -| | See below for a description of what all of these different policies do. | -+--------------------------------------------------+----------------------------------------------------------------------------+ -| :enum:`return_value_policy::automatic_reference` | As above, but use policy :enum:`return_value_policy::reference` when the | -| | return value is a pointer. This is the default conversion policy for | -| | function arguments when calling Python functions manually from C++ code | -| | (i.e. via handle::operator()). You probably won't need to use this. | -+--------------------------------------------------+----------------------------------------------------------------------------+ -| :enum:`return_value_policy::take_ownership` | Reference an existing object (i.e. do not create a new copy) and take | -| | ownership. Python will call the destructor and delete operator when the | -| | object's reference count reaches zero. Undefined behavior ensues when the | -| | C++ side does the same. | -+--------------------------------------------------+----------------------------------------------------------------------------+ -| :enum:`return_value_policy::copy` | Create a new copy of the returned object, which will be owned by Python. | -| | This policy is comparably safe because the lifetimes of the two instances | -| | are decoupled. | -+--------------------------------------------------+----------------------------------------------------------------------------+ -| :enum:`return_value_policy::move` | Use ``std::move`` to move the return value contents into a new instance | -| | that will be owned by Python. This policy is comparably safe because the | -| | lifetimes of the two instances (move source and destination) are decoupled.| -+--------------------------------------------------+----------------------------------------------------------------------------+ -| :enum:`return_value_policy::reference` | Reference an existing object, but do not take ownership. The C++ side is | -| | responsible for managing the object's lifetime and deallocating it when | -| | it is no longer used. Warning: undefined behavior will ensue when the C++ | -| | side deletes an object that is still referenced and used by Python. | -+--------------------------------------------------+----------------------------------------------------------------------------+ -| :enum:`return_value_policy::reference_internal` | This policy only applies to methods and properties. It references the | -| | object without taking ownership similar to the above | -| | :enum:`return_value_policy::reference` policy. In contrast to that policy, | -| | the function or property's implicit ``this`` argument (called the *parent*)| -| | is considered to be the the owner of the return value (the *child*). | -| | pybind11 then couples the lifetime of the parent to the child via a | -| | reference relationship that ensures that the parent cannot be garbage | -| | collected while Python is still using the child. More advanced variations | -| | of this scheme are also possible using combinations of | -| | :enum:`return_value_policy::reference` and the :class:`keep_alive` call | -| | policy described next. | -+--------------------------------------------------+----------------------------------------------------------------------------+ - -The following example snippet shows a use case of the -:enum:`return_value_policy::reference_internal` policy. - -.. code-block:: cpp - - class Example { - public: - Internal &get_internal() { return internal; } - private: - Internal internal; - }; - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - - py::class_(m, "Example") - .def(py::init<>()) - .def("get_internal", &Example::get_internal, "Return the internal data", - py::return_value_policy::reference_internal); - - return m.ptr(); - } - -.. warning:: - - Code with invalid call policies might access unitialized memory or free - data structures multiple times, which can lead to hard-to-debug - non-determinism and segmentation faults, hence it is worth spending the - time to understand all the different options in the table above. - - It is worth highlighting one common issue where a method (e.g. a getter) - returns a reference (or pointer) to the first attribute of a class. In this - case, the class and attribute will be located at the same address in - memory, which pybind11 will recongnize and return the parent instance - instead of creating a new Python object that represents the attribute. - Here, the :enum:`return_value_policy::reference_internal` policy should be - used rather than relying on the automatic one. - -.. note:: - - The next section on :ref:`call_policies` discusses *call policies* that can be - specified *in addition* to a return value policy from the list above. Call - policies indicate reference relationships that can involve both return values - and parameters of functions. - -.. note:: - - As an alternative to elaborate call policies and lifetime management logic, - consider using smart pointers (see the section on :ref:`smart_pointers` for - details). Smart pointers can tell whether an object is still referenced from - C++ or Python, which generally eliminates the kinds of inconsistencies that - can lead to crashes or undefined behavior. For functions returning smart - pointers, it is not necessary to specify a return value policy. - -.. _call_policies: - -Additional call policies -======================== - -In addition to the above return value policies, further `call policies` can be -specified to indicate dependencies between parameters. There is currently just -one policy named ``keep_alive``, which indicates that the -argument with index ``Patient`` should be kept alive at least until the -argument with index ``Nurse`` is freed by the garbage collector; argument -indices start at one, while zero refers to the return value. For methods, index -one refers to the implicit ``this`` pointer, while regular arguments begin at -index two. Arbitrarily many call policies can be specified. - -Consider the following example: the binding code for a list append operation -that ties the lifetime of the newly added element to the underlying container -might be declared as follows: - -.. code-block:: cpp - - py::class_(m, "List") - .def("append", &List::append, py::keep_alive<1, 2>()); - -.. note:: - - ``keep_alive`` is analogous to the ``with_custodian_and_ward`` (if Nurse, - Patient != 0) and ``with_custodian_and_ward_postcall`` (if Nurse/Patient == - 0) policies from Boost.Python. - -.. seealso:: - - The file :file:`example/example13.cpp` contains a complete example that - demonstrates using :class:`keep_alive` in more detail. - -Implicit type conversions -========================= - -Suppose that instances of two types ``A`` and ``B`` are used in a project, and -that an ``A`` can easily be converted into an instance of type ``B`` (examples of this -could be a fixed and an arbitrary precision number type). - -.. code-block:: cpp - - py::class_(m, "A") - /// ... members ... - - py::class_(m, "B") - .def(py::init()) - /// ... members ... - - m.def("func", - [](const B &) { /* .... */ } - ); - -To invoke the function ``func`` using a variable ``a`` containing an ``A`` -instance, we'd have to write ``func(B(a))`` in Python. On the other hand, C++ -will automatically apply an implicit type conversion, which makes it possible -to directly write ``func(a)``. - -In this situation (i.e. where ``B`` has a constructor that converts from -``A``), the following statement enables similar implicit conversions on the -Python side: - -.. code-block:: cpp - - py::implicitly_convertible(); - -.. note:: - - Implicit conversions from ``A`` to ``B`` only work when ``B`` is a custom - data type that is exposed to Python via pybind11. - -.. _static_properties: - -Static properties -================= - -The section on :ref:`properties` discussed the creation of instance properties -that are implemented in terms of C++ getters and setters. - -Static properties can also be created in a similar way to expose getters and -setters of static class attributes. It is important to note that the implicit -``self`` argument also exists in this case and is used to pass the Python -``type`` subclass instance. This parameter will often not be needed by the C++ -side, and the following example illustrates how to instantiate a lambda getter -function that ignores it: - -.. code-block:: cpp - - py::class_(m, "Foo") - .def_property_readonly_static("foo", [](py::object /* self */) { return Foo(); }); - -Unique pointers -=============== - -Given a class ``Example`` with Python bindings, it's possible to return -instances wrapped in C++11 unique pointers, like so - -.. code-block:: cpp - - std::unique_ptr create_example() { return std::unique_ptr(new Example()); } - -.. code-block:: cpp - - m.def("create_example", &create_example); - -In other words, there is nothing special that needs to be done. While returning -unique pointers in this way is allowed, it is *illegal* to use them as function -arguments. For instance, the following function signature cannot be processed -by pybind11. - -.. code-block:: cpp - - void do_something_with_example(std::unique_ptr ex) { ... } - -The above signature would imply that Python needs to give up ownership of an -object that is passed to this function, which is generally not possible (for -instance, the object might be referenced elsewhere). - -.. _smart_pointers: - -Smart pointers -============== - -This section explains how to pass values that are wrapped in "smart" pointer -types with internal reference counting. For the simpler C++11 unique pointers, -refer to the previous section. - -The binding generator for classes, :class:`class_`, takes an optional second -template type, which denotes a special *holder* type that is used to manage -references to the object. When wrapping a type named ``Type``, the default -value of this template parameter is ``std::unique_ptr``, which means that -the object is deallocated when Python's reference count goes to zero. - -It is possible to switch to other types of reference counting wrappers or smart -pointers, which is useful in codebases that rely on them. For instance, the -following snippet causes ``std::shared_ptr`` to be used instead. - -.. code-block:: cpp - - py::class_ /* <- holder type */> obj(m, "Example"); - -Note that any particular class can only be associated with a single holder type. - -To enable transparent conversions for functions that take shared pointers as an -argument or that return them, a macro invocation similar to the following must -be declared at the top level before any binding code: - -.. code-block:: cpp - - PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr); - -.. note:: - - The first argument of :func:`PYBIND11_DECLARE_HOLDER_TYPE` should be a - placeholder name that is used as a template parameter of the second - argument. Thus, feel free to use any identifier, but use it consistently on - both sides; also, don't use the name of a type that already exists in your - codebase. - -One potential stumbling block when using holder types is that they need to be -applied consistently. Can you guess what's broken about the following binding -code? - -.. code-block:: cpp - - class Child { }; - - class Parent { - public: - Parent() : child(std::make_shared()) { } - Child *get_child() { return child.get(); } /* Hint: ** DON'T DO THIS ** */ - private: - std::shared_ptr child; - }; - - PYBIND11_PLUGIN(example) { - py::module m("example"); - - py::class_>(m, "Child"); - - py::class_>(m, "Parent") - .def(py::init<>()) - .def("get_child", &Parent::get_child); - - return m.ptr(); - } - -The following Python code will cause undefined behavior (and likely a -segmentation fault). - -.. code-block:: python - - from example import Parent - print(Parent().get_child()) - -The problem is that ``Parent::get_child()`` returns a pointer to an instance of -``Child``, but the fact that this instance is already managed by -``std::shared_ptr<...>`` is lost when passing raw pointers. In this case, -pybind11 will create a second independent ``std::shared_ptr<...>`` that also -claims ownership of the pointer. In the end, the object will be freed **twice** -since these shared pointers have no way of knowing about each other. - -There are two ways to resolve this issue: - -1. For types that are managed by a smart pointer class, never use raw pointers - in function arguments or return values. In other words: always consistently - wrap pointers into their designated holder types (such as - ``std::shared_ptr<...>``). In this case, the signature of ``get_child()`` - should be modified as follows: - -.. code-block:: cpp - - std::shared_ptr get_child() { return child; } - -2. Adjust the definition of ``Child`` by specifying - ``std::enable_shared_from_this`` (see cppreference_ for details) as a - base class. This adds a small bit of information to ``Child`` that allows - pybind11 to realize that there is already an existing - ``std::shared_ptr<...>`` and communicate with it. In this case, the - declaration of ``Child`` should look as follows: - -.. _cppreference: http://en.cppreference.com/w/cpp/memory/enable_shared_from_this - -.. code-block:: cpp - - class Child : public std::enable_shared_from_this { }; - - -Please take a look at the :ref:`macro_notes` before using this feature. - -.. seealso:: - - The file :file:`example/example8.cpp` contains a complete example that - demonstrates how to work with custom reference-counting holder types in - more detail. - -.. _custom_constructors: - -Custom constructors -=================== - -The syntax for binding constructors was previously introduced, but it only -works when a constructor with the given parameters actually exists on the C++ -side. To extend this to more general cases, let's take a look at what actually -happens under the hood: the following statement - -.. code-block:: cpp - - py::class_(m, "Example") - .def(py::init()); - -is short hand notation for - -.. code-block:: cpp - - py::class_(m, "Example") - .def("__init__", - [](Example &instance, int arg) { - new (&instance) Example(arg); - } - ); - -In other words, :func:`init` creates an anonymous function that invokes an -in-place constructor. Memory allocation etc. is already take care of beforehand -within pybind11. - -Catching and throwing exceptions -================================ - -When C++ code invoked from Python throws an ``std::exception``, it is -automatically converted into a Python ``Exception``. pybind11 defines multiple -special exception classes that will map to different types of Python -exceptions: - -.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}| - -+--------------------------------------+------------------------------+ -| C++ exception type | Python exception type | -+======================================+==============================+ -| :class:`std::exception` | ``RuntimeError`` | -+--------------------------------------+------------------------------+ -| :class:`std::bad_alloc` | ``MemoryError`` | -+--------------------------------------+------------------------------+ -| :class:`std::domain_error` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`std::invalid_argument` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`std::length_error` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`std::out_of_range` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`std::range_error` | ``ValueError`` | -+--------------------------------------+------------------------------+ -| :class:`pybind11::stop_iteration` | ``StopIteration`` (used to | -| | implement custom iterators) | -+--------------------------------------+------------------------------+ -| :class:`pybind11::index_error` | ``IndexError`` (used to | -| | indicate out of bounds | -| | accesses in ``__getitem__``, | -| | ``__setitem__``, etc.) | -+--------------------------------------+------------------------------+ -| :class:`pybind11::value_error` | ``ValueError`` (used to | -| | indicate wrong value passed | -| | in ``container.remove(...)`` | -+--------------------------------------+------------------------------+ -| :class:`pybind11::error_already_set` | Indicates that the Python | -| | exception flag has already | -| | been initialized | -+--------------------------------------+------------------------------+ - -When a Python function invoked from C++ throws an exception, it is converted -into a C++ exception of type :class:`error_already_set` whose string payload -contains a textual summary. - -There is also a special exception :class:`cast_error` that is thrown by -:func:`handle::call` when the input arguments cannot be converted to Python -objects. - -.. _opaque: - -Treating STL data structures as opaque objects -============================================== - -pybind11 heavily relies on a template matching mechanism to convert parameters -and return values that are constructed from STL data types such as vectors, -linked lists, hash tables, etc. This even works in a recursive manner, for -instance to deal with lists of hash maps of pairs of elementary and custom -types, etc. - -However, a fundamental limitation of this approach is that internal conversions -between Python and C++ types involve a copy operation that prevents -pass-by-reference semantics. What does this mean? - -Suppose we bind the following function - -.. code-block:: cpp - - void append_1(std::vector &v) { - v.push_back(1); - } - -and call it from Python, the following happens: - -.. code-block:: pycon - - >>> v = [5, 6] - >>> append_1(v) - >>> print(v) - [5, 6] - -As you can see, when passing STL data structures by reference, modifications -are not propagated back the Python side. A similar situation arises when -exposing STL data structures using the ``def_readwrite`` or ``def_readonly`` -functions: - -.. code-block:: cpp - - /* ... definition ... */ - - class MyClass { - std::vector contents; - }; - - /* ... binding code ... */ - - py::class_(m, "MyClass") - .def(py::init<>) - .def_readwrite("contents", &MyClass::contents); - -In this case, properties can be read and written in their entirety. However, an -``append`` operaton involving such a list type has no effect: - -.. code-block:: pycon - - >>> m = MyClass() - >>> m.contents = [5, 6] - >>> print(m.contents) - [5, 6] - >>> m.contents.append(7) - >>> print(m.contents) - [5, 6] - -To deal with both of the above situations, pybind11 provides a macro named -``PYBIND11_MAKE_OPAQUE(T)`` that disables the template-based conversion -machinery of types, thus rendering them *opaque*. The contents of opaque -objects are never inspected or extracted, hence they can be passed by -reference. For instance, to turn ``std::vector`` into an opaque type, add -the declaration - -.. code-block:: cpp - - PYBIND11_MAKE_OPAQUE(std::vector); - -before any binding code (e.g. invocations to ``class_::def()``, etc.). This -macro must be specified at the top level, since instantiates a partial template -overload. If your binding code consists of multiple compilation units, it must -be present in every file preceding any usage of ``std::vector``. Opaque -types must also have a corresponding ``class_`` declaration to associate them -with a name in Python, and to define a set of available operations: - -.. code-block:: cpp - - py::class_>(m, "IntVector") - .def(py::init<>()) - .def("clear", &std::vector::clear) - .def("pop_back", &std::vector::pop_back) - .def("__len__", [](const std::vector &v) { return v.size(); }) - .def("__iter__", [](std::vector &v) { - return py::make_iterator(v.begin(), v.end()); - }, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */ - // .... - -Please take a look at the :ref:`macro_notes` before using this feature. - -.. seealso:: - - The file :file:`example/example14.cpp` contains a complete example that - demonstrates how to create and expose opaque types using pybind11 in more - detail. - -.. _eigen: - -Transparent conversion of dense and sparse Eigen data types -=========================================================== - -Eigen [#f1]_ is C++ header-based library for dense and sparse linear algebra. Due to -its popularity and widespread adoption, pybind11 provides transparent -conversion support between Eigen and Scientific Python linear algebra data types. - -Specifically, when including the optional header file :file:`pybind11/eigen.h`, -pybind11 will automatically and transparently convert - -1. Static and dynamic Eigen dense vectors and matrices to instances of - ``numpy.ndarray`` (and vice versa). - -1. Eigen sparse vectors and matrices to instances of - ``scipy.sparse.csr_matrix``/``scipy.sparse.csc_matrix`` (and vice versa). - -This makes it possible to bind most kinds of functions that rely on these types. -One major caveat are functions that take Eigen matrices *by reference* and modify -them somehow, in which case the information won't be propagated to the caller. - -.. code-block:: cpp - - /* The Python bindings of this function won't replicate - the intended effect of modifying the function argument */ - void scale_by_2(Eigen::Vector3f &v) { - v *= 2; - } - -To see why this is, refer to the section on :ref:`opaque` (although that -section specifically covers STL data types, the underlying issue is the same). -The next two sections discuss an efficient alternative for exposing the -underlying native Eigen types as opaque objects in a way that still integrates -with NumPy and SciPy. - -.. [#f1] http://eigen.tuxfamily.org - -.. seealso:: - - The file :file:`example/eigen.cpp` contains a complete example that - shows how to pass Eigen sparse and dense data types in more detail. - -Buffer protocol -=============== - -Python supports an extremely general and convenient approach for exchanging -data between plugin libraries. Types can expose a buffer view [#f2]_, which -provides fast direct access to the raw internal data representation. Suppose we -want to bind the following simplistic Matrix class: - -.. code-block:: cpp - - class Matrix { - public: - Matrix(size_t rows, size_t cols) : m_rows(rows), m_cols(cols) { - m_data = new float[rows*cols]; - } - float *data() { return m_data; } - size_t rows() const { return m_rows; } - size_t cols() const { return m_cols; } - private: - size_t m_rows, m_cols; - float *m_data; - }; - -The following binding code exposes the ``Matrix`` contents as a buffer object, -making it possible to cast Matrices into NumPy arrays. It is even possible to -completely avoid copy operations with Python expressions like -``np.array(matrix_instance, copy = False)``. - -.. code-block:: cpp - - py::class_(m, "Matrix") - .def_buffer([](Matrix &m) -> py::buffer_info { - return py::buffer_info( - m.data(), /* Pointer to buffer */ - sizeof(float), /* Size of one scalar */ - py::format_descriptor::value, /* Python struct-style format descriptor */ - 2, /* Number of dimensions */ - { m.rows(), m.cols() }, /* Buffer dimensions */ - { sizeof(float) * m.rows(), /* Strides (in bytes) for each index */ - sizeof(float) } - ); - }); - -The snippet above binds a lambda function, which can create ``py::buffer_info`` -description records on demand describing a given matrix. The contents of -``py::buffer_info`` mirror the Python buffer protocol specification. - -.. code-block:: cpp - - struct buffer_info { - void *ptr; - size_t itemsize; - std::string format; - int ndim; - std::vector shape; - std::vector strides; - }; - -To create a C++ function that can take a Python buffer object as an argument, -simply use the type ``py::buffer`` as one of its arguments. Buffers can exist -in a great variety of configurations, hence some safety checks are usually -necessary in the function body. Below, you can see an basic example on how to -define a custom constructor for the Eigen double precision matrix -(``Eigen::MatrixXd``) type, which supports initialization from compatible -buffer objects (e.g. a NumPy matrix). - -.. code-block:: cpp - - /* Bind MatrixXd (or some other Eigen type) to Python */ - typedef Eigen::MatrixXd Matrix; - - typedef Matrix::Scalar Scalar; - constexpr bool rowMajor = Matrix::Flags & Eigen::RowMajorBit; - - py::class_(m, "Matrix") - .def("__init__", [](Matrix &m, py::buffer b) { - typedef Eigen::Stride Strides; - - /* Request a buffer descriptor from Python */ - py::buffer_info info = b.request(); - - /* Some sanity checks ... */ - if (info.format != py::format_descriptor::value) - throw std::runtime_error("Incompatible format: expected a double array!"); - - if (info.ndim != 2) - throw std::runtime_error("Incompatible buffer dimension!"); - - auto strides = Strides( - info.strides[rowMajor ? 0 : 1] / sizeof(Scalar), - info.strides[rowMajor ? 1 : 0] / sizeof(Scalar)); - - auto map = Eigen::Map( - static_cat(info.ptr), info.shape[0], info.shape[1], strides); - - new (&m) Matrix(map); - }); - -For reference, the ``def_buffer()`` call for this Eigen data type should look -as follows: - -.. code-block:: cpp - - .def_buffer([](Matrix &m) -> py::buffer_info { - return py::buffer_info( - m.data(), /* Pointer to buffer */ - sizeof(Scalar), /* Size of one scalar */ - /* Python struct-style format descriptor */ - py::format_descriptor::value, - /* Number of dimensions */ - 2, - /* Buffer dimensions */ - { (size_t) m.rows(), - (size_t) m.cols() }, - /* Strides (in bytes) for each index */ - { sizeof(Scalar) * (rowMajor ? m.cols() : 1), - sizeof(Scalar) * (rowMajor ? 1 : m.rows()) } - ); - }) - -For a much easier approach of binding Eigen types (although with some -limitations), refer to the section on :ref:`eigen`. - -.. seealso:: - - The file :file:`example/example7.cpp` contains a complete example that - demonstrates using the buffer protocol with pybind11 in more detail. - -.. [#f2] http://docs.python.org/3/c-api/buffer.html - -NumPy support -============= - -By exchanging ``py::buffer`` with ``py::array`` in the above snippet, we can -restrict the function so that it only accepts NumPy arrays (rather than any -type of Python object satisfying the buffer protocol). - -In many situations, we want to define a function which only accepts a NumPy -array of a certain data type. This is possible via the ``py::array_t`` -template. For instance, the following function requires the argument to be a -NumPy array containing double precision values. - -.. code-block:: cpp - - void f(py::array_t array); - -When it is invoked with a different type (e.g. an integer or a list of -integers), the binding code will attempt to cast the input into a NumPy array -of the requested type. Note that this feature requires the -:file:``pybind11/numpy.h`` header to be included. - -Data in NumPy arrays is not guaranteed to packed in a dense manner; -furthermore, entries can be separated by arbitrary column and row strides. -Sometimes, it can be useful to require a function to only accept dense arrays -using either the C (row-major) or Fortran (column-major) ordering. This can be -accomplished via a second template argument with values ``py::array::c_style`` -or ``py::array::f_style``. - -.. code-block:: cpp - - void f(py::array_t array); - -The ``py::array::forcecast`` argument is the default value of the second -template paramenter, and it ensures that non-conforming arguments are converted -into an array satisfying the specified requirements instead of trying the next -function overload. - -Vectorizing functions -===================== - -Suppose we want to bind a function with the following signature to Python so -that it can process arbitrary NumPy array arguments (vectors, matrices, general -N-D arrays) in addition to its normal arguments: - -.. code-block:: cpp - - double my_func(int x, float y, double z); - -After including the ``pybind11/numpy.h`` header, this is extremely simple: - -.. code-block:: cpp - - m.def("vectorized_func", py::vectorize(my_func)); - -Invoking the function like below causes 4 calls to be made to ``my_func`` with -each of the array elements. The significant advantage of this compared to -solutions like ``numpy.vectorize()`` is that the loop over the elements runs -entirely on the C++ side and can be crunched down into a tight, optimized loop -by the compiler. The result is returned as a NumPy array of type -``numpy.dtype.float64``. - -.. code-block:: pycon - - >>> x = np.array([[1, 3],[5, 7]]) - >>> y = np.array([[2, 4],[6, 8]]) - >>> z = 3 - >>> result = vectorized_func(x, y, z) - -The scalar argument ``z`` is transparently replicated 4 times. The input -arrays ``x`` and ``y`` are automatically converted into the right types (they -are of type ``numpy.dtype.int64`` but need to be ``numpy.dtype.int32`` and -``numpy.dtype.float32``, respectively) - -Sometimes we might want to explicitly exclude an argument from the vectorization -because it makes little sense to wrap it in a NumPy array. For instance, -suppose the function signature was - -.. code-block:: cpp - - double my_func(int x, float y, my_custom_type *z); - -This can be done with a stateful Lambda closure: - -.. code-block:: cpp - - // Vectorize a lambda function with a capture object (e.g. to exclude some arguments from the vectorization) - m.def("vectorized_func", - [](py::array_t x, py::array_t y, my_custom_type *z) { - auto stateful_closure = [z](int x, float y) { return my_func(x, y, z); }; - return py::vectorize(stateful_closure)(x, y); - } - ); - -In cases where the computation is too complicated to be reduced to -``vectorize``, it will be necessary to create and access the buffer contents -manually. The following snippet contains a complete example that shows how this -works (the code is somewhat contrived, since it could have been done more -simply using ``vectorize``). - -.. code-block:: cpp - - #include - #include - - namespace py = pybind11; - - py::array_t add_arrays(py::array_t input1, py::array_t input2) { - auto buf1 = input1.request(), buf2 = input2.request(); - - if (buf1.ndim != 1 || buf2.ndim != 1) - throw std::runtime_error("Number of dimensions must be one"); - - if (buf1.shape[0] != buf2.shape[0]) - throw std::runtime_error("Input shapes must match"); - - auto result = py::array(py::buffer_info( - nullptr, /* Pointer to data (nullptr -> ask NumPy to allocate!) */ - sizeof(double), /* Size of one item */ - py::format_descriptor::value(), /* Buffer format */ - buf1.ndim, /* How many dimensions? */ - { buf1.shape[0] }, /* Number of elements for each dimension */ - { sizeof(double) } /* Strides for each dimension */ - )); - - auto buf3 = result.request(); - - double *ptr1 = (double *) buf1.ptr, - *ptr2 = (double *) buf2.ptr, - *ptr3 = (double *) buf3.ptr; - - for (size_t idx = 0; idx < buf1.shape[0]; idx++) - ptr3[idx] = ptr1[idx] + ptr2[idx]; - - return result; - } - - PYBIND11_PLUGIN(test) { - py::module m("test"); - m.def("add_arrays", &add_arrays, "Add two NumPy arrays"); - return m.ptr(); - } - -.. seealso:: - - The file :file:`example/example10.cpp` contains a complete example that - demonstrates using :func:`vectorize` in more detail. - -Functions taking Python objects as arguments -============================================ - -pybind11 exposes all major Python types using thin C++ wrapper classes. These -wrapper classes can also be used as parameters of functions in bindings, which -makes it possible to directly work with native Python types on the C++ side. -For instance, the following statement iterates over a Python ``dict``: - -.. code-block:: cpp - - void print_dict(py::dict dict) { - /* Easily interact with Python types */ - for (auto item : dict) - std::cout << "key=" << item.first << ", " - << "value=" << item.second << std::endl; - } - -Available types include :class:`handle`, :class:`object`, :class:`bool_`, -:class:`int_`, :class:`float_`, :class:`str`, :class:`bytes`, :class:`tuple`, -:class:`list`, :class:`dict`, :class:`slice`, :class:`none`, :class:`capsule`, -:class:`iterable`, :class:`iterator`, :class:`function`, :class:`buffer`, -:class:`array`, and :class:`array_t`. - -In this kind of mixed code, it is often necessary to convert arbitrary C++ -types to Python, which can be done using :func:`cast`: - -.. code-block:: cpp - - MyClass *cls = ..; - py::object obj = py::cast(cls); - -The reverse direction uses the following syntax: - -.. code-block:: cpp - - py::object obj = ...; - MyClass *cls = obj.cast(); - -When conversion fails, both directions throw the exception :class:`cast_error`. -It is also possible to call python functions via ``operator()``. - -.. code-block:: cpp - - py::function f = <...>; - py::object result_py = f(1234, "hello", some_instance); - MyClass &result = result_py.cast(); - -The special ``f(*args)`` and ``f(*args, **kwargs)`` syntax is also supported to -supply arbitrary argument and keyword lists, although these cannot be mixed -with other parameters. - -.. code-block:: cpp - - py::function f = <...>; - py::tuple args = py::make_tuple(1234); - py::dict kwargs; - kwargs["y"] = py::cast(5678); - py::object result = f(*args, **kwargs); - -.. seealso:: - - The file :file:`example/example2.cpp` contains a complete example that - demonstrates passing native Python types in more detail. The file - :file:`example/example11.cpp` discusses usage of ``args`` and ``kwargs``. - -Default arguments revisited -=========================== - -The section on :ref:`default_args` previously discussed basic usage of default -arguments using pybind11. One noteworthy aspect of their implementation is that -default arguments are converted to Python objects right at declaration time. -Consider the following example: - -.. code-block:: cpp - - py::class_("MyClass") - .def("myFunction", py::arg("arg") = SomeType(123)); - -In this case, pybind11 must already be set up to deal with values of the type -``SomeType`` (via a prior instantiation of ``py::class_``), or an -exception will be thrown. - -Another aspect worth highlighting is that the "preview" of the default argument -in the function signature is generated using the object's ``__repr__`` method. -If not available, the signature may not be very helpful, e.g.: - -.. code-block:: pycon - - FUNCTIONS - ... - | myFunction(...) - | Signature : (MyClass, arg : SomeType = ) -> NoneType - ... - -The first way of addressing this is by defining ``SomeType.__repr__``. -Alternatively, it is possible to specify the human-readable preview of the -default argument manually using the ``arg_t`` notation: - -.. code-block:: cpp - - py::class_("MyClass") - .def("myFunction", py::arg_t("arg", SomeType(123), "SomeType(123)")); - -Sometimes it may be necessary to pass a null pointer value as a default -argument. In this case, remember to cast it to the underlying type in question, -like so: - -.. code-block:: cpp - - py::class_("MyClass") - .def("myFunction", py::arg("arg") = (SomeType *) nullptr); - -Binding functions that accept arbitrary numbers of arguments and keywords arguments -=================================================================================== - -Python provides a useful mechanism to define functions that accept arbitrary -numbers of arguments and keyword arguments: - -.. code-block:: cpp - - def generic(*args, **kwargs): - # .. do something with args and kwargs - -Such functions can also be created using pybind11: - -.. code-block:: cpp - - void generic(py::args args, py::kwargs kwargs) { - /// .. do something with args - if (kwargs) - /// .. do something with kwargs - } - - /// Binding code - m.def("generic", &generic); - -(See ``example/example11.cpp``). The class ``py::args`` derives from -``py::list`` and ``py::kwargs`` derives from ``py::dict`` Note that the -``kwargs`` argument is invalid if no keyword arguments were actually provided. -Please refer to the other examples for details on how to iterate over these, -and on how to cast their entries into C++ objects. - -Partitioning code over multiple extension modules -================================================= - -It's straightforward to split binding code over multiple extension modules, -while referencing types that are declared elsewhere. Everything "just" works -without any special precautions. One exception to this rule occurs when -extending a type declared in another extension module. Recall the basic example -from Section :ref:`inheritance`. - -.. code-block:: cpp - - py::class_ pet(m, "Pet"); - pet.def(py::init()) - .def_readwrite("name", &Pet::name); - - py::class_(m, "Dog", pet /* <- specify parent */) - .def(py::init()) - .def("bark", &Dog::bark); - -Suppose now that ``Pet`` bindings are defined in a module named ``basic``, -whereas the ``Dog`` bindings are defined somewhere else. The challenge is of -course that the variable ``pet`` is not available anymore though it is needed -to indicate the inheritance relationship to the constructor of ``class_``. -However, it can be acquired as follows: - -.. code-block:: cpp - - py::object pet = (py::object) py::module::import("basic").attr("Pet"); - - py::class_(m, "Dog", pet) - .def(py::init()) - .def("bark", &Dog::bark); - -Alternatively, we can rely on the ``base`` tag, which performs an automated -lookup of the corresponding Python type. However, this also requires invoking -the ``import`` function once to ensure that the pybind11 binding code of the -module ``basic`` has been executed. - -.. code-block:: cpp - - py::module::import("basic"); - - py::class_(m, "Dog", py::base()) - .def(py::init()) - .def("bark", &Dog::bark); - -Naturally, both methods will fail when there are cyclic dependencies. - -Note that compiling code which has its default symbol visibility set to -*hidden* (e.g. via the command line flag ``-fvisibility=hidden`` on GCC/Clang) can interfere with the -ability to access types defined in another extension module. Workarounds -include changing the global symbol visibility (not recommended, because it will -lead unnecessarily large binaries) or manually exporting types that are -accessed by multiple extension modules: - -.. code-block:: cpp - - #ifdef _WIN32 - # define EXPORT_TYPE __declspec(dllexport) - #else - # define EXPORT_TYPE __attribute__ ((visibility("default"))) - #endif - - class EXPORT_TYPE Dog : public Animal { - ... - }; - - -Pickling support -================ - -Python's ``pickle`` module provides a powerful facility to serialize and -de-serialize a Python object graph into a binary data stream. To pickle and -unpickle C++ classes using pybind11, two additional functions must be provided. -Suppose the class in question has the following signature: - -.. code-block:: cpp - - class Pickleable { - public: - Pickleable(const std::string &value) : m_value(value) { } - const std::string &value() const { return m_value; } - - void setExtra(int extra) { m_extra = extra; } - int extra() const { return m_extra; } - private: - std::string m_value; - int m_extra = 0; - }; - -The binding code including the requisite ``__setstate__`` and ``__getstate__`` methods [#f3]_ -looks as follows: - -.. code-block:: cpp - - py::class_(m, "Pickleable") - .def(py::init()) - .def("value", &Pickleable::value) - .def("extra", &Pickleable::extra) - .def("setExtra", &Pickleable::setExtra) - .def("__getstate__", [](const Pickleable &p) { - /* Return a tuple that fully encodes the state of the object */ - return py::make_tuple(p.value(), p.extra()); - }) - .def("__setstate__", [](Pickleable &p, py::tuple t) { - if (t.size() != 2) - throw std::runtime_error("Invalid state!"); - - /* Invoke the in-place constructor. Note that this is needed even - when the object just has a trivial default constructor */ - new (&p) Pickleable(t[0].cast()); - - /* Assign any additional state */ - p.setExtra(t[1].cast()); - }); - -An instance can now be pickled as follows: - -.. code-block:: python - - try: - import cPickle as pickle # Use cPickle on Python 2.7 - except ImportError: - import pickle - - p = Pickleable("test_value") - p.setExtra(15) - data = pickle.dumps(p, 2) - -Note that only the cPickle module is supported on Python 2.7. The second -argument to ``dumps`` is also crucial: it selects the pickle protocol version -2, since the older version 1 is not supported. Newer versions are also fine—for -instance, specify ``-1`` to always use the latest available version. Beware: -failure to follow these instructions will cause important pybind11 memory -allocation routines to be skipped during unpickling, which will likely lead to -memory corruption and/or segmentation faults. - -.. seealso:: - - The file :file:`example/example15.cpp` contains a complete example that - demonstrates how to pickle and unpickle types using pybind11 in more detail. - -.. [#f3] http://docs.python.org/3/library/pickle.html#pickling-class-instances - -Generating documentation using Sphinx -===================================== - -Sphinx [#f4]_ has the ability to inspect the signatures and documentation -strings in pybind11-based extension modules to automatically generate beautiful -documentation in a variety formats. The python_example repository [#f5]_ contains a -simple example repository which uses this approach. - -There are two potential gotchas when using this approach: first, make sure that -the resulting strings do not contain any :kbd:`TAB` characters, which break the -docstring parsing routines. You may want to use C++11 raw string literals, -which are convenient for multi-line comments. Conveniently, any excess -indentation will be automatically be removed by Sphinx. However, for this to -work, it is important that all lines are indented consistently, i.e.: - -.. code-block:: cpp - - // ok - m.def("foo", &foo, R"mydelimiter( - The foo function - - Parameters - ---------- - )mydelimiter"); - - // *not ok* - m.def("foo", &foo, R"mydelimiter(The foo function - - Parameters - ---------- - )mydelimiter"); - -.. [#f4] http://www.sphinx-doc.org -.. [#f5] http://github.com/pybind/python_example diff --git a/stormpy/resources/pybind11/docs/basics.rst b/stormpy/resources/pybind11/docs/basics.rst deleted file mode 100644 index 1f40f198d..000000000 --- a/stormpy/resources/pybind11/docs/basics.rst +++ /dev/null @@ -1,309 +0,0 @@ -.. _basics: - -First steps -########### - -This sections demonstrates the basic features of pybind11. Before getting -started, make sure that development environment is set up to compile the -included set of examples, which also double as test cases. - - -Compiling the test cases -======================== - -Linux/MacOS ------------ - -On Linux you'll need to install the **python-dev** or **python3-dev** packages as -well as **cmake**. On Mac OS, the included python version works out of the box, -but **cmake** must still be installed. - -After installing the prerequisites, run - -.. code-block:: bash - - cmake . - make -j 4 - -followed by - -.. code-block:: bash - - make test - -Windows -------- - -On Windows, use the `CMake GUI`_ to create a Visual Studio project. Note that -only the 2015 release and newer versions are supported since pybind11 relies on -various C++11 language features that break older versions of Visual Studio. -After running CMake, open the created :file:`pybind11.sln` file and perform a -release build, which will will produce a file named -:file:`Release\\example.pyd`. Copy this file to the :file:`example` directory -and run :file:`example\\run_test.py` using the targeted Python version. - -.. _`CMake GUI`: https://cmake.org/runningcmake - -.. Note:: - - When all tests fail, make sure that - - 1. The Python binary and the testcases are compiled for the same processor - type and bitness (i.e. either **i386** or **x86_64**) - - 2. The Python binary used to run :file:`example\\run_test.py` matches the - Python version specified in the CMake GUI. This is controlled via - the ``PYTHON_EXECUTABLE`` ``PYTHON_INCLUDE_DIR``, and - ``PYTHON_LIBRARY`` variables. - -.. seealso:: - - Advanced users who are already familiar with Boost.Python may want to skip - the tutorial and look at the test cases in the :file:`example` directory, - which exercise all features of pybind11. - -Creating bindings for a simple function -======================================= - -Let's start by creating Python bindings for an extremely simple function, which -adds two numbers and returns their result: - -.. code-block:: cpp - - int add(int i, int j) { - return i + j; - } - -For simplicity [#f1]_, we'll put both this function and the binding code into -a file named :file:`example.cpp` with the following contents: - -.. code-block:: cpp - - #include - - int add(int i, int j) { - return i + j; - } - - namespace py = pybind11; - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - - m.def("add", &add, "A function which adds two numbers"); - - return m.ptr(); - } - -The :func:`PYBIND11_PLUGIN` macro creates a function that will be called when an -``import`` statement is issued from within Python. The next line creates a -module named ``example`` (with the supplied docstring). The method -:func:`module::def` generates binding code that exposes the -``add()`` function to Python. The last line returns the internal Python object -associated with ``m`` to the Python interpreter. - -.. note:: - - Notice how little code was needed to expose our function to Python: all - details regarding the function's parameters and return value were - automatically inferred using template metaprogramming. This overall - approach and the used syntax are borrowed from Boost.Python, though the - underlying implementation is very different. - -pybind11 is a header-only-library, hence it is not necessary to link against -any special libraries (other than Python itself). On Windows, use the CMake -build file discussed in section :ref:`cmake`. On Linux and Mac OS, the above -example can be compiled using the following command - -.. code-block:: bash - - $ c++ -O3 -shared -std=c++11 -I /include `python-config --cflags --ldflags` example.cpp -o example.so - -In general, it is advisable to include several additional build parameters -that can considerably reduce the size of the created binary. Refer to section -:ref:`cmake` for a detailed example of a suitable cross-platform CMake-based -build system. - -Assuming that the created file :file:`example.so` (:file:`example.pyd` on Windows) -is located in the current directory, the following interactive Python session -shows how to load and execute the example. - -.. code-block:: pycon - - $ python - Python 2.7.10 (default, Aug 22 2015, 20:33:39) - [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.1)] on darwin - Type "help", "copyright", "credits" or "license" for more information. - >>> import example - >>> example.add(1, 2) - 3L - >>> - -.. _keyword_args: - -Keyword arguments -================= - -With a simple modification code, it is possible to inform Python about the -names of the arguments ("i" and "j" in this case). - -.. code-block:: cpp - - m.def("add", &add, "A function which adds two numbers", - py::arg("i"), py::arg("j")); - -:class:`arg` is one of several special tag classes which can be used to pass -metadata into :func:`module::def`. With this modified binding code, we can now -call the function using keyword arguments, which is a more readable alternative -particularly for functions taking many parameters: - -.. code-block:: pycon - - >>> import example - >>> example.add(i=1, j=2) - 3L - -The keyword names also appear in the function signatures within the documentation. - -.. code-block:: pycon - - >>> help(example) - - .... - - FUNCTIONS - add(...) - Signature : (i: int, j: int) -> int - - A function which adds two numbers - -A shorter notation for named arguments is also available: - -.. code-block:: cpp - - // regular notation - m.def("add1", &add, py::arg("i"), py::arg("j")); - // shorthand - using namespace pybind11::literals; - m.def("add2", &add, "i"_a, "j"_a); - -The :var:`_a` suffix forms a C++11 literal which is equivalent to :class:`arg`. -Note that the literal operator must first be made visible with the directive -``using namespace pybind11::literals``. This does not bring in anything else -from the ``pybind11`` namespace except for literals. - -.. _default_args: - -Default arguments -================= - -Suppose now that the function to be bound has default arguments, e.g.: - -.. code-block:: cpp - - int add(int i = 1, int j = 2) { - return i + j; - } - -Unfortunately, pybind11 cannot automatically extract these parameters, since they -are not part of the function's type information. However, they are simple to specify -using an extension of :class:`arg`: - -.. code-block:: cpp - - m.def("add", &add, "A function which adds two numbers", - py::arg("i") = 1, py::arg("j") = 2); - -The default values also appear within the documentation. - -.. code-block:: pycon - - >>> help(example) - - .... - - FUNCTIONS - add(...) - Signature : (i: int = 1, j: int = 2) -> int - - A function which adds two numbers - -The shorthand notation is also available for default arguments: - -.. code-block:: cpp - - // regular notation - m.def("add1", &add, py::arg("i") = 1, py::arg("j") = 2); - // shorthand - m.def("add2", &add, "i"_a=1, "j"_a=2); - -.. _supported_types: - -Supported data types -==================== - -The following basic data types are supported out of the box (some may require -an additional extension header to be included). To pass other data structures -as arguments and return values, refer to the section on binding :ref:`classes`. - -+---------------------------------+--------------------------+-------------------------------+ -| Data type | Description | Header file | -+=================================+==========================+===============================+ -| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``char`` | Character literal | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::pair`` | Pair of two custom types | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::complex`` | Complex numbers | :file:`pybind11/complex.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::array`` | STL static array | :file:`pybind11/stl.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::vector`` | STL dynamic array | :file:`pybind11/stl.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::list`` | STL linked list | :file:`pybind11/stl.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::map`` | STL ordered map | :file:`pybind11/stl.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::unordered_map`` | STL unordered map | :file:`pybind11/stl.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::set`` | STL ordered set | :file:`pybind11/stl.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::unordered_set`` | STL unordered set | :file:`pybind11/stl.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``Eigen::Matrix<...>`` | Dense Eigen matrices | :file:`pybind11/eigen.h` | -+---------------------------------+--------------------------+-------------------------------+ -| ``Eigen::SparseMatrix<...>`` | Sparse Eigen matrices | :file:`pybind11/eigen.h` | -+---------------------------------+--------------------------+-------------------------------+ - - -.. [#f1] In practice, implementation and binding code will generally be located - in separate files. diff --git a/stormpy/resources/pybind11/docs/benchmark.py b/stormpy/resources/pybind11/docs/benchmark.py deleted file mode 100644 index 6f02e92ff..000000000 --- a/stormpy/resources/pybind11/docs/benchmark.py +++ /dev/null @@ -1,90 +0,0 @@ -import random -import os -import time -import datetime as dt - -nfns = 4 # Functions per class -nargs = 4 # Arguments per function - - -def generate_dummy_code_pybind11(nclasses=10): - decl = "" - bindings = "" - - for cl in range(nclasses): - decl += "class cl%03i;\n" % cl - decl += '\n' - - for cl in range(nclasses): - decl += "class cl%03i {\n" % cl - decl += "public:\n" - bindings += ' py::class_(m, "cl%03i")\n' % (cl, cl) - for fn in range(nfns): - ret = random.randint(0, nclasses - 1) - params = [random.randint(0, nclasses - 1) for i in range(nargs)] - decl += " cl%03i *fn_%03i(" % (ret, fn) - decl += ", ".join("cl%03i *" % p for p in params) - decl += ");\n" - bindings += ' .def("fn_%03i", &cl%03i::fn_%03i)\n' % \ - (fn, cl, fn) - decl += "};\n\n" - bindings += ' ;\n' - - result = "#include \n\n" - result += "namespace py = pybind11;\n\n" - result += decl + '\n' - result += "PYBIND11_PLUGIN(example) {\n" - result += " py::module m(\"example\");" - result += bindings - result += " return m.ptr();" - result += "}" - return result - - -def generate_dummy_code_boost(nclasses=10): - decl = "" - bindings = "" - - for cl in range(nclasses): - decl += "class cl%03i;\n" % cl - decl += '\n' - - for cl in range(nclasses): - decl += "class cl%03i {\n" % cl - decl += "public:\n" - bindings += ' py::class_("cl%03i")\n' % (cl, cl) - for fn in range(nfns): - ret = random.randint(0, nclasses - 1) - params = [random.randint(0, nclasses - 1) for i in range(nargs)] - decl += " cl%03i *fn_%03i(" % (ret, fn) - decl += ", ".join("cl%03i *" % p for p in params) - decl += ");\n" - bindings += ' .def("fn_%03i", &cl%03i::fn_%03i, py::return_value_policy())\n' % \ - (fn, cl, fn) - decl += "};\n\n" - bindings += ' ;\n' - - result = "#include \n\n" - result += "namespace py = boost::python;\n\n" - result += decl + '\n' - result += "BOOST_PYTHON_MODULE(example) {\n" - result += bindings - result += "}" - return result - - -for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]: - print ("{") - for i in range(0, 10): - nclasses = 2 ** i - with open("test.cpp", "w") as f: - f.write(codegen(nclasses)) - n1 = dt.datetime.now() - os.system("g++ -Os -shared -rdynamic -undefined dynamic_lookup " - "-fvisibility=hidden -std=c++14 test.cpp -I include " - "-I /System/Library/Frameworks/Python.framework/Headers -o test.so") - n2 = dt.datetime.now() - elapsed = (n2 - n1).total_seconds() - size = os.stat('test.so').st_size - print(" {%i, %f, %i}," % (nclasses * nfns, elapsed, size)) - print ("}") diff --git a/stormpy/resources/pybind11/docs/benchmark.rst b/stormpy/resources/pybind11/docs/benchmark.rst deleted file mode 100644 index 365919756..000000000 --- a/stormpy/resources/pybind11/docs/benchmark.rst +++ /dev/null @@ -1,96 +0,0 @@ -Benchmark -========= - -The following is the result of a synthetic benchmark comparing both compilation -time and module size of pybind11 against Boost.Python. - -Setup ------ - -A python script (see the ``docs/benchmark.py`` file) was used to generate a set -of files with dummy classes whose count increases for each successive benchmark -(between 1 and 2048 classes in powers of two). Each class has four methods with -a randomly generated signature with a return value and four arguments. (There -was no particular reason for this setup other than the desire to generate many -unique function signatures whose count could be controlled in a simple way.) - -Here is an example of the binding code for one class: - -.. code-block:: cpp - - ... - class cl034 { - public: - cl279 *fn_000(cl084 *, cl057 *, cl065 *, cl042 *); - cl025 *fn_001(cl098 *, cl262 *, cl414 *, cl121 *); - cl085 *fn_002(cl445 *, cl297 *, cl145 *, cl421 *); - cl470 *fn_003(cl200 *, cl323 *, cl332 *, cl492 *); - }; - ... - - PYBIND11_PLUGIN(example) { - py::module m("example"); - ... - py::class_(m, "cl034") - .def("fn_000", &cl034::fn_000) - .def("fn_001", &cl034::fn_001) - .def("fn_002", &cl034::fn_002) - .def("fn_003", &cl034::fn_003) - ... - return m.ptr(); - } - -The Boost.Python version looks almost identical except that a return value -policy had to be specified as an argument to ``def()``. For both libraries, -compilation was done with - -.. code-block:: bash - - Apple LLVM version 7.0.2 (clang-700.1.81) - -and the following compilation flags - -.. code-block:: bash - - g++ -Os -shared -rdynamic -undefined dynamic_lookup -fvisibility=hidden -std=c++14 - -Compilation time ----------------- - -The following log-log plot shows how the compilation time grows for an -increasing number of class and function declarations. pybind11 includes many -fewer headers, which initially leads to shorter compilation times, but the -performance is ultimately fairly similar (pybind11 is 19.8 seconds faster for -the largest largest file with 2048 classes and a total of 8192 methods -- a -modest **1.2x** speedup relative to Boost.Python, which required 116.35 -seconds). - -.. only:: not latex - - .. image:: pybind11_vs_boost_python1.svg - -.. only:: latex - - .. image:: pybind11_vs_boost_python1.png - -Module size ------------ - -Differences between the two libraries become much more pronounced when -considering the file size of the generated Python plugin: for the largest file, -the binary generated by Boost.Python required 16.8 MiB, which was **2.17 -times** / **9.1 megabytes** larger than the output generated by pybind11. For -very small inputs, Boost.Python has an edge in the plot below -- however, note -that it stores many definitions in an external library, whose size was not -included here, hence the comparison is slightly shifted in Boost.Python's -favor. - -.. only:: not latex - - .. image:: pybind11_vs_boost_python2.svg - -.. only:: latex - - .. image:: pybind11_vs_boost_python2.png - - diff --git a/stormpy/resources/pybind11/docs/changelog.rst b/stormpy/resources/pybind11/docs/changelog.rst deleted file mode 100644 index 6560072a6..000000000 --- a/stormpy/resources/pybind11/docs/changelog.rst +++ /dev/null @@ -1,172 +0,0 @@ -.. _changelog: - -Changelog -######### - -Starting with version 1.8, pybind11 releases use a -[semantic versioning](http://semver.org) policy. - -Breaking changes queued for v2.0.0 (Not yet released) ------------------------------------------------------ -* Redesigned virtual call mechanism and user-facing syntax (see - https://github.com/pybind/pybind11/commit/86d825f3302701d81414ddd3d38bcd09433076bc) - -* Remove ``handle.call()`` method - -1.9.0 (Not yet released) ------------------------- -* Queued changes: ``py::eval*``, map indexing suite, documentation for indexing suites. - -1.8.0 (June 14, 2016) ----------------------- -* Redesigned CMake build system which exports a convenient - ``pybind11_add_module`` function to parent projects. -* ``std::vector<>`` type bindings analogous to Boost.Python's ``indexing_suite`` -* Transparent conversion of sparse and dense Eigen matrices and vectors (``eigen.h``) -* Added an ``ExtraFlags`` template argument to the NumPy ``array_t<>`` wrapper - to disable an enforced cast that may lose precision, e.g. to create overloads - for different precisions and complex vs real-valued matrices. -* Prevent implicit conversion of floating point values to integral types in - function arguments -* Fixed incorrect default return value policy for functions returning a shared - pointer -* Don't allow registering a type via ``class_`` twice -* Don't allow casting a ``None`` value into a C++ lvalue reference -* Fixed a crash in ``enum_::operator==`` that was triggered by the ``help()`` command -* Improved detection of whether or not custom C++ types can be copy/move-constructed -* Extended ``str`` type to also work with ``bytes`` instances -* Added a ``"name"_a`` user defined string literal that is equivalent to ``py::arg("name")``. -* When specifying function arguments via ``py::arg``, the test that verifies - the number of arguments now runs at compile time. -* Added ``[[noreturn]]`` attribute to ``pybind11_fail()`` to quench some - compiler warnings -* List function arguments in exception text when the dispatch code cannot find - a matching overload -* Added ``PYBIND11_OVERLOAD_NAME`` and ``PYBIND11_OVERLOAD_PURE_NAME`` macros which - can be used to override virtual methods whose name differs in C++ and Python - (e.g. ``__call__`` and ``operator()``) -* Various minor ``iterator`` and ``make_iterator()`` improvements -* Transparently support ``__bool__`` on Python 2.x and Python 3.x -* Fixed issue with destructor of unpickled object not being called -* Minor CMake build system improvements on Windows -* New ``pybind11::args`` and ``pybind11::kwargs`` types to create functions which - take an arbitrary number of arguments and keyword arguments -* New syntax to call a Python function from C++ using ``*args`` and ``*kwargs`` -* The functions ``def_property_*`` now correctly process docstring arguments (these - formerly caused a segmentation fault) -* Many ``mkdoc.py`` improvements (enumerations, template arguments, ``DOC()`` - macro accepts more arguments) -* Cygwin support -* Documentation improvements (pickling support, ``keep_alive``, macro usage) - -1.7 (April 30, 2016) ----------------------- -* Added a new ``move`` return value policy that triggers C++11 move semantics. - The automatic return value policy falls back to this case whenever a rvalue - reference is encountered -* Significantly more general GIL state routines that are used instead of - Python's troublesome ``PyGILState_Ensure`` and ``PyGILState_Release`` API -* Redesign of opaque types that drastically simplifies their usage -* Extended ability to pass values of type ``[const] void *`` -* ``keep_alive`` fix: don't fail when there is no patient -* ``functional.h``: acquire the GIL before calling a Python function -* Added Python RAII type wrappers ``none`` and ``iterable`` -* Added ``*args`` and ``*kwargs`` pass-through parameters to - ``pybind11.get_include()`` function -* Iterator improvements and fixes -* Documentation on return value policies and opaque types improved - -1.6 (April 30, 2016) ----------------------- -* Skipped due to upload to PyPI gone wrong and inability to recover - (https://github.com/pypa/packaging-problems/issues/74) - -1.5 (April 21, 2016) ----------------------- -* For polymorphic types, use RTTI to try to return the closest type registered with pybind11 -* Pickling support for serializing and unserializing C++ instances to a byte stream in Python -* Added a convenience routine ``make_iterator()`` which turns a range indicated - by a pair of C++ iterators into a iterable Python object -* Added ``len()`` and a variadic ``make_tuple()`` function -* Addressed a rare issue that could confuse the current virtual function - dispatcher and another that could lead to crashes in multi-threaded - applications -* Added a ``get_include()`` function to the Python module that returns the path - of the directory containing the installed pybind11 header files -* Documentation improvements: import issues, symbol visibility, pickling, limitations -* Added casting support for ``std::reference_wrapper<>`` - -1.4 (April 7, 2016) --------------------------- -* Transparent type conversion for ``std::wstring`` and ``wchar_t`` -* Allow passing ``nullptr``-valued strings -* Transparent passing of ``void *`` pointers using capsules -* Transparent support for returning values wrapped in ``std::unique_ptr<>`` -* Improved docstring generation for compatibility with Sphinx -* Nicer debug error message when default parameter construction fails -* Support for "opaque" types that bypass the transparent conversion layer for STL containers -* Redesigned type casting interface to avoid ambiguities that could occasionally cause compiler errors -* Redesigned property implementation; fixes crashes due to an unfortunate default return value policy -* Anaconda package generation support - -1.3 (March 8, 2016) --------------------------- - -* Added support for the Intel C++ compiler (v15+) -* Added support for the STL unordered set/map data structures -* Added support for the STL linked list data structure -* NumPy-style broadcasting support in ``pybind11::vectorize`` -* pybind11 now displays more verbose error messages when ``arg::operator=()`` fails -* pybind11 internal data structures now live in a version-dependent namespace to avoid ABI issues -* Many, many bugfixes involving corner cases and advanced usage - -1.2 (February 7, 2016) --------------------------- - -* Optional: efficient generation of function signatures at compile time using C++14 -* Switched to a simpler and more general way of dealing with function default - arguments. Unused keyword arguments in function calls are now detected and - cause errors as expected -* New ``keep_alive`` call policy analogous to Boost.Python's ``with_custodian_and_ward`` -* New ``pybind11::base<>`` attribute to indicate a subclass relationship -* Improved interface for RAII type wrappers in ``pytypes.h`` -* Use RAII type wrappers consistently within pybind11 itself. This - fixes various potential refcount leaks when exceptions occur -* Added new ``bytes`` RAII type wrapper (maps to ``string`` in Python 2.7) -* Made handle and related RAII classes const correct, using them more - consistently everywhere now -* Got rid of the ugly ``__pybind11__`` attributes on the Python side---they are - now stored in a C++ hash table that is not visible in Python -* Fixed refcount leaks involving NumPy arrays and bound functions -* Vastly improved handling of shared/smart pointers -* Removed an unnecessary copy operation in ``pybind11::vectorize`` -* Fixed naming clashes when both pybind11 and NumPy headers are included -* Added conversions for additional exception types -* Documentation improvements (using multiple extension modules, smart pointers, - other minor clarifications) -* unified infrastructure for parsing variadic arguments in ``class_`` and cpp_function -* Fixed license text (was: ZLIB, should have been: 3-clause BSD) -* Python 3.2 compatibility -* Fixed remaining issues when accessing types in another plugin module -* Added enum comparison and casting methods -* Improved SFINAE-based detection of whether types are copy-constructible -* Eliminated many warnings about unused variables and the use of ``offsetof()`` -* Support for ``std::array<>`` conversions - -1.1 (December 7, 2015) --------------------------- - -* Documentation improvements (GIL, wrapping functions, casting, fixed many typos) -* Generalized conversion of integer types -* Improved support for casting function objects -* Improved support for ``std::shared_ptr<>`` conversions -* Initial support for ``std::set<>`` conversions -* Fixed type resolution issue for types defined in a separate plugin module -* Cmake build system improvements -* Factored out generic functionality to non-templated code (smaller code size) -* Added a code size / compile time benchmark vs Boost.Python -* Added an appveyor CI script - -1.0 (October 15, 2015) ------------------------- -* Initial release diff --git a/stormpy/resources/pybind11/docs/classes.rst b/stormpy/resources/pybind11/docs/classes.rst deleted file mode 100644 index 5afb21edc..000000000 --- a/stormpy/resources/pybind11/docs/classes.rst +++ /dev/null @@ -1,334 +0,0 @@ -.. _classes: - -Object-oriented code -#################### - -Creating bindings for a custom type -=================================== - -Let's now look at a more complex example where we'll create bindings for a -custom C++ data structure named ``Pet``. Its definition is given below: - -.. code-block:: cpp - - struct Pet { - Pet(const std::string &name) : name(name) { } - void setName(const std::string &name_) { name = name_; } - const std::string &getName() const { return name; } - - std::string name; - }; - -The binding code for ``Pet`` looks as follows: - -.. code-block:: cpp - - #include - - namespace py = pybind11; - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind11 example plugin"); - - py::class_(m, "Pet") - .def(py::init()) - .def("setName", &Pet::setName) - .def("getName", &Pet::getName); - - return m.ptr(); - } - -:class:`class_` creates bindings for a C++ `class` or `struct`-style data -structure. :func:`init` is a convenience function that takes the types of a -constructor's parameters as template arguments and wraps the corresponding -constructor (see the :ref:`custom_constructors` section for details). An -interactive Python session demonstrating this example is shown below: - -.. code-block:: pycon - - % python - >>> import example - >>> p = example.Pet('Molly') - >>> print(p) - - >>> p.getName() - u'Molly' - >>> p.setName('Charly') - >>> p.getName() - u'Charly' - -.. seealso:: - - Static member functions can be bound in the same way using - :func:`class_::def_static`. - -Keyword and default arguments -============================= -It is possible to specify keyword and default arguments using the syntax -discussed in the previous chapter. Refer to the sections :ref:`keyword_args` -and :ref:`default_args` for details. - -Binding lambda functions -======================== - -Note how ``print(p)`` produced a rather useless summary of our data structure in the example above: - -.. code-block:: pycon - - >>> print(p) - - -To address this, we could bind an utility function that returns a human-readable -summary to the special method slot named ``__repr__``. Unfortunately, there is no -suitable functionality in the ``Pet`` data structure, and it would be nice if -we did not have to change it. This can easily be accomplished by binding a -Lambda function instead: - -.. code-block:: cpp - - py::class_(m, "Pet") - .def(py::init()) - .def("setName", &Pet::setName) - .def("getName", &Pet::getName) - .def("__repr__", - [](const Pet &a) { - return ""; - } - ); - -Both stateless [#f1]_ and stateful lambda closures are supported by pybind11. -With the above change, the same Python code now produces the following output: - -.. code-block:: pycon - - >>> print(p) - - -.. _properties: - -Instance and static fields -========================== - -We can also directly expose the ``name`` field using the -:func:`class_::def_readwrite` method. A similar :func:`class_::def_readonly` -method also exists for ``const`` fields. - -.. code-block:: cpp - - py::class_(m, "Pet") - .def(py::init()) - .def_readwrite("name", &Pet::name) - // ... remainder ... - -This makes it possible to write - -.. code-block:: pycon - - >>> p = example.Pet('Molly') - >>> p.name - u'Molly' - >>> p.name = 'Charly' - >>> p.name - u'Charly' - -Now suppose that ``Pet::name`` was a private internal variable -that can only be accessed via setters and getters. - -.. code-block:: cpp - - class Pet { - public: - Pet(const std::string &name) : name(name) { } - void setName(const std::string &name_) { name = name_; } - const std::string &getName() const { return name; } - private: - std::string name; - }; - -In this case, the method :func:`class_::def_property` -(:func:`class_::def_property_readonly` for read-only data) can be used to -provide a field-like interface within Python that will transparently call -the setter and getter functions: - -.. code-block:: cpp - - py::class_(m, "Pet") - .def(py::init()) - .def_property("name", &Pet::getName, &Pet::setName) - // ... remainder ... - -.. seealso:: - - Similar functions :func:`class_::def_readwrite_static`, - :func:`class_::def_readonly_static` :func:`class_::def_property_static`, - and :func:`class_::def_property_readonly_static` are provided for binding - static variables and properties. Please also see the section on - :ref:`static_properties` in the advanced part of the documentation. - -.. _inheritance: - -Inheritance -=========== - -Suppose now that the example consists of two data structures with an -inheritance relationship: - -.. code-block:: cpp - - struct Pet { - Pet(const std::string &name) : name(name) { } - std::string name; - }; - - struct Dog : Pet { - Dog(const std::string &name) : Pet(name) { } - std::string bark() const { return "woof!"; } - }; - -There are two different ways of indicating a hierarchical relationship to -pybind11: the first is by specifying the C++ base class explicitly during -construction using the ``base`` attribute: - -.. code-block:: cpp - - py::class_(m, "Pet") - .def(py::init()) - .def_readwrite("name", &Pet::name); - - py::class_(m, "Dog", py::base() /* <- specify C++ parent type */) - .def(py::init()) - .def("bark", &Dog::bark); - -Alternatively, we can also assign a name to the previously bound ``Pet`` -:class:`class_` object and reference it when binding the ``Dog`` class: - -.. code-block:: cpp - - py::class_ pet(m, "Pet"); - pet.def(py::init()) - .def_readwrite("name", &Pet::name); - - py::class_(m, "Dog", pet /* <- specify Python parent type */) - .def(py::init()) - .def("bark", &Dog::bark); - -Functionality-wise, both approaches are completely equivalent. Afterwards, -instances will expose fields and methods of both types: - -.. code-block:: pycon - - >>> p = example.Dog('Molly') - >>> p.name - u'Molly' - >>> p.bark() - u'woof!' - -Overloaded methods -================== - -Sometimes there are several overloaded C++ methods with the same name taking -different kinds of input arguments: - -.. code-block:: cpp - - struct Pet { - Pet(const std::string &name, int age) : name(name), age(age) { } - - void set(int age) { age = age; } - void set(const std::string &name) { name = name; } - - std::string name; - int age; - }; - -Attempting to bind ``Pet::set`` will cause an error since the compiler does not -know which method the user intended to select. We can disambiguate by casting -them to function pointers. Binding multiple functions to the same Python name -automatically creates a chain of function overloads that will be tried in -sequence. - -.. code-block:: cpp - - py::class_(m, "Pet") - .def(py::init()) - .def("set", (void (Pet::*)(int)) &Pet::set, "Set the pet's age") - .def("set", (void (Pet::*)(const std::string &)) &Pet::set, "Set the pet's name"); - -The overload signatures are also visible in the method's docstring: - -.. code-block:: pycon - - >>> help(example.Pet) - - class Pet(__builtin__.object) - | Methods defined here: - | - | __init__(...) - | Signature : (Pet, str, int) -> NoneType - | - | set(...) - | 1. Signature : (Pet, int) -> NoneType - | - | Set the pet's age - | - | 2. Signature : (Pet, str) -> NoneType - | - | Set the pet's name - -.. note:: - - To define multiple overloaded constructors, simply declare one after the - other using the ``.def(py::init<...>())`` syntax. The existing machinery - for specifying keyword and default arguments also works. - -Enumerations and internal types -=============================== - -Let's now suppose that the example class contains an internal enumeration type, -e.g.: - -.. code-block:: cpp - - struct Pet { - enum Kind { - Dog = 0, - Cat - }; - - Pet(const std::string &name, Kind type) : name(name), type(type) { } - - std::string name; - Kind type; - }; - -The binding code for this example looks as follows: - -.. code-block:: cpp - - py::class_ pet(m, "Pet"); - - pet.def(py::init()) - .def_readwrite("name", &Pet::name) - .def_readwrite("type", &Pet::type); - - py::enum_(pet, "Kind") - .value("Dog", Pet::Kind::Dog) - .value("Cat", Pet::Kind::Cat) - .export_values(); - -To ensure that the ``Kind`` type is created within the scope of ``Pet``, the -``pet`` :class:`class_` instance must be supplied to the :class:`enum_`. -constructor. The :func:`enum_::export_values` function exports the enum entries -into the parent scope, which should be skipped for newer C++11-style strongly -typed enums. - -.. code-block:: pycon - - >>> p = Pet('Lucy', Pet.Cat) - >>> p.type - Kind.Cat - >>> int(p.type) - 1L - - -.. [#f1] Stateless closures are those with an empty pair of brackets ``[]`` as the capture object. diff --git a/stormpy/resources/pybind11/docs/compiling.rst b/stormpy/resources/pybind11/docs/compiling.rst deleted file mode 100644 index 9ec3bc273..000000000 --- a/stormpy/resources/pybind11/docs/compiling.rst +++ /dev/null @@ -1,53 +0,0 @@ -Build systems -############# - -Building with setuptools -======================== - -For projects on PyPI, building with setuptools is the way to go. Sylvain Corlay -has kindly provided an example project which shows how to set up everything, -including automatic generation of documentation using Sphinx. Please refer to -the [python_example]_ repository. - -.. [python_example] https://github.com/pybind/python_example - -Building with cppimport -======================== - - cppimport is a small Python import hook that determines whether there is a C++ - source file whose name matches the requested module. If there is, the file is - compiled as a Python extension using pybind11 and placed in the same folder as - the C++ source file. Python is then able to find the module and load it. - -.. [cppimport] https://github.com/tbenthompson/cppimport - -.. _cmake: - -Building with CMake -=================== - -For C++ codebases that have an existing CMake-based build system, a Python -extension module can be created with just a few lines of code: - -.. code-block:: cmake - - cmake_minimum_required(VERSION 2.8.12) - project(example) - - add_subdirectory(pybind11) - pybind11_add_module(example example.cpp) - -This assumes that the pybind11 repository is located in a subdirectory named -:file:`pybind11` and that the code is located in a file named :file:`example.cpp`. -The CMake command ``add_subdirectory`` will import a function with the signature -``pybind11_add_module( source1 [source2 ...])``. It will take care of all -the details needed to build a Python extension module on any platform. - -The target Python version can be selected by setting the ``PYBIND11_PYTHON_VERSION`` -variable before adding the pybind11 subdirectory. Alternatively, an exact Python -installation can be specified by setting ``PYTHON_EXECUTABLE``. - -A working sample project, including a way to invoke CMake from :file:`setup.py` for -PyPI integration, can be found in the [cmake_example]_ repository. - -.. [cmake_example] https://github.com/pybind/cmake_example diff --git a/stormpy/resources/pybind11/docs/conf.py b/stormpy/resources/pybind11/docs/conf.py deleted file mode 100644 index 4e2c4cef2..000000000 --- a/stormpy/resources/pybind11/docs/conf.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# pybind11 documentation build configuration file, created by -# sphinx-quickstart on Sun Oct 11 19:23:48 2015. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os -import shlex - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['.templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'pybind11' -copyright = '2015, Wenzel Jakob' -author = 'Wenzel Jakob' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '1.9' -# The full version, including alpha/beta/rc tags. -release = '1.9.dev0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['.build'] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -#pygments_style = 'monokai' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. - -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' - -if not on_rtd: # only import and set the theme if we're building docs locally - import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - - html_context = { - 'css_files': [ - '_static/theme_overrides.css' - ] - } -else: - html_context = { - 'css_files': [ - '//media.readthedocs.org/css/sphinx_rtd_theme.css', - '//media.readthedocs.org/css/readthedocs-doc-embed.css', - '_static/theme_overrides.css' - ] - } - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' -#html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'pybind11doc' - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -'preamble': '\DeclareUnicodeCharacter{00A0}{}', - -# Latex figure (float) alignment -#'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'pybind11.tex', 'pybind11 Documentation', - 'Wenzel Jakob', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = 'pybind11-logo.png' - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'pybind11', 'pybind11 Documentation', - [author], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'pybind11', 'pybind11 Documentation', - author, 'pybind11', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False - -primary_domain = 'cpp' -highlight_language = 'cpp' diff --git a/stormpy/resources/pybind11/docs/faq.rst b/stormpy/resources/pybind11/docs/faq.rst deleted file mode 100644 index 788b3b893..000000000 --- a/stormpy/resources/pybind11/docs/faq.rst +++ /dev/null @@ -1,208 +0,0 @@ -Frequently asked questions -########################## - -"ImportError: dynamic module does not define init function" -=========================================================== - -1. Make sure that the name specified in ``pybind::module`` and - ``PYBIND11_PLUGIN`` is consistent and identical to the filename of the - extension library. The latter should not contain any extra prefixes (e.g. - ``test.so`` instead of ``libtest.so``). - -2. If the above did not fix your issue, then you are likely using an - incompatible version of Python (for instance, the extension library was - compiled against Python 2, while the interpreter is running on top of some - version of Python 3, or vice versa) - -"Symbol not found: ``__Py_ZeroStruct`` / ``_PyInstanceMethod_Type``" -======================================================================== - -See item 2 of the first answer. - -The Python interpreter immediately crashes when importing my module -=================================================================== - -See item 2 of the first answer. - -CMake doesn't detect the right Python version -============================================= - -The CMake-based build system will try to automatically detect the installed -version of Python and link against that. When this fails, or when there are -multiple versions of Python and it finds the wrong one, delete -``CMakeCache.txt`` and then invoke CMake as follows: - -.. code-block:: bash - - cmake -DPYTHON_EXECUTABLE:FILEPATH= . - -Limitations involving reference arguments -========================================= - -In C++, it's fairly common to pass arguments using mutable references or -mutable pointers, which allows both read and write access to the value -supplied by the caller. This is sometimes done for efficiency reasons, or to -realize functions that have multiple return values. Here are two very basic -examples: - -.. code-block:: cpp - - void increment(int &i) { i++; } - void increment_ptr(int *i) { (*i)++; } - -In Python, all arguments are passed by reference, so there is no general -issue in binding such code from Python. - -However, certain basic Python types (like ``str``, ``int``, ``bool``, -``float``, etc.) are **immutable**. This means that the following attempt -to port the function to Python doesn't have the same effect on the value -provided by the caller -- in fact, it does nothing at all. - -.. code-block:: python - - def increment(i): - i += 1 # nope.. - -pybind11 is also affected by such language-level conventions, which means that -binding ``increment`` or ``increment_ptr`` will also create Python functions -that don't modify their arguments. - -Although inconvenient, one workaround is to encapsulate the immutable types in -a custom type that does allow modifications. - -An other alternative involves binding a small wrapper lambda function that -returns a tuple with all output arguments (see the remainder of the -documentation for examples on binding lambda functions). An example: - -.. code-block:: cpp - - int foo(int &i) { i++; return 123; } - -and the binding code - -.. code-block:: cpp - - m.def("foo", [](int i) { int rv = foo(i); return std::make_tuple(rv, i); }); - - -How can I reduce the build time? -================================ - -It's good practice to split binding code over multiple files, as is done in -the included file :file:`example/example.cpp`. - -.. code-block:: cpp - - void init_ex1(py::module &); - void init_ex2(py::module &); - /* ... */ - - PYBIND11_PLUGIN(example) { - py::module m("example", "pybind example plugin"); - - init_ex1(m); - init_ex2(m); - - /* ... */ - - return m.ptr(); - } - -The various ``init_ex`` functions should be contained in separate files that -can be compiled independently from another. Following this approach will - -1. reduce memory requirements per compilation unit. - -2. enable parallel builds (if desired). - -3. allow for faster incremental builds. For instance, when a single class - definiton is changed, only a subset of the binding code will generally need - to be recompiled. - -How can I create smaller binaries? -================================== - -To do its job, pybind11 extensively relies on a programming technique known as -*template metaprogramming*, which is a way of performing computation at compile -time using type information. Template metaprogamming usually instantiates code -involving significant numbers of deeply nested types that are either completely -removed or reduced to just a few instrutions during the compiler's optimization -phase. However, due to the nested nature of these types, the resulting symbol -names in the compiled extension library can be extremely long. For instance, -the included test suite contains the following symbol: - -.. only:: html - - .. code-block:: none - - _​_​Z​N​8​p​y​b​i​n​d​1​1​1​2​c​p​p​_​f​u​n​c​t​i​o​n​C​1​I​v​8​E​x​a​m​p​l​e​2​J​R​N​S​t​3​_​_​1​6​v​e​c​t​o​r​I​N​S​3​_​1​2​b​a​s​i​c​_​s​t​r​i​n​g​I​w​N​S​3​_​1​1​c​h​a​r​_​t​r​a​i​t​s​I​w​E​E​N​S​3​_​9​a​l​l​o​c​a​t​o​r​I​w​E​E​E​E​N​S​8​_​I​S​A​_​E​E​E​E​E​J​N​S​_​4​n​a​m​e​E​N​S​_​7​s​i​b​l​i​n​g​E​N​S​_​9​i​s​_​m​e​t​h​o​d​E​A​2​8​_​c​E​E​E​M​T​0​_​F​T​_​D​p​T​1​_​E​D​p​R​K​T​2​_​ - -.. only:: not html - - .. code-block:: cpp - - __ZN8pybind1112cpp_functionC1Iv8Example2JRNSt3__16vectorINS3_12basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEENS8_ISA_EEEEEJNS_4nameENS_7siblingENS_9is_methodEA28_cEEEMT0_FT_DpT1_EDpRKT2_ - -which is the mangled form of the following function type: - -.. code-block:: cpp - - pybind11::cpp_function::cpp_function, std::__1::allocator >, std::__1::allocator, std::__1::allocator > > >&, pybind11::name, pybind11::sibling, pybind11::is_method, char [28]>(void (Example2::*)(std::__1::vector, std::__1::allocator >, std::__1::allocator, std::__1::allocator > > >&), pybind11::name const&, pybind11::sibling const&, pybind11::is_method const&, char const (&) [28]) - -The memory needed to store just the mangled name of this function (196 bytes) -is larger than the actual piece of code (111 bytes) it represents! On the other -hand, it's silly to even give this function a name -- after all, it's just a -tiny cog in a bigger piece of machinery that is not exposed to the outside -world. So we'll generally only want to export symbols for those functions which -are actually called from the outside. - -This can be achieved by specifying the parameter ``-fvisibility=hidden`` to GCC -and Clang, which sets the default symbol visibility to *hidden*. It's best to -do this only for release builds, since the symbol names can be helpful in -debugging sessions. On Visual Studio, symbols are already hidden by default, so -nothing needs to be done there. Needless to say, this has a tremendous impact -on the final binary size of the resulting extension library. - -Another aspect that can require a fair bit of code are function signature -descriptions. pybind11 automatically generates human-readable function -signatures for docstrings, e.g.: - -.. code-block:: none - - | __init__(...) - | __init__(*args, **kwargs) - | Overloaded function. - | - | 1. __init__(example.Example1) -> NoneType - | - | Docstring for overload #1 goes here - | - | 2. __init__(example.Example1, int) -> NoneType - | - | Docstring for overload #2 goes here - | - | 3. __init__(example.Example1, example.Example1) -> NoneType - | - | Docstring for overload #3 goes here - - -In C++11 mode, these are generated at run time using string concatenation, -which can amount to 10-20% of the size of the resulting binary. If you can, -enable C++14 language features (using ``-std=c++14`` for GCC/Clang), in which -case signatures are efficiently pre-generated at compile time. Unfortunately, -Visual Studio's C++14 support (``constexpr``) is not good enough as of April -2016, so it always uses the more expensive run-time approach. - -Working with ancient Visual Studio 2009 builds on Windows -========================================================= - -The official Windows distributions of Python are compiled using truly -ancient versions of Visual Studio that lack good C++11 support. Some users -implicitly assume that it would be impossible to load a plugin built with -Visual Studio 2015 into a Python distribution that was compiled using Visual -Studio 2009. However, no such issue exists: it's perfectly legitimate to -interface DLLs that are built with different compilers and/or C libraries. -Common gotchas to watch out for involve not ``free()``-ing memory region -that that were ``malloc()``-ed in another shared library, using data -structures with incompatible ABIs, and so on. pybind11 is very careful not -to make these types of mistakes. diff --git a/stormpy/resources/pybind11/docs/index.rst b/stormpy/resources/pybind11/docs/index.rst deleted file mode 100644 index ab9a1fc82..000000000 --- a/stormpy/resources/pybind11/docs/index.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. only: not latex - - .. image:: pybind11-logo.png - -pybind11 --- Seamless operability between C++11 and Python -========================================================== - -.. only: not latex - - Contents: - -.. toctree:: - :maxdepth: 2 - - intro - basics - classes - advanced - compiling - benchmark - limitations - faq - reference - changelog diff --git a/stormpy/resources/pybind11/docs/intro.rst b/stormpy/resources/pybind11/docs/intro.rst deleted file mode 100644 index af35db9eb..000000000 --- a/stormpy/resources/pybind11/docs/intro.rst +++ /dev/null @@ -1,87 +0,0 @@ -.. image:: pybind11-logo.png - -About this project -================== -**pybind11** is a lightweight header-only library that exposes C++ types in Python -and vice versa, mainly to create Python bindings of existing C++ code. Its -goals and syntax are similar to the excellent `Boost.Python`_ library by David -Abrahams: to minimize boilerplate code in traditional extension modules by -inferring type information using compile-time introspection. - -.. _Boost.Python: http://www.boost.org/doc/libs/release/libs/python/doc/index.html - -The main issue with Boost.Python—and the reason for creating such a similar -project—is Boost. Boost is an enormously large and complex suite of utility -libraries that works with almost every C++ compiler in existence. This -compatibility has its cost: arcane template tricks and workarounds are -necessary to support the oldest and buggiest of compiler specimens. Now that -C++11-compatible compilers are widely available, this heavy machinery has -become an excessively large and unnecessary dependency. - -Think of this library as a tiny self-contained version of Boost.Python with -everything stripped away that isn't relevant for binding generation. Without -comments, the core header files only require ~2.5K lines of code and depend on -Python (2.7 or 3.x) and the C++ standard library. This compact implementation -was possible thanks to some of the new C++11 language features (specifically: -tuples, lambda functions and variadic templates). Since its creation, this -library has grown beyond Boost.Python in many ways, leading to dramatically -simpler binding code in many common situations. - -Core features -************* -The following core C++ features can be mapped to Python - -- Functions accepting and returning custom data structures per value, reference, or pointer -- Instance methods and static methods -- Overloaded functions -- Instance attributes and static attributes -- Exceptions -- Enumerations -- Iterators and ranges -- Callbacks -- Custom operators -- STL data structures -- Smart pointers with reference counting like ``std::shared_ptr`` -- Internal references with correct reference counting -- C++ classes with virtual (and pure virtual) methods can be extended in Python - -Goodies -******* -In addition to the core functionality, pybind11 provides some extra goodies: - -- It is possible to bind C++11 lambda functions with captured variables. The - lambda capture data is stored inside the resulting Python function object. - -- pybind11 uses C++11 move constructors and move assignment operators whenever - possible to efficiently transfer custom data types. - -- It's easy to expose the internal storage of custom data types through - Pythons' buffer protocols. This is handy e.g. for fast conversion between - C++ matrix classes like Eigen and NumPy without expensive copy operations. - -- pybind11 can automatically vectorize functions so that they are transparently - applied to all entries of one or more NumPy array arguments. - -- Python's slice-based access and assignment operations can be supported with - just a few lines of code. - -- Everything is contained in just a few header files; there is no need to link - against any additional libraries. - -- Binaries are generally smaller by a factor of 2 or more compared to - equivalent bindings generated by Boost.Python. - -- When supported by the compiler, two new C++14 features (relaxed constexpr and - return value deduction) are used to precompute function signatures at compile - time, leading to smaller binaries. - -- With little extra effort, C++ types can be pickled and unpickled similar to - regular Python objects. - -Supported compilers -******************* - -1. Clang/LLVM (any non-ancient version with C++11 support) -2. GCC (any non-ancient version with C++11 support) -3. Microsoft Visual Studio 2015 or newer -4. Intel C++ compiler v15 or newer diff --git a/stormpy/resources/pybind11/docs/limitations.rst b/stormpy/resources/pybind11/docs/limitations.rst deleted file mode 100644 index c6100d167..000000000 --- a/stormpy/resources/pybind11/docs/limitations.rst +++ /dev/null @@ -1,23 +0,0 @@ -Limitations -########### - -pybind11 strives to be a general solution to binding generation, but it also has -certain limitations: - -- pybind11 casts away ``const``-ness in function arguments and return values. - This is in line with the Python language, which has no concept of ``const`` - values. This means that some additional care is needed to avoid bugs that - would be caught by the type checker in a traditional C++ program. - -- Multiple inheritance relationships on the C++ side cannot be mapped to - Python. - -- The NumPy interface ``pybind11::array`` greatly simplifies accessing - numerical data from C++ (and vice versa), but it's not a full-blown array - class like ``Eigen::Array`` or ``boost.multi_array``. - -All of these features could be implemented but would lead to a significant -increase in complexity. I've decided to draw the line here to keep this project -simple and compact. Users who absolutely require these features are encouraged -to fork pybind11. - diff --git a/stormpy/resources/pybind11/docs/pybind11-logo.png b/stormpy/resources/pybind11/docs/pybind11-logo.png deleted file mode 100644 index 4cbad54f7..000000000 Binary files a/stormpy/resources/pybind11/docs/pybind11-logo.png and /dev/null differ diff --git a/stormpy/resources/pybind11/docs/pybind11_vs_boost_python1.png b/stormpy/resources/pybind11/docs/pybind11_vs_boost_python1.png deleted file mode 100644 index 833231f24..000000000 Binary files a/stormpy/resources/pybind11/docs/pybind11_vs_boost_python1.png and /dev/null differ diff --git a/stormpy/resources/pybind11/docs/pybind11_vs_boost_python1.svg b/stormpy/resources/pybind11/docs/pybind11_vs_boost_python1.svg deleted file mode 100644 index 5bf950e6f..000000000 --- a/stormpy/resources/pybind11/docs/pybind11_vs_boost_python1.svg +++ /dev/null @@ -1,427 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stormpy/resources/pybind11/docs/pybind11_vs_boost_python2.png b/stormpy/resources/pybind11/docs/pybind11_vs_boost_python2.png deleted file mode 100644 index 9f17272c5..000000000 Binary files a/stormpy/resources/pybind11/docs/pybind11_vs_boost_python2.png and /dev/null differ diff --git a/stormpy/resources/pybind11/docs/pybind11_vs_boost_python2.svg b/stormpy/resources/pybind11/docs/pybind11_vs_boost_python2.svg deleted file mode 100644 index 5ed6530ca..000000000 --- a/stormpy/resources/pybind11/docs/pybind11_vs_boost_python2.svg +++ /dev/null @@ -1,427 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stormpy/resources/pybind11/docs/reference.rst b/stormpy/resources/pybind11/docs/reference.rst deleted file mode 100644 index 4df4344a8..000000000 --- a/stormpy/resources/pybind11/docs/reference.rst +++ /dev/null @@ -1,246 +0,0 @@ -.. _reference: - -.. warning:: - - Please be advised that the reference documentation discussing pybind11 - internals is currently incomplete. Please refer to the previous sections - and the pybind11 header files for the nitty gritty details. - -Reference -######### - -Macros -====== - -.. function:: PYBIND11_PLUGIN(const char *name) - - This macro creates the entry point that will be invoked when the Python - interpreter imports a plugin library. Please create a - :class:`module` in the function body and return the pointer to its - underlying Python object at the end. - - .. code-block:: cpp - - PYBIND11_PLUGIN(example) { - pybind11::module m("example", "pybind11 example plugin"); - /// Set up bindings here - return m.ptr(); - } - -.. _core_types: - -Convenience classes for arbitrary Python types -============================================== - -Without reference counting --------------------------- - -.. class:: handle - - The :class:`handle` class is a thin wrapper around an arbitrary Python - object (i.e. a ``PyObject *`` in Python's C API). It does not perform any - automatic reference counting and merely provides a basic C++ interface to - various Python API functions. - -.. seealso:: - - The :class:`object` class inherits from :class:`handle` and adds automatic - reference counting features. - -.. function:: handle::handle() - - The default constructor creates a handle with a ``nullptr``-valued pointer. - -.. function:: handle::handle(const handle&) - - Copy constructor - -.. function:: handle::handle(PyObject *) - - Creates a :class:`handle` from the given raw Python object pointer. - -.. function:: PyObject * handle::ptr() const - - Return the ``PyObject *`` underlying a :class:`handle`. - -.. function:: const handle& handle::inc_ref() const - - Manually increase the reference count of the Python object. Usually, it is - preferable to use the :class:`object` class which derives from - :class:`handle` and calls this function automatically. Returns a reference - to itself. - -.. function:: const handle& handle::dec_ref() const - - Manually decrease the reference count of the Python object. Usually, it is - preferable to use the :class:`object` class which derives from - :class:`handle` and calls this function automatically. Returns a reference - to itself. - -.. function:: void handle::ref_count() const - - Return the object's current reference count - -.. function:: handle handle::get_type() const - - Return a handle to the Python type object underlying the instance - -.. function detail::accessor handle::operator[](handle key) const - - Return an internal functor to invoke the object's sequence protocol. - Casting the returned ``detail::accessor`` instance to a :class:`handle` or - :class:`object` subclass causes a corresponding call to ``__getitem__``. - Assigning a :class:`handle` or :class:`object` subclass causes a call to - ``__setitem__``. - -.. function detail::accessor handle::operator[](const char *key) const - - See the above function (the only difference is that they key is provided as - a string literal). - -.. function detail::accessor handle::attr(handle key) const - - Return an internal functor to access the object's attributes. - Casting the returned ``detail::accessor`` instance to a :class:`handle` or - :class:`object` subclass causes a corresponding call to ``__getattr``. - Assigning a :class:`handle` or :class:`object` subclass causes a call to - ``__setattr``. - -.. function detail::accessor handle::attr(const char *key) const - - See the above function (the only difference is that they key is provided as - a string literal). - -.. function operator handle::bool() const - - Return ``true`` when the :class:`handle` wraps a valid Python object. - -.. function str handle::str() const - - Return a string representation of the object. This is analogous to - the ``str()`` function in Python. - -.. function:: template T handle::cast() const - - Attempt to cast the Python object into the given C++ type. A - :class:`cast_error` will be throw upon failure. - -.. function:: template object handle::call(Args&&... args) const - - Assuming the Python object is a function or implements the ``__call__`` - protocol, ``call()`` invokes the underlying function, passing an arbitrary - set of parameters. The result is returned as a :class:`object` and may need - to be converted back into a Python object using :func:`handle::cast`. - - When some of the arguments cannot be converted to Python objects, the - function will throw a :class:`cast_error` exception. When the Python - function call fails, a :class:`error_already_set` exception is thrown. - -With reference counting ------------------------ - -.. class:: object : public handle - - Like :class:`handle`, the object class is a thin wrapper around an - arbitrary Python object (i.e. a ``PyObject *`` in Python's C API). In - contrast to :class:`handle`, it optionally increases the object's reference - count upon construction, and it *always* decreases the reference count when - the :class:`object` instance goes out of scope and is destructed. When - using :class:`object` instances consistently, it is much easier to get - reference counting right at the first attempt. - -.. function:: object::object(const object &o) - - Copy constructor; always increases the reference count - -.. function:: object::object(const handle &h, bool borrowed) - - Creates a :class:`object` from the given :class:`handle`. The reference - count is only increased if the ``borrowed`` parameter is set to ``true``. - -.. function:: object::object(PyObject *ptr, bool borrowed) - - Creates a :class:`object` from the given raw Python object pointer. The - reference count is only increased if the ``borrowed`` parameter is set to - ``true``. - -.. function:: object::object(object &&other) - - Move constructor; steals the object from ``other`` and preserves its - reference count. - -.. function:: handle object::release() - - Resets the internal pointer to ``nullptr`` without without decreasing the - object's reference count. The function returns a raw handle to the original - Python object. - -.. function:: object::~object() - - Destructor, which automatically calls :func:`handle::dec_ref()`. - -Convenience classes for specific Python types -============================================= - - -.. class:: module : public object - -.. function:: module::module(const char *name, const char *doc = nullptr) - - Create a new top-level Python module with the given name and docstring - -.. function:: module module::def_submodule(const char *name, const char *doc = nullptr) - - Create and return a new Python submodule with the given name and docstring. - This also works recursively, i.e. - - .. code-block:: cpp - - pybind11::module m("example", "pybind11 example plugin"); - pybind11::module m2 = m.def_submodule("sub", "A submodule of 'example'"); - pybind11::module m3 = m2.def_submodule("subsub", "A submodule of 'example.sub'"); - -.. cpp:function:: template module& module::def(const char *name, Func && f, Extra && ... extra) - - Create Python binding for a new function within the module scope. ``Func`` - can be a plain C++ function, a function pointer, or a lambda function. For - details on the ``Extra&& ... extra`` argument, see section :ref:`extras`. - -.. _extras: - -Passing extra arguments to the def function -=========================================== - -.. class:: arg - -.. function:: arg::arg(const char *name) - -.. function:: template arg_t arg::operator=(const T &value) - -.. class:: template arg_t : public arg - - Represents a named argument with a default value - -.. class:: sibling - - Used to specify a handle to an existing sibling function; used internally - to implement function overloading in :func:`module::def` and - :func:`class_::def`. - -.. function:: sibling::sibling(handle handle) - -.. class doc - - This is class is internally used by pybind11. - -.. function:: doc::doc(const char *value) - - Create a new docstring with the specified value - -.. class name - - This is class is internally used by pybind11. - -.. function:: name::name(const char *value) - - Used to specify the function name diff --git a/stormpy/resources/pybind11/docs/release.rst b/stormpy/resources/pybind11/docs/release.rst deleted file mode 100644 index 43934ecf3..000000000 --- a/stormpy/resources/pybind11/docs/release.rst +++ /dev/null @@ -1,21 +0,0 @@ -To release a new version of pybind11: - -- Update the version number and push to pypi - - Update ``pybind11/_version.py`` (set release version, remove 'dev') - - Update version in ``docs/conf.py`` - - Tag release date in ``docs/changelog.rst``. - - ``git add`` and ``git commit``. - - ``git tag -a vX.Y -m 'vX.Y release'``. - - ``git push`` - - ``git push --tags``. - - ``python setup.py sdist upload``. - - ``python setup.py bdist_wheel upload``. -- Update conda-forge (https://github.com/conda-forge/pybind11-feedstock) via PR - - change version number in ``recipe/meta.yml`` - - update checksum to match the one computed by pypi -- Get back to work - - Update ``_version.py`` (add 'dev' and increment minor). - - Update version in ``docs/conf.py`` - - Update version macros in ``include/pybind11/common.h`` - - ``git add`` and ``git commit``. - ``git push`` diff --git a/stormpy/resources/pybind11/example/eigen.cpp b/stormpy/resources/pybind11/example/eigen.cpp deleted file mode 100644 index b6fa24a42..000000000 --- a/stormpy/resources/pybind11/example/eigen.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - example/eigen.cpp -- automatic conversion of Eigen types - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include - -void init_eigen(py::module &m) { - typedef Eigen::Matrix FixedMatrixR; - typedef Eigen::Matrix FixedMatrixC; - typedef Eigen::Matrix DenseMatrixR; - typedef Eigen::Matrix DenseMatrixC; - typedef Eigen::SparseMatrix SparseMatrixR; - typedef Eigen::SparseMatrix SparseMatrixC; - - // Non-symmetric matrix with zero elements - Eigen::MatrixXf mat(5, 6); - mat << 0, 3, 0, 0, 0, 11, 22, 0, 0, 0, 17, 11, 7, 5, 0, 1, 0, 11, 0, - 0, 0, 0, 0, 11, 0, 0, 14, 0, 8, 11; - - m.def("fixed_r", [mat]() -> FixedMatrixR { - return FixedMatrixR(mat); - }); - - m.def("fixed_c", [mat]() -> FixedMatrixC { - return FixedMatrixC(mat); - }); - - m.def("fixed_passthrough_r", [](const FixedMatrixR &m) -> FixedMatrixR { - return m; - }); - - m.def("fixed_passthrough_c", [](const FixedMatrixC &m) -> FixedMatrixC { - return m; - }); - - m.def("dense_r", [mat]() -> DenseMatrixR { - return DenseMatrixR(mat); - }); - - m.def("dense_c", [mat]() -> DenseMatrixC { - return DenseMatrixC(mat); - }); - - m.def("dense_passthrough_r", [](const DenseMatrixR &m) -> DenseMatrixR { - return m; - }); - - m.def("dense_passthrough_c", [](const DenseMatrixC &m) -> DenseMatrixC { - return m; - }); - - m.def("sparse_r", [mat]() -> SparseMatrixR { - return Eigen::SparseView(mat); - }); - - m.def("sparse_c", [mat]() -> SparseMatrixC { - return Eigen::SparseView(mat); - }); - - m.def("sparse_passthrough_r", [](const SparseMatrixR &m) -> SparseMatrixR { - return m; - }); - - m.def("sparse_passthrough_c", [](const SparseMatrixC &m) -> SparseMatrixC { - return m; - }); -} diff --git a/stormpy/resources/pybind11/example/eigen.py b/stormpy/resources/pybind11/example/eigen.py deleted file mode 100644 index accaf236a..000000000 --- a/stormpy/resources/pybind11/example/eigen.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example import fixed_r, fixed_c -from example import fixed_passthrough_r, fixed_passthrough_c -from example import dense_r, dense_c -from example import dense_passthrough_r, dense_passthrough_c -from example import sparse_r, sparse_c -from example import sparse_passthrough_r, sparse_passthrough_c -import numpy as np - -ref = np.array( - [[0, 3, 0, 0, 0, 11], - [22, 0, 0, 0, 17, 11], - [7, 5, 0, 1, 0, 11], - [0, 0, 0, 0, 0, 11], - [0, 0, 14, 0, 8, 11]]) - - -def check(mat): - return 'OK' if np.sum(mat - ref) == 0 else 'NOT OK' - -print("fixed_r = %s" % check(fixed_r())) -print("fixed_c = %s" % check(fixed_c())) -print("pt_r(fixed_r) = %s" % check(fixed_passthrough_r(fixed_r()))) -print("pt_c(fixed_c) = %s" % check(fixed_passthrough_c(fixed_c()))) -print("pt_r(fixed_c) = %s" % check(fixed_passthrough_r(fixed_c()))) -print("pt_c(fixed_r) = %s" % check(fixed_passthrough_c(fixed_r()))) - -print("dense_r = %s" % check(dense_r())) -print("dense_c = %s" % check(dense_c())) -print("pt_r(dense_r) = %s" % check(dense_passthrough_r(dense_r()))) -print("pt_c(dense_c) = %s" % check(dense_passthrough_c(dense_c()))) -print("pt_r(dense_c) = %s" % check(dense_passthrough_r(dense_c()))) -print("pt_c(dense_r) = %s" % check(dense_passthrough_c(dense_r()))) - -print("sparse_r = %s" % check(sparse_r())) -print("sparse_c = %s" % check(sparse_c())) -print("pt_r(sparse_r) = %s" % check(sparse_passthrough_r(sparse_r()))) -print("pt_c(sparse_c) = %s" % check(sparse_passthrough_c(sparse_c()))) -print("pt_r(sparse_c) = %s" % check(sparse_passthrough_r(sparse_c()))) -print("pt_c(sparse_r) = %s" % check(sparse_passthrough_c(sparse_r()))) diff --git a/stormpy/resources/pybind11/example/eigen.ref b/stormpy/resources/pybind11/example/eigen.ref deleted file mode 100644 index b87f8ede3..000000000 --- a/stormpy/resources/pybind11/example/eigen.ref +++ /dev/null @@ -1,18 +0,0 @@ -fixed_r = OK -fixed_c = OK -pt_r(fixed_r) = OK -pt_c(fixed_c) = OK -pt_r(fixed_c) = OK -pt_c(fixed_r) = OK -dense_r = OK -dense_c = OK -pt_r(dense_r) = OK -pt_c(dense_c) = OK -pt_r(dense_c) = OK -pt_c(dense_r) = OK -sparse_r = OK -sparse_c = OK -pt_r(sparse_r) = OK -pt_c(sparse_c) = OK -pt_r(sparse_c) = OK -pt_c(sparse_r) = OK diff --git a/stormpy/resources/pybind11/example/example.cpp b/stormpy/resources/pybind11/example/example.cpp deleted file mode 100644 index 470684a3b..000000000 --- a/stormpy/resources/pybind11/example/example.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - example/example.cpp -- pybind example plugin - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -void init_ex1(py::module &); -void init_ex2(py::module &); -void init_ex3(py::module &); -void init_ex4(py::module &); -void init_ex5(py::module &); -void init_ex6(py::module &); -void init_ex7(py::module &); -void init_ex8(py::module &); -void init_ex9(py::module &); -void init_ex10(py::module &); -void init_ex11(py::module &); -void init_ex12(py::module &); -void init_ex13(py::module &); -void init_ex14(py::module &); -void init_ex15(py::module &); -void init_ex16(py::module &); -void init_ex17(py::module &); -void init_issues(py::module &); - -#if defined(PYBIND11_TEST_EIGEN) - void init_eigen(py::module &); -#endif - -PYBIND11_PLUGIN(example) { - py::module m("example", "pybind example plugin"); - - init_ex1(m); - init_ex2(m); - init_ex3(m); - init_ex4(m); - init_ex5(m); - init_ex6(m); - init_ex7(m); - init_ex8(m); - init_ex9(m); - init_ex10(m); - init_ex11(m); - init_ex12(m); - init_ex13(m); - init_ex14(m); - init_ex15(m); - init_ex16(m); - init_ex17(m); - init_issues(m); - - #if defined(PYBIND11_TEST_EIGEN) - init_eigen(m); - #endif - - return m.ptr(); -} diff --git a/stormpy/resources/pybind11/example/example.h b/stormpy/resources/pybind11/example/example.h deleted file mode 100644 index ab8fff796..000000000 --- a/stormpy/resources/pybind11/example/example.h +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - -using std::cout; -using std::endl; - -namespace py = pybind11; diff --git a/stormpy/resources/pybind11/example/example1.cpp b/stormpy/resources/pybind11/example/example1.cpp deleted file mode 100644 index dd651fbaf..000000000 --- a/stormpy/resources/pybind11/example/example1.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - example/example1.cpp -- constructors, deconstructors, attribute access, - __str__, argument and return value conventions - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -class Example1 { -public: - Example1() { - cout << "Called Example1 default constructor.." << endl; - } - Example1(int value) : value(value) { - cout << "Called Example1 constructor with value " << value << ".." << endl; - } - Example1(const Example1 &e) : value(e.value) { - cout << "Called Example1 copy constructor with value " << value << ".." << endl; - } - Example1(Example1 &&e) : value(e.value) { - cout << "Called Example1 move constructor with value " << value << ".." << endl; - e.value = 0; - } - ~Example1() { - cout << "Called Example1 destructor (" << value << ")" << endl; - } - std::string toString() { - return "Example1[value=" + std::to_string(value) + "]"; - } - - void operator=(const Example1 &e) { cout << "Assignment operator" << endl; value = e.value; } - void operator=(Example1 &&e) { cout << "Move assignment operator" << endl; value = e.value; e.value = 0;} - - void add1(Example1 other) { value += other.value; } // passing by value - void add2(Example1 &other) { value += other.value; } // passing by reference - void add3(const Example1 &other) { value += other.value; } // passing by const reference - void add4(Example1 *other) { value += other->value; } // passing by pointer - void add5(const Example1 *other) { value += other->value; } // passing by const pointer - - void add6(int other) { value += other; } // passing by value - void add7(int &other) { value += other; } // passing by reference - void add8(const int &other) { value += other; } // passing by const reference - void add9(int *other) { value += *other; } // passing by pointer - void add10(const int *other) { value += *other; } // passing by const pointer - - Example1 self1() { return *this; } // return by value - Example1 &self2() { return *this; } // return by reference - const Example1 &self3() { return *this; } // return by const reference - Example1 *self4() { return this; } // return by pointer - const Example1 *self5() { return this; } // return by const pointer - - int internal1() { return value; } // return by value - int &internal2() { return value; } // return by reference - const int &internal3() { return value; } // return by const reference - int *internal4() { return &value; } // return by pointer - const int *internal5() { return &value; } // return by const pointer - - int value = 0; -}; - -void init_ex1(py::module &m) { - py::class_(m, "Example1") - .def(py::init<>()) - .def(py::init()) - .def(py::init()) - .def("add1", &Example1::add1) - .def("add2", &Example1::add2) - .def("add3", &Example1::add3) - .def("add4", &Example1::add4) - .def("add5", &Example1::add5) - .def("add6", &Example1::add6) - .def("add7", &Example1::add7) - .def("add8", &Example1::add8) - .def("add9", &Example1::add9) - .def("add10", &Example1::add10) - .def("self1", &Example1::self1) - .def("self2", &Example1::self2) - .def("self3", &Example1::self3) - .def("self4", &Example1::self4) - .def("self5", &Example1::self5) - .def("internal1", &Example1::internal1) - .def("internal2", &Example1::internal2) - .def("internal3", &Example1::internal3) - .def("internal4", &Example1::internal4) - .def("internal5", &Example1::internal5) - .def("__str__", &Example1::toString) - .def_readwrite("value", &Example1::value); -} diff --git a/stormpy/resources/pybind11/example/example1.py b/stormpy/resources/pybind11/example/example1.py deleted file mode 100755 index f89b662d8..000000000 --- a/stormpy/resources/pybind11/example/example1.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example import Example1 - -instance1 = Example1() -instance2 = Example1(32) -instance1.add1(instance2) -instance1.add2(instance2) -instance1.add3(instance2) -instance1.add4(instance2) -instance1.add5(instance2) -instance1.add6(32) -instance1.add7(32) -instance1.add8(32) -instance1.add9(32) -instance1.add10(32) - -print("Instance 1: " + str(instance1)) -print("Instance 2: " + str(instance2)) - -print(instance1.self1()) -print(instance1.self2()) -print(instance1.self3()) -print(instance1.self4()) -print(instance1.self5()) -print(instance1.internal1()) -print(instance1.internal2()) -print(instance1.internal3()) -print(instance1.internal4()) -print(instance1.internal5()) - -print("Instance 1, direct access = %i" % instance1.value) -instance1.value = 100 -print("Instance 1: " + str(instance1)) diff --git a/stormpy/resources/pybind11/example/example1.ref b/stormpy/resources/pybind11/example/example1.ref deleted file mode 100644 index 2c242f9c4..000000000 --- a/stormpy/resources/pybind11/example/example1.ref +++ /dev/null @@ -1,26 +0,0 @@ -Called Example1 default constructor.. -Called Example1 constructor with value 32.. -Called Example1 copy constructor with value 32.. -Called Example1 copy constructor with value 32.. -Called Example1 destructor (32) -Called Example1 destructor (32) -Instance 1: Example1[value=320] -Instance 2: Example1[value=32] -Called Example1 copy constructor with value 320.. -Called Example1 move constructor with value 320.. -Called Example1 destructor (0) -Example1[value=320] -Called Example1 destructor (320) -Example1[value=320] -Example1[value=320] -Example1[value=320] -Example1[value=320] -320 -320 -320 -320 -320 -Instance 1, direct access = 320 -Instance 1: Example1[value=100] -Called Example1 destructor (32) -Called Example1 destructor (100) diff --git a/stormpy/resources/pybind11/example/example10.cpp b/stormpy/resources/pybind11/example/example10.cpp deleted file mode 100644 index 06528c2f0..000000000 --- a/stormpy/resources/pybind11/example/example10.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - example/example10.cpp -- auto-vectorize functions over NumPy array - arguments - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include - -double my_func(int x, float y, double z) { - std::cout << "my_func(x:int=" << x << ", y:float=" << y << ", z:float=" << z << ")" << std::endl; - return (float) x*y*z; -} - -std::complex my_func3(std::complex c) { - return c * std::complex(2.f); -} - -void init_ex10(py::module &m) { - // Vectorize all arguments of a function (though non-vector arguments are also allowed) - m.def("vectorized_func", py::vectorize(my_func)); - - // Vectorize a lambda function with a capture object (e.g. to exclude some arguments from the vectorization) - m.def("vectorized_func2", - [](py::array_t x, py::array_t y, float z) { - return py::vectorize([z](int x, float y) { return my_func(x, y, z); })(x, y); - } - ); - - // Vectorize a complex-valued function - m.def("vectorized_func3", py::vectorize(my_func3)); - - /// Numpy function which only accepts specific data types - m.def("selective_func", [](py::array_t) { std::cout << "Int branch taken. "<< std::endl; }); - m.def("selective_func", [](py::array_t) { std::cout << "Float branch taken. "<< std::endl; }); - m.def("selective_func", [](py::array_t, py::array::c_style>) { std::cout << "Complex float branch taken. "<< std::endl; }); -} diff --git a/stormpy/resources/pybind11/example/example10.py b/stormpy/resources/pybind11/example/example10.py deleted file mode 100755 index b18e729a6..000000000 --- a/stormpy/resources/pybind11/example/example10.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -import example -try: - import numpy as np -except ImportError: - print('NumPy missing') - exit(0) - -from example import vectorized_func -from example import vectorized_func2 -from example import vectorized_func3 - -print(vectorized_func3(np.array(3+7j))) - -for f in [vectorized_func, vectorized_func2]: - print(f(1, 2, 3)) - print(f(np.array(1), np.array(2), 3)) - print(f(np.array([1, 3]), np.array([2, 4]), 3)) - print(f(np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3)) - print(np.array([[1, 3, 5], [7, 9, 11]])* np.array([[2, 4, 6], [8, 10, 12]])*3) - print(f(np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2)) - print(np.array([[1, 2, 3], [4, 5, 6]])* np.array([2, 3, 4])* 2) - print(f(np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2)) - print(np.array([[1, 2, 3], [4, 5, 6]])* np.array([[2], [3]])* 2) - -from example import selective_func - -selective_func(np.array([1], dtype=np.int32)) -selective_func(np.array([1.0], dtype=np.float32)) -selective_func(np.array([1.0j], dtype=np.complex64)) diff --git a/stormpy/resources/pybind11/example/example10.ref b/stormpy/resources/pybind11/example/example10.ref deleted file mode 100644 index 4885fc1ca..000000000 --- a/stormpy/resources/pybind11/example/example10.ref +++ /dev/null @@ -1,78 +0,0 @@ -(6+14j) -my_func(x:int=1, y:float=2, z:float=3) -6.0 -my_func(x:int=1, y:float=2, z:float=3) -6.0 -my_func(x:int=1, y:float=2, z:float=3) -my_func(x:int=3, y:float=4, z:float=3) -[ 6. 36.] -my_func(x:int=1, y:float=2, z:float=3) -my_func(x:int=3, y:float=4, z:float=3) -my_func(x:int=5, y:float=6, z:float=3) -my_func(x:int=7, y:float=8, z:float=3) -my_func(x:int=9, y:float=10, z:float=3) -my_func(x:int=11, y:float=12, z:float=3) -[[ 6. 36. 90.] - [ 168. 270. 396.]] -[[ 6 36 90] - [168 270 396]] -my_func(x:int=1, y:float=2, z:float=2) -my_func(x:int=2, y:float=3, z:float=2) -my_func(x:int=3, y:float=4, z:float=2) -my_func(x:int=4, y:float=2, z:float=2) -my_func(x:int=5, y:float=3, z:float=2) -my_func(x:int=6, y:float=4, z:float=2) -[[ 4. 12. 24.] - [ 16. 30. 48.]] -[[ 4 12 24] - [16 30 48]] -my_func(x:int=1, y:float=2, z:float=2) -my_func(x:int=2, y:float=2, z:float=2) -my_func(x:int=3, y:float=2, z:float=2) -my_func(x:int=4, y:float=3, z:float=2) -my_func(x:int=5, y:float=3, z:float=2) -my_func(x:int=6, y:float=3, z:float=2) -[[ 4. 8. 12.] - [ 24. 30. 36.]] -[[ 4 8 12] - [24 30 36]] -my_func(x:int=1, y:float=2, z:float=3) -6.0 -my_func(x:int=1, y:float=2, z:float=3) -6.0 -my_func(x:int=1, y:float=2, z:float=3) -my_func(x:int=3, y:float=4, z:float=3) -[ 6. 36.] -my_func(x:int=1, y:float=2, z:float=3) -my_func(x:int=3, y:float=4, z:float=3) -my_func(x:int=5, y:float=6, z:float=3) -my_func(x:int=7, y:float=8, z:float=3) -my_func(x:int=9, y:float=10, z:float=3) -my_func(x:int=11, y:float=12, z:float=3) -[[ 6. 36. 90.] - [ 168. 270. 396.]] -[[ 6 36 90] - [168 270 396]] -my_func(x:int=1, y:float=2, z:float=2) -my_func(x:int=2, y:float=3, z:float=2) -my_func(x:int=3, y:float=4, z:float=2) -my_func(x:int=4, y:float=2, z:float=2) -my_func(x:int=5, y:float=3, z:float=2) -my_func(x:int=6, y:float=4, z:float=2) -[[ 4. 12. 24.] - [ 16. 30. 48.]] -[[ 4 12 24] - [16 30 48]] -my_func(x:int=1, y:float=2, z:float=2) -my_func(x:int=2, y:float=2, z:float=2) -my_func(x:int=3, y:float=2, z:float=2) -my_func(x:int=4, y:float=3, z:float=2) -my_func(x:int=5, y:float=3, z:float=2) -my_func(x:int=6, y:float=3, z:float=2) -[[ 4. 8. 12.] - [ 24. 30. 36.]] -[[ 4 8 12] - [24 30 36]] -Int branch taken. -Float branch taken. -Complex float branch taken. diff --git a/stormpy/resources/pybind11/example/example11.cpp b/stormpy/resources/pybind11/example/example11.cpp deleted file mode 100644 index 4b3c6d08b..000000000 --- a/stormpy/resources/pybind11/example/example11.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - example/example11.cpp -- keyword arguments and default values - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include - -void kw_func(int x, int y) { std::cout << "kw_func(x=" << x << ", y=" << y << ")" << std::endl; } - -void kw_func4(const std::vector &entries) { - std::cout << "kw_func4: "; - for (int i : entries) - std::cout << i << " "; - std::cout << endl; -} - -py::object call_kw_func(py::function f) { - py::tuple args = py::make_tuple(1234); - py::dict kwargs; - kwargs["y"] = py::cast(5678); - return f(*args, **kwargs); -} - -void args_function(py::args args) { - for (size_t it=0; it " << item.second << std::endl; - } -} - -void init_ex11(py::module &m) { - m.def("kw_func", &kw_func, py::arg("x"), py::arg("y")); - m.def("kw_func2", &kw_func, py::arg("x") = 100, py::arg("y") = 200); - m.def("kw_func3", [](const char *) { }, py::arg("data") = std::string("Hello world!")); - - /* A fancier default argument */ - std::vector list; - list.push_back(13); - list.push_back(17); - - m.def("kw_func4", &kw_func4, py::arg("myList") = list); - m.def("call_kw_func", &call_kw_func); - - m.def("args_function", &args_function); - m.def("args_kwargs_function", &args_kwargs_function); - - using namespace py::literals; - m.def("kw_func_udl", &kw_func, "x"_a, "y"_a=300); - m.def("kw_func_udl_z", &kw_func, "x"_a, "y"_a=0); -} diff --git a/stormpy/resources/pybind11/example/example11.py b/stormpy/resources/pybind11/example/example11.py deleted file mode 100755 index 09ba13e6c..000000000 --- a/stormpy/resources/pybind11/example/example11.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -import pydoc - -sys.path.append('.') - -from example import kw_func, kw_func2, kw_func3, kw_func4, call_kw_func -from example import args_function, args_kwargs_function, kw_func_udl, kw_func_udl_z - -print(pydoc.render_doc(kw_func, "Help on %s")) -print(pydoc.render_doc(kw_func2, "Help on %s")) -print(pydoc.render_doc(kw_func3, "Help on %s")) -print(pydoc.render_doc(kw_func4, "Help on %s")) -print(pydoc.render_doc(kw_func_udl, "Help on %s")) -print(pydoc.render_doc(kw_func_udl_z, "Help on %s")) - -kw_func(5, 10) -kw_func(5, y=10) -kw_func(y=10, x=5) - -kw_func2() - -kw_func2(5) -kw_func2(x=5) - -kw_func2(y=10) - -kw_func2(5, 10) -kw_func2(x=5, y=10) - -try: - kw_func2(x=5, y=10, z=12) -except Exception as e: - print("Caught expected exception: " + str(e)) - -kw_func4() -kw_func4(myList=[1, 2, 3]) - -call_kw_func(kw_func2) - -args_function('arg1_value', 'arg2_value', 3) -args_kwargs_function('arg1_value', 'arg2_value', arg3='arg3_value', arg4=4) - -kw_func_udl(x=5, y=10) -kw_func_udl_z(x=5) diff --git a/stormpy/resources/pybind11/example/example11.ref b/stormpy/resources/pybind11/example/example11.ref deleted file mode 100644 index a693b6ceb..000000000 --- a/stormpy/resources/pybind11/example/example11.ref +++ /dev/null @@ -1,55 +0,0 @@ -Help on built-in function kw_func in module example - -kkww__ffuunncc(...) - kw_func(x : int, y : int) -> NoneType - -Help on built-in function kw_func2 in module example - -kkww__ffuunncc22(...) - kw_func2(x : int = 100L, y : int = 200L) -> NoneType - -Help on built-in function kw_func3 in module example - -kkww__ffuunncc33(...) - kw_func3(data : unicode = u'Hello world!') -> NoneType - -Help on built-in function kw_func4 in module example - -kkww__ffuunncc44(...) - kw_func4(myList : list = [13L, 17L]) -> NoneType - -Help on built-in function kw_func_udl in module example - -kkww__ffuunncc__uuddll(...) - kw_func_udl(x : int, y : int = 300L) -> NoneType - -Help on built-in function kw_func_udl_z in module example - -kkww__ffuunncc__uuddll__zz(...) - kw_func_udl_z(x : int, y : int = 0L) -> NoneType - -kw_func(x=5, y=10) -kw_func(x=5, y=10) -kw_func(x=5, y=10) -kw_func(x=100, y=200) -kw_func(x=5, y=200) -kw_func(x=5, y=200) -kw_func(x=100, y=10) -kw_func(x=5, y=10) -kw_func(x=5, y=10) -Caught expected exception: Incompatible function arguments. The following argument types are supported: - 1. (x : int = 100L, y : int = 200L) -> NoneType - Invoked with: -kw_func4: 13 17 -kw_func4: 1 2 3 -kw_func(x=1234, y=5678) -got argument: arg1_value -got argument: arg2_value -got argument: 3 -got argument: arg1_value -got argument: arg2_value -got keyword argument: arg3 -> arg3_value -got keyword argument: arg4 -> 4 - -kw_func(x=5, y=10) -kw_func(x=5, y=0) diff --git a/stormpy/resources/pybind11/example/example12.cpp b/stormpy/resources/pybind11/example/example12.cpp deleted file mode 100644 index e5555f53a..000000000 --- a/stormpy/resources/pybind11/example/example12.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - example/example12.cpp -- overriding virtual functions from Python - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include - -/* This is an example class that we'll want to be able to extend from Python */ -class Example12 { -public: - Example12(int state) : state(state) { - cout << "Constructing Example12.." << endl; - } - - ~Example12() { - cout << "Destructing Example12.." << endl; - } - - virtual int run(int value) { - std::cout << "Original implementation of Example12::run(state=" << state - << ", value=" << value << ")" << std::endl; - return state + value; - } - - virtual bool run_bool() = 0; - virtual void pure_virtual() = 0; -private: - int state; -}; - -/* This is a wrapper class that must be generated */ -class PyExample12 : public Example12 { -public: - using Example12::Example12; /* Inherit constructors */ - - virtual int run(int value) { - /* Generate wrapping code that enables native function overloading */ - PYBIND11_OVERLOAD( - int, /* Return type */ - Example12, /* Parent class */ - run, /* Name of function */ - value /* Argument(s) */ - ); - } - - virtual bool run_bool() { - PYBIND11_OVERLOAD_PURE( - bool, /* Return type */ - Example12, /* Parent class */ - run_bool, /* Name of function */ - /* This function has no arguments. The trailing comma - in the previous line is needed for some compilers */ - ); - } - - virtual void pure_virtual() { - PYBIND11_OVERLOAD_PURE( - void, /* Return type */ - Example12, /* Parent class */ - pure_virtual, /* Name of function */ - /* This function has no arguments. The trailing comma - in the previous line is needed for some compilers */ - ); - } -}; - -int runExample12(Example12 *ex, int value) { - return ex->run(value); -} - -bool runExample12Bool(Example12* ex) { - return ex->run_bool(); -} - -void runExample12Virtual(Example12 *ex) { - ex->pure_virtual(); -} - -void init_ex12(py::module &m) { - /* Important: indicate the trampoline class PyExample12 using the third - argument to py::class_. The second argument with the unique pointer - is simply the default holder type used by pybind11. */ - py::class_, PyExample12>(m, "Example12") - .def(py::init()) - /* Reference original class in function definitions */ - .def("run", &Example12::run) - .def("run_bool", &Example12::run_bool) - .def("pure_virtual", &Example12::pure_virtual); - - m.def("runExample12", &runExample12); - m.def("runExample12Bool", &runExample12Bool); - m.def("runExample12Virtual", &runExample12Virtual); -} diff --git a/stormpy/resources/pybind11/example/example12.py b/stormpy/resources/pybind11/example/example12.py deleted file mode 100644 index eb175239f..000000000 --- a/stormpy/resources/pybind11/example/example12.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example import Example12, runExample12, runExample12Virtual, runExample12Bool - - -class ExtendedExample12(Example12): - def __init__(self, state): - super(ExtendedExample12, self).__init__(state + 1) - self.data = "Hello world" - - def run(self, value): - print('ExtendedExample12::run(%i), calling parent..' % value) - return super(ExtendedExample12, self).run(value + 1) - - def run_bool(self): - print('ExtendedExample12::run_bool()') - return False - - def pure_virtual(self): - print('ExtendedExample12::pure_virtual(): %s' % self.data) - - -ex12 = Example12(10) -print(runExample12(ex12, 20)) -try: - runExample12Virtual(ex12) -except Exception as e: - print("Caught expected exception: " + str(e)) - -ex12p = ExtendedExample12(10) -print(runExample12(ex12p, 20)) -print(runExample12Bool(ex12p)) -runExample12Virtual(ex12p) diff --git a/stormpy/resources/pybind11/example/example12.ref b/stormpy/resources/pybind11/example/example12.ref deleted file mode 100644 index a25023fae..000000000 --- a/stormpy/resources/pybind11/example/example12.ref +++ /dev/null @@ -1,13 +0,0 @@ -Constructing Example12.. -Original implementation of Example12::run(state=10, value=20) -30 -Caught expected exception: Tried to call pure virtual function "Example12::pure_virtual" -Constructing Example12.. -ExtendedExample12::run(20), calling parent.. -Original implementation of Example12::run(state=11, value=21) -32 -ExtendedExample12::run_bool() -False -ExtendedExample12::pure_virtual(): Hello world -Destructing Example12.. -Destructing Example12.. diff --git a/stormpy/resources/pybind11/example/example13.cpp b/stormpy/resources/pybind11/example/example13.cpp deleted file mode 100644 index 6c1b8765d..000000000 --- a/stormpy/resources/pybind11/example/example13.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - example/example13.cpp -- keep_alive modifier (pybind11's version - of Boost.Python's with_custodian_and_ward / with_custodian_and_ward_postcall) - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -class Child { -public: - Child() { std::cout << "Allocating child." << std::endl; } - ~Child() { std::cout << "Releasing child." << std::endl; } -}; - -class Parent { -public: - Parent() { std::cout << "Allocating parent." << std::endl; } - ~Parent() { std::cout << "Releasing parent." << std::endl; } - void addChild(Child *) { } - Child *returnChild() { return new Child(); } -}; - -void init_ex13(py::module &m) { - py::class_(m, "Parent") - .def(py::init<>()) - .def("addChild", &Parent::addChild) - .def("addChildKeepAlive", &Parent::addChild, py::keep_alive<1, 2>()) - .def("returnChild", &Parent::returnChild) - .def("returnChildKeepAlive", &Parent::returnChild, py::keep_alive<1, 0>()); - - py::class_(m, "Child") - .def(py::init<>()); -} diff --git a/stormpy/resources/pybind11/example/example13.py b/stormpy/resources/pybind11/example/example13.py deleted file mode 100644 index ad0176ed4..000000000 --- a/stormpy/resources/pybind11/example/example13.py +++ /dev/null @@ -1,46 +0,0 @@ -from __future__ import print_function -import sys -import gc -sys.path.append('.') - -from example import Parent, Child - -if True: - p = Parent() - p.addChild(Child()) - gc.collect() - print(p) - p = None - -gc.collect() -print("") - -if True: - p = Parent() - p.returnChild() - gc.collect() - print(p) - p = None - -gc.collect() -print("") - -if True: - p = Parent() - p.addChildKeepAlive(Child()) - gc.collect() - print(p) - p = None -gc.collect() -print("") - -if True: - p = Parent() - p.returnChildKeepAlive() - gc.collect() - print(p) - p = None - -gc.collect() -print("") -print("Terminating..") diff --git a/stormpy/resources/pybind11/example/example13.ref b/stormpy/resources/pybind11/example/example13.ref deleted file mode 100644 index 7eb02c51f..000000000 --- a/stormpy/resources/pybind11/example/example13.ref +++ /dev/null @@ -1,25 +0,0 @@ -Allocating parent. -Allocating child. -Releasing child. - -Releasing parent. - -Allocating parent. -Allocating child. -Releasing child. - -Releasing parent. - -Allocating parent. -Allocating child. - -Releasing parent. -Releasing child. - -Allocating parent. -Allocating child. - -Releasing parent. -Releasing child. - -Terminating.. diff --git a/stormpy/resources/pybind11/example/example14.cpp b/stormpy/resources/pybind11/example/example14.cpp deleted file mode 100644 index ad67fe419..000000000 --- a/stormpy/resources/pybind11/example/example14.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - example/example14.cpp -- opaque types, passing void pointers - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include -#include - -typedef std::vector StringList; - -class ClassWithSTLVecProperty { -public: - StringList stringList; -}; - -/* IMPORTANT: Disable internal pybind11 translation mechanisms for STL data structures */ -PYBIND11_MAKE_OPAQUE(StringList); - -void init_ex14(py::module &m) { - py::class_(m, "StringList") - .def(py::init<>()) - .def("pop_back", &StringList::pop_back) - /* There are multiple versions of push_back(), etc. Select the right ones. */ - .def("push_back", (void (StringList::*)(const std::string &)) &StringList::push_back) - .def("back", (std::string &(StringList::*)()) &StringList::back) - .def("__len__", [](const StringList &v) { return v.size(); }) - .def("__iter__", [](StringList &v) { - return py::make_iterator(v.begin(), v.end()); - }, py::keep_alive<0, 1>()); - - py::class_(m, "ClassWithSTLVecProperty") - .def(py::init<>()) - .def_readwrite("stringList", &ClassWithSTLVecProperty::stringList); - - m.def("print_opaque_list", [](const StringList &l) { - std::cout << "Opaque list: ["; - bool first = true; - for (auto entry : l) { - if (!first) - std::cout << ", "; - std::cout << entry; - first = false; - } - std::cout << "]" << std::endl; - }); - - m.def("return_void_ptr", []() { return (void *) 0x1234; }); - m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : 0x" << std::hex << (uint64_t) ptr << std::endl; }); - m.def("return_null_str", []() { return (char *) nullptr; }); - m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : 0x" << std::hex << (uint64_t) ptr << std::endl; }); - - m.def("return_unique_ptr", []() -> std::unique_ptr { - StringList *result = new StringList(); - result->push_back("some value"); - return std::unique_ptr(result); - }); -} diff --git a/stormpy/resources/pybind11/example/example14.py b/stormpy/resources/pybind11/example/example14.py deleted file mode 100644 index c653e0cea..000000000 --- a/stormpy/resources/pybind11/example/example14.py +++ /dev/null @@ -1,50 +0,0 @@ -from __future__ import print_function -import sys - -sys.path.append('.') - -from example import StringList, print_opaque_list -from example import ClassWithSTLVecProperty -from example import return_void_ptr, print_void_ptr -from example import return_null_str, print_null_str -from example import return_unique_ptr -from example import Example1 - -##### - -l = StringList() -l.push_back("Element 1") -l.push_back("Element 2") -print_opaque_list(l) -print("Back element is %s" % l.back()) -for i, k in enumerate(l): - print("%i/%i : %s" % (i + 1, len(l), k)) -l.pop_back() -print_opaque_list(l) - -##### -cvp = ClassWithSTLVecProperty() -print_opaque_list(cvp.stringList) - -cvp.stringList = l -cvp.stringList.push_back("Element 3") -print_opaque_list(cvp.stringList) - -##### - -print_void_ptr(return_void_ptr()) -print_void_ptr(Example1()) # Should also work for other C++ types - -try: - print_void_ptr([1, 2, 3]) # This should not work -except Exception as e: - print("Caught expected exception: " + str(e)) - -print(return_null_str()) -print_null_str(return_null_str()) - -##### - -ptr = return_unique_ptr() -print(ptr) -print_opaque_list(ptr) diff --git a/stormpy/resources/pybind11/example/example14.ref b/stormpy/resources/pybind11/example/example14.ref deleted file mode 100644 index 44e682098..000000000 --- a/stormpy/resources/pybind11/example/example14.ref +++ /dev/null @@ -1,18 +0,0 @@ -Opaque list: [Element 1, Element 2] -Back element is Element 2 -1/2 : Element 1 -2/2 : Element 2 -Opaque list: [Element 1] -Opaque list: [] -Opaque list: [Element 1, Element 3] -Got void ptr : 0x1234 -Called Example1 default constructor.. -Got void ptr : 0x7f9ba0f3c430 -Called Example1 destructor (0) -Caught expected exception: Incompatible function arguments. The following argument types are supported: - 1. (capsule) -> NoneType - Invoked with: [1, 2, 3] -None -Got null str : 0x0 - -Opaque list: [some value] diff --git a/stormpy/resources/pybind11/example/example15.cpp b/stormpy/resources/pybind11/example/example15.cpp deleted file mode 100644 index acdd36823..000000000 --- a/stormpy/resources/pybind11/example/example15.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - example/example15.cpp -- pickle support - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -class Pickleable { -public: - Pickleable(const std::string &value) : m_value(value) { } - const std::string &value() const { return m_value; } - - void setExtra1(int extra1) { m_extra1 = extra1; } - void setExtra2(int extra2) { m_extra2 = extra2; } - int extra1() const { return m_extra1; } - int extra2() const { return m_extra2; } -private: - std::string m_value; - int m_extra1 = 0; - int m_extra2 = 0; -}; - -void init_ex15(py::module &m) { - py::class_(m, "Pickleable") - .def(py::init()) - .def("value", &Pickleable::value) - .def("extra1", &Pickleable::extra1) - .def("extra2", &Pickleable::extra2) - .def("setExtra1", &Pickleable::setExtra1) - .def("setExtra2", &Pickleable::setExtra2) - // For details on the methods below, refer to - // http://docs.python.org/3/library/pickle.html#pickling-class-instances - .def("__getstate__", [](const Pickleable &p) { - /* Return a tuple that fully encodes the state of the object */ - return py::make_tuple(p.value(), p.extra1(), p.extra2()); - }) - .def("__setstate__", [](Pickleable &p, py::tuple t) { - if (t.size() != 3) - throw std::runtime_error("Invalid state!"); - /* Invoke the constructor (need to use in-place version) */ - new (&p) Pickleable(t[0].cast()); - - /* Assign any additional state */ - p.setExtra1(t[1].cast()); - p.setExtra2(t[2].cast()); - }); -} diff --git a/stormpy/resources/pybind11/example/example15.py b/stormpy/resources/pybind11/example/example15.py deleted file mode 100644 index 1810d3e2e..000000000 --- a/stormpy/resources/pybind11/example/example15.py +++ /dev/null @@ -1,21 +0,0 @@ -from __future__ import print_function -import sys - -sys.path.append('.') - -from example import Pickleable - -try: - import cPickle as pickle # Use cPickle on Python 2.7 -except ImportError: - import pickle - -p = Pickleable("test_value") -p.setExtra1(15) -p.setExtra2(48) - -data = pickle.dumps(p, 2) # Must use pickle protocol >= 2 -print("%s %i %i" % (p.value(), p.extra1(), p.extra2())) - -p2 = pickle.loads(data) -print("%s %i %i" % (p2.value(), p2.extra1(), p2.extra2())) diff --git a/stormpy/resources/pybind11/example/example15.ref b/stormpy/resources/pybind11/example/example15.ref deleted file mode 100644 index d804973a1..000000000 --- a/stormpy/resources/pybind11/example/example15.ref +++ /dev/null @@ -1,2 +0,0 @@ -test_value 15 48 -test_value 15 48 diff --git a/stormpy/resources/pybind11/example/example16.cpp b/stormpy/resources/pybind11/example/example16.cpp deleted file mode 100644 index 7b676a9dc..000000000 --- a/stormpy/resources/pybind11/example/example16.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - example/example16.cpp -- automatic upcasting for polymorphic types - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -struct BaseClass { virtual ~BaseClass() {} }; -struct DerivedClass1 : BaseClass { }; -struct DerivedClass2 : BaseClass { }; - -void init_ex16(py::module &m) { - py::class_(m, "BaseClass").def(py::init<>()); - py::class_(m, "DerivedClass1").def(py::init<>()); - py::class_(m, "DerivedClass2").def(py::init<>()); - - m.def("return_class_1", []() -> BaseClass* { return new DerivedClass1(); }); - m.def("return_class_2", []() -> BaseClass* { return new DerivedClass2(); }); - m.def("return_none", []() -> BaseClass* { return nullptr; }); -} diff --git a/stormpy/resources/pybind11/example/example16.py b/stormpy/resources/pybind11/example/example16.py deleted file mode 100644 index b4bcb655d..000000000 --- a/stormpy/resources/pybind11/example/example16.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import print_function -import sys - -sys.path.append('.') - -from example import return_class_1 -from example import return_class_2 -from example import return_none - -print(type(return_class_1()).__name__) -print(type(return_class_2()).__name__) -print(type(return_none()).__name__) diff --git a/stormpy/resources/pybind11/example/example16.ref b/stormpy/resources/pybind11/example/example16.ref deleted file mode 100644 index 96003367b..000000000 --- a/stormpy/resources/pybind11/example/example16.ref +++ /dev/null @@ -1,3 +0,0 @@ -DerivedClass1 -DerivedClass2 -NoneType diff --git a/stormpy/resources/pybind11/example/example17.cpp b/stormpy/resources/pybind11/example/example17.cpp deleted file mode 100644 index 8fd4ad642..000000000 --- a/stormpy/resources/pybind11/example/example17.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - example/example17.cpp -- Usage of stl_binders functions - - Copyright (c) 2016 Sergey Lyskov - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -#include - -class El { -public: - El() = delete; - El(int v) : a(v) { } - - int a; -}; - -std::ostream & operator<<(std::ostream &s, El const&v) { - s << "El{" << v.a << '}'; - return s; -} - -void init_ex17(py::module &m) { - pybind11::class_(m, "El") - .def(pybind11::init()); - - pybind11::bind_vector(m, "VectorInt"); - pybind11::bind_vector(m, "VectorBool"); - - pybind11::bind_vector(m, "VectorEl"); - - pybind11::bind_vector>(m, "VectorVectorEl"); -} diff --git a/stormpy/resources/pybind11/example/example17.py b/stormpy/resources/pybind11/example/example17.py deleted file mode 100644 index feae30708..000000000 --- a/stormpy/resources/pybind11/example/example17.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function - -from example import VectorInt, El, VectorEl, VectorVectorEl, VectorBool - -v_int = VectorInt([0, 0]) -print(len(v_int)) - -print(bool(v_int)) - -v_int2 = VectorInt([0, 0]) -print(v_int == v_int2) - -v_int2[1] = 1 -print(v_int != v_int2) - -v_int2.append(2) -v_int2.append(3) -v_int2.insert(0, 1) -v_int2.insert(0, 2) -v_int2.insert(0, 3) -print(v_int2) - -v_int.append(99) -v_int2[2:-2] = v_int -print(v_int2) -del v_int2[1:3] -print(v_int2) -del v_int2[0] -print(v_int2) - -v_a = VectorEl() -v_a.append(El(1)) -v_a.append(El(2)) -print(v_a) - -vv_a = VectorVectorEl() -vv_a.append(v_a) -vv_b = vv_a[0] -print(vv_b) - -vv_c = VectorBool() -for i in range(10): - vv_c.append(i % 2 == 0) -for i in range(10): - if vv_c[i] != (i % 2 == 0): - print("Error!") -print(vv_c) diff --git a/stormpy/resources/pybind11/example/example17.ref b/stormpy/resources/pybind11/example/example17.ref deleted file mode 100644 index cc271f3a9..000000000 --- a/stormpy/resources/pybind11/example/example17.ref +++ /dev/null @@ -1,11 +0,0 @@ -2 -True -True -True -VectorInt[3, 2, 1, 0, 1, 2, 3] -VectorInt[3, 2, 0, 0, 99, 2, 3] -VectorInt[3, 0, 99, 2, 3] -VectorInt[0, 99, 2, 3] -VectorEl[El{1}, El{2}] -VectorEl[El{1}, El{2}] -VectorBool[1, 0, 1, 0, 1, 0, 1, 0, 1, 0] diff --git a/stormpy/resources/pybind11/example/example2.cpp b/stormpy/resources/pybind11/example/example2.cpp deleted file mode 100644 index 4b15823f2..000000000 --- a/stormpy/resources/pybind11/example/example2.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - example/example2.cpp2 -- singleton design pattern, static functions and - variables, passing and interacting with Python types - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include - -#ifdef _WIN32 -# include -# include -#endif - -class Example2 { -public: - static Example2 *new_instance() { - return new Example2(); - } - ~Example2() { - std::cout << "Destructing Example2" << std::endl; - } - - /* Create and return a Python dictionary */ - py::dict get_dict() { - py::dict dict; - dict[py::str("key")] = py::str("value"); - return dict; - } - - /* Create and return a Python set */ - py::set get_set() { - py::set set; - set.add(py::str("key1")); - set.add(py::str("key2")); - return set; - } - - /* Create and return a C++ dictionary */ - std::map get_dict_2() { - std::map result; - result["key"] = "value"; - return result; - } - - /* Create and return a C++ set */ - std::set get_set_2() { - std::set result; - result.insert("key1"); - result.insert("key2"); - return result; - } - - /* Create, manipulate, and return a Python list */ - py::list get_list() { - py::list list; - list.append(py::str("value")); - cout << "Entry at positon 0: " << py::object(list[0]) << endl; - list[0] = py::str("overwritten"); - return list; - } - - /* C++ STL data types are automatically casted */ - std::vector get_list_2() { - std::vector list; - list.push_back(L"value"); - return list; - } - - /* C++ STL data types are automatically casted */ - std::array get_array() { - return std::array {{ "array entry 1" , "array entry 2"}}; - } - - /* Easily iterate over a dictionary using a C++11 range-based for loop */ - void print_dict(py::dict dict) { - for (auto item : dict) - std::cout << "key: " << item.first << ", value=" << item.second << std::endl; - } - - /* Easily iterate over a set using a C++11 range-based for loop */ - void print_set(py::set set) { - for (auto item : set) - std::cout << "key: " << item << std::endl; - } - - /* Easily iterate over a list using a C++11 range-based for loop */ - void print_list(py::list list) { - int index = 0; - for (auto item : list) - std::cout << "list item " << index++ << ": " << item << std::endl; - } - - /* STL data types (such as maps) are automatically casted from Python */ - void print_dict_2(const std::map &dict) { - for (auto item : dict) - std::cout << "key: " << item.first << ", value=" << item.second << std::endl; - } - - /* STL data types (such as sets) are automatically casted from Python */ - void print_set_2(const std::set &set) { - for (auto item : set) - std::cout << "key: " << item << std::endl; - } - - /* STL data types (such as vectors) are automatically casted from Python */ - void print_list_2(std::vector &list) { -#ifdef _WIN32 /* Can't easily mix cout and wcout on Windows */ - _setmode(_fileno(stdout), _O_TEXT); -#endif - int index = 0; - for (auto item : list) - std::wcout << L"list item " << index++ << L": " << item << std::endl; - } - - /* pybind automatically translates between C++11 and Python tuples */ - std::pair pair_passthrough(std::pair input) { - return std::make_pair(input.second, input.first); - } - - /* pybind automatically translates between C++11 and Python tuples */ - std::tuple tuple_passthrough(std::tuple input) { - return std::make_tuple(std::get<2>(input), std::get<1>(input), std::get<0>(input)); - } - - /* STL data types (such as arrays) are automatically casted from Python */ - void print_array(std::array &array) { - int index = 0; - for (auto item : array) - std::cout << "array item " << index++ << ": " << item << std::endl; - } - - void throw_exception() { - throw std::runtime_error("This exception was intentionally thrown."); - } - - static int value; - static const int value2; -}; - -int Example2::value = 0; -const int Example2::value2 = 5; - -void init_ex2(py::module &m) { - /* No constructor is explicitly defined below. An exception is raised when - trying to construct it directly from Python */ - py::class_(m, "Example2", "Example 2 documentation") - .def("get_dict", &Example2::get_dict, "Return a Python dictionary") - .def("get_dict_2", &Example2::get_dict_2, "Return a C++ dictionary") - .def("get_list", &Example2::get_list, "Return a Python list") - .def("get_list_2", &Example2::get_list_2, "Return a C++ list") - .def("get_set", &Example2::get_set, "Return a Python set") - .def("get_set2", &Example2::get_set_2, "Return a C++ set") - .def("get_array", &Example2::get_array, "Return a C++ array") - .def("print_dict", &Example2::print_dict, "Print entries of a Python dictionary") - .def("print_dict_2", &Example2::print_dict_2, "Print entries of a C++ dictionary") - .def("print_set", &Example2::print_set, "Print entries of a Python set") - .def("print_set_2", &Example2::print_set_2, "Print entries of a C++ set") - .def("print_list", &Example2::print_list, "Print entries of a Python list") - .def("print_list_2", &Example2::print_list_2, "Print entries of a C++ list") - .def("print_array", &Example2::print_array, "Print entries of a C++ array") - .def("pair_passthrough", &Example2::pair_passthrough, "Return a pair in reversed order") - .def("tuple_passthrough", &Example2::tuple_passthrough, "Return a triple in reversed order") - .def("throw_exception", &Example2::throw_exception, "Throw an exception") - .def_static("new_instance", &Example2::new_instance, "Return an instance") - .def_readwrite_static("value", &Example2::value, "Static value member") - .def_readonly_static("value2", &Example2::value2, "Static value member (readonly)"); -} diff --git a/stormpy/resources/pybind11/example/example2.py b/stormpy/resources/pybind11/example/example2.py deleted file mode 100755 index d335acc3d..000000000 --- a/stormpy/resources/pybind11/example/example2.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys, pydoc -sys.path.append('.') - -import example -from example import Example2 - -Example2.value = 15 -print(Example2.value) -print(Example2.value2) - -try: - Example2() -except Exception as e: - print(e) - -try: - Example2.value2 = 15 -except Exception as e: - print(e) - -instance = Example2.new_instance() - -dict_result = instance.get_dict() -dict_result['key2'] = 'value2' -instance.print_dict(dict_result) - -dict_result = instance.get_dict_2() -dict_result['key2'] = 'value2' -instance.print_dict_2(dict_result) - -set_result = instance.get_set() -set_result.add('key3') -instance.print_set(set_result) - -set_result = instance.get_set2() -set_result.add('key3') -instance.print_set_2(set_result) - -list_result = instance.get_list() -list_result.append('value2') -instance.print_list(list_result) - -list_result = instance.get_list_2() -list_result.append('value2') -instance.print_list_2(list_result) - -array_result = instance.get_array() -print(array_result) -instance.print_array(array_result) - -try: - instance.throw_exception() -except Exception as e: - print(e) - -print(instance.pair_passthrough((True, "test"))) -print(instance.tuple_passthrough((True, "test", 5))) - -print(pydoc.render_doc(Example2, "Help on %s")) - -print("__name__(example) = %s" % example.__name__) -print("__name__(example.Example2) = %s" % Example2.__name__) -print("__module__(example.Example2) = %s" % Example2.__module__) -print("__name__(example.Example2.get_set) = %s" % Example2.get_set.__name__) -print("__module__(example.Example2.get_set) = %s" % Example2.get_set.__module__) diff --git a/stormpy/resources/pybind11/example/example2.ref b/stormpy/resources/pybind11/example/example2.ref deleted file mode 100644 index fd6c83dda..000000000 --- a/stormpy/resources/pybind11/example/example2.ref +++ /dev/null @@ -1,137 +0,0 @@ -15 -5 -example.Example2: No constructor defined! -can't set attribute -key: key2, value=value2 -key: key, value=value -key: key, value=value -key: key2, value=value2 -key: key3 -key: key2 -key: key1 -key: key1 -key: key2 -key: key3 -Entry at positon 0: value -list item 0: overwritten -list item 1: value2 -list item 0: value -list item 1: value2 -[u'array entry 1', u'array entry 2'] -array item 0: array entry 1 -array item 1: array entry 2 -This exception was intentionally thrown. -(u'test', True) -(5L, u'test', True) -Help on class Example2 in module example - -class EExxaammppllee22(__builtin__.object) - | Example 2 documentation - | - | Methods defined here: - | - | ____iinniitt____(...) - | x.__init__(...) initializes x; see help(type(x)) for signature - | - | ggeett__aarrrraayy(...) - | Signature : (example.Example2) -> list[2] - | - | Return a C++ array - | - | ggeett__ddiicctt(...) - | Signature : (example.Example2) -> dict - | - | Return a Python dictionary - | - | ggeett__ddiicctt__22(...) - | Signature : (example.Example2) -> dict - | - | Return a C++ dictionary - | - | ggeett__lliisstt(...) - | Signature : (example.Example2) -> list - | - | Return a Python list - | - | ggeett__lliisstt__22(...) - | Signature : (example.Example2) -> list - | - | Return a C++ list - | - | ggeett__sseett(...) - | Signature : (example.Example2) -> set - | - | Return a Python set - | - | ggeett__sseett22(...) - | Signature : (example.Example2) -> set - | - | Return a C++ set - | - | ppaaiirr__ppaasssstthhrroouugghh(...) - | Signature : (example.Example2, (bool, unicode)) -> (unicode, bool) - | - | Return a pair in reversed order - | - | pprriinntt__aarrrraayy(...) - | Signature : (example.Example2, list[2]) -> NoneType - | - | Print entries of a C++ array - | - | pprriinntt__ddiicctt(...) - | Signature : (example.Example2, dict) -> NoneType - | - | Print entries of a Python dictionary - | - | pprriinntt__ddiicctt__22(...) - | Signature : (example.Example2, dict) -> NoneType - | - | Print entries of a C++ dictionary - | - | pprriinntt__lliisstt(...) - | Signature : (example.Example2, list) -> NoneType - | - | Print entries of a Python list - | - | pprriinntt__lliisstt__22(...) - | Signature : (example.Example2, list) -> NoneType - | - | Print entries of a C++ list - | - | pprriinntt__sseett(...) - | Signature : (example.Example2, set) -> NoneType - | - | Print entries of a Python set - | - | pprriinntt__sseett__22(...) - | Signature : (example.Example2, set) -> NoneType - | - | Print entries of a C++ set - | - | tthhrrooww__eexxcceeppttiioonn(...) - | Signature : (example.Example2) -> NoneType - | - | Throw an exception - | - | ttuuppllee__ppaasssstthhrroouugghh(...) - | Signature : (example.Example2, (bool, unicode, int)) -> (int, unicode, bool) - | - | Return a triple in reversed order - | - | ---------------------------------------------------------------------- - | Data and other attributes defined here: - | - | ____nneeww____ = - | T.__new__(S, ...) -> a new object with type S, a subtype of T - | - | nneeww__iinnssttaannccee = - | Signature : () -> example.Example2 - | - | Return an instance - -__name__(example) = example -__name__(example.Example2) = Example2 -__module__(example.Example2) = example -__name__(example.Example2.get_set) = get_set -__module__(example.Example2.get_set) = example -Destructing Example2 diff --git a/stormpy/resources/pybind11/example/example3.cpp b/stormpy/resources/pybind11/example/example3.cpp deleted file mode 100644 index af956b13e..000000000 --- a/stormpy/resources/pybind11/example/example3.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - example/example3.cpp -- operator overloading - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include - -class Vector2 { -public: - Vector2(float x, float y) : x(x), y(y) { std::cout << "Value constructor" << std::endl; } - Vector2(const Vector2 &v) : x(v.x), y(v.y) { std::cout << "Copy constructor" << std::endl; } - Vector2(Vector2 &&v) : x(v.x), y(v.y) { std::cout << "Move constructor" << std::endl; v.x = v.y = 0; } - ~Vector2() { std::cout << "Destructor." << std::endl; } - - std::string toString() const { - return "[" + std::to_string(x) + ", " + std::to_string(y) + "]"; - } - - void operator=(const Vector2 &v) { - cout << "Assignment operator" << endl; - x = v.x; - y = v.y; - } - - void operator=(Vector2 &&v) { - cout << "Move assignment operator" << endl; - x = v.x; y = v.y; v.x = v.y = 0; - } - - Vector2 operator+(const Vector2 &v) const { return Vector2(x + v.x, y + v.y); } - Vector2 operator-(const Vector2 &v) const { return Vector2(x - v.x, y - v.y); } - Vector2 operator-(float value) const { return Vector2(x - value, y - value); } - Vector2 operator+(float value) const { return Vector2(x + value, y + value); } - Vector2 operator*(float value) const { return Vector2(x * value, y * value); } - Vector2 operator/(float value) const { return Vector2(x / value, y / value); } - Vector2& operator+=(const Vector2 &v) { x += v.x; y += v.y; return *this; } - Vector2& operator-=(const Vector2 &v) { x -= v.x; y -= v.y; return *this; } - Vector2& operator*=(float v) { x *= v; y *= v; return *this; } - Vector2& operator/=(float v) { x /= v; y /= v; return *this; } - - friend Vector2 operator+(float f, const Vector2 &v) { return Vector2(f + v.x, f + v.y); } - friend Vector2 operator-(float f, const Vector2 &v) { return Vector2(f - v.x, f - v.y); } - friend Vector2 operator*(float f, const Vector2 &v) { return Vector2(f * v.x, f * v.y); } - friend Vector2 operator/(float f, const Vector2 &v) { return Vector2(f / v.x, f / v.y); } -private: - float x, y; -}; - - -void init_ex3(py::module &m) { - py::class_(m, "Vector2") - .def(py::init()) - .def(py::self + py::self) - .def(py::self + float()) - .def(py::self - py::self) - .def(py::self - float()) - .def(py::self * float()) - .def(py::self / float()) - .def(py::self += py::self) - .def(py::self -= py::self) - .def(py::self *= float()) - .def(py::self /= float()) - .def(float() + py::self) - .def(float() - py::self) - .def(float() * py::self) - .def(float() / py::self) - .def("__str__", &Vector2::toString); - - m.attr("Vector") = m.attr("Vector2"); -} diff --git a/stormpy/resources/pybind11/example/example3.py b/stormpy/resources/pybind11/example/example3.py deleted file mode 100755 index 591ae391c..000000000 --- a/stormpy/resources/pybind11/example/example3.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example import Vector2, Vector - -v1 = Vector2(1, 2) -v2 = Vector(3, -1) - -print("v1 = " + str(v1)) -print("v2 = " + str(v2)) -print("v1+v2 = " + str(v1+v2)) -print("v1-v2 = " + str(v1-v2)) -print("v1-8 = " + str(v1-8)) -print("v1+8 = " + str(v1+8)) -print("v1*8 = " + str(v1*8)) -print("v1/8 = " + str(v1/8)) -print("8-v1 = " + str(8-v1)) -print("8+v1 = " + str(8+v1)) -print("8*v1 = " + str(8*v1)) -print("8/v1 = " + str(8/v1)) - -v1 += v2 -v1 *= 2 - -print("(v1+v2)*2 = " + str(v1)) diff --git a/stormpy/resources/pybind11/example/example3.ref b/stormpy/resources/pybind11/example/example3.ref deleted file mode 100644 index 8f2c29886..000000000 --- a/stormpy/resources/pybind11/example/example3.ref +++ /dev/null @@ -1,57 +0,0 @@ -Value constructor -Value constructor -v1 = [1.000000, 2.000000] -v2 = [3.000000, -1.000000] -Value constructor -Move constructor -Destructor. -Destructor. -v1+v2 = [4.000000, 1.000000] -Value constructor -Move constructor -Destructor. -Destructor. -v1-v2 = [-2.000000, 3.000000] -Value constructor -Move constructor -Destructor. -Destructor. -v1-8 = [-7.000000, -6.000000] -Value constructor -Move constructor -Destructor. -Destructor. -v1+8 = [9.000000, 10.000000] -Value constructor -Move constructor -Destructor. -Destructor. -v1*8 = [8.000000, 16.000000] -Value constructor -Move constructor -Destructor. -Destructor. -v1/8 = [0.125000, 0.250000] -Value constructor -Move constructor -Destructor. -Destructor. -8-v1 = [7.000000, 6.000000] -Value constructor -Move constructor -Destructor. -Destructor. -8+v1 = [9.000000, 10.000000] -Value constructor -Move constructor -Destructor. -Destructor. -8*v1 = [8.000000, 16.000000] -Value constructor -Move constructor -Destructor. -Destructor. -8/v1 = [8.000000, 4.000000] -(v1+v2)*2 = [8.000000, 2.000000] -Destructor. -Destructor. diff --git a/stormpy/resources/pybind11/example/example4.cpp b/stormpy/resources/pybind11/example/example4.cpp deleted file mode 100644 index 7e17864e0..000000000 --- a/stormpy/resources/pybind11/example/example4.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - example/example4.cpp -- global constants and functions, enumerations, raw byte strings - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -enum EMyEnumeration { - EFirstEntry = 1, - ESecondEntry -}; - -class Example4 { -public: - enum EMode { - EFirstMode = 1, - ESecondMode - }; - - static EMode test_function(EMode mode) { - std::cout << "Example4::test_function(enum=" << mode << ")" << std::endl; - return mode; - } -}; - -bool test_function1() { - std::cout << "test_function()" << std::endl; - return false; -} - -void test_function2(EMyEnumeration k) { - std::cout << "test_function(enum=" << k << ")" << std::endl; -} - -float test_function3(int i) { - std::cout << "test_function(" << i << ")" << std::endl; - return (float) i / 2.f; -} - -py::bytes return_bytes() { - const char *data = "\x01\x00\x02\x00"; - return std::string(data, 4); -} - -void print_bytes(py::bytes bytes) { - std::string value = (std::string) bytes; - for (size_t i = 0; i < value.length(); ++i) - std::cout << "bytes[" << i << "]=" << (int) value[i] << std::endl; -} - -void init_ex4(py::module &m) { - m.def("test_function", &test_function1); - m.def("test_function", &test_function2); - m.def("test_function", &test_function3); - m.attr("some_constant") = py::int_(14); - - py::enum_(m, "EMyEnumeration") - .value("EFirstEntry", EFirstEntry) - .value("ESecondEntry", ESecondEntry) - .export_values(); - - py::class_ ex4_class(m, "Example4"); - ex4_class.def_static("test_function", &Example4::test_function); - py::enum_(ex4_class, "EMode") - .value("EFirstMode", Example4::EFirstMode) - .value("ESecondMode", Example4::ESecondMode) - .export_values(); - - m.def("return_bytes", &return_bytes); - m.def("print_bytes", &print_bytes); -} diff --git a/stormpy/resources/pybind11/example/example4.py b/stormpy/resources/pybind11/example/example4.py deleted file mode 100755 index 37d952f2b..000000000 --- a/stormpy/resources/pybind11/example/example4.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example import test_function -from example import some_constant -from example import EMyEnumeration -from example import EFirstEntry -from example import Example4 -from example import return_bytes -from example import print_bytes - -print(EMyEnumeration) -print(EMyEnumeration.EFirstEntry) -print(EMyEnumeration.ESecondEntry) -print(EFirstEntry) - -print(test_function()) -print(test_function(7)) -print(test_function(EMyEnumeration.EFirstEntry)) -print(test_function(EMyEnumeration.ESecondEntry)) -print("enum->integer = %i" % int(EMyEnumeration.ESecondEntry)) -print("integer->enum = %s" % str(EMyEnumeration(2))) - -print("A constant = " + str(some_constant)) - -print(Example4.EMode) -print(Example4.EMode.EFirstMode) -print(Example4.EFirstMode) -Example4.test_function(Example4.EFirstMode) - -print("Equality test 1: " + str( - Example4.test_function(Example4.EFirstMode) == - Example4.test_function(Example4.EFirstMode))) - -print("Inequality test 1: " + str( - Example4.test_function(Example4.EFirstMode) != - Example4.test_function(Example4.EFirstMode))) - -print("Equality test 2: " + str( - Example4.test_function(Example4.EFirstMode) == - Example4.test_function(Example4.ESecondMode))) - -print("Inequality test 2: " + str( - Example4.test_function(Example4.EFirstMode) != - Example4.test_function(Example4.ESecondMode))) - -x = { - Example4.test_function(Example4.EFirstMode): 1, - Example4.test_function(Example4.ESecondMode): 2 -} - -x[Example4.test_function(Example4.EFirstMode)] = 3 -x[Example4.test_function(Example4.ESecondMode)] = 4 -print("Hashing test = " + str(x)) - -print_bytes(return_bytes()) diff --git a/stormpy/resources/pybind11/example/example4.ref b/stormpy/resources/pybind11/example/example4.ref deleted file mode 100644 index a21f62c93..000000000 --- a/stormpy/resources/pybind11/example/example4.ref +++ /dev/null @@ -1,40 +0,0 @@ - -EMyEnumeration.EFirstEntry -EMyEnumeration.ESecondEntry -EMyEnumeration.EFirstEntry -test_function() -False -test_function(7) -3.5 -test_function(enum=1) -None -test_function(enum=2) -None -enum->integer = 2 -integer->enum = EMyEnumeration.ESecondEntry -A constant = 14 - -EMode.EFirstMode -EMode.EFirstMode -Example4::test_function(enum=1) -Example4::test_function(enum=1) -Example4::test_function(enum=1) -Equality test 1: True -Example4::test_function(enum=1) -Example4::test_function(enum=1) -Inequality test 1: False -Example4::test_function(enum=1) -Example4::test_function(enum=2) -Equality test 2: False -Example4::test_function(enum=1) -Example4::test_function(enum=2) -Inequality test 2: True -Example4::test_function(enum=1) -Example4::test_function(enum=2) -Example4::test_function(enum=1) -Example4::test_function(enum=2) -Hashing test = {EMode.EFirstMode: 3, EMode.ESecondMode: 4} -bytes[0]=1 -bytes[1]=0 -bytes[2]=2 -bytes[3]=0 diff --git a/stormpy/resources/pybind11/example/example5.cpp b/stormpy/resources/pybind11/example/example5.cpp deleted file mode 100644 index 0e1d2cd13..000000000 --- a/stormpy/resources/pybind11/example/example5.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - example/example5.cpp -- inheritance, callbacks, acquiring and releasing the - global interpreter lock - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include - - -class Pet { -public: - Pet(const std::string &name, const std::string &species) - : m_name(name), m_species(species) {} - std::string name() const { return m_name; } - std::string species() const { return m_species; } -private: - std::string m_name; - std::string m_species; -}; - -class Dog : public Pet { -public: - Dog(const std::string &name) : Pet(name, "dog") {} - void bark() const { std::cout << "Woof!" << std::endl; } -}; - -class Rabbit : public Pet { -public: - Rabbit(const std::string &name) : Pet(name, "parrot") {} -}; - -void pet_print(const Pet &pet) { - std::cout << pet.name() + " is a " + pet.species() << std::endl; -} - -void dog_bark(const Dog &dog) { - dog.bark(); -} - -bool test_callback1(py::object func) { - func(); - return false; -} - -int test_callback2(py::object func) { - py::object result = func("Hello", 'x', true, 5); - return result.cast(); -} - -void test_callback3(const std::function &func) { - cout << "func(43) = " << func(43)<< std::endl; -} - -std::function test_callback4() { - return [](int i) { return i+1; }; -} - -py::cpp_function test_callback5() { - return py::cpp_function([](int i) { return i+1; }, - py::arg("number")); -} - -void init_ex5(py::module &m) { - py::class_ pet_class(m, "Pet"); - pet_class - .def(py::init()) - .def("name", &Pet::name) - .def("species", &Pet::species); - - /* One way of declaring a subclass relationship: reference parent's class_ object */ - py::class_(m, "Dog", pet_class) - .def(py::init()); - - /* Another way of declaring a subclass relationship: reference parent's C++ type */ - py::class_(m, "Rabbit", py::base()) - .def(py::init()); - - m.def("pet_print", pet_print); - m.def("dog_bark", dog_bark); - - m.def("test_callback1", &test_callback1); - m.def("test_callback2", &test_callback2); - m.def("test_callback3", &test_callback3); - m.def("test_callback4", &test_callback4); - m.def("test_callback5", &test_callback5); - - /* Test cleanup of lambda closure */ - - struct Payload { - Payload() { - std::cout << "Payload constructor" << std::endl; - } - ~Payload() { - std::cout << "Payload destructor" << std::endl; - } - Payload(const Payload &) { - std::cout << "Payload copy constructor" << std::endl; - } - Payload(Payload &&) { - std::cout << "Payload move constructor" << std::endl; - } - }; - - m.def("test_cleanup", []() -> std::function { - Payload p; - - return [p]() { - /* p should be cleaned up when the returned function is garbage collected */ - }; - }); -} diff --git a/stormpy/resources/pybind11/example/example5.py b/stormpy/resources/pybind11/example/example5.py deleted file mode 100755 index 1361c7519..000000000 --- a/stormpy/resources/pybind11/example/example5.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -from functools import partial -import sys -sys.path.append('.') - -from example import Pet -from example import Dog -from example import Rabbit -from example import dog_bark -from example import pet_print - -polly = Pet('Polly', 'parrot') -molly = Dog('Molly') -roger = Rabbit('Rabbit') -print(roger.name() + " is a " + roger.species()) -pet_print(roger) -print(polly.name() + " is a " + polly.species()) -pet_print(polly) -print(molly.name() + " is a " + molly.species()) -pet_print(molly) -dog_bark(molly) -try: - dog_bark(polly) -except Exception as e: - print('The following error is expected: ' + str(e)) - -from example import test_callback1 -from example import test_callback2 -from example import test_callback3 -from example import test_callback4 -from example import test_callback5 -from example import test_cleanup - -def func1(): - print('Callback function 1 called!') - -def func2(a, b, c, d): - print('Callback function 2 called : ' + str(a) + ", " + str(b) + ", " + str(c) + ", "+ str(d)) - return d - -def func3(a): - print('Callback function 3 called : ' + str(a)) - -print(test_callback1(func1)) -print(test_callback2(func2)) -print(test_callback1(partial(func2, "Hello", "from", "partial", "object"))) -print(test_callback1(partial(func3, "Partial object with one argument"))) - -test_callback3(lambda i: i + 1) -f = test_callback4() -print("func(43) = %i" % f(43)) -f = test_callback5() -print("func(number=43) = %i" % f(number=43)) - -test_cleanup() diff --git a/stormpy/resources/pybind11/example/example5.ref b/stormpy/resources/pybind11/example/example5.ref deleted file mode 100644 index f32ba3af1..000000000 --- a/stormpy/resources/pybind11/example/example5.ref +++ /dev/null @@ -1,27 +0,0 @@ -Rabbit is a parrot -Polly is a parrot -Molly is a dog -Woof! -func(43) = 44 -Payload constructor -Payload copy constructor -Payload move constructor -Payload destructor -Payload destructor -Payload destructor -Rabbit is a parrot -Polly is a parrot -Molly is a dog -The following error is expected: Incompatible function arguments. The following argument types are supported: - 1. (example.Dog) -> NoneType - Invoked with: -Callback function 1 called! -False -Callback function 2 called : Hello, x, True, 5 -5 -Callback function 2 called : Hello, from, partial, object -False -Callback function 3 called : Partial object with one argument -False -func(43) = 44 -func(number=43) = 44 diff --git a/stormpy/resources/pybind11/example/example6.cpp b/stormpy/resources/pybind11/example/example6.cpp deleted file mode 100644 index e0bfb9e70..000000000 --- a/stormpy/resources/pybind11/example/example6.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - example/example6.cpp -- supporting Pythons' sequence protocol, iterators, - etc. - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include -#include - -class Sequence { -public: - Sequence(size_t size) : m_size(size) { - std::cout << "Value constructor: Creating a sequence with " << m_size << " entries" << std::endl; - m_data = new float[size]; - memset(m_data, 0, sizeof(float) * size); - } - - Sequence(const std::vector &value) : m_size(value.size()) { - std::cout << "Value constructor: Creating a sequence with " << m_size << " entries" << std::endl; - m_data = new float[m_size]; - memcpy(m_data, &value[0], sizeof(float) * m_size); - } - - Sequence(const Sequence &s) : m_size(s.m_size) { - std::cout << "Copy constructor: Creating a sequence with " << m_size << " entries" << std::endl; - m_data = new float[m_size]; - memcpy(m_data, s.m_data, sizeof(float)*m_size); - } - - Sequence(Sequence &&s) : m_size(s.m_size), m_data(s.m_data) { - std::cout << "Move constructor: Creating a sequence with " << m_size << " entries" << std::endl; - s.m_size = 0; - s.m_data = nullptr; - } - - ~Sequence() { - std::cout << "Freeing a sequence with " << m_size << " entries" << std::endl; - delete[] m_data; - } - - Sequence &operator=(const Sequence &s) { - std::cout << "Assignment operator: Creating a sequence with " << s.m_size << " entries" << std::endl; - delete[] m_data; - m_size = s.m_size; - m_data = new float[m_size]; - memcpy(m_data, s.m_data, sizeof(float)*m_size); - return *this; - } - - Sequence &operator=(Sequence &&s) { - std::cout << "Move assignment operator: Creating a sequence with " << s.m_size << " entries" << std::endl; - if (&s != this) { - delete[] m_data; - m_size = s.m_size; - m_data = s.m_data; - s.m_size = 0; - s.m_data = nullptr; - } - return *this; - } - - bool operator==(const Sequence &s) const { - if (m_size != s.size()) - return false; - for (size_t i=0; i seq(m, "Sequence"); - - seq.def(py::init()) - .def(py::init&>()) - /// Bare bones interface - .def("__getitem__", [](const Sequence &s, size_t i) { - if (i >= s.size()) - throw py::index_error(); - return s[i]; - }) - .def("__setitem__", [](Sequence &s, size_t i, float v) { - if (i >= s.size()) - throw py::index_error(); - s[i] = v; - }) - .def("__len__", &Sequence::size) - /// Optional sequence protocol operations - .def("__iter__", [](const Sequence &s) { return py::make_iterator(s.begin(), s.end()); }, - py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */) - .def("__contains__", [](const Sequence &s, float v) { return s.contains(v); }) - .def("__reversed__", [](const Sequence &s) -> Sequence { return s.reversed(); }) - /// Slicing protocol (optional) - .def("__getitem__", [](const Sequence &s, py::slice slice) -> Sequence* { - size_t start, stop, step, slicelength; - if (!slice.compute(s.size(), &start, &stop, &step, &slicelength)) - throw py::error_already_set(); - Sequence *seq = new Sequence(slicelength); - for (size_t i=0; i(seq, "Iterator") - .def("__iter__", [](PySequenceIterator &it) -> PySequenceIterator& { return it; }) - .def("__next__", &PySequenceIterator::next); - - On the actual Sequence object, the iterator would be constructed as follows: - .def("__iter__", [](py::object s) { return PySequenceIterator(s.cast(), s); }) -#endif -} diff --git a/stormpy/resources/pybind11/example/example6.py b/stormpy/resources/pybind11/example/example6.py deleted file mode 100755 index 5a014dda9..000000000 --- a/stormpy/resources/pybind11/example/example6.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example import Sequence - -s = Sequence(5) -print("s = " + str(s)) -print("len(s) = " + str(len(s))) -print("s[0], s[3] = %f %f" % (s[0], s[3])) -print('12.34 in s: ' + str(12.34 in s)) -s[0], s[3] = 12.34, 56.78 -print('12.34 in s: ' + str(12.34 in s)) -print("s[0], s[3] = %f %f" % (s[0], s[3])) -rev = reversed(s) -rev2 = s[::-1] -print("rev[0], rev[1], rev[2], rev[3], rev[4] = %f %f %f %f %f" % (rev[0], rev[1], rev[2], rev[3], rev[4])) - -for i in rev: - print(i, end=' ') -print('') -for i in rev2: - print(i, end=' ') -print('') -print(rev == rev2) -rev[0::2] = Sequence([2.0, 2.0, 2.0]) -for i in rev: - print(i, end=' ') -print('') diff --git a/stormpy/resources/pybind11/example/example6.ref b/stormpy/resources/pybind11/example/example6.ref deleted file mode 100644 index c02dc76af..000000000 --- a/stormpy/resources/pybind11/example/example6.ref +++ /dev/null @@ -1,21 +0,0 @@ -Value constructor: Creating a sequence with 5 entries -s = -len(s) = 5 -s[0], s[3] = 0.000000 0.000000 -12.34 in s: False -12.34 in s: True -s[0], s[3] = 12.340000 56.779999 -Value constructor: Creating a sequence with 5 entries -Move constructor: Creating a sequence with 5 entries -Freeing a sequence with 0 entries -Value constructor: Creating a sequence with 5 entries -rev[0], rev[1], rev[2], rev[3], rev[4] = 0.000000 56.779999 0.000000 0.000000 12.340000 -0.0 56.7799987793 0.0 0.0 12.3400001526 -0.0 56.7799987793 0.0 0.0 12.3400001526 -True -Value constructor: Creating a sequence with 3 entries -Freeing a sequence with 3 entries -2.0 56.7799987793 2.0 0.0 2.0 -Freeing a sequence with 5 entries -Freeing a sequence with 5 entries -Freeing a sequence with 5 entries diff --git a/stormpy/resources/pybind11/example/example7.cpp b/stormpy/resources/pybind11/example/example7.cpp deleted file mode 100644 index 6aabf1c1c..000000000 --- a/stormpy/resources/pybind11/example/example7.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - example/example7.cpp -- supporting Pythons' buffer protocol - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -class Matrix { -public: - Matrix(size_t rows, size_t cols) : m_rows(rows), m_cols(cols) { - std::cout << "Value constructor: Creating a " << rows << "x" << cols << " matrix " << std::endl; - m_data = new float[rows*cols]; - memset(m_data, 0, sizeof(float) * rows * cols); - } - - Matrix(const Matrix &s) : m_rows(s.m_rows), m_cols(s.m_cols) { - std::cout << "Copy constructor: Creating a " << m_rows << "x" << m_cols << " matrix " << std::endl; - m_data = new float[m_rows * m_cols]; - memcpy(m_data, s.m_data, sizeof(float) * m_rows * m_cols); - } - - Matrix(Matrix &&s) : m_rows(s.m_rows), m_cols(s.m_cols), m_data(s.m_data) { - std::cout << "Move constructor: Creating a " << m_rows << "x" << m_cols << " matrix " << std::endl; - s.m_rows = 0; - s.m_cols = 0; - s.m_data = nullptr; - } - - ~Matrix() { - std::cout << "Freeing a " << m_rows << "x" << m_cols << " matrix " << std::endl; - delete[] m_data; - } - - Matrix &operator=(const Matrix &s) { - std::cout << "Assignment operator : Creating a " << s.m_rows << "x" << s.m_cols << " matrix " << std::endl; - delete[] m_data; - m_rows = s.m_rows; - m_cols = s.m_cols; - m_data = new float[m_rows * m_cols]; - memcpy(m_data, s.m_data, sizeof(float) * m_rows * m_cols); - return *this; - } - - Matrix &operator=(Matrix &&s) { - std::cout << "Move assignment operator : Creating a " << s.m_rows << "x" << s.m_cols << " matrix " << std::endl; - if (&s != this) { - delete[] m_data; - m_rows = s.m_rows; m_cols = s.m_cols; m_data = s.m_data; - s.m_rows = 0; s.m_cols = 0; s.m_data = nullptr; - } - return *this; - } - - float operator()(size_t i, size_t j) const { - return m_data[i*m_cols + j]; - } - - float &operator()(size_t i, size_t j) { - return m_data[i*m_cols + j]; - } - - float *data() { return m_data; } - - size_t rows() const { return m_rows; } - size_t cols() const { return m_cols; } -private: - size_t m_rows; - size_t m_cols; - float *m_data; -}; - -void init_ex7(py::module &m) { - py::class_ mtx(m, "Matrix"); - - mtx.def(py::init()) - /// Construct from a buffer - .def("__init__", [](Matrix &v, py::buffer b) { - py::buffer_info info = b.request(); - if (info.format != py::format_descriptor::value || info.ndim != 2) - throw std::runtime_error("Incompatible buffer format!"); - new (&v) Matrix(info.shape[0], info.shape[1]); - memcpy(v.data(), info.ptr, sizeof(float) * v.rows() * v.cols()); - }) - - .def("rows", &Matrix::rows) - .def("cols", &Matrix::cols) - - /// Bare bones interface - .def("__getitem__", [](const Matrix &m, std::pair i) { - if (i.first >= m.rows() || i.second >= m.cols()) - throw py::index_error(); - return m(i.first, i.second); - }) - .def("__setitem__", [](Matrix &m, std::pair i, float v) { - if (i.first >= m.rows() || i.second >= m.cols()) - throw py::index_error(); - m(i.first, i.second) = v; - }) - /// Provide buffer access - .def_buffer([](Matrix &m) -> py::buffer_info { - return py::buffer_info( - m.data(), /* Pointer to buffer */ - sizeof(float), /* Size of one scalar */ - py::format_descriptor::value, /* Python struct-style format descriptor */ - 2, /* Number of dimensions */ - { m.rows(), m.cols() }, /* Buffer dimensions */ - { sizeof(float) * m.rows(), /* Strides (in bytes) for each index */ - sizeof(float) } - ); - }); -} diff --git a/stormpy/resources/pybind11/example/example7.py b/stormpy/resources/pybind11/example/example7.py deleted file mode 100755 index 62d330174..000000000 --- a/stormpy/resources/pybind11/example/example7.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example import Matrix - -try: - import numpy as np -except ImportError: - print('NumPy missing') - exit(0) - -m = Matrix(5, 5) - -print(m[2, 3]) -m[2, 3] = 4 -print(m[2, 3]) - -m2 = np.array(m, copy=False) -print(m2) -print(m2[2, 3]) -m2[2, 3] = 5 -print(m[2, 3]) - -m3 = np.array([[1,2,3],[4,5,6]]).astype(np.float32) -print(m3) -m4 = Matrix(m3) -for i in range(m4.rows()): - for j in range(m4.cols()): - print(m4[i, j], end = ' ') - print() diff --git a/stormpy/resources/pybind11/example/example7.ref b/stormpy/resources/pybind11/example/example7.ref deleted file mode 100644 index 75db9633b..000000000 --- a/stormpy/resources/pybind11/example/example7.ref +++ /dev/null @@ -1,17 +0,0 @@ -Value constructor: Creating a 5x5 matrix -0.0 -4.0 -[[ 0. 0. 0. 0. 0.] - [ 0. 0. 0. 0. 0.] - [ 0. 0. 0. 4. 0.] - [ 0. 0. 0. 0. 0.] - [ 0. 0. 0. 0. 0.]] -4.0 -5.0 -[[ 1. 2. 3.] - [ 4. 5. 6.]] -Value constructor: Creating a 2x3 matrix -1.0 2.0 3.0 -4.0 5.0 6.0 -Freeing a 2x3 matrix -Freeing a 5x5 matrix diff --git a/stormpy/resources/pybind11/example/example8.cpp b/stormpy/resources/pybind11/example/example8.cpp deleted file mode 100644 index dbdd4218d..000000000 --- a/stormpy/resources/pybind11/example/example8.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - example/example8.cpp -- binding classes with custom reference counting, - implicit conversions between types - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include "object.h" - -/// Custom object with builtin reference counting (see 'object.h' for the implementation) -class MyObject1 : public Object { -public: - MyObject1(int value) : value(value) { - std::cout << toString() << " constructor" << std::endl; - } - - std::string toString() const { - return "MyObject1[" + std::to_string(value) + "]"; - } - -protected: - virtual ~MyObject1() { - std::cout << toString() << " destructor" << std::endl; - } - -private: - int value; -}; - -/// Object managed by a std::shared_ptr<> -class MyObject2 { -public: - MyObject2(int value) : value(value) { - std::cout << toString() << " constructor" << std::endl; - } - - std::string toString() const { - return "MyObject2[" + std::to_string(value) + "]"; - } - - virtual ~MyObject2() { - std::cout << toString() << " destructor" << std::endl; - } - -private: - int value; -}; - -/// Object managed by a std::shared_ptr<>, additionally derives from std::enable_shared_from_this<> -class MyObject3 : public std::enable_shared_from_this { -public: - MyObject3(int value) : value(value) { - std::cout << toString() << " constructor" << std::endl; - } - - std::string toString() const { - return "MyObject3[" + std::to_string(value) + "]"; - } - - virtual ~MyObject3() { - std::cout << toString() << " destructor" << std::endl; - } - -private: - int value; -}; - -/// Make pybind aware of the ref-counted wrapper type (s) -PYBIND11_DECLARE_HOLDER_TYPE(T, ref); -PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr); - -Object *make_object_1() { return new MyObject1(1); } -ref make_object_2() { return new MyObject1(2); } - -MyObject1 *make_myobject1_1() { return new MyObject1(4); } -ref make_myobject1_2() { return new MyObject1(5); } - -MyObject2 *make_myobject2_1() { return new MyObject2(6); } -std::shared_ptr make_myobject2_2() { return std::make_shared(7); } - -MyObject3 *make_myobject3_1() { return new MyObject3(8); } -std::shared_ptr make_myobject3_2() { return std::make_shared(9); } - -void print_object_1(const Object *obj) { std::cout << obj->toString() << std::endl; } -void print_object_2(ref obj) { std::cout << obj->toString() << std::endl; } -void print_object_3(const ref &obj) { std::cout << obj->toString() << std::endl; } -void print_object_4(const ref *obj) { std::cout << (*obj)->toString() << std::endl; } - -void print_myobject1_1(const MyObject1 *obj) { std::cout << obj->toString() << std::endl; } -void print_myobject1_2(ref obj) { std::cout << obj->toString() << std::endl; } -void print_myobject1_3(const ref &obj) { std::cout << obj->toString() << std::endl; } -void print_myobject1_4(const ref *obj) { std::cout << (*obj)->toString() << std::endl; } - -void print_myobject2_1(const MyObject2 *obj) { std::cout << obj->toString() << std::endl; } -void print_myobject2_2(std::shared_ptr obj) { std::cout << obj->toString() << std::endl; } -void print_myobject2_3(const std::shared_ptr &obj) { std::cout << obj->toString() << std::endl; } -void print_myobject2_4(const std::shared_ptr *obj) { std::cout << (*obj)->toString() << std::endl; } - -void print_myobject3_1(const MyObject3 *obj) { std::cout << obj->toString() << std::endl; } -void print_myobject3_2(std::shared_ptr obj) { std::cout << obj->toString() << std::endl; } -void print_myobject3_3(const std::shared_ptr &obj) { std::cout << obj->toString() << std::endl; } -void print_myobject3_4(const std::shared_ptr *obj) { std::cout << (*obj)->toString() << std::endl; } - -void init_ex8(py::module &m) { - py::class_> obj(m, "Object"); - obj.def("getRefCount", &Object::getRefCount); - - py::class_>(m, "MyObject1", obj) - .def(py::init()); - - m.def("make_object_1", &make_object_1); - m.def("make_object_2", &make_object_2); - m.def("make_myobject1_1", &make_myobject1_1); - m.def("make_myobject1_2", &make_myobject1_2); - m.def("print_object_1", &print_object_1); - m.def("print_object_2", &print_object_2); - m.def("print_object_3", &print_object_3); - m.def("print_object_4", &print_object_4); - m.def("print_myobject1_1", &print_myobject1_1); - m.def("print_myobject1_2", &print_myobject1_2); - m.def("print_myobject1_3", &print_myobject1_3); - m.def("print_myobject1_4", &print_myobject1_4); - - py::class_>(m, "MyObject2") - .def(py::init()); - m.def("make_myobject2_1", &make_myobject2_1); - m.def("make_myobject2_2", &make_myobject2_2); - m.def("print_myobject2_1", &print_myobject2_1); - m.def("print_myobject2_2", &print_myobject2_2); - m.def("print_myobject2_3", &print_myobject2_3); - m.def("print_myobject2_4", &print_myobject2_4); - - py::class_>(m, "MyObject3") - .def(py::init()); - m.def("make_myobject3_1", &make_myobject3_1); - m.def("make_myobject3_2", &make_myobject3_2); - m.def("print_myobject3_1", &print_myobject3_1); - m.def("print_myobject3_2", &print_myobject3_2); - m.def("print_myobject3_3", &print_myobject3_3); - m.def("print_myobject3_4", &print_myobject3_4); - - py::implicitly_convertible(); -} diff --git a/stormpy/resources/pybind11/example/example8.py b/stormpy/resources/pybind11/example/example8.py deleted file mode 100755 index b12c5b999..000000000 --- a/stormpy/resources/pybind11/example/example8.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example import MyObject1 -from example import MyObject2 -from example import MyObject3 - -from example import make_object_1 -from example import make_object_2 -from example import make_myobject1_1 -from example import make_myobject1_2 -from example import make_myobject2_1 -from example import make_myobject2_2 -from example import make_myobject3_1 -from example import make_myobject3_2 - -from example import print_object_1 -from example import print_object_2 -from example import print_object_3 -from example import print_object_4 - -from example import print_myobject1_1 -from example import print_myobject1_2 -from example import print_myobject1_3 -from example import print_myobject1_4 - -from example import print_myobject2_1 -from example import print_myobject2_2 -from example import print_myobject2_3 -from example import print_myobject2_4 - -from example import print_myobject3_1 -from example import print_myobject3_2 -from example import print_myobject3_3 -from example import print_myobject3_4 - -for o in [make_object_1(), make_object_2(), MyObject1(3)]: - print("Reference count = %i" % o.getRefCount()) - print_object_1(o) - print_object_2(o) - print_object_3(o) - print_object_4(o) - -for o in [make_myobject1_1(), make_myobject1_2(), MyObject1(6), 7]: - print(o) - if not isinstance(o, int): - print_object_1(o) - print_object_2(o) - print_object_3(o) - print_object_4(o) - print_myobject1_1(o) - print_myobject1_2(o) - print_myobject1_3(o) - print_myobject1_4(o) - -for o in [MyObject2(8), make_myobject2_1(), make_myobject2_2()]: - print(o) - print_myobject2_1(o) - print_myobject2_2(o) - print_myobject2_3(o) - print_myobject2_4(o) - -for o in [MyObject3(9), make_myobject3_1(), make_myobject3_2()]: - print(o) - print_myobject3_1(o) - print_myobject3_2(o) - print_myobject3_3(o) - print_myobject3_4(o) diff --git a/stormpy/resources/pybind11/example/example8.ref b/stormpy/resources/pybind11/example/example8.ref deleted file mode 100644 index 641abd0c4..000000000 --- a/stormpy/resources/pybind11/example/example8.ref +++ /dev/null @@ -1,243 +0,0 @@ -MyObject1[1] constructor -Initialized ref from pointer 0x1347ba0 -MyObject1[2] constructor -Initialized ref from pointer 0x12b9270 -Initialized ref from ref 0x12b9270 -Destructing ref 0x12b9270 -MyObject1[3] constructor -Initialized ref from pointer 0x12a2a90 -MyObject1[1] -Created empty ref -Assigning ref 0x1347ba0 -Initialized ref from ref 0x1347ba0 -MyObject1[1] -Destructing ref 0x1347ba0 -Destructing ref 0x1347ba0 -Created empty ref -Assigning ref 0x1347ba0 -MyObject1[1] -Destructing ref 0x1347ba0 -Created empty ref -Assigning ref 0x1347ba0 -MyObject1[1] -Destructing ref 0x1347ba0 -MyObject1[2] -Created empty ref -Assigning ref 0x12b9270 -Initialized ref from ref 0x12b9270 -MyObject1[2] -Destructing ref 0x12b9270 -Destructing ref 0x12b9270 -Created empty ref -Assigning ref 0x12b9270 -MyObject1[2] -Destructing ref 0x12b9270 -Created empty ref -Assigning ref 0x12b9270 -MyObject1[2] -Destructing ref 0x12b9270 -MyObject1[3] -Created empty ref -Assigning ref 0x12a2a90 -Initialized ref from ref 0x12a2a90 -MyObject1[3] -Destructing ref 0x12a2a90 -Destructing ref 0x12a2a90 -Created empty ref -Assigning ref 0x12a2a90 -MyObject1[3] -Destructing ref 0x12a2a90 -Created empty ref -Assigning ref 0x12a2a90 -MyObject1[3] -Destructing ref 0x12a2a90 -Destructing ref 0x12b9270 -MyObject1[2] destructor -Destructing ref 0x1347ba0 -MyObject1[1] destructor -MyObject1[4] constructor -Initialized ref from pointer 0x1347ba0 -MyObject1[5] constructor -Initialized ref from pointer 0x1299190 -Initialized ref from ref 0x1299190 -Destructing ref 0x1299190 -MyObject1[6] constructor -Initialized ref from pointer 0x133e2f0 -Destructing ref 0x12a2a90 -MyObject1[3] destructor -MyObject1[4] -Created empty ref -Assigning ref 0x1347ba0 -Initialized ref from ref 0x1347ba0 -MyObject1[4] -Destructing ref 0x1347ba0 -Destructing ref 0x1347ba0 -Created empty ref -Assigning ref 0x1347ba0 -MyObject1[4] -Destructing ref 0x1347ba0 -Created empty ref -Assigning ref 0x1347ba0 -MyObject1[4] -Destructing ref 0x1347ba0 -MyObject1[4] -Created empty ref -Assigning ref 0x1347ba0 -Initialized ref from ref 0x1347ba0 -MyObject1[4] -Destructing ref 0x1347ba0 -Destructing ref 0x1347ba0 -Created empty ref -Assigning ref 0x1347ba0 -MyObject1[4] -Destructing ref 0x1347ba0 -Created empty ref -Assigning ref 0x1347ba0 -MyObject1[4] -Destructing ref 0x1347ba0 -MyObject1[5] -Created empty ref -Assigning ref 0x1299190 -Initialized ref from ref 0x1299190 -MyObject1[5] -Destructing ref 0x1299190 -Destructing ref 0x1299190 -Created empty ref -Assigning ref 0x1299190 -MyObject1[5] -Destructing ref 0x1299190 -Created empty ref -Assigning ref 0x1299190 -MyObject1[5] -Destructing ref 0x1299190 -MyObject1[5] -Created empty ref -Assigning ref 0x1299190 -Initialized ref from ref 0x1299190 -MyObject1[5] -Destructing ref 0x1299190 -Destructing ref 0x1299190 -Created empty ref -Assigning ref 0x1299190 -MyObject1[5] -Destructing ref 0x1299190 -Created empty ref -Assigning ref 0x1299190 -MyObject1[5] -Destructing ref 0x1299190 -MyObject1[6] -Created empty ref -Assigning ref 0x133e2f0 -Initialized ref from ref 0x133e2f0 -MyObject1[6] -Destructing ref 0x133e2f0 -Destructing ref 0x133e2f0 -Created empty ref -Assigning ref 0x133e2f0 -MyObject1[6] -Destructing ref 0x133e2f0 -Created empty ref -Assigning ref 0x133e2f0 -MyObject1[6] -Destructing ref 0x133e2f0 -MyObject1[6] -Created empty ref -Assigning ref 0x133e2f0 -Initialized ref from ref 0x133e2f0 -MyObject1[6] -Destructing ref 0x133e2f0 -Destructing ref 0x133e2f0 -Created empty ref -Assigning ref 0x133e2f0 -MyObject1[6] -Destructing ref 0x133e2f0 -Created empty ref -Assigning ref 0x133e2f0 -MyObject1[6] -Destructing ref 0x133e2f0 -MyObject1[7] constructor -Initialized ref from pointer 0x133f3a0 -MyObject1[7] -Destructing ref 0x133f3a0 -MyObject1[7] destructor -Created empty ref -MyObject1[7] constructor -Initialized ref from pointer 0x12a2a90 -Assigning ref 0x12a2a90 -Initialized ref from ref 0x12a2a90 -MyObject1[7] -Destructing ref 0x12a2a90 -Destructing ref 0x12a2a90 -Destructing ref 0x12a2a90 -MyObject1[7] destructor -Created empty ref -MyObject1[7] constructor -Initialized ref from pointer 0x133f3a0 -Assigning ref 0x133f3a0 -MyObject1[7] -Destructing ref 0x133f3a0 -Destructing ref 0x133f3a0 -MyObject1[7] destructor -Created empty ref -MyObject1[7] constructor -Initialized ref from pointer 0x12a2a90 -Assigning ref 0x12a2a90 -MyObject1[7] -Destructing ref 0x12a2a90 -Destructing ref 0x12a2a90 -MyObject1[7] destructor -Destructing ref 0x133e2f0 -MyObject1[6] destructor -Destructing ref 0x1299190 -MyObject1[5] destructor -Destructing ref 0x1347ba0 -MyObject1[4] destructor -MyObject2[8] constructor -MyObject2[6] constructor -MyObject2[7] constructor -MyObject2[8] -MyObject2[8] -MyObject2[8] -MyObject2[8] -MyObject2[6] -MyObject2[6] -MyObject2[6] -MyObject2[6] -MyObject2[7] -MyObject2[7] -MyObject2[7] -MyObject2[7] -MyObject2[6] destructor -MyObject2[8] destructor -MyObject3[9] constructor -MyObject3[8] constructor -MyObject3[9] constructor -MyObject2[7] destructor -MyObject3[9] -MyObject3[9] -MyObject3[9] -MyObject3[9] -MyObject3[8] -MyObject3[8] -MyObject3[8] -MyObject3[8] -MyObject3[9] -MyObject3[9] -MyObject3[9] -MyObject3[9] -MyObject3[8] destructor -MyObject3[9] destructor -Reference count = 1 -Reference count = 1 -Reference count = 1 - - - -7 - - - - - - -MyObject3[9] destructor diff --git a/stormpy/resources/pybind11/example/example9.cpp b/stormpy/resources/pybind11/example/example9.cpp deleted file mode 100644 index ca75ecc79..000000000 --- a/stormpy/resources/pybind11/example/example9.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - example/example9.cpp -- nested modules, importing modules, and - internal references - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" - -void submodule_func() { - std::cout << "submodule_func()" << std::endl; -} - -class A { -public: - A(int v) : v(v) { std::cout << "A constructor" << std::endl; } - ~A() { std::cout << "A destructor" << std::endl; } - A(const A&) { std::cout << "A copy constructor" << std::endl; } - std::string toString() { return "A[" + std::to_string(v) + "]"; } -private: - int v; -}; - -class B { -public: - B() { std::cout << "B constructor" << std::endl; } - ~B() { std::cout << "B destructor" << std::endl; } - B(const B&) { std::cout << "B copy constructor" << std::endl; } - A &get_a1() { return a1; } - A &get_a2() { return a2; } - - A a1{1}; - A a2{2}; -}; - -void init_ex9(py::module &m) { - py::module m_sub = m.def_submodule("submodule"); - m_sub.def("submodule_func", &submodule_func); - - py::class_(m_sub, "A") - .def(py::init()) - .def("__repr__", &A::toString); - - py::class_(m_sub, "B") - .def(py::init<>()) - .def("get_a1", &B::get_a1, "Return the internal A 1", py::return_value_policy::reference_internal) - .def("get_a2", &B::get_a2, "Return the internal A 2", py::return_value_policy::reference_internal) - .def_readwrite("a1", &B::a1) // def_readonly uses an internal reference return policy by default - .def_readwrite("a2", &B::a2); - - m.attr("OD") = py::module::import("collections").attr("OrderedDict"); -} diff --git a/stormpy/resources/pybind11/example/example9.py b/stormpy/resources/pybind11/example/example9.py deleted file mode 100755 index 2262fcf5c..000000000 --- a/stormpy/resources/pybind11/example/example9.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -import example - -print(example.__name__) -print(example.submodule.__name__) - -from example.submodule import * -from example import OD - -submodule_func() - -b = B() -print(b.get_a1()) -print(b.a1) -print(b.get_a2()) -print(b.a2) - -b.a1 = A(42) -b.a2 = A(43) - -print(b.get_a1()) -print(b.a1) -print(b.get_a2()) -print(b.a2) - -print(OD([(1, 'a'), (2, 'b')])) diff --git a/stormpy/resources/pybind11/example/example9.ref b/stormpy/resources/pybind11/example/example9.ref deleted file mode 100644 index 9c783135c..000000000 --- a/stormpy/resources/pybind11/example/example9.ref +++ /dev/null @@ -1,22 +0,0 @@ -example -example.submodule -submodule_func() -A constructor -A constructor -B constructor -A[1] -A[1] -A[2] -A[2] -A constructor -A destructor -A constructor -A destructor -A[42] -A[42] -A[43] -A[43] -OrderedDict([(1, 'a'), (2, 'b')]) -B destructor -A destructor -A destructor diff --git a/stormpy/resources/pybind11/example/issues.cpp b/stormpy/resources/pybind11/example/issues.cpp deleted file mode 100644 index d75da1cef..000000000 --- a/stormpy/resources/pybind11/example/issues.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - example/issues.cpp -- collection of testcases for miscellaneous issues - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#include "example.h" -#include - -PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr); - -void init_issues(py::module &m) { - py::module m2 = m.def_submodule("issues"); - -#if !defined(_MSC_VER) - // Visual Studio 2015 currently cannot compile this test - // (see the comment in type_caster_base::make_copy_constructor) - // #70 compilation issue if operator new is not public - class NonConstructible { private: void *operator new(size_t bytes) throw(); }; - py::class_(m, "Foo"); - m2.def("getstmt", []() -> NonConstructible * { return nullptr; }, - py::return_value_policy::reference); -#endif - - // #137: const char* isn't handled properly - m2.def("print_cchar", [](const char *string) { std::cout << string << std::endl; }); - - // #150: char bindings broken - m2.def("print_char", [](char c) { std::cout << c << std::endl; }); - - // #159: virtual function dispatch has problems with similar-named functions - struct Base { virtual void dispatch(void) const { - /* for some reason MSVC2015 can't compile this if the function is pure virtual */ - }; }; - - struct DispatchIssue : Base { - virtual void dispatch(void) const { - PYBIND11_OVERLOAD_PURE(void, Base, dispatch, /* no arguments */); - } - }; - - py::class_, DispatchIssue>(m2, "DispatchIssue") - .def(py::init<>()) - .def("dispatch", &Base::dispatch); - - m2.def("dispatch_issue_go", [](const Base * b) { b->dispatch(); }); - - struct Placeholder { int i; Placeholder(int i) : i(i) { } }; - - py::class_(m2, "Placeholder") - .def(py::init()) - .def("__repr__", [](const Placeholder &p) { return "Placeholder[" + std::to_string(p.i) + "]"; }); - - // #171: Can't return reference wrappers (or STL datastructures containing them) - m2.def("return_vec_of_reference_wrapper", [](std::reference_wrapper p4){ - Placeholder *p1 = new Placeholder{1}; - Placeholder *p2 = new Placeholder{2}; - Placeholder *p3 = new Placeholder{3}; - std::vector> v; - v.push_back(std::ref(*p1)); - v.push_back(std::ref(*p2)); - v.push_back(std::ref(*p3)); - v.push_back(p4); - return v; - }); - - // #181: iterator passthrough did not compile - m2.def("iterator_passthrough", [](py::iterator s) -> py::iterator { - return py::make_iterator(std::begin(s), std::end(s)); - }); - - // #187: issue involving std::shared_ptr<> return value policy & garbage collection - struct ElementBase { virtual void foo() { } /* Force creation of virtual table */ }; - struct ElementA : ElementBase { - ElementA(int v) : v(v) { } - int value() { return v; } - int v; - }; - - struct ElementList { - void add(std::shared_ptr e) { l.push_back(e); } - std::vector> l; - }; - - py::class_> (m2, "ElementBase"); - - py::class_>(m2, "ElementA", py::base()) - .def(py::init()) - .def("value", &ElementA::value); - - py::class_>(m2, "ElementList") - .def(py::init<>()) - .def("add", &ElementList::add) - .def("get", [](ElementList &el){ - py::list list; - for (auto &e : el.l) - list.append(py::cast(e)); - return list; - }); - - // (no id): should not be able to pass 'None' to a reference argument - m2.def("print_element", [](ElementA &el) { std::cout << el.value() << std::endl; }); - - // (no id): don't cast doubles to ints - m2.def("expect_float", [](float f) { return f; }); - m2.def("expect_int", [](int i) { return i; }); - - // (no id): don't invoke Python dispatch code when instantiating C++ - // classes that were not extended on the Python side - struct A { - virtual ~A() {} - virtual void f() { std::cout << "A.f()" << std::endl; } - }; - - struct PyA : A { - PyA() { std::cout << "PyA.PyA()" << std::endl; } - - void f() override { - std::cout << "PyA.f()" << std::endl; - PYBIND11_OVERLOAD(void, A, f); - } - }; - - auto call_f = [](A *a) { a->f(); }; - - pybind11::class_, PyA>(m2, "A") - .def(py::init<>()) - .def("f", &A::f); - - m2.def("call_f", call_f); - - try { - py::class_(m2, "Placeholder"); - throw std::logic_error("Expected an exception!"); - } catch (std::runtime_error &) { - /* All good */ - } -} diff --git a/stormpy/resources/pybind11/example/issues.py b/stormpy/resources/pybind11/example/issues.py deleted file mode 100644 index 257f08e18..000000000 --- a/stormpy/resources/pybind11/example/issues.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import sys -sys.path.append('.') - -from example.issues import print_cchar, print_char -from example.issues import DispatchIssue, dispatch_issue_go -from example.issues import Placeholder, return_vec_of_reference_wrapper -from example.issues import iterator_passthrough -from example.issues import ElementList, ElementA, print_element -from example.issues import expect_float, expect_int -from example.issues import A, call_f -import gc - -print_cchar("const char *") -print_char('c') - - -class PyClass1(DispatchIssue): - def dispatch(self): - print("Yay..") - - -class PyClass2(DispatchIssue): - def dispatch(self): - try: - super(PyClass2, self).dispatch() - except Exception as e: - print("Failed as expected: " + str(e)) - p = PyClass1() - dispatch_issue_go(p) - -b = PyClass2() -dispatch_issue_go(b) - -print(return_vec_of_reference_wrapper(Placeholder(4))) - -print(list(iterator_passthrough(iter([3, 5, 7, 9, 11, 13, 15])))) - -el = ElementList() -for i in range(10): - el.add(ElementA(i)) -gc.collect() -for i, v in enumerate(el.get()): - print("%i==%i, " % (i, v.value()), end='') -print() - -try: - print_element(None) -except Exception as e: - print("Failed as expected: " + str(e)) - -try: - print(expect_int(5.2)) -except Exception as e: - print("Failed as expected: " + str(e)) - -print(expect_float(12)) - -class B(A): - def __init__(self): - super(B, self).__init__() - - def f(self): - print("In python f()") - -print("C++ version") -a = A() -call_f(a) - -print("Python version") -b = B() -call_f(b) - diff --git a/stormpy/resources/pybind11/example/issues.ref b/stormpy/resources/pybind11/example/issues.ref deleted file mode 100644 index 58cc7985f..000000000 --- a/stormpy/resources/pybind11/example/issues.ref +++ /dev/null @@ -1,20 +0,0 @@ -const char * -c -Failed as expected: Tried to call pure virtual function "Base::dispatch" -Yay.. -[Placeholder[1], Placeholder[2], Placeholder[3], Placeholder[4]] -[3, 5, 7, 9, 11, 13, 15] -0==0, 1==1, 2==2, 3==3, 4==4, 5==5, 6==6, 7==7, 8==8, 9==9, -Failed as expected: Incompatible function arguments. The following argument types are supported: - 1. (example.issues.ElementA) -> NoneType - Invoked with: None -Failed as expected: Incompatible function arguments. The following argument types are supported: - 1. (int) -> int - Invoked with: 5.2 -12.0 -C++ version -A.f() -Python version -PyA.PyA() -PyA.f() -In python f() diff --git a/stormpy/resources/pybind11/example/object.h b/stormpy/resources/pybind11/example/object.h deleted file mode 100644 index 8097bd671..000000000 --- a/stormpy/resources/pybind11/example/object.h +++ /dev/null @@ -1,160 +0,0 @@ -#if !defined(__OBJECT_H) -#define __OBJECT_H - -#include - -/// Reference counted object base class -class Object { -public: - /// Default constructor - Object() { } - - /// Copy constructor - Object(const Object &) : m_refCount(0) {} - - /// Return the current reference count - int getRefCount() const { return m_refCount; }; - - /// Increase the object's reference count by one - void incRef() const { ++m_refCount; } - - /** \brief Decrease the reference count of - * the object and possibly deallocate it. - * - * The object will automatically be deallocated once - * the reference count reaches zero. - */ - void decRef(bool dealloc = true) const { - --m_refCount; - if (m_refCount == 0 && dealloc) - delete this; - else if (m_refCount < 0) - throw std::runtime_error("Internal error: reference count < 0!"); - } - - virtual std::string toString() const = 0; -protected: - /** \brief Virtual protected deconstructor. - * (Will only be called by \ref ref) - */ - virtual ~Object() { } -private: - mutable std::atomic m_refCount { 0 }; -}; - -/** - * \brief Reference counting helper - * - * The \a ref refeference template is a simple wrapper to store a - * pointer to an object. It takes care of increasing and decreasing - * the reference count of the object. When the last reference goes - * out of scope, the associated object will be deallocated. - * - * \ingroup libcore - */ -template class ref { -public: - /// Create a nullptr reference - ref() : m_ptr(nullptr) { std::cout << "Created empty ref" << std::endl; } - - /// Construct a reference from a pointer - ref(T *ptr) : m_ptr(ptr) { - std::cout << "Initialized ref from pointer " << ptr<< std::endl; - if (m_ptr) ((Object *) m_ptr)->incRef(); - } - - /// Copy constructor - ref(const ref &r) : m_ptr(r.m_ptr) { - std::cout << "Initialized ref from ref " << r.m_ptr << std::endl; - if (m_ptr) - ((Object *) m_ptr)->incRef(); - } - - /// Move constructor - ref(ref &&r) : m_ptr(r.m_ptr) { - std::cout << "Initialized ref with move from ref " << r.m_ptr << std::endl; - r.m_ptr = nullptr; - } - - /// Destroy this reference - ~ref() { - std::cout << "Destructing ref " << m_ptr << std::endl; - if (m_ptr) - ((Object *) m_ptr)->decRef(); - } - - /// Move another reference into the current one - ref& operator=(ref&& r) { - std::cout << "Move-assigning ref " << r.m_ptr << std::endl; - if (*this == r) - return *this; - if (m_ptr) - ((Object *) m_ptr)->decRef(); - m_ptr = r.m_ptr; - r.m_ptr = nullptr; - return *this; - } - - /// Overwrite this reference with another reference - ref& operator=(const ref& r) { - std::cout << "Assigning ref " << r.m_ptr << std::endl; - if (m_ptr == r.m_ptr) - return *this; - if (m_ptr) - ((Object *) m_ptr)->decRef(); - m_ptr = r.m_ptr; - if (m_ptr) - ((Object *) m_ptr)->incRef(); - return *this; - } - - /// Overwrite this reference with a pointer to another object - ref& operator=(T *ptr) { - std::cout << "Assigning ptr " << ptr << " to ref" << std::endl; - if (m_ptr == ptr) - return *this; - if (m_ptr) - ((Object *) m_ptr)->decRef(); - m_ptr = ptr; - if (m_ptr) - ((Object *) m_ptr)->incRef(); - return *this; - } - - /// Compare this reference with another reference - bool operator==(const ref &r) const { return m_ptr == r.m_ptr; } - - /// Compare this reference with another reference - bool operator!=(const ref &r) const { return m_ptr != r.m_ptr; } - - /// Compare this reference with a pointer - bool operator==(const T* ptr) const { return m_ptr == ptr; } - - /// Compare this reference with a pointer - bool operator!=(const T* ptr) const { return m_ptr != ptr; } - - /// Access the object referenced by this reference - T* operator->() { return m_ptr; } - - /// Access the object referenced by this reference - const T* operator->() const { return m_ptr; } - - /// Return a C++ reference to the referenced object - T& operator*() { return *m_ptr; } - - /// Return a const C++ reference to the referenced object - const T& operator*() const { return *m_ptr; } - - /// Return a pointer to the referenced object - operator T* () { return m_ptr; } - - /// Return a const pointer to the referenced object - T* get() { return m_ptr; } - - /// Return a pointer to the referenced object - const T* get() const { return m_ptr; } -private: - T *m_ptr; -}; - -#endif /* __OBJECT_H */ diff --git a/stormpy/resources/pybind11/example/run_test.py b/stormpy/resources/pybind11/example/run_test.py deleted file mode 100755 index 70ce4a6c0..000000000 --- a/stormpy/resources/pybind11/example/run_test.py +++ /dev/null @@ -1,73 +0,0 @@ -import sys -import os -import re -import subprocess -import difflib - -remove_unicode_marker = re.compile(r'u(\'[^\']*\')') -remove_long_marker = re.compile(r'([0-9])L') -remove_hex = re.compile(r'0x[0-9a-fA-F]+') -shorten_floats = re.compile(r'([1-9][0-9]*\.[0-9]{4})[0-9]*') - -relaxed = False - -def sanitize(lines): - lines = lines.split('\n') - for i in range(len(lines)): - line = lines[i] - if line.startswith(" |"): - line = "" - line = remove_unicode_marker.sub(r'\1', line) - line = remove_long_marker.sub(r'\1', line) - line = remove_hex.sub(r'0', line) - line = shorten_floats.sub(r'\1', line) - line = line.replace('__builtin__', 'builtins') - line = line.replace('example.', '') - line = line.replace('unicode', 'str') - line = line.replace('Example4.EMode', 'EMode') - line = line.replace('example.EMode', 'EMode') - line = line.replace('method of builtins.PyCapsule instance', '') - line = line.strip() - if relaxed: - lower = line.lower() - # The precise pattern of allocations and deallocations is dependent on the compiler - # and optimization level, so we unfortunately can't reliably check it in this kind of test case - if 'constructor' in lower or 'destructor' in lower \ - or 'ref' in lower or 'freeing' in lower: - line = "" - lines[i] = line - - return '\n'.join(sorted([l for l in lines if l != ""])) - -path = os.path.dirname(__file__) -if path != '': - os.chdir(path) - -if len(sys.argv) < 2: - print("Syntax: %s [--relaxed] " % sys.argv[0]) - exit(0) - -if len(sys.argv) == 3 and sys.argv[1] == '--relaxed': - del sys.argv[1] - relaxed = True - -name = sys.argv[1] -output_bytes = subprocess.check_output([sys.executable, name + ".py"], - stderr=subprocess.STDOUT) - -output = sanitize(output_bytes.decode('utf-8')) -reference = sanitize(open(name + '.ref', 'r').read()) - -if 'NumPy missing' in output: - print('Test "%s" could not be run.' % name) - exit(0) -elif output == reference: - print('Test "%s" succeeded.' % name) - exit(0) -else: - print('Test "%s" FAILED!' % name) - print('--- output') - print('+++ reference') - print(''.join(difflib.ndiff(output.splitlines(keepends=True), - reference.splitlines(keepends=True)))) - exit(-1) diff --git a/stormpy/resources/pybind11/include/pybind11/attr.h b/stormpy/resources/pybind11/include/pybind11/attr.h deleted file mode 100644 index 1e063a5f9..000000000 --- a/stormpy/resources/pybind11/include/pybind11/attr.h +++ /dev/null @@ -1,338 +0,0 @@ -/* - pybind11/pybind11.h: Infrastructure for processing custom - type and function attributes - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "cast.h" - -NAMESPACE_BEGIN(pybind11) - -template struct arg_t; - -/// Annotation for keyword arguments -struct arg { - constexpr explicit arg(const char *name) : name(name) { } - - template - constexpr arg_t operator=(const T &value) const { return {name, value}; } - template - constexpr arg_t operator=(T const (&value)[N]) const { - return operator=((const T *) value); - } - - const char *name; -}; - -/// Annotation for keyword arguments with default values -template struct arg_t : public arg { - constexpr arg_t(const char *name, const T &value, const char *descr = nullptr) - : arg(name), value(value), descr(descr) { } - T value; - const char *descr; -}; - -inline namespace literals { -/// String literal version of arg -constexpr arg operator"" _a(const char *name, size_t) { return arg(name); } -} - -/// Annotation for methods -struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; - -/// Annotation for parent scope -struct scope { handle value; scope(const handle &s) : value(s) { } }; - -/// Annotation for documentation -struct doc { const char *value; doc(const char *value) : value(value) { } }; - -/// Annotation for function names -struct name { const char *value; name(const char *value) : value(value) { } }; - -/// Annotation indicating that a function is an overload associated with a given "sibling" -struct sibling { handle value; sibling(const handle &value) : value(value.ptr()) { } }; - -/// Annotation indicating that a class derives from another given type -template struct base { }; - -/// Keep patient alive while nurse lives -template struct keep_alive { }; - -NAMESPACE_BEGIN(detail) -/* Forward declarations */ -enum op_id : int; -enum op_type : int; -struct undefined_t; -template struct op_; -template struct init; -template struct init_alias; -inline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret); - -/// Internal data structure which holds metadata about a keyword argument -struct argument_record { - const char *name; ///< Argument name - const char *descr; ///< Human-readable version of the argument value - handle value; ///< Associated Python object - - argument_record(const char *name, const char *descr, handle value) - : name(name), descr(descr), value(value) { } -}; - -/// Internal data structure which holds metadata about a bound function (signature, overloads, etc.) -struct function_record { - /// Function name - char *name = nullptr; /* why no C++ strings? They generate heavier code.. */ - - // User-specified documentation string - char *doc = nullptr; - - /// Human-readable version of the function signature - char *signature = nullptr; - - /// List of registered keyword arguments - std::vector args; - - /// Pointer to lambda function which converts arguments and performs the actual call - handle (*impl) (function_record *, handle, handle, handle) = nullptr; - - /// Storage for the wrapped function pointer and captured data, if any - void *data[3] = { }; - - /// Pointer to custom destructor for 'data' (if needed) - void (*free_data) (function_record *ptr) = nullptr; - - /// Return value policy associated with this function - return_value_policy policy = return_value_policy::automatic; - - /// True if name == '__init__' - bool is_constructor : 1; - - /// True if the function has a '*args' argument - bool has_args : 1; - - /// True if the function has a '**kwargs' argument - bool has_kwargs : 1; - - /// Number of arguments - uint16_t nargs; - - /// Python method object - PyMethodDef *def = nullptr; - - /// Python handle to the associated class (if this is method) - handle class_; - - /// Python handle to the parent scope (a class or a module) - handle scope; - - /// Python handle to the sibling function representing an overload chain - handle sibling; - - /// Pointer to next overload - function_record *next = nullptr; -}; - -/// Special data structure which (temporarily) holds metadata about a bound class -struct type_record { - /// Handle to the parent scope - handle scope; - - /// Name of the class - const char *name = nullptr; - - // Pointer to RTTI type_info data structure - const std::type_info *type = nullptr; - - /// How large is the underlying C++ type? - size_t type_size = 0; - - /// How large is pybind11::instance? - size_t instance_size = 0; - - /// Function pointer to class_<..>::init_holder - void (*init_holder)(PyObject *, const void *) = nullptr; - - /// Function pointer to class_<..>::dealloc - void (*dealloc)(PyObject *) = nullptr; - - // Pointer to RTTI type_info data structure of base class - const std::type_info *base_type = nullptr; - - /// OR: Python handle to base class - handle base_handle; - - /// Optional docstring - const char *doc = nullptr; -}; - -/** - * Partial template specializations to process custom attributes provided to - * cpp_function_ and class_. These are either used to initialize the respective - * fields in the type_record and function_record data structures or executed - * at runtime to deal with custom call policies (e.g. keep_alive). - */ -template struct process_attribute; - -template struct process_attribute_default { - /// Default implementation: do nothing - static void init(const T &, function_record *) { } - static void init(const T &, type_record *) { } - static void precall(handle) { } - static void postcall(handle, handle) { } -}; - -/// Process an attribute specifying the function's name -template <> struct process_attribute : process_attribute_default { - static void init(const name &n, function_record *r) { r->name = const_cast(n.value); } -}; - -/// Process an attribute specifying the function's docstring -template <> struct process_attribute : process_attribute_default { - static void init(const doc &n, function_record *r) { r->doc = const_cast(n.value); } -}; - -/// Process an attribute specifying the function's docstring (provided as a C-style string) -template <> struct process_attribute : process_attribute_default { - static void init(const char *d, function_record *r) { r->doc = const_cast(d); } - static void init(const char *d, type_record *r) { r->doc = const_cast(d); } -}; -template <> struct process_attribute : process_attribute { }; - -/// Process an attribute indicating the function's return value policy -template <> struct process_attribute : process_attribute_default { - static void init(const return_value_policy &p, function_record *r) { r->policy = p; } -}; - -/// Process an attribute which indicates that this is an overloaded function associated with a given sibling -template <> struct process_attribute : process_attribute_default { - static void init(const sibling &s, function_record *r) { r->sibling = s.value; } -}; - -/// Process an attribute which indicates that this function is a method -template <> struct process_attribute : process_attribute_default { - static void init(const is_method &s, function_record *r) { r->class_ = s.class_; r->scope = s.class_; } -}; - -/// Process an attribute which indicates the parent scope of a method -template <> struct process_attribute : process_attribute_default { - static void init(const scope &s, function_record *r) { r->scope = s.value; } -}; - - -/// Process a keyword argument attribute (*without* a default value) -template <> struct process_attribute : process_attribute_default { - static void init(const arg &a, function_record *r) { - if (r->class_ && r->args.empty()) - r->args.emplace_back("self", nullptr, handle()); - r->args.emplace_back(a.name, nullptr, handle()); - } -}; - -/// Process a keyword argument attribute (*with* a default value) -template -struct process_attribute> : process_attribute_default> { - static void init(const arg_t &a, function_record *r) { - if (r->class_ && r->args.empty()) - r->args.emplace_back("self", nullptr, handle()); - - /* Convert keyword value into a Python object */ - object o = object(detail::type_caster::type>::cast( - a.value, return_value_policy::automatic, handle()), false); - - if (!o) { -#if !defined(NDEBUG) - std::string descr(typeid(T).name()); - detail::clean_type_id(descr); - descr = "'" + std::string(a.name) + ": " + descr + "'"; - if (r->class_) { - if (r->name) - descr += " in method '" + (std::string) r->class_.str() + "." + (std::string) r->name + "'"; - else - descr += " in method of '" + (std::string) r->class_.str() + "'"; - } else if (r->name) { - descr += " in function named '" + (std::string) r->name + "'"; - } - pybind11_fail("arg(): could not convert default keyword argument " - + descr + " into a Python object (type not registered yet?)"); -#else - pybind11_fail("arg(): could not convert default keyword argument " - "into a Python object (type not registered yet?). " - "Compile in debug mode for more information."); -#endif - } - r->args.emplace_back(a.name, a.descr, o.release()); - } -}; - -/// Process a parent class attribute -template -struct process_attribute::value>::type> : process_attribute_default { - static void init(const handle &h, type_record *r) { r->base_handle = h; } -}; - -/// Process a parent class attribute -template -struct process_attribute> : process_attribute_default> { - static void init(const base &, type_record *r) { r->base_type = &typeid(T); } -}; - -/*** - * Process a keep_alive call policy -- invokes keep_alive_impl during the - * pre-call handler if both Nurse, Patient != 0 and use the post-call handler - * otherwise - */ -template struct process_attribute> : public process_attribute_default> { - template ::type = 0> - static void precall(handle args) { keep_alive_impl(Nurse, Patient, args, handle()); } - template ::type = 0> - static void postcall(handle, handle) { } - template ::type = 0> - static void precall(handle) { } - template ::type = 0> - static void postcall(handle args, handle ret) { keep_alive_impl(Nurse, Patient, args, ret); } -}; - -/// Ignore that a variable is unused in compiler warnings -inline void ignore_unused(const int *) { } - -/// Recursively iterate over variadic template arguments -template struct process_attributes { - static void init(const Args&... args, function_record *r) { - int unused[] = { 0, (process_attribute::type>::init(args, r), 0) ... }; - ignore_unused(unused); - } - static void init(const Args&... args, type_record *r) { - int unused[] = { 0, (process_attribute::type>::init(args, r), 0) ... }; - ignore_unused(unused); - } - static void precall(handle fn_args) { - int unused[] = { 0, (process_attribute::type>::precall(fn_args), 0) ... }; - ignore_unused(unused); - } - static void postcall(handle fn_args, handle fn_ret) { - int unused[] = { 0, (process_attribute::type>::postcall(fn_args, fn_ret), 0) ... }; - ignore_unused(unused); - } -}; - -/// Compile-time integer sum -constexpr size_t constexpr_sum() { return 0; } -template -constexpr size_t constexpr_sum(T n, Ts... ns) { return n + constexpr_sum(ns...); } - -/// Check the number of named arguments at compile time -template ::value...), - size_t self = constexpr_sum(std::is_same::value...)> -constexpr bool expected_num_args(size_t nargs) { - return named == 0 || (self + named) == nargs; -} - -NAMESPACE_END(detail) -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/cast.h b/stormpy/resources/pybind11/include/pybind11/cast.h deleted file mode 100644 index a4e76aab5..000000000 --- a/stormpy/resources/pybind11/include/pybind11/cast.h +++ /dev/null @@ -1,878 +0,0 @@ -/* - pybind11/cast.h: Partial template specializations to cast between - C++ and Python types - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "pytypes.h" -#include "typeid.h" -#include "descr.h" -#include -#include -#include - -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) - -/// Additional type information which does not fit into the PyTypeObject -struct type_info { - PyTypeObject *type; - size_t type_size; - void (*init_holder)(PyObject *, const void *); - std::vector implicit_conversions; - buffer_info *(*get_buffer)(PyObject *, void *) = nullptr; - void *get_buffer_data = nullptr; -}; - -PYBIND11_NOINLINE inline internals &get_internals() { - static internals *internals_ptr = nullptr; - if (internals_ptr) - return *internals_ptr; - handle builtins(PyEval_GetBuiltins()); - const char *id = PYBIND11_INTERNALS_ID; - capsule caps(builtins[id]); - if (caps.check()) { - internals_ptr = caps; - } else { - internals_ptr = new internals(); - #if defined(WITH_THREAD) - PyEval_InitThreads(); - PyThreadState *tstate = PyThreadState_Get(); - internals_ptr->tstate = PyThread_create_key(); - PyThread_set_key_value(internals_ptr->tstate, tstate); - internals_ptr->istate = tstate->interp; - #endif - builtins[id] = capsule(internals_ptr); - } - return *internals_ptr; -} - -PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type, bool throw_if_missing = true) { - auto const &type_dict = get_internals().registered_types_py; - do { - auto it = type_dict.find(type); - if (it != type_dict.end()) - return (detail::type_info *) it->second; - type = type->tp_base; - if (!type) { - if (throw_if_missing) - pybind11_fail("pybind11::detail::get_type_info: unable to find type object!"); - return nullptr; - } - } while (true); -} - -PYBIND11_NOINLINE inline detail::type_info *get_type_info(const std::type_info &tp) { - auto &types = get_internals().registered_types_cpp; - - auto it = types.find(std::type_index(tp)); - if (it != types.end()) - return (detail::type_info *) it->second; - return nullptr; -} - -PYBIND11_NOINLINE inline handle get_type_handle(const std::type_info &tp) { - detail::type_info *type_info = get_type_info(tp); - return handle(type_info ? ((PyObject *) type_info->type) : nullptr); -} - -PYBIND11_NOINLINE inline std::string error_string() { - std::string errorString; - PyThreadState *tstate = PyThreadState_GET(); - if (tstate == nullptr) - return ""; - - if (tstate->curexc_type) { - errorString += (std::string) handle(tstate->curexc_type).str(); - errorString += ": "; - } - if (tstate->curexc_value) - errorString += (std::string) handle(tstate->curexc_value).str(); - - return errorString; -} - -PYBIND11_NOINLINE inline handle get_object_handle(const void *ptr) { - auto instances = get_internals().registered_instances; - auto it = instances.find(ptr); - if (it == instances.end()) - return handle(); - return handle((PyObject *) it->second); -} - -inline PyThreadState *get_thread_state_unchecked() { -#if PY_VERSION_HEX < 0x03000000 - return _PyThreadState_Current; -#elif PY_VERSION_HEX < 0x03050000 - return (PyThreadState*) _Py_atomic_load_relaxed(&_PyThreadState_Current); -#elif PY_VERSION_HEX < 0x03050200 - return (PyThreadState*) _PyThreadState_Current.value; -#else - return _PyThreadState_UncheckedGet(); -#endif -} - -class type_caster_generic { -public: - PYBIND11_NOINLINE type_caster_generic(const std::type_info &type_info) - : typeinfo(get_type_info(type_info)) { } - - PYBIND11_NOINLINE bool load(handle src, bool convert) { - if (!src || !typeinfo) - return false; - if (src.ptr() == Py_None) { - value = nullptr; - return true; - } else if (PyType_IsSubtype(Py_TYPE(src.ptr()), typeinfo->type)) { - value = ((instance *) src.ptr())->value; - return true; - } - if (convert) { - for (auto &converter : typeinfo->implicit_conversions) { - temp = object(converter(src.ptr(), typeinfo->type), false); - if (load(temp, false)) - return true; - } - } - return false; - } - - PYBIND11_NOINLINE static handle cast(const void *_src, return_value_policy policy, handle parent, - const std::type_info *type_info, - const std::type_info *type_info_backup, - void *(*copy_constructor)(const void *), - void *(*move_constructor)(const void *), - const void *existing_holder = nullptr) { - void *src = const_cast(_src); - if (src == nullptr) - return handle(Py_None).inc_ref(); - - // avoid an issue with internal references matching their parent's address - bool dont_cache = policy == return_value_policy::reference_internal && - parent && ((instance *) parent.ptr())->value == (void *) src; - - auto& internals = get_internals(); - auto it_instance = internals.registered_instances.find(src); - if (it_instance != internals.registered_instances.end() && !dont_cache) - return handle((PyObject *) it_instance->second).inc_ref(); - - auto it = internals.registered_types_cpp.find(std::type_index(*type_info)); - if (it == internals.registered_types_cpp.end()) { - type_info = type_info_backup; - it = internals.registered_types_cpp.find(std::type_index(*type_info)); - } - - if (it == internals.registered_types_cpp.end()) { - std::string tname = type_info->name(); - detail::clean_type_id(tname); - std::string msg = "Unregistered type : " + tname; - PyErr_SetString(PyExc_TypeError, msg.c_str()); - return handle(); - } - - auto tinfo = (const detail::type_info *) it->second; - object inst(PyType_GenericAlloc(tinfo->type, 0), false); - - auto wrapper = (instance *) inst.ptr(); - - wrapper->value = src; - wrapper->owned = true; - wrapper->parent = nullptr; - - if (policy == return_value_policy::automatic) - policy = return_value_policy::take_ownership; - else if (policy == return_value_policy::automatic_reference) - policy = return_value_policy::reference; - - if (policy == return_value_policy::copy) { - wrapper->value = copy_constructor(wrapper->value); - if (wrapper->value == nullptr) - throw cast_error("return_value_policy = copy, but the object is non-copyable!"); - } else if (policy == return_value_policy::move) { - wrapper->value = move_constructor(wrapper->value); - if (wrapper->value == nullptr) - wrapper->value = copy_constructor(wrapper->value); - if (wrapper->value == nullptr) - throw cast_error("return_value_policy = move, but the object is neither movable nor copyable!"); - } else if (policy == return_value_policy::reference) { - wrapper->owned = false; - } else if (policy == return_value_policy::reference_internal) { - wrapper->owned = false; - wrapper->parent = parent.inc_ref().ptr(); - } - - tinfo->init_holder(inst.ptr(), existing_holder); - if (!dont_cache) - internals.registered_instances[wrapper->value] = inst.ptr(); - - return inst.release(); - } - -protected: - const type_info *typeinfo = nullptr; - void *value = nullptr; - object temp; -}; - -/* Determine suitable casting operator */ -template -using cast_op_type = typename std::conditional::type>::value, - typename std::add_pointer::type>::type, - typename std::add_lvalue_reference::type>::type>::type; - -/// Generic type caster for objects stored on the heap -template class type_caster_base : public type_caster_generic { -public: - static PYBIND11_DESCR name() { return type_descr(_()); } - - type_caster_base() : type_caster_generic(typeid(type)) { } - - static handle cast(const type &src, return_value_policy policy, handle parent) { - if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference) - policy = return_value_policy::copy; - return cast(&src, policy, parent); - } - - static handle cast(type &&src, return_value_policy policy, handle parent) { - if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference) - policy = return_value_policy::move; - return cast(&src, policy, parent); - } - - static handle cast(const type *src, return_value_policy policy, handle parent) { - return type_caster_generic::cast( - src, policy, parent, src ? &typeid(*src) : nullptr, &typeid(type), - make_copy_constructor(src), make_move_constructor(src)); - } - - template using cast_op_type = pybind11::detail::cast_op_type; - - operator type*() { return (type *) value; } - operator type&() { if (!value) throw cast_error(); return *((type *) value); } - -protected: - typedef void *(*Constructor)(const void *stream); -#if !defined(_MSC_VER) - /* Only enabled when the types are {copy,move}-constructible *and* when the type - does not have a private operator new implementaton. */ - template static auto make_copy_constructor(const T *value) -> decltype(new T(*value), Constructor(nullptr)) { - return [](const void *arg) -> void * { return new T(*((const T *) arg)); }; } - template static auto make_move_constructor(const T *value) -> decltype(new T(std::move(*((T *) value))), Constructor(nullptr)) { - return [](const void *arg) -> void * { return (void *) new T(std::move(*((T *) arg))); }; } -#else - /* Visual Studio 2015's SFINAE implementation doesn't yet handle the above robustly in all situations. - Use a workaround that only tests for constructibility for now. */ - template ::value>::type> - static Constructor make_copy_constructor(const T *value) { - return [](const void *arg) -> void * { return new T(*((const T *)arg)); }; } - template ::value>::type> - static Constructor make_move_constructor(const T *value) { - return [](const void *arg) -> void * { return (void *) new T(std::move(*((T *)arg))); }; } -#endif - static Constructor make_copy_constructor(...) { return nullptr; } - static Constructor make_move_constructor(...) { return nullptr; } -}; - -template class type_caster : public type_caster_base { }; - -template class type_caster> : public type_caster_base { -public: - static handle cast(const std::reference_wrapper &src, return_value_policy policy, handle parent) { - return type_caster_base::cast(&src.get(), policy, parent); - } - template using cast_op_type = std::reference_wrapper; - operator std::reference_wrapper() { return std::ref(*((type *) this->value)); } -}; - -#define PYBIND11_TYPE_CASTER(type, py_name) \ - protected: \ - type value; \ - public: \ - static PYBIND11_DESCR name() { return type_descr(py_name); } \ - static handle cast(const type *src, return_value_policy policy, handle parent) { \ - return cast(*src, policy, parent); \ - } \ - operator type*() { return &value; } \ - operator type&() { return value; } \ - template using cast_op_type = pybind11::detail::cast_op_type<_T> - -#define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type) \ - namespace pybind11 { namespace detail { \ - template class type_caster \ - : public type_caster_holder { }; \ - }} - - -template -struct type_caster< - T, typename std::enable_if::value || - std::is_floating_point::value>::type> { - typedef typename std::conditional::type _py_type_0; - typedef typename std::conditional::value, _py_type_0, typename std::make_unsigned<_py_type_0>::type>::type _py_type_1; - typedef typename std::conditional::value, double, _py_type_1>::type py_type; -public: - - bool load(handle src, bool) { - py_type py_value; - - if (!src) { - return false; - } if (std::is_floating_point::value) { - py_value = (py_type) PyFloat_AsDouble(src.ptr()); - } else if (sizeof(T) <= sizeof(long)) { - if (PyFloat_Check(src.ptr())) - return false; - if (std::is_signed::value) - py_value = (py_type) PyLong_AsLong(src.ptr()); - else - py_value = (py_type) PyLong_AsUnsignedLong(src.ptr()); - } else { - if (PyFloat_Check(src.ptr())) - return false; - if (std::is_signed::value) - py_value = (py_type) PYBIND11_LONG_AS_LONGLONG(src.ptr()); - else - py_value = (py_type) PYBIND11_LONG_AS_UNSIGNED_LONGLONG(src.ptr()); - } - - if ((py_value == (py_type) -1 && PyErr_Occurred()) || - (std::is_integral::value && sizeof(py_type) != sizeof(T) && - (py_value < (py_type) std::numeric_limits::min() || - py_value > (py_type) std::numeric_limits::max()))) { - PyErr_Clear(); - return false; - } - - value = (T) py_value; - return true; - } - - static handle cast(T src, return_value_policy /* policy */, handle /* parent */) { - if (std::is_floating_point::value) { - return PyFloat_FromDouble((double) src); - } else if (sizeof(T) <= sizeof(long)) { - if (std::is_signed::value) - return PyLong_FromLong((long) src); - else - return PyLong_FromUnsignedLong((unsigned long) src); - } else { - if (std::is_signed::value) - return PyLong_FromLongLong((long long) src); - else - return PyLong_FromUnsignedLongLong((unsigned long long) src); - } - } - - static handle cast(const T *src, return_value_policy policy, handle parent) { - return cast(*src, policy, parent); - } - - template ::value, int>::type = 0> - static PYBIND11_DESCR name() { return type_descr(_("int")); } - - template ::value, int>::type = 0> - static PYBIND11_DESCR name() { return type_descr(_("float")); } - - operator T*() { return &value; } - operator T&() { return value; } - - template using cast_op_type = pybind11::detail::cast_op_type; -protected: - T value; -}; - -template <> class type_caster { -public: - bool load(handle, bool) { return false; } - static handle cast(void_type, return_value_policy /* policy */, handle /* parent */) { - return handle(Py_None).inc_ref(); - } - PYBIND11_TYPE_CASTER(void_type, _("NoneType")); -}; - -template <> class type_caster : public type_caster { -public: - using type_caster::cast; - - bool load(handle h, bool) { - if (!h) { - return false; - } else if (h.ptr() == Py_None) { - value = nullptr; - return true; - } - - /* Check if this is a capsule */ - capsule c(h, true); - if (c.check()) { - value = (void *) c; - return true; - } - - /* Check if this is a C++ type */ - if (get_type_info((PyTypeObject *) h.get_type().ptr(), false)) { - value = ((instance *) h.ptr())->value; - return true; - } - - /* Fail */ - return false; - } - - static handle cast(const void *ptr, return_value_policy /* policy */, handle /* parent */) { - if (ptr) - return capsule(ptr).release(); - else - return handle(Py_None).inc_ref(); - } - - template using cast_op_type = void*&; - operator void *&() { return value; } - static PYBIND11_DESCR name() { return _("capsule"); } -private: - void *value = nullptr; -}; - -template <> class type_caster : public type_caster { }; - -template <> class type_caster { -public: - bool load(handle src, bool) { - if (!src) return false; - else if (src.ptr() == Py_True) { value = true; return true; } - else if (src.ptr() == Py_False) { value = false; return true; } - else return false; - } - static handle cast(bool src, return_value_policy /* policy */, handle /* parent */) { - return handle(src ? Py_True : Py_False).inc_ref(); - } - PYBIND11_TYPE_CASTER(bool, _("bool")); -}; - -template <> class type_caster { -public: - bool load(handle src, bool) { - object temp; - handle load_src = src; - if (!src) { - return false; - } else if (PyUnicode_Check(load_src.ptr())) { - temp = object(PyUnicode_AsUTF8String(load_src.ptr()), false); - if (!temp) { PyErr_Clear(); return false; } // UnicodeEncodeError - load_src = temp; - } - char *buffer; - ssize_t length; - int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(load_src.ptr(), &buffer, &length); - if (err == -1) { PyErr_Clear(); return false; } // TypeError - value = std::string(buffer, (size_t) length); - success = true; - return true; - } - - static handle cast(const std::string &src, return_value_policy /* policy */, handle /* parent */) { - return PyUnicode_FromStringAndSize(src.c_str(), (ssize_t) src.length()); - } - - PYBIND11_TYPE_CASTER(std::string, _(PYBIND11_STRING_NAME)); -protected: - bool success = false; -}; - -template class type_caster> { -public: - static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { - handle result = type_caster_base::cast(src.get(), policy, parent); - if (result) - src.release(); - return result; - } - static PYBIND11_DESCR name() { return type_caster_base::name(); } -}; - -template <> class type_caster { -public: - bool load(handle src, bool) { - object temp; - handle load_src = src; - if (!src) { - return false; - } else if (!PyUnicode_Check(load_src.ptr())) { - temp = object(PyUnicode_FromObject(load_src.ptr()), false); - if (!temp) { PyErr_Clear(); return false; } - load_src = temp; - } - wchar_t *buffer = nullptr; - ssize_t length = -1; -#if PY_MAJOR_VERSION >= 3 - buffer = PyUnicode_AsWideCharString(load_src.ptr(), &length); -#else - temp = object( - sizeof(wchar_t) == sizeof(short) - ? PyUnicode_AsUTF16String(load_src.ptr()) - : PyUnicode_AsUTF32String(load_src.ptr()), false); - if (temp) { - int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), (char **) &buffer, &length); - if (err == -1) { buffer = nullptr; } // TypeError - length = length / (ssize_t) sizeof(wchar_t) - 1; ++buffer; // Skip BOM - } -#endif - if (!buffer) { PyErr_Clear(); return false; } - value = std::wstring(buffer, (size_t) length); - success = true; - return true; - } - - static handle cast(const std::wstring &src, return_value_policy /* policy */, handle /* parent */) { - return PyUnicode_FromWideChar(src.c_str(), (ssize_t) src.length()); - } - - PYBIND11_TYPE_CASTER(std::wstring, _(PYBIND11_STRING_NAME)); -protected: - bool success = false; -}; - -template <> class type_caster : public type_caster { -public: - bool load(handle src, bool convert) { - if (src.ptr() == Py_None) return true; - return type_caster::load(src, convert); - } - - static handle cast(const char *src, return_value_policy /* policy */, handle /* parent */) { - if (src == nullptr) return handle(Py_None).inc_ref(); - return PyUnicode_FromString(src); - } - - static handle cast(char src, return_value_policy /* policy */, handle /* parent */) { - char str[2] = { src, '\0' }; - return PyUnicode_DecodeLatin1(str, 1, nullptr); - } - - operator char*() { return success ? (char *) value.c_str() : nullptr; } - operator char&() { return value[0]; } - - static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } -}; - -template <> class type_caster : public type_caster { -public: - bool load(handle src, bool convert) { - if (src.ptr() == Py_None) return true; - return type_caster::load(src, convert); - } - - static handle cast(const wchar_t *src, return_value_policy /* policy */, handle /* parent */) { - if (src == nullptr) return handle(Py_None).inc_ref(); - return PyUnicode_FromWideChar(src, (ssize_t) wcslen(src)); - } - - static handle cast(wchar_t src, return_value_policy /* policy */, handle /* parent */) { - wchar_t wstr[2] = { src, L'\0' }; - return PyUnicode_FromWideChar(wstr, 1); - } - - operator wchar_t*() { return success ? (wchar_t *) value.c_str() : nullptr; } - operator wchar_t&() { return value[0]; } - - static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } -}; - -template class type_caster> { - typedef std::pair type; -public: - bool load(handle src, bool convert) { - if (!src) - return false; - else if (!PyTuple_Check(src.ptr()) || PyTuple_Size(src.ptr()) != 2) - return false; - return first.load(PyTuple_GET_ITEM(src.ptr(), 0), convert) && - second.load(PyTuple_GET_ITEM(src.ptr(), 1), convert); - } - - static handle cast(const type &src, return_value_policy policy, handle parent) { - object o1 = object(type_caster::type>::cast(src.first, policy, parent), false); - object o2 = object(type_caster::type>::cast(src.second, policy, parent), false); - if (!o1 || !o2) - return handle(); - tuple result(2); - PyTuple_SET_ITEM(result.ptr(), 0, o1.release().ptr()); - PyTuple_SET_ITEM(result.ptr(), 1, o2.release().ptr()); - return result.release(); - } - - static PYBIND11_DESCR name() { - return type_descr( - _("(") + type_caster::type>::name() + - _(", ") + type_caster::type>::name() + _(")")); - } - - template using cast_op_type = type; - - operator type() { - return type(first .operator typename type_caster::type>::template cast_op_type(), - second.operator typename type_caster::type>::template cast_op_type()); - } -protected: - type_caster::type> first; - type_caster::type> second; -}; - -template class type_caster> { - typedef std::tuple type; - typedef std::tuple::type...> itype; - typedef std::tuple args_type; - typedef std::tuple args_kwargs_type; -public: - enum { size = sizeof...(Tuple) }; - - static constexpr const bool has_kwargs = std::is_same::value; - static constexpr const bool has_args = has_kwargs || std::is_same::value; - - bool load(handle src, bool convert) { - if (!src || !PyTuple_Check(src.ptr()) || PyTuple_GET_SIZE(src.ptr()) != size) - return false; - return load(src, convert, typename make_index_sequence::type()); - } - - template ::value && - !std::is_same::value, int>::type = 0> - bool load_args(handle args, handle, bool convert) { - return load(args, convert, typename make_index_sequence::type()); - } - - template ::value, int>::type = 0> - bool load_args(handle args, handle, bool convert) { - std::get<0>(value).load(args, convert); - return true; - } - - template ::value, int>::type = 0> - bool load_args(handle args, handle kwargs, bool convert) { - std::get<0>(value).load(args, convert); - std::get<1>(value).load(kwargs, convert); - return true; - } - - static handle cast(const type &src, return_value_policy policy, handle parent) { - return cast(src, policy, parent, typename make_index_sequence::type()); - } - - static PYBIND11_DESCR name() { - return type_descr( - _("(") + - detail::concat(type_caster::type>::name()...) + - _(")")); - } - - template typename std::enable_if::value, ReturnValue>::type call(Func &&f) { - return call(std::forward(f), typename make_index_sequence::type()); - } - - template typename std::enable_if::value, void_type>::type call(Func &&f) { - call(std::forward(f), typename make_index_sequence::type()); - return void_type(); - } - - template using cast_op_type = type; - - operator type() { - return cast(typename make_index_sequence::type()); - } - -protected: - template ReturnValue call(Func &&f, index_sequence) { - return f(std::get(value) - .operator typename type_caster::type>::template cast_op_type()...); - } - - template type cast(index_sequence) { - return type(std::get(value) - .operator typename type_caster::type>::template cast_op_type()...); - } - - template bool load(handle src, bool convert, index_sequence) { - std::array success {{ - std::get(value).load(PyTuple_GET_ITEM(src.ptr(), Indices), convert)... - }}; - (void) convert; /* avoid a warning when the tuple is empty */ - for (bool r : success) - if (!r) - return false; - return true; - } - - /* Implementation: Convert a C++ tuple into a Python tuple */ - template static handle cast(const type &src, return_value_policy policy, handle parent, index_sequence) { - std::array entries {{ - object(type_caster::type>::cast(std::get(src), policy, parent), false)... - }}; - for (const auto &entry: entries) - if (!entry) - return handle(); - tuple result(size); - int counter = 0; - for (auto & entry: entries) - PyTuple_SET_ITEM(result.ptr(), counter++, entry.release().ptr()); - return result.release(); - } - -protected: - std::tuple::type>...> value; -}; - -/// Type caster for holder types like std::shared_ptr, etc. -template class type_caster_holder : public type_caster_base { -public: - using type_caster_base::cast; - using type_caster_base::typeinfo; - using type_caster_base::value; - using type_caster_base::temp; - - bool load(handle src, bool convert) { - if (!src || !typeinfo) { - return false; - } else if (src.ptr() == Py_None) { - value = nullptr; - return true; - } else if (PyType_IsSubtype(Py_TYPE(src.ptr()), typeinfo->type)) { - auto inst = (instance *) src.ptr(); - value = (void *) inst->value; - holder = inst->holder; - return true; - } - - if (convert) { - for (auto &converter : typeinfo->implicit_conversions) { - temp = object(converter(src.ptr(), typeinfo->type), false); - if (load(temp, false)) - return true; - } - } - return false; - } - - explicit operator type*() { return this->value; } - explicit operator type&() { return *(this->value); } - explicit operator holder_type*() { return &holder; } - - // Workaround for Intel compiler bug - // see pybind11 issue 94 - #if defined(__ICC) || defined(__INTEL_COMPILER) - operator holder_type&() { return holder; } - #else - explicit operator holder_type&() { return holder; } - #endif - - static handle cast(const holder_type &src, return_value_policy, handle) { - return type_caster_generic::cast( - src.get(), return_value_policy::take_ownership, handle(), - src.get() ? &typeid(*src.get()) : nullptr, &typeid(type), - nullptr, nullptr, &src); - } - -protected: - holder_type holder; -}; - -template struct handle_type_name { static PYBIND11_DESCR name() { return _(); } }; -template <> struct handle_type_name { static PYBIND11_DESCR name() { return _(PYBIND11_BYTES_NAME); } }; -template <> struct handle_type_name { static PYBIND11_DESCR name() { return _("*args"); } }; -template <> struct handle_type_name { static PYBIND11_DESCR name() { return _("**kwargs"); } }; - -template -struct type_caster::value>::type> { -public: - template ::value, int>::type = 0> - bool load(handle src, bool /* convert */) { value = type(src); return value.check(); } - - template ::value, int>::type = 0> - bool load(handle src, bool /* convert */) { value = type(src, true); return value.check(); } - - static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) { - return src.inc_ref(); - } - PYBIND11_TYPE_CASTER(type, handle_type_name::name()); -}; - -NAMESPACE_END(detail) - -template T cast(handle handle) { - typedef detail::type_caster::type> type_caster; - type_caster conv; - if (!conv.load(handle, true)) - throw cast_error("Unable to cast Python object to C++ type"); - return conv.operator typename type_caster::template cast_op_type(); -} - -template object cast(const T &value, - return_value_policy policy = return_value_policy::automatic_reference, - handle parent = handle()) { - if (policy == return_value_policy::automatic) - policy = std::is_pointer::value ? return_value_policy::take_ownership : return_value_policy::copy; - else if (policy == return_value_policy::automatic_reference) - policy = std::is_pointer::value ? return_value_policy::reference : return_value_policy::copy; - return object(detail::type_caster::type>::cast(value, policy, parent), false); -} - -template T handle::cast() const { return pybind11::cast(*this); } -template <> inline void handle::cast() const { return; } - -template tuple make_tuple(Args&&... args_) { - const size_t size = sizeof...(Args); - std::array args { - { object(detail::type_caster::type>::cast( - std::forward(args_), policy, nullptr), false)... } - }; - for (auto &arg_value : args) - if (!arg_value) - throw cast_error("make_tuple(): unable to convert arguments to Python objects"); - tuple result(size); - int counter = 0; - for (auto &arg_value : args) - PyTuple_SET_ITEM(result.ptr(), counter++, arg_value.release().ptr()); - return result; -} - -template object handle::operator()(Args&&... args) const { - tuple args_tuple = pybind11::make_tuple(std::forward(args)...); - object result(PyObject_CallObject(m_ptr, args_tuple.ptr()), false); - if (!result) - throw error_already_set(); - return result; -} - -template object handle::call(Args &&... args) const { - return operator()(std::forward(args)...); -} - -inline object handle::operator()(detail::args_proxy args) const { - object result(PyObject_CallObject(m_ptr, args.ptr()), false); - if (!result) - throw error_already_set(); - return result; -} - -inline object handle::operator()(detail::args_proxy args, detail::kwargs_proxy kwargs) const { - object result(PyObject_Call(m_ptr, args.ptr(), kwargs.ptr()), false); - if (!result) - throw error_already_set(); - return result; -} - -#define PYBIND11_MAKE_OPAQUE(Type) \ - namespace pybind11 { namespace detail { \ - template<> class type_caster : public type_caster_base { }; \ - }} - -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/common.h b/stormpy/resources/pybind11/include/pybind11/common.h deleted file mode 100644 index 3075fb3c6..000000000 --- a/stormpy/resources/pybind11/include/pybind11/common.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - pybind11/common.h -- Basic macros - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#if !defined(NAMESPACE_BEGIN) -# define NAMESPACE_BEGIN(name) namespace name { -#endif -#if !defined(NAMESPACE_END) -# define NAMESPACE_END(name) } -#endif - -#if !defined(PYBIND11_EXPORT) -# if defined(WIN32) || defined(_WIN32) -# define PYBIND11_EXPORT __declspec(dllexport) -# else -# define PYBIND11_EXPORT __attribute__ ((visibility("default"))) -# endif -#endif - -#if defined(_MSC_VER) -# define PYBIND11_NOINLINE __declspec(noinline) -#else -# define PYBIND11_NOINLINE __attribute__ ((noinline)) -#endif - -#define PYBIND11_VERSION_MAJOR 1 -#define PYBIND11_VERSION_MINOR 9 - -/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode -#if defined(_MSC_VER) -# define HAVE_ROUND -# pragma warning(push) -# pragma warning(disable: 4510 4610 4512 4005) -# if _DEBUG -# define PYBIND11_DEBUG_MARKER -# undef _DEBUG -# endif -#endif - -#include -#include -#include - -#ifdef isalnum -# undef isalnum -# undef isalpha -# undef islower -# undef isspace -# undef isupper -# undef tolower -# undef toupper -#endif - -#if defined(_MSC_VER) -# if defined(PYBIND11_DEBUG_MARKER) -# define _DEBUG -# undef PYBIND11_DEBUG_MARKER -# endif -# pragma warning(pop) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions -#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr) -#define PYBIND11_BYTES_CHECK PyBytes_Check -#define PYBIND11_BYTES_FROM_STRING PyBytes_FromString -#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize -#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize -#define PYBIND11_BYTES_AS_STRING PyBytes_AsString -#define PYBIND11_BYTES_CHECK PyBytes_Check -#define PYBIND11_LONG_CHECK(o) PyLong_Check(o) -#define PYBIND11_LONG_AS_LONGLONG(o) PyLong_AsLongLong(o) -#define PYBIND11_LONG_AS_UNSIGNED_LONGLONG(o) PyLong_AsUnsignedLongLong(o) -#define PYBIND11_BYTES_NAME "bytes" -#define PYBIND11_STRING_NAME "str" -#define PYBIND11_SLICE_OBJECT PyObject -#define PYBIND11_FROM_STRING PyUnicode_FromString -#define PYBIND11_OB_TYPE(ht_type) (ht_type).ob_base.ob_base.ob_type -#define PYBIND11_PLUGIN_IMPL(name) \ - extern "C" PYBIND11_EXPORT PyObject *PyInit_##name() -#else -#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyMethod_New(ptr, nullptr, class_) -#define PYBIND11_BYTES_CHECK PyString_Check -#define PYBIND11_BYTES_FROM_STRING PyString_FromString -#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyString_FromStringAndSize -#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyString_AsStringAndSize -#define PYBIND11_BYTES_AS_STRING PyString_AsString -#define PYBIND11_BYTES_CHECK PyString_Check -#define PYBIND11_LONG_CHECK(o) (PyInt_Check(o) || PyLong_Check(o)) -#define PYBIND11_LONG_AS_LONGLONG(o) (PyInt_Check(o) ? (long long) PyLong_AsLong(o) : PyLong_AsLongLong(o)) -#define PYBIND11_LONG_AS_UNSIGNED_LONGLONG(o) (PyInt_Check(o) ? (unsigned long long) PyLong_AsUnsignedLong(o) : PyLong_AsUnsignedLongLong(o)) -#define PYBIND11_BYTES_NAME "str" -#define PYBIND11_STRING_NAME "unicode" -#define PYBIND11_SLICE_OBJECT PySliceObject -#define PYBIND11_FROM_STRING PyString_FromString -#define PYBIND11_OB_TYPE(ht_type) (ht_type).ob_type -#define PYBIND11_PLUGIN_IMPL(name) \ - extern "C" PYBIND11_EXPORT PyObject *init##name() -#endif - -#if PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03050200 -extern "C" { - struct _Py_atomic_address { void *value; }; - PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current; -} -#endif - -#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code -#define PYBIND11_STRINGIFY(x) #x -#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x) -#define PYBIND11_INTERNALS_ID "__pybind11_" \ - PYBIND11_TOSTRING(PYBIND11_VERSION_MAJOR) "_" PYBIND11_TOSTRING(PYBIND11_VERSION_MINOR) "__" - -#define PYBIND11_PLUGIN(name) \ - static PyObject *pybind11_init(); \ - PYBIND11_PLUGIN_IMPL(name) { \ - try { \ - return pybind11_init(); \ - } catch (const std::exception &e) { \ - PyErr_SetString(PyExc_ImportError, e.what()); \ - return nullptr; \ - } \ - } \ - PyObject *pybind11_init() - -NAMESPACE_BEGIN(pybind11) - -typedef Py_ssize_t ssize_t; - -/// Approach used to cast a previously unknown C++ instance into a Python object -enum class return_value_policy : uint8_t { - /** This is the default return value policy, which falls back to the policy - return_value_policy::take_ownership when the return value is a pointer. - Otherwise, it uses return_value::move or return_value::copy for rvalue - and lvalue references, respectively. See below for a description of what - all of these different policies do. */ - automatic = 0, - - /** As above, but use policy return_value_policy::reference when the return - value is a pointer. This is the default conversion policy for function - arguments when calling Python functions manually from C++ code (i.e. via - handle::operator()). You probably won't need to use this. */ - automatic_reference, - - /** Reference an existing object (i.e. do not create a new copy) and take - ownership. Python will call the destructor and delete operator when the - object’s reference count reaches zero. Undefined behavior ensues when - the C++ side does the same.. */ - take_ownership, - - /** Create a new copy of the returned object, which will be owned by - Python. This policy is comparably safe because the lifetimes of the two - instances are decoupled. */ - copy, - - /** Use std::move to move the return value contents into a new instance - that will be owned by Python. This policy is comparably safe because the - lifetimes of the two instances (move source and destination) are - decoupled. */ - move, - - /** Reference an existing object, but do not take ownership. The C++ side - is responsible for managing the object’s lifetime and deallocating it - when it is no longer used. Warning: undefined behavior will ensue when - the C++ side deletes an object that is still referenced and used by - Python. */ - reference, - - /** This policy only applies to methods and properties. It references the - object without taking ownership similar to the above - return_value_policy::reference policy. In contrast to that policy, the - function or property’s implicit this argument (called the parent) is - considered to be the the owner of the return value (the child). - pybind11 then couples the lifetime of the parent to the child via a - reference relationship that ensures that the parent cannot be garbage - collected while Python is still using the child. More advanced - variations of this scheme are also possible using combinations of - return_value_policy::reference and the keep_alive call policy */ - reference_internal -}; - -/// Information record describing a Python buffer object -struct buffer_info { - void *ptr; // Pointer to the underlying storage - size_t itemsize; // Size of individual items in bytes - size_t size; // Total number of entries - std::string format; // For homogeneous buffers, this should be set to format_descriptor::value - size_t ndim; // Number of dimensions - std::vector shape; // Shape of the tensor (1 entry per dimension) - std::vector strides; // Number of entries between adjacent entries (for each per dimension) - - buffer_info() : ptr(nullptr), view(nullptr) {} - buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t ndim, - const std::vector &shape, const std::vector &strides) - : ptr(ptr), itemsize(itemsize), size(1), format(format), - ndim(ndim), shape(shape), strides(strides) { - for (size_t i = 0; i < ndim; ++i) - size *= shape[i]; - } - - buffer_info(Py_buffer *view) - : ptr(view->buf), itemsize((size_t) view->itemsize), size(1), format(view->format), - ndim((size_t) view->ndim), shape((size_t) view->ndim), strides((size_t) view->ndim), view(view) { - for (size_t i = 0; i < (size_t) view->ndim; ++i) { - shape[i] = (size_t) view->shape[i]; - strides[i] = (size_t) view->strides[i]; - size *= shape[i]; - } - } - - ~buffer_info() { - if (view) { PyBuffer_Release(view); delete view; } - } -private: - Py_buffer *view = nullptr; -}; - -NAMESPACE_BEGIN(detail) - -inline static constexpr int log2(size_t n, int k = 0) { return (n <= 1) ? k : log2(n >> 1, k + 1); } - -inline std::string error_string(); - -/// Core part of the 'instance' type which POD (needed to be able to use 'offsetof') -template struct instance_essentials { - PyObject_HEAD - type *value; - PyObject *parent; - PyObject *weakrefs; - bool owned : 1; - bool constructed : 1; -}; - -/// PyObject wrapper around generic types, includes a special holder type that is responsible for lifetime management -template > struct instance : instance_essentials { - holder_type holder; -}; - -struct overload_hash { - inline std::size_t operator()(const std::pair& v) const { - size_t value = std::hash()(v.first); - value ^= std::hash()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2); - return value; - } -}; - -/// Internal data struture used to track registered instances and types -struct internals { - std::unordered_map registered_types_cpp; // std::type_index -> type_info - std::unordered_map registered_types_py; // PyTypeObject* -> type_info - std::unordered_map registered_instances; // void * -> PyObject* - std::unordered_set, overload_hash> inactive_overload_cache; -#if defined(WITH_THREAD) - decltype(PyThread_create_key()) tstate = 0; // Usually an int but a long on Cygwin64 with Python 3.x - PyInterpreterState *istate = nullptr; -#endif -}; - -/// Return a reference to the current 'internals' information -inline internals &get_internals(); - -/// Index sequence for convenient template metaprogramming involving tuples -template struct index_sequence { }; -template struct make_index_sequence : make_index_sequence { }; -template struct make_index_sequence <0, S...> { typedef index_sequence type; }; - -/// Strip the class from a method type -template struct remove_class { }; -template struct remove_class { typedef R type(A...); }; -template struct remove_class { typedef R type(A...); }; - -/// Helper template to strip away type modifiers -template struct intrinsic_type { typedef T type; }; -template struct intrinsic_type { typedef typename intrinsic_type::type type; }; -template struct intrinsic_type { typedef typename intrinsic_type::type type; }; -template struct intrinsic_type { typedef typename intrinsic_type::type type; }; -template struct intrinsic_type { typedef typename intrinsic_type::type type; }; -template struct intrinsic_type { typedef typename intrinsic_type::type type; }; -template struct intrinsic_type { typedef typename intrinsic_type::type type; }; - -/// Helper type to replace 'void' in some expressions -struct void_type { }; - -NAMESPACE_END(detail) - -#define PYBIND11_RUNTIME_EXCEPTION(name) \ - class name : public std::runtime_error { public: \ - name(const std::string &w) : std::runtime_error(w) { }; \ - name(const char *s) : std::runtime_error(s) { }; \ - name() : std::runtime_error("") { } \ - }; - -// C++ bindings of core Python exceptions -class error_already_set : public std::runtime_error { public: error_already_set() : std::runtime_error(detail::error_string()) {} }; -PYBIND11_RUNTIME_EXCEPTION(stop_iteration) -PYBIND11_RUNTIME_EXCEPTION(index_error) -PYBIND11_RUNTIME_EXCEPTION(value_error) -PYBIND11_RUNTIME_EXCEPTION(cast_error) /// Thrown when pybind11::cast or handle::call fail due to a type casting error - -[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const char *reason) { throw std::runtime_error(reason); } -[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const std::string &reason) { throw std::runtime_error(reason); } - -/// Format strings for basic number types -#define PYBIND11_DECL_FMT(t, v) template<> struct format_descriptor { static constexpr const char *value = v; } -template struct format_descriptor { }; -template struct format_descriptor::value>::type> { - static constexpr const char value[2] = - { "bBhHiIqQ"[detail::log2(sizeof(T))*2 + (std::is_unsigned::value ? 1 : 0)], '\0' }; -}; -template constexpr const char format_descriptor< - T, typename std::enable_if::value>::type>::value[2]; -PYBIND11_DECL_FMT(float, "f"); PYBIND11_DECL_FMT(double, "d"); PYBIND11_DECL_FMT(bool, "?"); - -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/complex.h b/stormpy/resources/pybind11/include/pybind11/complex.h deleted file mode 100644 index f767f354c..000000000 --- a/stormpy/resources/pybind11/include/pybind11/complex.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - pybind11/complex.h: Complex number support - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "pybind11.h" -#include - -/// glibc defines I as a macro which breaks things, e.g., boost template names -#ifdef I -# undef I -#endif - -NAMESPACE_BEGIN(pybind11) - -PYBIND11_DECL_FMT(std::complex, "Zf"); -PYBIND11_DECL_FMT(std::complex, "Zd"); - -NAMESPACE_BEGIN(detail) -template class type_caster> { -public: - bool load(handle src, bool) { - if (!src) - return false; - Py_complex result = PyComplex_AsCComplex(src.ptr()); - if (result.real == -1.0 && PyErr_Occurred()) { - PyErr_Clear(); - return false; - } - value = std::complex((T) result.real, (T) result.imag); - return true; - } - - static handle cast(const std::complex &src, return_value_policy /* policy */, handle /* parent */) { - return PyComplex_FromDoubles((double) src.real(), (double) src.imag()); - } - - PYBIND11_TYPE_CASTER(std::complex, _("complex")); -}; -NAMESPACE_END(detail) -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/descr.h b/stormpy/resources/pybind11/include/pybind11/descr.h deleted file mode 100644 index 6c1d86432..000000000 --- a/stormpy/resources/pybind11/include/pybind11/descr.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - pybind11/descr.h: Helper type for concatenating type signatures - either at runtime (C++11) or compile time (C++14) - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "common.h" - -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) - - -#if defined(__clang__) -# if __has_feature(cxx_return_type_deduction) && __has_feature(cxx_relaxed_constexpr) -# define PYBIND11_CPP14 -# endif -#elif defined(__GNUG__) -# if __cpp_constexpr >= 201304 && __cpp_decltype_auto >= 201304 -# define PYBIND11_CPP14 -# endif -#endif - -#if defined(PYBIND11_CPP14) /* Concatenate type signatures at compile time using C++14 */ - -template class descr { - template friend class descr; -public: - constexpr descr(char const (&text) [Size1+1], const std::type_info * const (&types)[Size2+1]) - : descr(text, types, - typename make_index_sequence::type(), - typename make_index_sequence::type()) { } - - constexpr const char *text() const { return m_text; } - constexpr const std::type_info * const * types() const { return m_types; } - - template - constexpr descr operator+(const descr &other) const { - return concat(other, - typename make_index_sequence::type(), - typename make_index_sequence::type(), - typename make_index_sequence::type(), - typename make_index_sequence::type()); - } - -protected: - template - constexpr descr( - char const (&text) [Size1+1], - const std::type_info * const (&types) [Size2+1], - index_sequence, index_sequence) - : m_text{text[Indices1]..., '\0'}, - m_types{types[Indices2]..., nullptr } {} - - template - constexpr descr - concat(const descr &other, - index_sequence, index_sequence, - index_sequence, index_sequence) const { - return descr( - { m_text[Indices1]..., other.m_text[OtherIndices1]..., '\0' }, - { m_types[Indices2]..., other.m_types[OtherIndices2]..., nullptr } - ); - } - -protected: - char m_text[Size1 + 1]; - const std::type_info * m_types[Size2 + 1]; -}; - -template constexpr descr _(char const(&text)[Size]) { - return descr(text, { nullptr }); -} - -template struct int_to_str : int_to_str { }; -template struct int_to_str<0, Digits...> { - static constexpr auto digits = descr({ ('0' + Digits)..., '\0' }, { nullptr }); -}; - -template auto constexpr _() { - return int_to_str::digits; -} - -template constexpr descr<1, 1> _() { - return descr<1, 1>({ '%', '\0' }, { &typeid(Type), nullptr }); -} - -inline constexpr descr<0, 0> concat() { return _(""); } -template auto constexpr concat(descr descr) { return descr; } -template auto constexpr concat(descr descr, Args&&... args) { return descr + _(", ") + concat(args...); } -template auto constexpr type_descr(descr descr) { return _("{") + descr + _("}"); } - -#define PYBIND11_DESCR constexpr auto - -#else /* Simpler C++11 implementation based on run-time memory allocation and copying */ - -class descr { -public: - PYBIND11_NOINLINE descr(const char *text, const std::type_info * const * types) { - size_t nChars = len(text), nTypes = len(types); - m_text = new char[nChars]; - m_types = new const std::type_info *[nTypes]; - memcpy(m_text, text, nChars * sizeof(char)); - memcpy(m_types, types, nTypes * sizeof(const std::type_info *)); - } - - PYBIND11_NOINLINE descr friend operator+(descr &&d1, descr &&d2) { - descr r; - - size_t nChars1 = len(d1.m_text), nTypes1 = len(d1.m_types); - size_t nChars2 = len(d2.m_text), nTypes2 = len(d2.m_types); - - r.m_text = new char[nChars1 + nChars2 - 1]; - r.m_types = new const std::type_info *[nTypes1 + nTypes2 - 1]; - memcpy(r.m_text, d1.m_text, (nChars1-1) * sizeof(char)); - memcpy(r.m_text + nChars1 - 1, d2.m_text, nChars2 * sizeof(char)); - memcpy(r.m_types, d1.m_types, (nTypes1-1) * sizeof(std::type_info *)); - memcpy(r.m_types + nTypes1 - 1, d2.m_types, nTypes2 * sizeof(std::type_info *)); - - delete[] d1.m_text; delete[] d1.m_types; - delete[] d2.m_text; delete[] d2.m_types; - - return r; - } - - char *text() { return m_text; } - const std::type_info * * types() { return m_types; } - -protected: - PYBIND11_NOINLINE descr() { } - - template static size_t len(const T *ptr) { // return length including null termination - const T *it = ptr; - while (*it++ != (T) 0) - ; - return static_cast(it - ptr); - } - - const std::type_info **m_types = nullptr; - char *m_text = nullptr; -}; - -/* The 'PYBIND11_NOINLINE inline' combinations below are intentional to get the desired linkage while producing as little object code as possible */ - -PYBIND11_NOINLINE inline descr _(const char *text) { - const std::type_info *types[1] = { nullptr }; - return descr(text, types); -} - -template PYBIND11_NOINLINE descr _() { - const std::type_info *types[2] = { &typeid(Type), nullptr }; - return descr("%", types); -} - -template PYBIND11_NOINLINE descr _() { - const std::type_info *types[1] = { nullptr }; - return descr(std::to_string(Size).c_str(), types); -} - -PYBIND11_NOINLINE inline descr concat() { return _(""); } -PYBIND11_NOINLINE inline descr concat(descr &&d) { return d; } -template PYBIND11_NOINLINE descr concat(descr &&d, Args&&... args) { return std::move(d) + _(", ") + concat(std::forward(args)...); } -PYBIND11_NOINLINE inline descr type_descr(descr&& d) { return _("{") + std::move(d) + _("}"); } - -#define PYBIND11_DESCR descr -#endif - -NAMESPACE_END(detail) -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/eigen.h b/stormpy/resources/pybind11/include/pybind11/eigen.h deleted file mode 100644 index 718107947..000000000 --- a/stormpy/resources/pybind11/include/pybind11/eigen.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - pybind11/eigen.h: Transparent conversion for dense and sparse Eigen matrices - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "numpy.h" - -#if defined(__GNUG__) || defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - -#include -#include - -#if defined(__GNUG__) || defined(__clang__) -# pragma GCC diagnostic pop -#endif - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant -#endif - -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) - -template class is_eigen_dense { -private: - template static std::true_type test(const Eigen::DenseBase &); - static std::false_type test(...); -public: - static constexpr bool value = decltype(test(std::declval()))::value; -}; - -template class is_eigen_sparse { -private: - template static std::true_type test(const Eigen::SparseMatrixBase &); - static std::false_type test(...); -public: - static constexpr bool value = decltype(test(std::declval()))::value; -}; - -template -struct type_caster::value>::type> { - typedef typename Type::Scalar Scalar; - static constexpr bool rowMajor = Type::Flags & Eigen::RowMajorBit; - static constexpr bool isVector = Type::IsVectorAtCompileTime; - - bool load(handle src, bool) { - array_t buffer(src, true); - if (!buffer.check()) - return false; - - buffer_info info = buffer.request(); - if (info.ndim == 1) { - typedef Eigen::Stride Strides; - if (!isVector && - !(Type::RowsAtCompileTime == Eigen::Dynamic && - Type::ColsAtCompileTime == Eigen::Dynamic)) - return false; - - if (Type::SizeAtCompileTime != Eigen::Dynamic && - info.shape[0] != (size_t) Type::SizeAtCompileTime) - return false; - - auto strides = Strides(info.strides[0] / sizeof(Scalar), 0); - - value = Eigen::Map( - (Scalar *) info.ptr, typename Strides::Index(info.shape[0]), 1, strides); - } else if (info.ndim == 2) { - typedef Eigen::Stride Strides; - - if ((Type::RowsAtCompileTime != Eigen::Dynamic && info.shape[0] != (size_t) Type::RowsAtCompileTime) || - (Type::ColsAtCompileTime != Eigen::Dynamic && info.shape[1] != (size_t) Type::ColsAtCompileTime)) - return false; - - auto strides = Strides( - info.strides[rowMajor ? 0 : 1] / sizeof(Scalar), - info.strides[rowMajor ? 1 : 0] / sizeof(Scalar)); - - value = Eigen::Map( - (Scalar *) info.ptr, - typename Strides::Index(info.shape[0]), - typename Strides::Index(info.shape[1]), strides); - } else { - return false; - } - return true; - } - - static handle cast(const Type *src, return_value_policy policy, handle parent) { - return cast(*src, policy, parent); - } - - static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) { - if (isVector) { - return array(buffer_info( - /* Pointer to buffer */ - const_cast(src.data()), - /* Size of one scalar */ - sizeof(Scalar), - /* Python struct-style format descriptor */ - format_descriptor::value, - /* Number of dimensions */ - 1, - /* Buffer dimensions */ - { (size_t) src.size() }, - /* Strides (in bytes) for each index */ - { sizeof(Scalar) } - )).release(); - } else { - return array(buffer_info( - /* Pointer to buffer */ - const_cast(src.data()), - /* Size of one scalar */ - sizeof(Scalar), - /* Python struct-style format descriptor */ - format_descriptor::value, - /* Number of dimensions */ - isVector ? 1 : 2, - /* Buffer dimensions */ - { (size_t) src.rows(), - (size_t) src.cols() }, - /* Strides (in bytes) for each index */ - { sizeof(Scalar) * (rowMajor ? (size_t) src.cols() : 1), - sizeof(Scalar) * (rowMajor ? 1 : (size_t) src.rows()) } - )).release(); - } - } - - template using cast_op_type = pybind11::detail::cast_op_type<_T>; - - static PYBIND11_DESCR name() { - return _("numpy.ndarray[dtype=") + npy_format_descriptor::name() + - _(", shape=(") + rows() + _(", ") + cols() + _(")]"); - } - - operator Type*() { return &value; } - operator Type&() { return value; } - -protected: - template ::type = 0> - static PYBIND11_DESCR rows() { return _("m"); } - template ::type = 0> - static PYBIND11_DESCR rows() { return _(); } - template ::type = 0> - static PYBIND11_DESCR cols() { return _("n"); } - template ::type = 0> - static PYBIND11_DESCR cols() { return _(); } - -protected: - Type value; -}; - -template -struct type_caster::value>::type> { - typedef typename Type::Scalar Scalar; - typedef typename std::remove_reference().outerIndexPtr())>::type StorageIndex; - typedef typename Type::Index Index; - static constexpr bool rowMajor = Type::Flags & Eigen::RowMajorBit; - - bool load(handle src, bool) { - if (!src) - return false; - - object obj(src, true); - object sparse_module = module::import("scipy.sparse"); - object matrix_type = sparse_module.attr( - rowMajor ? "csr_matrix" : "csc_matrix"); - - if (obj.get_type() != matrix_type.ptr()) { - try { - obj = matrix_type(obj); - } catch (const error_already_set &) { - PyErr_Clear(); - return false; - } - } - - auto valuesArray = array_t((object) obj.attr("data")); - auto innerIndicesArray = array_t((object) obj.attr("indices")); - auto outerIndicesArray = array_t((object) obj.attr("indptr")); - auto shape = pybind11::tuple((pybind11::object) obj.attr("shape")); - auto nnz = obj.attr("nnz").cast(); - - if (!valuesArray.check() || !innerIndicesArray.check() || - !outerIndicesArray.check()) - return false; - - buffer_info outerIndices = outerIndicesArray.request(); - buffer_info innerIndices = innerIndicesArray.request(); - buffer_info values = valuesArray.request(); - - value = Eigen::MappedSparseMatrix( - shape[0].cast(), - shape[1].cast(), - nnz, - static_cast(outerIndices.ptr), - static_cast(innerIndices.ptr), - static_cast(values.ptr) - ); - - return true; - } - - static handle cast(const Type *src, return_value_policy policy, handle parent) { - return cast(*src, policy, parent); - } - - static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) { - const_cast(src).makeCompressed(); - - object matrix_type = module::import("scipy.sparse").attr( - rowMajor ? "csr_matrix" : "csc_matrix"); - - array data(buffer_info( - // Pointer to buffer - const_cast(src.valuePtr()), - // Size of one scalar - sizeof(Scalar), - // Python struct-style format descriptor - format_descriptor::value, - // Number of dimensions - 1, - // Buffer dimensions - { (size_t) src.nonZeros() }, - // Strides - { sizeof(Scalar) } - )); - - array outerIndices(buffer_info( - // Pointer to buffer - const_cast(src.outerIndexPtr()), - // Size of one scalar - sizeof(StorageIndex), - // Python struct-style format descriptor - format_descriptor::value, - // Number of dimensions - 1, - // Buffer dimensions - { (size_t) (rowMajor ? src.rows() : src.cols()) + 1 }, - // Strides - { sizeof(StorageIndex) } - )); - - array innerIndices(buffer_info( - // Pointer to buffer - const_cast(src.innerIndexPtr()), - // Size of one scalar - sizeof(StorageIndex), - // Python struct-style format descriptor - format_descriptor::value, - // Number of dimensions - 1, - // Buffer dimensions - { (size_t) src.nonZeros() }, - // Strides - { sizeof(StorageIndex) } - )); - - return matrix_type( - std::make_tuple(data, innerIndices, outerIndices), - std::make_pair(src.rows(), src.cols()) - ).release(); - } - - template using cast_op_type = pybind11::detail::cast_op_type<_T>; - - template ::type = 0> - static PYBIND11_DESCR name() { return _("scipy.sparse.csr_matrix[dtype=") + npy_format_descriptor::name() + _("]"); } - template ::type = 0> - static PYBIND11_DESCR name() { return _("scipy.sparse.csc_matrix[dtype=") + npy_format_descriptor::name() + _("]"); } - - operator Type*() { return &value; } - operator Type&() { return value; } - -protected: - Type value; -}; - -NAMESPACE_END(detail) -NAMESPACE_END(pybind11) - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif diff --git a/stormpy/resources/pybind11/include/pybind11/functional.h b/stormpy/resources/pybind11/include/pybind11/functional.h deleted file mode 100644 index f74a9bdf9..000000000 --- a/stormpy/resources/pybind11/include/pybind11/functional.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - pybind11/functional.h: std::function<> support - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "pybind11.h" -#include - -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) - -template struct type_caster> { - typedef std::function type; - typedef typename std::conditional::value, void_type, Return>::type retval_type; -public: - bool load(handle src_, bool) { - src_ = detail::get_function(src_); - if (!src_ || !PyCallable_Check(src_.ptr())) - return false; - object src(src_, true); - value = [src](Args... args) -> Return { - gil_scoped_acquire acq; - object retval(src(std::move(args)...)); - /* Visual studio 2015 parser issue: need parentheses around this expression */ - return (retval.template cast()); - }; - return true; - } - - template - static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) { - return cpp_function(std::forward(f_), policy).release(); - } - - PYBIND11_TYPE_CASTER(type, _("function<") + - type_caster>::name() + _(" -> ") + - type_caster::name() + - _(">")); -}; - -NAMESPACE_END(detail) -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/numpy.h b/stormpy/resources/pybind11/include/pybind11/numpy.h deleted file mode 100644 index 0180d95cd..000000000 --- a/stormpy/resources/pybind11/include/pybind11/numpy.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - pybind11/numpy.h: Basic NumPy support, vectorize() wrapper - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "pybind11.h" -#include "complex.h" -#include -#include - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant -#endif - -NAMESPACE_BEGIN(pybind11) -namespace detail { template struct npy_format_descriptor { }; } - -class array : public buffer { -public: - struct API { - enum Entries { - API_PyArray_Type = 2, - API_PyArray_DescrFromType = 45, - API_PyArray_FromAny = 69, - API_PyArray_NewCopy = 85, - API_PyArray_NewFromDescr = 94, - - NPY_C_CONTIGUOUS_ = 0x0001, - NPY_F_CONTIGUOUS_ = 0x0002, - NPY_ARRAY_FORCECAST_ = 0x0010, - NPY_ENSURE_ARRAY_ = 0x0040, - NPY_BOOL_ = 0, - NPY_BYTE_, NPY_UBYTE_, - NPY_SHORT_, NPY_USHORT_, - NPY_INT_, NPY_UINT_, - NPY_LONG_, NPY_ULONG_, - NPY_LONGLONG_, NPY_ULONGLONG_, - NPY_FLOAT_, NPY_DOUBLE_, NPY_LONGDOUBLE_, - NPY_CFLOAT_, NPY_CDOUBLE_, NPY_CLONGDOUBLE_ - }; - - static API lookup() { - module m = module::import("numpy.core.multiarray"); - object c = (object) m.attr("_ARRAY_API"); -#if PY_MAJOR_VERSION >= 3 - void **api_ptr = (void **) (c ? PyCapsule_GetPointer(c.ptr(), NULL) : nullptr); -#else - void **api_ptr = (void **) (c ? PyCObject_AsVoidPtr(c.ptr()) : nullptr); -#endif - API api; - api.PyArray_Type_ = (decltype(api.PyArray_Type_)) api_ptr[API_PyArray_Type]; - api.PyArray_DescrFromType_ = (decltype(api.PyArray_DescrFromType_)) api_ptr[API_PyArray_DescrFromType]; - api.PyArray_FromAny_ = (decltype(api.PyArray_FromAny_)) api_ptr[API_PyArray_FromAny]; - api.PyArray_NewCopy_ = (decltype(api.PyArray_NewCopy_)) api_ptr[API_PyArray_NewCopy]; - api.PyArray_NewFromDescr_ = (decltype(api.PyArray_NewFromDescr_)) api_ptr[API_PyArray_NewFromDescr]; - return api; - } - - bool PyArray_Check_(PyObject *obj) const { return (bool) PyObject_TypeCheck(obj, PyArray_Type_); } - - PyObject *(*PyArray_DescrFromType_)(int); - PyObject *(*PyArray_NewFromDescr_) - (PyTypeObject *, PyObject *, int, Py_intptr_t *, - Py_intptr_t *, void *, int, PyObject *); - PyObject *(*PyArray_NewCopy_)(PyObject *, int); - PyTypeObject *PyArray_Type_; - PyObject *(*PyArray_FromAny_) (PyObject *, PyObject *, int, int, int, PyObject *); - }; - - PYBIND11_OBJECT_DEFAULT(array, buffer, lookup_api().PyArray_Check_) - - enum { - c_style = API::NPY_C_CONTIGUOUS_, - f_style = API::NPY_F_CONTIGUOUS_, - forcecast = API::NPY_ARRAY_FORCECAST_ - }; - - template array(size_t size, const Type *ptr) { - API& api = lookup_api(); - PyObject *descr = api.PyArray_DescrFromType_(detail::npy_format_descriptor::value); - if (descr == nullptr) - pybind11_fail("NumPy: unsupported buffer format!"); - Py_intptr_t shape = (Py_intptr_t) size; - object tmp = object(api.PyArray_NewFromDescr_( - api.PyArray_Type_, descr, 1, &shape, nullptr, (void *) ptr, 0, nullptr), false); - if (ptr && tmp) - tmp = object(api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */), false); - if (!tmp) - pybind11_fail("NumPy: unable to create array!"); - m_ptr = tmp.release().ptr(); - } - - array(const buffer_info &info) { - API& api = lookup_api(); - if ((info.format.size() < 1) || (info.format.size() > 2)) - pybind11_fail("Unsupported buffer format!"); - int fmt = (int) info.format[0]; - if (info.format == "Zd") fmt = API::NPY_CDOUBLE_; - else if (info.format == "Zf") fmt = API::NPY_CFLOAT_; - - PyObject *descr = api.PyArray_DescrFromType_(fmt); - if (descr == nullptr) - pybind11_fail("NumPy: unsupported buffer format '" + info.format + "'!"); - object tmp(api.PyArray_NewFromDescr_( - api.PyArray_Type_, descr, (int) info.ndim, (Py_intptr_t *) &info.shape[0], - (Py_intptr_t *) &info.strides[0], info.ptr, 0, nullptr), false); - if (info.ptr && tmp) - tmp = object(api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */), false); - if (!tmp) - pybind11_fail("NumPy: unable to create array!"); - m_ptr = tmp.release().ptr(); - } - -protected: - static API &lookup_api() { - static API api = API::lookup(); - return api; - } -}; - -template class array_t : public array { -public: - PYBIND11_OBJECT_CVT(array_t, array, is_non_null, m_ptr = ensure(m_ptr)); - array_t() : array() { } - array_t(const buffer_info& info) : array(info) {} - static bool is_non_null(PyObject *ptr) { return ptr != nullptr; } - static PyObject *ensure(PyObject *ptr) { - if (ptr == nullptr) - return nullptr; - API &api = lookup_api(); - PyObject *descr = api.PyArray_DescrFromType_(detail::npy_format_descriptor::value); - PyObject *result = api.PyArray_FromAny_(ptr, descr, 0, 0, API::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr); - if (!result) - PyErr_Clear(); - Py_DECREF(ptr); - return result; - } -}; - -NAMESPACE_BEGIN(detail) - -template struct npy_format_descriptor::value>::type> { -private: - constexpr static const int values[8] = { - array::API::NPY_BYTE_, array::API::NPY_UBYTE_, array::API::NPY_SHORT_, array::API::NPY_USHORT_, - array::API::NPY_INT_, array::API::NPY_UINT_, array::API::NPY_LONGLONG_, array::API::NPY_ULONGLONG_ }; -public: - enum { value = values[detail::log2(sizeof(T)) * 2 + (std::is_unsigned::value ? 1 : 0)] }; - template ::value, int>::type = 0> - static PYBIND11_DESCR name() { return _("int") + _(); } - template ::value, int>::type = 0> - static PYBIND11_DESCR name() { return _("uint") + _(); } -}; -template constexpr const int npy_format_descriptor< - T, typename std::enable_if::value>::type>::values[8]; - -#define DECL_FMT(Type, NumPyName, Name) template<> struct npy_format_descriptor { \ - enum { value = array::API::NumPyName }; \ - static PYBIND11_DESCR name() { return _(Name); } } -DECL_FMT(float, NPY_FLOAT_, "float32"); DECL_FMT(double, NPY_DOUBLE_, "float64"); DECL_FMT(bool, NPY_BOOL_, "bool"); -DECL_FMT(std::complex, NPY_CFLOAT_, "complex64"); DECL_FMT(std::complex, NPY_CDOUBLE_, "complex128"); -#undef DECL_FMT - -template -using array_iterator = typename std::add_pointer::type; - -template -array_iterator array_begin(const buffer_info& buffer) { - return array_iterator(reinterpret_cast(buffer.ptr)); -} - -template -array_iterator array_end(const buffer_info& buffer) { - return array_iterator(reinterpret_cast(buffer.ptr) + buffer.size); -} - -class common_iterator { -public: - using container_type = std::vector; - using value_type = container_type::value_type; - using size_type = container_type::size_type; - - common_iterator() : p_ptr(0), m_strides() {} - - common_iterator(void* ptr, const container_type& strides, const std::vector& shape) - : p_ptr(reinterpret_cast(ptr)), m_strides(strides.size()) { - m_strides.back() = static_cast(strides.back()); - for (size_type i = m_strides.size() - 1; i != 0; --i) { - size_type j = i - 1; - value_type s = static_cast(shape[i]); - m_strides[j] = strides[j] + m_strides[i] - strides[i] * s; - } - } - - void increment(size_type dim) { - p_ptr += m_strides[dim]; - } - - void* data() const { - return p_ptr; - } - -private: - char* p_ptr; - container_type m_strides; -}; - -template class multi_array_iterator { -public: - using container_type = std::vector; - - multi_array_iterator(const std::array &buffers, - const std::vector &shape) - : m_shape(shape.size()), m_index(shape.size(), 0), - m_common_iterator() { - - // Manual copy to avoid conversion warning if using std::copy - for (size_t i = 0; i < shape.size(); ++i) - m_shape[i] = static_cast(shape[i]); - - container_type strides(shape.size()); - for (size_t i = 0; i < N; ++i) - init_common_iterator(buffers[i], shape, m_common_iterator[i], strides); - } - - multi_array_iterator& operator++() { - for (size_t j = m_index.size(); j != 0; --j) { - size_t i = j - 1; - if (++m_index[i] != m_shape[i]) { - increment_common_iterator(i); - break; - } else { - m_index[i] = 0; - } - } - return *this; - } - - template const T& data() const { - return *reinterpret_cast(m_common_iterator[K].data()); - } - -private: - - using common_iter = common_iterator; - - void init_common_iterator(const buffer_info &buffer, - const std::vector &shape, - common_iter &iterator, container_type &strides) { - auto buffer_shape_iter = buffer.shape.rbegin(); - auto buffer_strides_iter = buffer.strides.rbegin(); - auto shape_iter = shape.rbegin(); - auto strides_iter = strides.rbegin(); - - while (buffer_shape_iter != buffer.shape.rend()) { - if (*shape_iter == *buffer_shape_iter) - *strides_iter = static_cast(*buffer_strides_iter); - else - *strides_iter = 0; - - ++buffer_shape_iter; - ++buffer_strides_iter; - ++shape_iter; - ++strides_iter; - } - - std::fill(strides_iter, strides.rend(), 0); - iterator = common_iter(buffer.ptr, strides, shape); - } - - void increment_common_iterator(size_t dim) { - for (auto &iter : m_common_iterator) - iter.increment(dim); - } - - container_type m_shape; - container_type m_index; - std::array m_common_iterator; -}; - -template -bool broadcast(const std::array& buffers, size_t& ndim, std::vector& shape) { - ndim = std::accumulate(buffers.begin(), buffers.end(), size_t(0), [](size_t res, const buffer_info& buf) { - return std::max(res, buf.ndim); - }); - - shape = std::vector(ndim, 1); - bool trivial_broadcast = true; - for (size_t i = 0; i < N; ++i) { - auto res_iter = shape.rbegin(); - bool i_trivial_broadcast = (buffers[i].size == 1) || (buffers[i].ndim == ndim); - for (auto shape_iter = buffers[i].shape.rbegin(); - shape_iter != buffers[i].shape.rend(); ++shape_iter, ++res_iter) { - - if (*res_iter == 1) - *res_iter = *shape_iter; - else if ((*shape_iter != 1) && (*res_iter != *shape_iter)) - pybind11_fail("pybind11::vectorize: incompatible size/dimension of inputs!"); - - i_trivial_broadcast = i_trivial_broadcast && (*res_iter == *shape_iter); - } - trivial_broadcast = trivial_broadcast && i_trivial_broadcast; - } - return trivial_broadcast; -} - -template -struct vectorize_helper { - typename std::remove_reference::type f; - - template - vectorize_helper(T&&f) : f(std::forward(f)) { } - - object operator()(array_t... args) { - return run(args..., typename make_index_sequence::type()); - } - - template object run(array_t&... args, index_sequence index) { - /* Request buffers from all parameters */ - const size_t N = sizeof...(Args); - - std::array buffers {{ args.request()... }}; - - /* Determine dimensions parameters of output array */ - size_t ndim = 0; - std::vector shape(0); - bool trivial_broadcast = broadcast(buffers, ndim, shape); - - size_t size = 1; - std::vector strides(ndim); - if (ndim > 0) { - strides[ndim-1] = sizeof(Return); - for (size_t i = ndim - 1; i > 0; --i) { - strides[i - 1] = strides[i] * shape[i]; - size *= shape[i]; - } - size *= shape[0]; - } - - if (size == 1) - return cast(f(*((Args *) buffers[Index].ptr)...)); - - array result(buffer_info(nullptr, sizeof(Return), - format_descriptor::value, - ndim, shape, strides)); - - buffer_info buf = result.request(); - Return *output = (Return *) buf.ptr; - - if (trivial_broadcast) { - /* Call the function */ - for (size_t i=0; i(buffers, buf, index); - } - - return result; - } - - template - void apply_broadcast(const std::array &buffers, - buffer_info &output, index_sequence) { - using input_iterator = multi_array_iterator; - using output_iterator = array_iterator; - - input_iterator input_iter(buffers, output.shape); - output_iterator output_end = array_end(output); - - for (output_iterator iter = array_begin(output); - iter != output_end; ++iter, ++input_iter) { - *iter = f((input_iter.template data())...); - } - } -}; - -template struct handle_type_name> { - static PYBIND11_DESCR name() { return _("numpy.ndarray[dtype=") + type_caster::name() + _("]"); } -}; - -NAMESPACE_END(detail) - -template -detail::vectorize_helper vectorize(const Func &f, Return (*) (Args ...)) { - return detail::vectorize_helper(f); -} - -template -detail::vectorize_helper vectorize(Return (*f) (Args ...)) { - return vectorize(f, f); -} - -template auto vectorize(func &&f) -> decltype( - vectorize(std::forward(f), (typename detail::remove_class::type::operator())>::type *) nullptr)) { - return vectorize(std::forward(f), (typename detail::remove_class::type::operator())>::type *) nullptr); -} - -NAMESPACE_END(pybind11) - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif diff --git a/stormpy/resources/pybind11/include/pybind11/operators.h b/stormpy/resources/pybind11/include/pybind11/operators.h deleted file mode 100644 index 305cd2cd5..000000000 --- a/stormpy/resources/pybind11/include/pybind11/operators.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - pybind11/operator.h: Metatemplates for operator overloading - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "pybind11.h" -#include - -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wunsequenced" // multiple unsequenced modifications to 'self' (when using def(py::self OP Type())) -#endif - -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) - -/// Enumeration with all supported operator types -enum op_id : int { - op_add, op_sub, op_mul, op_div, op_mod, op_divmod, op_pow, op_lshift, - op_rshift, op_and, op_xor, op_or, op_neg, op_pos, op_abs, op_invert, - op_int, op_long, op_float, op_str, op_cmp, op_gt, op_ge, op_lt, op_le, - op_eq, op_ne, op_iadd, op_isub, op_imul, op_idiv, op_imod, op_ilshift, - op_irshift, op_iand, op_ixor, op_ior, op_complex, op_bool, op_nonzero, - op_repr, op_truediv -}; - -enum op_type : int { - op_l, /* base type on left */ - op_r, /* base type on right */ - op_u /* unary operator */ -}; - -struct self_t { }; -static const self_t self = self_t(); - -/// Type for an unused type slot -struct undefined_t { }; - -/// Don't warn about an unused variable -inline self_t __self() { return self; } - -/// base template of operator implementations -template struct op_impl { }; - -/// Operator implementation generator -template struct op_ { - template void execute(pybind11::class_ &class_, const Extra&... extra) const { - typedef typename std::conditional::value, Base, L>::type L_type; - typedef typename std::conditional::value, Base, R>::type R_type; - typedef op_impl op; - class_.def(op::name(), &op::execute, extra...); - } - template void execute_cast(pybind11::class_ &class_, const Extra&... extra) const { - typedef typename std::conditional::value, Base, L>::type L_type; - typedef typename std::conditional::value, Base, R>::type R_type; - typedef op_impl op; - class_.def(op::name(), &op::execute_cast, extra...); - } -}; - -#define PYBIND11_BINARY_OPERATOR(id, rid, op, expr) \ -template struct op_impl { \ - static char const* name() { return "__" #id "__"; } \ - static auto execute(const L &l, const R &r) -> decltype(expr) { return (expr); } \ - static B execute_cast(const L &l, const R &r) { return B(expr); } \ -}; \ -template struct op_impl { \ - static char const* name() { return "__" #rid "__"; } \ - static auto execute(const R &r, const L &l) -> decltype(expr) { return (expr); } \ - static B execute_cast(const R &r, const L &l) { return B(expr); } \ -}; \ -inline op_ op(const self_t &, const self_t &) { \ - return op_(); \ -} \ -template op_ op(const self_t &, const T &) { \ - return op_(); \ -} \ -template op_ op(const T &, const self_t &) { \ - return op_(); \ -} - -#define PYBIND11_INPLACE_OPERATOR(id, op, expr) \ -template struct op_impl { \ - static char const* name() { return "__" #id "__"; } \ - static auto execute(L &l, const R &r) -> decltype(expr) { return expr; } \ - static B execute_cast(L &l, const R &r) { return B(expr); } \ -}; \ -template op_ op(const self_t &, const T &) { \ - return op_(); \ -} - -#define PYBIND11_UNARY_OPERATOR(id, op, expr) \ -template struct op_impl { \ - static char const* name() { return "__" #id "__"; } \ - static auto execute(const L &l) -> decltype(expr) { return expr; } \ - static B execute_cast(const L &l) { return B(expr); } \ -}; \ -inline op_ op(const self_t &) { \ - return op_(); \ -} - -PYBIND11_BINARY_OPERATOR(sub, rsub, operator-, l - r) -PYBIND11_BINARY_OPERATOR(add, radd, operator+, l + r) -PYBIND11_BINARY_OPERATOR(mul, rmul, operator*, l * r) -#if PY_MAJOR_VERSION >= 3 -PYBIND11_BINARY_OPERATOR(truediv, rtruediv, operator/, l / r) -#else -PYBIND11_BINARY_OPERATOR(div, rdiv, operator/, l / r) -#endif -PYBIND11_BINARY_OPERATOR(mod, rmod, operator%, l % r) -PYBIND11_BINARY_OPERATOR(lshift, rlshift, operator<<, l << r) -PYBIND11_BINARY_OPERATOR(rshift, rrshift, operator>>, l >> r) -PYBIND11_BINARY_OPERATOR(and, rand, operator&, l & r) -PYBIND11_BINARY_OPERATOR(xor, rxor, operator^, l ^ r) -PYBIND11_BINARY_OPERATOR(eq, eq, operator==, l == r) -PYBIND11_BINARY_OPERATOR(ne, ne, operator!=, l != r) -PYBIND11_BINARY_OPERATOR(or, ror, operator|, l | r) -PYBIND11_BINARY_OPERATOR(gt, lt, operator>, l > r) -PYBIND11_BINARY_OPERATOR(ge, le, operator>=, l >= r) -PYBIND11_BINARY_OPERATOR(lt, gt, operator<, l < r) -PYBIND11_BINARY_OPERATOR(le, ge, operator<=, l <= r) -//PYBIND11_BINARY_OPERATOR(pow, rpow, pow, std::pow(l, r)) -PYBIND11_INPLACE_OPERATOR(iadd, operator+=, l += r) -PYBIND11_INPLACE_OPERATOR(isub, operator-=, l -= r) -PYBIND11_INPLACE_OPERATOR(imul, operator*=, l *= r) -PYBIND11_INPLACE_OPERATOR(idiv, operator/=, l /= r) -PYBIND11_INPLACE_OPERATOR(imod, operator%=, l %= r) -PYBIND11_INPLACE_OPERATOR(ilshift, operator<<=, l <<= r) -PYBIND11_INPLACE_OPERATOR(irshift, operator>>=, l >>= r) -PYBIND11_INPLACE_OPERATOR(iand, operator&=, l &= r) -PYBIND11_INPLACE_OPERATOR(ixor, operator^=, l ^= r) -PYBIND11_INPLACE_OPERATOR(ior, operator|=, l |= r) -PYBIND11_UNARY_OPERATOR(neg, operator-, -l) -PYBIND11_UNARY_OPERATOR(pos, operator+, +l) -PYBIND11_UNARY_OPERATOR(abs, abs, std::abs(l)) -PYBIND11_UNARY_OPERATOR(invert, operator~, (~l)) -PYBIND11_UNARY_OPERATOR(bool, operator!, !!l) -PYBIND11_UNARY_OPERATOR(int, int_, (int) l) -PYBIND11_UNARY_OPERATOR(float, float_, (double) l) - -#undef PYBIND11_BINARY_OPERATOR -#undef PYBIND11_INPLACE_OPERATOR -#undef PYBIND11_UNARY_OPERATOR -NAMESPACE_END(detail) - -using detail::self; - -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/pybind11.h b/stormpy/resources/pybind11/include/pybind11/pybind11.h deleted file mode 100644 index 0a3ef1870..000000000 --- a/stormpy/resources/pybind11/include/pybind11/pybind11.h +++ /dev/null @@ -1,1273 +0,0 @@ -/* - pybind11/pybind11.h: Main header file of the C++11 python - binding generator library - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant -# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning) -# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name -# pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter -# pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted -#elif defined(__ICC) || defined(__INTEL_COMPILER) -# pragma warning(push) -# pragma warning(disable:2196) // warning #2196: routine is both "inline" and "noinline" -#elif defined(__GNUG__) && !defined(__clang__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-but-set-parameter" -# pragma GCC diagnostic ignored "-Wunused-but-set-variable" -# pragma GCC diagnostic ignored "-Wmissing-field-initializers" -# pragma GCC diagnostic ignored "-Wstrict-aliasing" -# pragma GCC diagnostic ignored "-Wattributes" -#endif - -#include "attr.h" - -NAMESPACE_BEGIN(pybind11) - -/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object -class cpp_function : public function { -public: - cpp_function() { } - - /// Construct a cpp_function from a vanilla function pointer - template - cpp_function(Return (*f)(Args...), const Extra&... extra) { - initialize(f, f, extra...); - } - - /// Construct a cpp_function from a lambda function (possibly with internal state) - template cpp_function(Func &&f, const Extra&... extra) { - initialize(std::forward(f), - (typename detail::remove_class::type::operator())>::type *) nullptr, extra...); - } - - /// Construct a cpp_function from a class method (non-const) - template - cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) { - initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); }, - (Return (*) (Class *, Arg...)) nullptr, extra...); - } - - /// Construct a cpp_function from a class method (const) - template - cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) { - initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); }, - (Return (*)(const Class *, Arg ...)) nullptr, extra...); - } - - /// Return the function name - object name() const { return attr("__name__"); } - -protected: - /// Special internal constructor for functors, lambda functions, etc. - template - void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) { - static_assert(detail::expected_num_args(sizeof...(Args)), - "The number of named arguments does not match the function signature"); - - struct capture { typename std::remove_reference::type f; }; - - /* Store the function including any extra state it might have (e.g. a lambda capture object) */ - auto rec = new detail::function_record(); - - /* Store the capture object directly in the function record if there is enough space */ - if (sizeof(capture) <= sizeof(rec->data)) { - new ((capture *) &rec->data) capture { std::forward(f) }; - if (!std::is_trivially_destructible::value) - rec->free_data = [](detail::function_record *r) { ((capture *) &r->data)->~capture(); }; - } else { - rec->data[0] = new capture { std::forward(f) }; - rec->free_data = [](detail::function_record *r) { delete ((capture *) r->data[0]); }; - } - - /* Type casters for the function arguments and return value */ - typedef detail::type_caster> cast_in; - typedef detail::type_caster::value, detail::void_type, - typename detail::intrinsic_type::type>::type> cast_out; - - /* Dispatch code which converts function arguments and performs the actual function call */ - rec->impl = [](detail::function_record *rec, handle args, handle kwargs, handle parent) -> handle { - cast_in args_converter; - - /* Try to cast the function arguments into the C++ domain */ - if (!args_converter.load_args(args, kwargs, true)) - return PYBIND11_TRY_NEXT_OVERLOAD; - - /* Invoke call policy pre-call hook */ - detail::process_attributes::precall(args); - - /* Get a pointer to the capture object */ - capture *cap = (capture *) (sizeof(capture) <= sizeof(rec->data) - ? &rec->data : rec->data[0]); - - /* Perform the functioncall */ - handle result = cast_out::cast(args_converter.template call(cap->f), - rec->policy, parent); - - /* Invoke call policy post-call hook */ - detail::process_attributes::postcall(args, result); - - return result; - }; - - /* Process any user-provided function attributes */ - detail::process_attributes::init(extra..., rec); - - /* Generate a readable signature describing the function's arguments and return value types */ - using detail::descr; - PYBIND11_DESCR signature = cast_in::name() + detail::_(" -> ") + cast_out::name(); - - /* Register the function with Python from generic (non-templated) code */ - initialize_generic(rec, signature.text(), signature.types(), sizeof...(Args)); - - if (cast_in::has_args) rec->has_args = true; - if (cast_in::has_kwargs) rec->has_kwargs = true; - } - - /// Register a function call with Python (generic non-templated code goes here) - void initialize_generic(detail::function_record *rec, const char *text, - const std::type_info *const *types, int args) { - - /* Create copies of all referenced C-style strings */ - rec->name = strdup(rec->name ? rec->name : ""); - if (rec->doc) rec->doc = strdup(rec->doc); - for (auto &a: rec->args) { - if (a.name) - a.name = strdup(a.name); - if (a.descr) - a.descr = strdup(a.descr); - else if (a.value) - a.descr = strdup(((std::string) ((object) handle(a.value).attr("__repr__"))().str()).c_str()); - } - auto const ®istered_types = detail::get_internals().registered_types_cpp; - - /* Generate a proper function signature */ - std::string signature; - size_t type_depth = 0, char_index = 0, type_index = 0, arg_index = 0; - while (true) { - char c = text[char_index++]; - if (c == '\0') - break; - - if (c == '{') { - if (type_depth == 1 && arg_index < rec->args.size()) { - signature += rec->args[arg_index].name; - signature += " : "; - } - ++type_depth; - } else if (c == '}') { - --type_depth; - if (type_depth == 1 && arg_index < rec->args.size()) { - if (rec->args[arg_index].descr) { - signature += " = "; - signature += rec->args[arg_index].descr; - } - arg_index++; - } - } else if (c == '%') { - const std::type_info *t = types[type_index++]; - if (!t) - pybind11_fail("Internal error while parsing type signature (1)"); - auto it = registered_types.find(std::type_index(*t)); - if (it != registered_types.end()) { - signature += ((const detail::type_info *) it->second)->type->tp_name; - } else { - std::string tname(t->name()); - detail::clean_type_id(tname); - signature += tname; - } - } else { - signature += c; - } - } - if (type_depth != 0 || types[type_index] != nullptr) - pybind11_fail("Internal error while parsing type signature (2)"); - - #if !defined(PYBIND11_CPP14) - delete[] types; - delete[] text; - #endif - -#if PY_MAJOR_VERSION < 3 - if (strcmp(rec->name, "__next__") == 0) { - std::free(rec->name); - rec->name = strdup("next"); - } else if (strcmp(rec->name, "__bool__") == 0) { - std::free(rec->name); - rec->name = strdup("__nonzero__"); - } -#endif - - rec->signature = strdup(signature.c_str()); - rec->args.shrink_to_fit(); - rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__"); - rec->has_args = false; - rec->has_kwargs = false; - rec->nargs = (uint16_t) args; - -#if PY_MAJOR_VERSION < 3 - if (rec->sibling && PyMethod_Check(rec->sibling.ptr())) - rec->sibling = PyMethod_GET_FUNCTION(rec->sibling.ptr()); -#endif - - detail::function_record *chain = nullptr, *chain_start = rec; - if (rec->sibling && PyCFunction_Check(rec->sibling.ptr())) { - capsule rec_capsule(PyCFunction_GetSelf(rec->sibling.ptr()), true); - chain = (detail::function_record *) rec_capsule; - /* Never append a method to an overload chain of a parent class; - instead, hide the parent's overloads in this case */ - if (chain->class_ != rec->class_) - chain = nullptr; - } - - if (!chain) { - /* No existing overload was found, create a new function object */ - rec->def = new PyMethodDef(); - memset(rec->def, 0, sizeof(PyMethodDef)); - rec->def->ml_name = rec->name; - rec->def->ml_meth = reinterpret_cast(*dispatcher); - rec->def->ml_flags = METH_VARARGS | METH_KEYWORDS; - - capsule rec_capsule(rec, [](PyObject *o) { - destruct((detail::function_record *) PyCapsule_GetPointer(o, nullptr)); - }); - - object scope_module; - if (rec->scope) { - scope_module = (object) rec->scope.attr("__module__"); - if (!scope_module) - scope_module = (object) rec->scope.attr("__name__"); - } - - m_ptr = PyCFunction_NewEx(rec->def, rec_capsule.ptr(), scope_module.ptr()); - if (!m_ptr) - pybind11_fail("cpp_function::cpp_function(): Could not allocate function object"); - } else { - /* Append at the end of the overload chain */ - m_ptr = rec->sibling.ptr(); - inc_ref(); - chain_start = chain; - while (chain->next) - chain = chain->next; - chain->next = rec; - } - - std::string signatures; - int index = 0; - /* Create a nice pydoc rec including all signatures and - docstrings of the functions in the overload chain */ - if (chain) { - // First a generic signature - signatures += rec->name; - signatures += "(*args, **kwargs)\n"; - signatures += "Overloaded function.\n\n"; - } - // Then specific overload signatures - for (auto it = chain_start; it != nullptr; it = it->next) { - if (chain) - signatures += std::to_string(++index) + ". "; - signatures += rec->name; - signatures += it->signature; - signatures += "\n"; - if (it->doc && strlen(it->doc) > 0) { - signatures += "\n"; - signatures += it->doc; - signatures += "\n"; - } - if (it->next) - signatures += "\n"; - } - - /* Install docstring */ - PyCFunctionObject *func = (PyCFunctionObject *) m_ptr; - if (func->m_ml->ml_doc) - std::free((char *) func->m_ml->ml_doc); - func->m_ml->ml_doc = strdup(signatures.c_str()); - - if (rec->class_) { - m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->class_.ptr()); - if (!m_ptr) - pybind11_fail("cpp_function::cpp_function(): Could not allocate instance method object"); - Py_DECREF(func); - } - } - - /// When a cpp_function is GCed, release any memory allocated by pybind11 - static void destruct(detail::function_record *rec) { - while (rec) { - detail::function_record *next = rec->next; - if (rec->free_data) - rec->free_data(rec); - std::free((char *) rec->name); - std::free((char *) rec->doc); - std::free((char *) rec->signature); - for (auto &arg: rec->args) { - std::free((char *) arg.name); - std::free((char *) arg.descr); - arg.value.dec_ref(); - } - if (rec->def) { - std::free((char *) rec->def->ml_doc); - delete rec->def; - } - delete rec; - rec = next; - } - } - - /// Main dispatch logic for calls to functions bound using pybind11 - static PyObject *dispatcher(PyObject *self, PyObject *args, PyObject *kwargs) { - /* Iterator over the list of potentially admissible overloads */ - detail::function_record *overloads = (detail::function_record *) PyCapsule_GetPointer(self, nullptr), - *it = overloads; - - /* Need to know how many arguments + keyword arguments there are to pick the right overload */ - size_t nargs = (size_t) PyTuple_GET_SIZE(args), - nkwargs = kwargs ? (size_t) PyDict_Size(kwargs) : 0; - - handle parent = nargs > 0 ? PyTuple_GET_ITEM(args, 0) : nullptr, - result = PYBIND11_TRY_NEXT_OVERLOAD; - try { - for (; it != nullptr; it = it->next) { - tuple args_(args, true); - size_t kwargs_consumed = 0; - - /* For each overload: - 1. If the required list of arguments is longer than the - actually provided amount, create a copy of the argument - list and fill in any available keyword/default arguments. - 2. Ensure that all keyword arguments were "consumed" - 3. Call the function call dispatcher (function_record::impl) - */ - size_t nargs_ = nargs; - if (nargs < it->args.size()) { - nargs_ = it->args.size(); - args_ = tuple(nargs_); - for (size_t i = 0; i < nargs; ++i) { - handle item = PyTuple_GET_ITEM(args, i); - PyTuple_SET_ITEM(args_.ptr(), i, item.inc_ref().ptr()); - } - - int arg_ctr = 0; - for (auto const &it2 : it->args) { - int index = arg_ctr++; - if (PyTuple_GET_ITEM(args_.ptr(), index)) - continue; - - handle value; - if (kwargs) - value = PyDict_GetItemString(kwargs, it2.name); - - if (value) - kwargs_consumed++; - else if (it2.value) - value = it2.value; - - if (value) { - PyTuple_SET_ITEM(args_.ptr(), index, value.inc_ref().ptr()); - } else { - kwargs_consumed = (size_t) -1; /* definite failure */ - break; - } - } - } - - try { - if ((kwargs_consumed == nkwargs || it->has_kwargs) && - (nargs_ == it->nargs || it->has_args)) - result = it->impl(it, args_, kwargs, parent); - } catch (cast_error &) { - result = PYBIND11_TRY_NEXT_OVERLOAD; - } - - if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD) - break; - } - } catch (const error_already_set &) { return nullptr; - } catch (const index_error &e) { PyErr_SetString(PyExc_IndexError, e.what()); return nullptr; - } catch (const value_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr; - } catch (const stop_iteration &e) { PyErr_SetString(PyExc_StopIteration, e.what()); return nullptr; - } catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return nullptr; - } catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr; - } catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr; - } catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr; - } catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return nullptr; - } catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr; - } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return nullptr; - } catch (...) { - PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!"); - return nullptr; - } - - if (result.ptr() == PYBIND11_TRY_NEXT_OVERLOAD) { - std::string msg = "Incompatible function arguments. The " - "following argument types are supported:\n"; - int ctr = 0; - for (detail::function_record *it2 = overloads; it2 != nullptr; it2 = it2->next) { - msg += " "+ std::to_string(++ctr) + ". "; - msg += it2->signature; - msg += "\n"; - } - msg += " Invoked with: "; - tuple args_(args, true); - for( std::size_t ti = 0; ti != args_.size(); ++ti) - { - msg += static_cast(static_cast(args_[ti]).str()); - if ((ti + 1) != args_.size() ) - msg += ", "; - } - PyErr_SetString(PyExc_TypeError, msg.c_str()); - return nullptr; - } else if (!result) { - std::string msg = "Unable to convert function return value to a " - "Python type! The signature was\n\t"; - msg += it->signature; - PyErr_SetString(PyExc_TypeError, msg.c_str()); - return nullptr; - } else { - if (overloads->is_constructor) { - /* When a constructor ran successfully, the corresponding - holder type (e.g. std::unique_ptr) must still be initialized. */ - PyObject *inst = PyTuple_GET_ITEM(args, 0); - auto tinfo = detail::get_type_info(Py_TYPE(inst)); - tinfo->init_holder(inst, nullptr); - } - return result.ptr(); - } - } -}; - -/// Wrapper for Python extension modules -class module : public object { -public: - PYBIND11_OBJECT_DEFAULT(module, object, PyModule_Check) - - module(const char *name, const char *doc = nullptr) { -#if PY_MAJOR_VERSION >= 3 - PyModuleDef *def = new PyModuleDef(); - memset(def, 0, sizeof(PyModuleDef)); - def->m_name = name; - def->m_doc = doc; - def->m_size = -1; - Py_INCREF(def); - m_ptr = PyModule_Create(def); -#else - m_ptr = Py_InitModule3(name, nullptr, doc); -#endif - if (m_ptr == nullptr) - pybind11_fail("Internal error in module::module()"); - inc_ref(); - } - - template - module &def(const char *name_, Func &&f, const Extra& ... extra) { - cpp_function func(std::forward(f), name(name_), - sibling((handle) attr(name_)), scope(*this), extra...); - /* PyModule_AddObject steals a reference to 'func' */ - PyModule_AddObject(ptr(), name_, func.inc_ref().ptr()); - return *this; - } - - module def_submodule(const char *name, const char *doc = nullptr) { - std::string full_name = std::string(PyModule_GetName(m_ptr)) - + std::string(".") + std::string(name); - module result(PyImport_AddModule(full_name.c_str()), true); - if (doc) - result.attr("__doc__") = pybind11::str(doc); - attr(name) = result; - return result; - } - - static module import(const char *name) { - PyObject *obj = PyImport_ImportModule(name); - if (!obj) - pybind11_fail("Module \"" + std::string(name) + "\" not found!"); - return module(obj, false); - } -}; - -NAMESPACE_BEGIN(detail) -/// Generic support for creating new Python heap types -class generic_type : public object { - template friend class class_; -public: - PYBIND11_OBJECT_DEFAULT(generic_type, object, PyType_Check) -protected: - void initialize(type_record *rec) { - if (rec->base_type) { - if (rec->base_handle) - pybind11_fail("generic_type: specified base type multiple times!"); - rec->base_handle = detail::get_type_handle(*(rec->base_type)); - if (!rec->base_handle) { - std::string tname(rec->base_type->name()); - detail::clean_type_id(tname); - pybind11_fail("generic_type: type \"" + std::string(rec->name) + - "\" referenced unknown base type \"" + tname + "\""); - } - } - - auto &internals = get_internals(); - auto tindex = std::type_index(*(rec->type)); - - if (internals.registered_types_cpp.find(tindex) != - internals.registered_types_cpp.end()) - pybind11_fail("generic_type: type \"" + std::string(rec->name) + - "\" is already registered!"); - - object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false); - object name(PYBIND11_FROM_STRING(rec->name), false); - auto type = (PyHeapTypeObject*) type_holder.ptr(); - - if (!type_holder || !name) - pybind11_fail("generic_type: unable to create type object!"); - - /* Register supplemental type information in C++ dict */ - detail::type_info *tinfo = new detail::type_info(); - tinfo->type = (PyTypeObject *) type; - tinfo->type_size = rec->type_size; - tinfo->init_holder = rec->init_holder; - internals.registered_types_cpp[tindex] = tinfo; - internals.registered_types_py[type] = tinfo; - - object scope_module; - if (rec->scope) { - scope_module = (object) rec->scope.attr("__module__"); - if (!scope_module) - scope_module = (object) rec->scope.attr("__name__"); - } - - std::string full_name = (scope_module ? ((std::string) scope_module.str() + "." + rec->name) - : std::string(rec->name)); - /* Basic type attributes */ - type->ht_type.tp_name = strdup(full_name.c_str()); - type->ht_type.tp_basicsize = (ssize_t) rec->instance_size; - type->ht_type.tp_base = (PyTypeObject *) rec->base_handle.ptr(); - rec->base_handle.inc_ref(); - -#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 - /* Qualified names for Python >= 3.3 */ - object scope_qualname; - if (rec->scope) - scope_qualname = (object) rec->scope.attr("__qualname__"); - if (scope_qualname) { - type->ht_qualname = PyUnicode_FromFormat( - "%U.%U", scope_qualname.ptr(), name.ptr()); - } else { - type->ht_qualname = name.ptr(); - name.inc_ref(); - } -#endif - type->ht_name = name.release().ptr(); - - /* Supported protocols */ - type->ht_type.tp_as_number = &type->as_number; - type->ht_type.tp_as_sequence = &type->as_sequence; - type->ht_type.tp_as_mapping = &type->as_mapping; - - /* Supported elementary operations */ - type->ht_type.tp_init = (initproc) init; - type->ht_type.tp_new = (newfunc) new_instance; - type->ht_type.tp_dealloc = rec->dealloc; - - /* Support weak references (needed for the keep_alive feature) */ - type->ht_type.tp_weaklistoffset = offsetof(instance_essentials, weakrefs); - - /* Flags */ - type->ht_type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE; -#if PY_MAJOR_VERSION < 3 - type->ht_type.tp_flags |= Py_TPFLAGS_CHECKTYPES; -#endif - type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC; - - if (rec->doc) { - /* Allocate memory for docstring (using PyObject_MALLOC, since - Python will free this later on) */ - size_t size = strlen(rec->doc) + 1; - type->ht_type.tp_doc = (char *) PyObject_MALLOC(size); - memcpy((void *) type->ht_type.tp_doc, rec->doc, size); - } - - if (PyType_Ready(&type->ht_type) < 0) - pybind11_fail("generic_type: PyType_Ready failed!"); - - m_ptr = type_holder.ptr(); - - if (scope_module) // Needed by pydoc - attr("__module__") = scope_module; - - /* Register type with the parent scope */ - if (rec->scope) - rec->scope.attr(handle(type->ht_name)) = *this; - - type_holder.release(); - } - - /// Allocate a metaclass on demand (for static properties) - handle metaclass() { - auto &ht_type = ((PyHeapTypeObject *) m_ptr)->ht_type; - auto &ob_type = PYBIND11_OB_TYPE(ht_type); - - if (ob_type == &PyType_Type) { - std::string name_ = std::string(ht_type.tp_name) + "__Meta"; - object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false); - object name(PYBIND11_FROM_STRING(name_.c_str()), false); - if (!type_holder || !name) - pybind11_fail("generic_type::metaclass(): unable to create type object!"); - - auto type = (PyHeapTypeObject*) type_holder.ptr(); - type->ht_name = name.release().ptr(); -#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 - /* Qualified names for Python >= 3.3 */ - type->ht_qualname = PyUnicode_FromFormat( - "%U__Meta", ((object) attr("__qualname__")).ptr()); -#endif - type->ht_type.tp_name = strdup(name_.c_str()); - type->ht_type.tp_base = ob_type; - type->ht_type.tp_flags |= (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE) & - ~Py_TPFLAGS_HAVE_GC; - - if (PyType_Ready(&type->ht_type) < 0) - pybind11_fail("generic_type::metaclass(): PyType_Ready failed!"); - - ob_type = (PyTypeObject *) type_holder.release().ptr(); - } - return handle((PyObject *) ob_type); - } - - static int init(void *self, PyObject *, PyObject *) { - std::string msg = std::string(Py_TYPE(self)->tp_name) + ": No constructor defined!"; - PyErr_SetString(PyExc_TypeError, msg.c_str()); - return -1; - } - - static PyObject *new_instance(PyTypeObject *type, PyObject *, PyObject *) { - instance *self = (instance *) PyType_GenericAlloc((PyTypeObject *) type, 0); - auto tinfo = detail::get_type_info(type); - self->value = ::operator new(tinfo->type_size); - self->owned = true; - self->parent = nullptr; - self->constructed = false; - detail::get_internals().registered_instances[self->value] = (PyObject *) self; - return (PyObject *) self; - } - - static void dealloc(instance *self) { - if (self->value) { - bool dont_cache = self->parent && ((instance *) self->parent)->value == self->value; - if (!dont_cache) { // avoid an issue with internal references matching their parent's address - auto ®istered_instances = detail::get_internals().registered_instances; - auto it = registered_instances.find(self->value); - if (it == registered_instances.end()) - pybind11_fail("generic_type::dealloc(): Tried to deallocate unregistered instance!"); - registered_instances.erase(it); - } - Py_XDECREF(self->parent); - if (self->weakrefs) - PyObject_ClearWeakRefs((PyObject *) self); - } - Py_TYPE(self)->tp_free((PyObject*) self); - } - - void install_buffer_funcs( - buffer_info *(*get_buffer)(PyObject *, void *), - void *get_buffer_data) { - PyHeapTypeObject *type = (PyHeapTypeObject*) m_ptr; - type->ht_type.tp_as_buffer = &type->as_buffer; -#if PY_MAJOR_VERSION < 3 - type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; -#endif - type->as_buffer.bf_getbuffer = getbuffer; - type->as_buffer.bf_releasebuffer = releasebuffer; - auto tinfo = detail::get_type_info(&type->ht_type); - tinfo->get_buffer = get_buffer; - tinfo->get_buffer_data = get_buffer_data; - } - - static int getbuffer(PyObject *obj, Py_buffer *view, int flags) { - auto tinfo = detail::get_type_info(Py_TYPE(obj)); - if (view == nullptr || obj == nullptr || !tinfo || !tinfo->get_buffer) { - PyErr_SetString(PyExc_BufferError, "generic_type::getbuffer(): Internal error"); - return -1; - } - memset(view, 0, sizeof(Py_buffer)); - buffer_info *info = tinfo->get_buffer(obj, tinfo->get_buffer_data); - view->obj = obj; - view->ndim = 1; - view->internal = info; - view->buf = info->ptr; - view->itemsize = (ssize_t) info->itemsize; - view->len = view->itemsize; - for (auto s : info->shape) - view->len *= s; - if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) - view->format = const_cast(info->format.c_str()); - if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { - view->ndim = (int) info->ndim; - view->strides = (ssize_t *) &info->strides[0]; - view->shape = (ssize_t *) &info->shape[0]; - } - Py_INCREF(view->obj); - return 0; - } - - static void releasebuffer(PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal; } -}; -NAMESPACE_END(detail) - -template , typename type_alias = type> -class class_ : public detail::generic_type { -public: - typedef detail::instance instance_type; - - PYBIND11_OBJECT(class_, detail::generic_type, PyType_Check) - - template - class_(handle scope, const char *name, const Extra &... extra) { - detail::type_record record; - record.scope = scope; - record.name = name; - record.type = &typeid(type); - record.type_size = sizeof(type); - record.instance_size = sizeof(instance_type); - record.init_holder = init_holder; - record.dealloc = dealloc; - - /* Process optional arguments, if any */ - detail::process_attributes::init(extra..., &record); - - detail::generic_type::initialize(&record); - - if (!std::is_same::value) { - auto &instances = pybind11::detail::get_internals().registered_types_cpp; - instances[std::type_index(typeid(type_alias))] = instances[std::type_index(typeid(type))]; - } - } - - template - class_ &def(const char *name_, Func&& f, const Extra&... extra) { - cpp_function cf(std::forward(f), name(name_), - sibling(attr(name_)), is_method(*this), - extra...); - attr(cf.name()) = cf; - return *this; - } - - template class_ & - def_static(const char *name_, Func f, const Extra&... extra) { - cpp_function cf(std::forward(f), name(name_), - sibling(attr(name_)), scope(*this), extra...); - attr(cf.name()) = cf; - return *this; - } - - template - class_ &def(const detail::op_ &op, const Extra&... extra) { - op.template execute(*this, extra...); - return *this; - } - - template - class_ & def_cast(const detail::op_ &op, const Extra&... extra) { - op.template execute_cast(*this, extra...); - return *this; - } - - template - class_ &def(const detail::init &init, const Extra&... extra) { - init.template execute(*this, extra...); - return *this; - } - - template - class_ &def(const detail::init_alias &init, const Extra&... extra) { - init.template execute(*this, extra...); - return *this; - } - - template class_& def_buffer(Func &&func) { - struct capture { Func func; }; - capture *ptr = new capture { std::forward(func) }; - install_buffer_funcs([](PyObject *obj, void *ptr) -> buffer_info* { - detail::type_caster caster; - if (!caster.load(obj, false)) - return nullptr; - return new buffer_info(((capture *) ptr)->func(caster)); - }, ptr); - return *this; - } - - template - class_ &def_readwrite(const char *name, D C::*pm, const Extra&... extra) { - cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; }, is_method(*this)), - fset([pm](C &c, const D &value) { c.*pm = value; }, is_method(*this)); - def_property(name, fget, fset, return_value_policy::reference_internal, extra...); - return *this; - } - - template - class_ &def_readonly(const char *name, const D C::*pm, const Extra& ...extra) { - cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; }, is_method(*this)); - def_property_readonly(name, fget, return_value_policy::reference_internal, extra...); - return *this; - } - - template - class_ &def_readwrite_static(const char *name, D *pm, const Extra& ...extra) { - cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)), - fset([pm](object, const D &value) { *pm = value; }, scope(*this)); - def_property_static(name, fget, fset, return_value_policy::reference, extra...); - return *this; - } - - template - class_ &def_readonly_static(const char *name, const D *pm, const Extra& ...extra) { - cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)); - def_property_readonly_static(name, fget, return_value_policy::reference, extra...); - return *this; - } - - template - class_ &def_property_readonly(const char *name, const cpp_function &fget, const Extra& ...extra) { - def_property(name, fget, cpp_function(), extra...); - return *this; - } - - template - class_ &def_property_readonly_static(const char *name, const cpp_function &fget, const Extra& ...extra) { - def_property_static(name, fget, cpp_function(), extra...); - return *this; - } - - template - class_ &def_property(const char *name, const cpp_function &fget, const cpp_function &fset, const Extra& ...extra) { - return def_property_static(name, fget, fset, is_method(*this), extra...); - } - - template - class_ &def_property_static(const char *name, const cpp_function &fget, const cpp_function &fset, const Extra& ...extra) { - auto rec_fget = get_function_record(fget), rec_fset = get_function_record(fset); - char *doc_prev = rec_fget->doc; /* 'extra' field may include a property-specific documentation string */ - detail::process_attributes::init(extra..., rec_fget); - if (rec_fget->doc && rec_fget->doc != doc_prev) { - free(doc_prev); - rec_fget->doc = strdup(rec_fget->doc); - } - if (rec_fset) { - doc_prev = rec_fset->doc; - detail::process_attributes::init(extra..., rec_fset); - if (rec_fset->doc && rec_fset->doc != doc_prev) { - free(doc_prev); - rec_fset->doc = strdup(rec_fset->doc); - } - } - pybind11::str doc_obj = pybind11::str(rec_fget->doc ? rec_fget->doc : ""); - object property( - PyObject_CallFunctionObjArgs((PyObject *) &PyProperty_Type, fget.ptr() ? fget.ptr() : Py_None, - fset.ptr() ? fset.ptr() : Py_None, Py_None, doc_obj.ptr(), nullptr), false); - if (rec_fget->class_) - attr(name) = property; - else - metaclass().attr(name) = property; - return *this; - } - -private: - /// Initialize holder object, variant 1: object derives from enable_shared_from_this - template - static void init_holder_helper(instance_type *inst, const holder_type * /* unused */, const std::enable_shared_from_this * /* dummy */) { - try { - new (&inst->holder) holder_type(std::static_pointer_cast(inst->value->shared_from_this())); - } catch (const std::bad_weak_ptr &) { - new (&inst->holder) holder_type(inst->value); - } - } - - /// Initialize holder object, variant 2: try to construct from existing holder object, if possible - template ::value, int>::type = 0> - static void init_holder_helper(instance_type *inst, const holder_type *holder_ptr, const void * /* dummy */) { - if (holder_ptr) - new (&inst->holder) holder_type(*holder_ptr); - else - new (&inst->holder) holder_type(inst->value); - } - - /// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer - template ::value, int>::type = 0> - static void init_holder_helper(instance_type *inst, const holder_type * /* unused */, const void * /* dummy */) { - new (&inst->holder) holder_type(inst->value); - } - - /// Initialize holder object of an instance, possibly given a pointer to an existing holder - static void init_holder(PyObject *inst_, const void *holder_ptr) { - auto inst = (instance_type *) inst_; - init_holder_helper(inst, (const holder_type *) holder_ptr, inst->value); - inst->constructed = true; - } - - static void dealloc(PyObject *inst_) { - instance_type *inst = (instance_type *) inst_; - if (inst->owned) { - if (inst->constructed) - inst->holder.~holder_type(); - else - ::operator delete(inst->value); - } - generic_type::dealloc((detail::instance *) inst); - } - - static detail::function_record *get_function_record(handle h) { - h = detail::get_function(h); - return h ? (detail::function_record *) capsule( - PyCFunction_GetSelf(h.ptr()), true) : nullptr; - } -}; - -/// Binds C++ enumerations and enumeration classes to Python -template class enum_ : public class_ { -public: - template - enum_(const handle &scope, const char *name, const Extra&... extra) - : class_(scope, name, extra...), m_parent(scope) { - auto entries = new std::unordered_map(); - this->def("__repr__", [name, entries](Type value) -> std::string { - auto it = entries->find((int) value); - return std::string(name) + "." + - ((it == entries->end()) ? std::string("???") - : std::string(it->second)); - }); - this->def("__init__", [](Type& value, int i) { value = (Type)i; }); - this->def("__init__", [](Type& value, int i) { new (&value) Type((Type) i); }); - this->def("__int__", [](Type value) { return (int) value; }); - this->def("__eq__", [](const Type &value, Type *value2) { return value2 && value == *value2; }); - this->def("__ne__", [](const Type &value, Type *value2) { return !value2 || value != *value2; }); - this->def("__hash__", [](const Type &value) { return (int) value; }); - m_entries = entries; - } - - /// Export enumeration entries into the parent scope - void export_values() { - PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict; - PyObject *key, *value; - ssize_t pos = 0; - while (PyDict_Next(dict, &pos, &key, &value)) - if (PyObject_IsInstance(value, this->m_ptr)) - m_parent.attr(key) = value; - } - - /// Add an enumeration entry - enum_& value(char const* name, Type value) { - this->attr(name) = pybind11::cast(value, return_value_policy::copy); - (*m_entries)[(int) value] = name; - return *this; - } -private: - std::unordered_map *m_entries; - handle m_parent; -}; - -NAMESPACE_BEGIN(detail) -template struct init { - template ::value, int>::type = 0> - void execute(pybind11::class_ &class_, const Extra&... extra) const { - /// Function which calls a specific C++ in-place constructor - class_.def("__init__", [](Base *self_, Args... args) { new (self_) Base(args...); }, extra...); - } - - template ::value && - std::is_constructible::value, int>::type = 0> - void execute(pybind11::class_ &class_, const Extra&... extra) const { - handle cl_type = class_; - class_.def("__init__", [cl_type](handle self_, Args... args) { - if (self_.get_type() == cl_type) - new (self_.cast()) Base(args...); - else - new (self_.cast()) Alias(args...); - }, extra...); - } - - template ::value && - !std::is_constructible::value, int>::type = 0> - void execute(pybind11::class_ &class_, const Extra&... extra) const { - class_.def("__init__", [](Alias *self_, Args... args) { new (self_) Alias(args...); }, extra...); - } -}; - -PYBIND11_NOINLINE inline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret) { - /* Clever approach based on weak references taken from Boost.Python */ - handle nurse (Nurse > 0 ? PyTuple_GetItem(args.ptr(), Nurse - 1) : ret.ptr()); - handle patient(Patient > 0 ? PyTuple_GetItem(args.ptr(), Patient - 1) : ret.ptr()); - - if (!nurse || !patient) - pybind11_fail("Could not activate keep_alive!"); - - if (patient.ptr() == Py_None) - return; /* Nothing to keep alive */ - - cpp_function disable_lifesupport( - [patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); }); - - weakref wr(nurse, disable_lifesupport); - - patient.inc_ref(); /* reference patient and leak the weak reference */ - (void) wr.release(); -} - -template struct iterator_state { - Iterator it, end; - bool first; -}; - -NAMESPACE_END(detail) - -template detail::init init() { return detail::init(); } - -template ()), - typename... Extra> -iterator make_iterator(Iterator first, Iterator last, Extra &&... extra) { - typedef detail::iterator_state state; - - if (!detail::get_type_info(typeid(state))) { - class_(handle(), "") - .def("__iter__", [](state &s) -> state& { return s; }) - .def("__next__", [](state &s) -> ValueType { - if (!s.first) - ++s.it; - else - s.first = false; - if (s.it == s.end) - throw stop_iteration(); - return *s.it; - }, return_value_policy::reference_internal, std::forward(extra)...); - } - - return (iterator) cast(state { first, last, true }); -} - -template iterator make_iterator(Type &value, Extra&&... extra) { - return make_iterator(std::begin(value), std::end(value), extra...); -} - -template void implicitly_convertible() { - auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * { - if (!detail::type_caster().load(obj, false)) - return nullptr; - tuple args(1); - args[0] = obj; - PyObject *result = PyObject_Call((PyObject *) type, args.ptr(), nullptr); - if (result == nullptr) - PyErr_Clear(); - return result; - }; - auto ®istered_types = detail::get_internals().registered_types_cpp; - auto it = registered_types.find(std::type_index(typeid(OutputType))); - if (it == registered_types.end()) - pybind11_fail("implicitly_convertible: Unable to find type " + type_id()); - ((detail::type_info *) it->second)->implicit_conversions.push_back(implicit_caster); -} - -#if defined(WITH_THREAD) - -/* The functions below essentially reproduce the PyGILState_* API using a RAII - * pattern, but there are a few important differences: - * - * 1. When acquiring the GIL from an non-main thread during the finalization - * phase, the GILState API blindly terminates the calling thread, which - * is often not what is wanted. This API does not do this. - * - * 2. The gil_scoped_release function can optionally cut the relationship - * of a PyThreadState and its associated thread, which allows moving it to - * another thread (this is a fairly rare/advanced use case). - * - * 3. The reference count of an acquired thread state can be controlled. This - * can be handy to prevent cases where callbacks issued from an external - * thread would otherwise constantly construct and destroy thread state data - * structures. - * - * See the Python bindings of NanoGUI (http://github.com/wjakob/nanogui) for an - * example which uses features 2 and 3 to migrate the Python thread of - * execution to another thread (to run the event loop on the original thread, - * in this case). - */ - -class gil_scoped_acquire { -public: - PYBIND11_NOINLINE gil_scoped_acquire() { - auto const &internals = detail::get_internals(); - tstate = (PyThreadState *) PyThread_get_key_value(internals.tstate); - - if (!tstate) { - tstate = PyThreadState_New(internals.istate); - #if !defined(NDEBUG) - if (!tstate) - pybind11_fail("scoped_acquire: could not create thread state!"); - #endif - tstate->gilstate_counter = 0; - #if PY_MAJOR_VERSION < 3 - PyThread_delete_key_value(internals.tstate); - #endif - PyThread_set_key_value(internals.tstate, tstate); - } else { - release = detail::get_thread_state_unchecked() != tstate; - } - - if (release) { - /* Work around an annoying assertion in PyThreadState_Swap */ - #if defined(Py_DEBUG) - PyInterpreterState *interp = tstate->interp; - tstate->interp = nullptr; - #endif - PyEval_AcquireThread(tstate); - #if defined(Py_DEBUG) - tstate->interp = interp; - #endif - } - - inc_ref(); - } - - void inc_ref() { - ++tstate->gilstate_counter; - } - - PYBIND11_NOINLINE void dec_ref() { - --tstate->gilstate_counter; - #if !defined(NDEBUG) - if (detail::get_thread_state_unchecked() != tstate) - pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!"); - if (tstate->gilstate_counter < 0) - pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!"); - #endif - if (tstate->gilstate_counter == 0) { - #if !defined(NDEBUG) - if (!release) - pybind11_fail("scoped_acquire::dec_ref(): internal error!"); - #endif - PyThreadState_Clear(tstate); - PyThreadState_DeleteCurrent(); - PyThread_delete_key_value(detail::get_internals().tstate); - release = false; - } - } - - PYBIND11_NOINLINE ~gil_scoped_acquire() { - dec_ref(); - if (release) - PyEval_SaveThread(); - } -private: - PyThreadState *tstate = nullptr; - bool release = true; -}; - -class gil_scoped_release { -public: - gil_scoped_release(bool disassoc = false) : disassoc(disassoc) { - tstate = PyEval_SaveThread(); - if (disassoc) { - auto key = detail::get_internals().tstate; - #if PY_MAJOR_VERSION < 3 - PyThread_delete_key_value(key); - #else - PyThread_set_key_value(key, nullptr); - #endif - } - } - ~gil_scoped_release() { - if (!tstate) - return; - PyEval_RestoreThread(tstate); - if (disassoc) { - auto key = detail::get_internals().tstate; - #if PY_MAJOR_VERSION < 3 - PyThread_delete_key_value(key); - #endif - PyThread_set_key_value(key, tstate); - } - } -private: - PyThreadState *tstate; - bool disassoc; -}; -#else -class gil_scoped_acquire { }; -class gil_scoped_release { }; -#endif - -inline function get_overload(const void *this_ptr, const char *name) { - handle py_object = detail::get_object_handle(this_ptr); - if (!py_object) - return function(); - handle type = py_object.get_type(); - auto key = std::make_pair(type.ptr(), name); - - /* Cache functions that aren't overloaded in Python to avoid - many costly Python dictionary lookups below */ - auto &cache = detail::get_internals().inactive_overload_cache; - if (cache.find(key) != cache.end()) - return function(); - - function overload = (function) py_object.attr(name); - if (overload.is_cpp_function()) { - cache.insert(key); - return function(); - } - - /* Don't call dispatch code if invoked from overridden function */ - PyFrameObject *frame = PyThreadState_Get()->frame; - if (frame && (std::string) pybind11::handle(frame->f_code->co_name).str() == name && - frame->f_code->co_argcount > 0) { - PyFrame_FastToLocals(frame); - PyObject *self_caller = PyDict_GetItem( - frame->f_locals, PyTuple_GET_ITEM(frame->f_code->co_varnames, 0)); - if (self_caller == py_object.ptr()) - return function(); - } - return overload; -} - -#define PYBIND11_OVERLOAD_INT(ret_type, name, ...) { \ - pybind11::gil_scoped_acquire gil; \ - pybind11::function overload = pybind11::get_overload(this, name); \ - if (overload) \ - return overload(__VA_ARGS__).template cast(); } - -#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \ - PYBIND11_OVERLOAD_INT(ret_type, name, __VA_ARGS__) \ - return cname::fn(__VA_ARGS__) - -#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \ - PYBIND11_OVERLOAD_INT(ret_type, name, __VA_ARGS__) \ - pybind11::pybind11_fail("Tried to call pure virtual function \"" #cname "::" name "\""); - -#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \ - PYBIND11_OVERLOAD_NAME(ret_type, cname, #fn, fn, __VA_ARGS__) - -#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \ - PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, #fn, fn, __VA_ARGS__) - -NAMESPACE_END(pybind11) - -#if defined(_MSC_VER) -# pragma warning(pop) -#elif defined(__ICC) || defined(__INTEL_COMPILER) -# pragma warning(pop) -#elif defined(__GNUG__) && !defined(__clang__) -# pragma GCC diagnostic pop -#endif diff --git a/stormpy/resources/pybind11/include/pybind11/pytypes.h b/stormpy/resources/pybind11/include/pybind11/pytypes.h deleted file mode 100644 index 6eee186db..000000000 --- a/stormpy/resources/pybind11/include/pybind11/pytypes.h +++ /dev/null @@ -1,570 +0,0 @@ -/* - pybind11/typeid.h: Convenience wrapper classes for basic Python types - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "common.h" -#include -#include - -NAMESPACE_BEGIN(pybind11) - -/* A few forward declarations */ -class object; class str; class object; class dict; class iterator; -namespace detail { class accessor; class args_proxy; class kwargs_proxy; } - -/// Holds a reference to a Python object (no reference counting) -class handle { -public: - handle() : m_ptr(nullptr) { } - handle(const handle &other) : m_ptr(other.m_ptr) { } - handle(PyObject *ptr) : m_ptr(ptr) { } - PyObject *ptr() const { return m_ptr; } - PyObject *&ptr() { return m_ptr; } - const handle& inc_ref() const { Py_XINCREF(m_ptr); return *this; } - const handle& dec_ref() const { Py_XDECREF(m_ptr); return *this; } - int ref_count() const { return (int) Py_REFCNT(m_ptr); } - handle get_type() const { return handle((PyObject *) Py_TYPE(m_ptr)); } - inline iterator begin() const; - inline iterator end() const; - inline detail::accessor operator[](handle key) const; - inline detail::accessor operator[](const char *key) const; - inline detail::accessor attr(handle key) const; - inline detail::accessor attr(const char *key) const; - inline pybind11::str str() const; - template T cast() const; - template - #if __cplusplus > 201103L - [[deprecated("call(...) was deprecated in favor of operator()(...)")]] - #endif - object call(Args&&... args) const; - template - object operator()(Args&&... args) const; - inline object operator()(detail::args_proxy args) const; - inline object operator()(detail::args_proxy f_args, detail::kwargs_proxy kwargs) const; - operator bool() const { return m_ptr != nullptr; } - bool operator==(const handle &h) const { return m_ptr == h.m_ptr; } - bool operator!=(const handle &h) const { return m_ptr != h.m_ptr; } - bool check() const { return m_ptr != nullptr; } - inline detail::args_proxy operator*() const; -protected: - PyObject *m_ptr; -}; - -/// Holds a reference to a Python object (with reference counting) -class object : public handle { -public: - object() { } - object(const object &o) : handle(o) { inc_ref(); } - object(const handle &h, bool borrowed) : handle(h) { if (borrowed) inc_ref(); } - object(PyObject *ptr, bool borrowed) : handle(ptr) { if (borrowed) inc_ref(); } - object(object &&other) noexcept { m_ptr = other.m_ptr; other.m_ptr = nullptr; } - ~object() { dec_ref(); } - - handle release() { - PyObject *tmp = m_ptr; - m_ptr = nullptr; - return handle(tmp); - } - - object& operator=(const object &other) { - other.inc_ref(); - dec_ref(); - m_ptr = other.m_ptr; - return *this; - } - - object& operator=(object &&other) noexcept { - if (this != &other) { - handle temp(m_ptr); - m_ptr = other.m_ptr; - other.m_ptr = nullptr; - temp.dec_ref(); - } - return *this; - } -}; - -NAMESPACE_BEGIN(detail) -inline handle get_function(handle value) { - if (value) { -#if PY_MAJOR_VERSION >= 3 - if (PyInstanceMethod_Check(value.ptr())) - value = PyInstanceMethod_GET_FUNCTION(value.ptr()); -#endif - if (PyMethod_Check(value.ptr())) - value = PyMethod_GET_FUNCTION(value.ptr()); - } - return value; -} - -class accessor { -public: - accessor(handle obj, handle key, bool attr) - : obj(obj), key(key, true), attr(attr) { } - accessor(handle obj, const char *key, bool attr) - : obj(obj), key(PyUnicode_FromString(key), false), attr(attr) { } - accessor(const accessor &a) : obj(a.obj), key(a.key), attr(a.attr) { } - - void operator=(accessor o) { operator=(object(o)); } - - void operator=(const handle &value) { - if (attr) { - if (PyObject_SetAttr(obj.ptr(), key.ptr(), value.ptr()) == -1) - pybind11_fail("Unable to set object attribute"); - } else { - if (PyObject_SetItem(obj.ptr(), key.ptr(), value.ptr()) == -1) - pybind11_fail("Unable to set object item"); - } - } - - operator object() const { - object result(attr ? PyObject_GetAttr(obj.ptr(), key.ptr()) - : PyObject_GetItem(obj.ptr(), key.ptr()), false); - if (!result) {PyErr_Clear(); } - return result; - } - - template T cast() const { return operator object().cast(); } - - operator bool() const { - if (attr) { - return (bool) PyObject_HasAttr(obj.ptr(), key.ptr()); - } else { - object result(PyObject_GetItem(obj.ptr(), key.ptr()), false); - if (!result) PyErr_Clear(); - return (bool) result; - } - }; - -private: - handle obj; - object key; - bool attr; -}; - -struct list_accessor { -public: - list_accessor(handle list, size_t index) : list(list), index(index) { } - - void operator=(list_accessor o) { return operator=(object(o)); } - - void operator=(const handle &o) { - // PyList_SetItem steals a reference to 'o' - if (PyList_SetItem(list.ptr(), (ssize_t) index, o.inc_ref().ptr()) < 0) - pybind11_fail("Unable to assign value in Python list!"); - } - - operator object() const { - PyObject *result = PyList_GetItem(list.ptr(), (ssize_t) index); - if (!result) - pybind11_fail("Unable to retrieve value from Python list!"); - return object(result, true); - } - - template T cast() const { return operator object().cast(); } -private: - handle list; - size_t index; -}; - -struct tuple_accessor { -public: - tuple_accessor(handle tuple, size_t index) : tuple(tuple), index(index) { } - - void operator=(tuple_accessor o) { return operator=(object(o)); } - - void operator=(const handle &o) { - // PyTuple_SetItem steals a referenceto 'o' - if (PyTuple_SetItem(tuple.ptr(), (ssize_t) index, o.inc_ref().ptr()) < 0) - pybind11_fail("Unable to assign value in Python tuple!"); - } - - operator object() const { - PyObject *result = PyTuple_GetItem(tuple.ptr(), (ssize_t) index); - if (!result) - pybind11_fail("Unable to retrieve value from Python tuple!"); - return object(result, true); - } - - template T cast() const { return operator object().cast(); } -private: - handle tuple; - size_t index; -}; - -struct dict_iterator { -public: - dict_iterator(handle dict = handle(), ssize_t pos = -1) : dict(dict), pos(pos) { } - dict_iterator& operator++() { - if (!PyDict_Next(dict.ptr(), &pos, &key.ptr(), &value.ptr())) - pos = -1; - return *this; - } - std::pair operator*() const { - return std::make_pair(key, value); - } - bool operator==(const dict_iterator &it) const { return it.pos == pos; } - bool operator!=(const dict_iterator &it) const { return it.pos != pos; } -private: - handle dict, key, value; - ssize_t pos = 0; -}; - -inline bool PyIterable_Check(PyObject *obj) { - PyObject *iter = PyObject_GetIter(obj); - if (iter) { - Py_DECREF(iter); - return true; - } else { - PyErr_Clear(); - return false; - } -} - -inline bool PyNone_Check(PyObject *o) { return o == Py_None; } - -inline bool PyUnicode_Check_Permissive(PyObject *o) { return PyUnicode_Check(o) || PYBIND11_BYTES_CHECK(o); } - -class kwargs_proxy : public handle { -public: - kwargs_proxy(handle h) : handle(h) { } -}; - -class args_proxy : public handle { -public: - args_proxy(handle h) : handle(h) { } - kwargs_proxy operator*() const { return kwargs_proxy(*this); } -}; - -NAMESPACE_END(detail) - -#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, CvtStmt) \ - public: \ - Name(const handle &h, bool borrowed) : Parent(h, borrowed) { CvtStmt; } \ - Name(const object& o): Parent(o) { CvtStmt; } \ - Name(object&& o) noexcept : Parent(std::move(o)) { CvtStmt; } \ - Name& operator=(object&& o) noexcept { (void) object::operator=(std::move(o)); CvtStmt; return *this; } \ - Name& operator=(const object& o) { return static_cast(object::operator=(o)); CvtStmt; } \ - bool check() const { return m_ptr != nullptr && (bool) CheckFun(m_ptr); } - -#define PYBIND11_OBJECT(Name, Parent, CheckFun) \ - PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ) - -#define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun) \ - PYBIND11_OBJECT(Name, Parent, CheckFun) \ - Name() : Parent() { } - -class iterator : public object { -public: - PYBIND11_OBJECT_CVT(iterator, object, PyIter_Check, value = object(); ready = false) - iterator() : object(), value(object()), ready(false) { } - iterator(const iterator& it) : object(it), value(it.value), ready(it.ready) { } - iterator(iterator&& it) : object(std::move(it)), value(std::move(it.value)), ready(it.ready) { } - - /** Caveat: this copy constructor does not (and cannot) clone the internal - state of the Python iterable */ - iterator &operator=(const iterator &it) { - (void) object::operator=(it); - value = it.value; - ready = it.ready; - return *this; - } - - iterator &operator=(iterator &&it) noexcept { - (void) object::operator=(std::move(it)); - value = std::move(it.value); - ready = it.ready; - return *this; - } - - iterator& operator++() { - if (m_ptr) - advance(); - return *this; - } - - /** Caveat: this postincrement operator does not (and cannot) clone the - internal state of the Python iterable. It should only be used to - retrieve the current iterate using operator*() */ - iterator operator++(int) { - iterator rv(*this); - rv.value = value; - if (m_ptr) - advance(); - return rv; - } - - bool operator==(const iterator &it) const { return *it == **this; } - bool operator!=(const iterator &it) const { return *it != **this; } - - handle operator*() const { - if (!ready && m_ptr) { - auto& self = const_cast(*this); - self.advance(); - self.ready = true; - } - return value; - } - -private: - void advance() { value = object(PyIter_Next(m_ptr), false); } - -private: - object value; - bool ready; -}; - -class iterable : public object { -public: - PYBIND11_OBJECT_DEFAULT(iterable, object, detail::PyIterable_Check) -}; - -inline detail::accessor handle::operator[](handle key) const { return detail::accessor(*this, key, false); } -inline detail::accessor handle::operator[](const char *key) const { return detail::accessor(*this, key, false); } -inline detail::accessor handle::attr(handle key) const { return detail::accessor(*this, key, true); } -inline detail::accessor handle::attr(const char *key) const { return detail::accessor(*this, key, true); } -inline iterator handle::begin() const { return iterator(PyObject_GetIter(ptr()), false); } -inline iterator handle::end() const { return iterator(nullptr, false); } -inline detail::args_proxy handle::operator*() const { return detail::args_proxy(*this); } - -class str : public object { -public: - PYBIND11_OBJECT_DEFAULT(str, object, detail::PyUnicode_Check_Permissive) - - str(const std::string &s) - : object(PyUnicode_FromStringAndSize(s.c_str(), (ssize_t) s.length()), false) { - if (!m_ptr) pybind11_fail("Could not allocate string object!"); - } - - operator std::string() const { - object temp = *this; - if (PyUnicode_Check(m_ptr)) { - temp = object(PyUnicode_AsUTF8String(m_ptr), false); - if (!temp) - pybind11_fail("Unable to extract string contents! (encoding issue)"); - } - char *buffer; - ssize_t length; - int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length); - if (err == -1) - pybind11_fail("Unable to extract string contents! (invalid type)"); - return std::string(buffer, (size_t) length); - } -}; - -inline pybind11::str handle::str() const { - PyObject *strValue = PyObject_Str(m_ptr); -#if PY_MAJOR_VERSION < 3 - PyObject *unicode = PyUnicode_FromEncodedObject(strValue, "utf-8", nullptr); - Py_XDECREF(strValue); strValue = unicode; -#endif - return pybind11::str(strValue, false); -} - -class bytes : public object { -public: - PYBIND11_OBJECT_DEFAULT(bytes, object, PYBIND11_BYTES_CHECK) - - bytes(const std::string &s) - : object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(s.data(), (ssize_t) s.size()), false) { - if (!m_ptr) pybind11_fail("Could not allocate bytes object!"); - } - - operator std::string() const { - char *buffer; - ssize_t length; - int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length); - if (err == -1) - pybind11_fail("Unable to extract bytes contents!"); - return std::string(buffer, (size_t) length); - } -}; - -class none : public object { -public: - PYBIND11_OBJECT(none, object, detail::PyNone_Check) - none() : object(Py_None, true) { } -}; - -class bool_ : public object { -public: - PYBIND11_OBJECT_DEFAULT(bool_, object, PyBool_Check) - bool_(bool value) : object(value ? Py_True : Py_False, true) { } - operator bool() const { return m_ptr && PyLong_AsLong(m_ptr) != 0; } -}; - -class int_ : public object { -public: - PYBIND11_OBJECT_DEFAULT(int_, object, PYBIND11_LONG_CHECK) - template ::value, int>::type = 0> - int_(T value) { - if (sizeof(T) <= sizeof(long)) { - if (std::is_signed::value) - m_ptr = PyLong_FromLong((long) value); - else - m_ptr = PyLong_FromUnsignedLong((unsigned long) value); - } else { - if (std::is_signed::value) - m_ptr = PyLong_FromLongLong((long long) value); - else - m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value); - } - if (!m_ptr) pybind11_fail("Could not allocate int object!"); - } - - template ::value, int>::type = 0> - operator T() const { - if (sizeof(T) <= sizeof(long)) { - if (std::is_signed::value) - return (T) PyLong_AsLong(m_ptr); - else - return (T) PyLong_AsUnsignedLong(m_ptr); - } else { - if (std::is_signed::value) - return (T) PYBIND11_LONG_AS_LONGLONG(m_ptr); - else - return (T) PYBIND11_LONG_AS_UNSIGNED_LONGLONG(m_ptr); - } - } -}; - -class float_ : public object { -public: - PYBIND11_OBJECT_DEFAULT(float_, object, PyFloat_Check) - float_(float value) : object(PyFloat_FromDouble((double) value), false) { - if (!m_ptr) pybind11_fail("Could not allocate float object!"); - } - float_(double value) : object(PyFloat_FromDouble((double) value), false) { - if (!m_ptr) pybind11_fail("Could not allocate float object!"); - } - operator float() const { return (float) PyFloat_AsDouble(m_ptr); } - operator double() const { return (double) PyFloat_AsDouble(m_ptr); } -}; - -class weakref : public object { -public: - PYBIND11_OBJECT_DEFAULT(weakref, object, PyWeakref_Check) - weakref(handle obj, handle callback = handle()) : object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), false) { - if (!m_ptr) pybind11_fail("Could not allocate weak reference!"); - } -}; - -class slice : public object { -public: - PYBIND11_OBJECT_DEFAULT(slice, object, PySlice_Check) - slice(ssize_t start_, ssize_t stop_, ssize_t step_) { - int_ start(start_), stop(stop_), step(step_); - m_ptr = PySlice_New(start.ptr(), stop.ptr(), step.ptr()); - if (!m_ptr) pybind11_fail("Could not allocate slice object!"); - } - bool compute(size_t length, size_t *start, size_t *stop, size_t *step, - size_t *slicelength) const { - return PySlice_GetIndicesEx((PYBIND11_SLICE_OBJECT *) m_ptr, - (ssize_t) length, (ssize_t *) start, - (ssize_t *) stop, (ssize_t *) step, - (ssize_t *) slicelength) == 0; - } -}; - -class capsule : public object { -public: - PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact) - capsule(PyObject *obj, bool borrowed) : object(obj, borrowed) { } - capsule(const void *value, void (*destruct)(PyObject *) = nullptr) - : object(PyCapsule_New(const_cast(value), nullptr, destruct), false) { - if (!m_ptr) pybind11_fail("Could not allocate capsule object!"); - } - template operator T *() const { - T * result = static_cast(PyCapsule_GetPointer(m_ptr, nullptr)); - if (!result) pybind11_fail("Unable to extract capsule contents!"); - return result; - } -}; - -class tuple : public object { -public: - PYBIND11_OBJECT(tuple, object, PyTuple_Check) - tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), false) { - if (!m_ptr) pybind11_fail("Could not allocate tuple object!"); - } - size_t size() const { return (size_t) PyTuple_Size(m_ptr); } - detail::tuple_accessor operator[](size_t index) const { return detail::tuple_accessor(*this, index); } -}; - -class dict : public object { -public: - PYBIND11_OBJECT(dict, object, PyDict_Check) - dict() : object(PyDict_New(), false) { - if (!m_ptr) pybind11_fail("Could not allocate dict object!"); - } - size_t size() const { return (size_t) PyDict_Size(m_ptr); } - detail::dict_iterator begin() const { return (++detail::dict_iterator(*this, 0)); } - detail::dict_iterator end() const { return detail::dict_iterator(); } - void clear() const { PyDict_Clear(ptr()); } -}; - -class list : public object { -public: - PYBIND11_OBJECT(list, object, PyList_Check) - list(size_t size = 0) : object(PyList_New((ssize_t) size), false) { - if (!m_ptr) pybind11_fail("Could not allocate list object!"); - } - size_t size() const { return (size_t) PyList_Size(m_ptr); } - detail::list_accessor operator[](size_t index) const { return detail::list_accessor(*this, index); } - void append(const object &object) const { PyList_Append(m_ptr, object.ptr()); } -}; - -class args : public tuple { PYBIND11_OBJECT_DEFAULT(args, tuple, PyTuple_Check) }; -class kwargs : public dict { PYBIND11_OBJECT_DEFAULT(kwargs, dict, PyDict_Check) }; - -class set : public object { -public: - PYBIND11_OBJECT(set, object, PySet_Check) - set() : object(PySet_New(nullptr), false) { - if (!m_ptr) pybind11_fail("Could not allocate set object!"); - } - size_t size() const { return (size_t) PySet_Size(m_ptr); } - bool add(const object &object) const { return PySet_Add(m_ptr, object.ptr()) == 0; } - void clear() const { PySet_Clear(m_ptr); } -}; - -class function : public object { -public: - PYBIND11_OBJECT_DEFAULT(function, object, PyCallable_Check) - bool is_cpp_function() const { - handle fun = detail::get_function(m_ptr); - return fun && PyCFunction_Check(fun.ptr()); - } -}; - -class buffer : public object { -public: - PYBIND11_OBJECT_DEFAULT(buffer, object, PyObject_CheckBuffer) - - buffer_info request(bool writable = false) { - int flags = PyBUF_STRIDES | PyBUF_FORMAT; - if (writable) flags |= PyBUF_WRITABLE; - Py_buffer *view = new Py_buffer(); - if (PyObject_GetBuffer(m_ptr, view, flags) != 0) - throw error_already_set(); - return buffer_info(view); - } -}; - -inline size_t len(handle h) { - ssize_t result = PyObject_Length(h.ptr()); - if (result < 0) - pybind11_fail("Unable to compute length of object"); - return (size_t) result; -} - -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/stl.h b/stormpy/resources/pybind11/include/pybind11/stl.h deleted file mode 100644 index e0177de40..000000000 --- a/stormpy/resources/pybind11/include/pybind11/stl.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - pybind11/stl.h: Transparent conversion for STL data types - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "pybind11.h" -#include -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant -#endif - -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) - -template struct set_caster { - typedef Type type; - typedef type_caster::type> key_conv; - - bool load(handle src, bool convert) { - pybind11::set s(src, true); - if (!s.check()) - return false; - value.clear(); - key_conv conv; - for (auto entry : s) { - if (!conv.load(entry, convert)) - return false; - value.insert((Key) conv); - } - return true; - } - - static handle cast(const type &src, return_value_policy policy, handle parent) { - pybind11::set s; - for (auto const &value: src) { - object value_ = object(key_conv::cast(value, policy, parent), false); - if (!value_ || !s.add(value_)) - return handle(); - } - return s.release(); - } - - PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">")); -}; - -template struct map_caster { - typedef Type type; - typedef type_caster::type> key_conv; - typedef type_caster::type> value_conv; - - bool load(handle src, bool convert) { - dict d(src, true); - if (!d.check()) - return false; - key_conv kconv; - value_conv vconv; - value.clear(); - for (auto it : d) { - if (!kconv.load(it.first.ptr(), convert) || - !vconv.load(it.second.ptr(), convert)) - return false; - value.emplace((Key) kconv, (Value) vconv); - } - return true; - } - - static handle cast(const type &src, return_value_policy policy, handle parent) { - dict d; - for (auto const &kv: src) { - object key = object(key_conv::cast(kv.first, policy, parent), false); - object value = object(value_conv::cast(kv.second, policy, parent), false); - if (!key || !value) - return handle(); - d[key] = value; - } - return d.release(); - } - - PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">")); -}; - -template struct list_caster { - typedef Type type; - typedef type_caster::type> value_conv; - - bool load(handle src, bool convert) { - list l(src, true); - if (!l.check()) - return false; - value_conv conv; - value.clear(); - reserve_maybe(l, &value); - for (auto it : l) { - if (!conv.load(it, convert)) - return false; - value.push_back((Value) conv); - } - return true; - } - - template ().reserve(0)), void>::value, int>::type = 0> - void reserve_maybe(list l, Type *) { value.reserve(l.size()); } - void reserve_maybe(list, void *) { } - - static handle cast(const Type &src, return_value_policy policy, handle parent) { - list l(src.size()); - size_t index = 0; - for (auto const &value: src) { - object value_ = object(value_conv::cast(value, policy, parent), false); - if (!value_) - return handle(); - PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference - } - return l.release(); - } - - PYBIND11_TYPE_CASTER(Type, _("list<") + value_conv::name() + _(">")); -}; - -template struct type_caster> - : list_caster, Type> { }; - -template struct type_caster> - : list_caster, Type> { }; - -template struct type_caster> { - typedef std::array array_type; - typedef type_caster::type> value_conv; - - bool load(handle src, bool convert) { - list l(src, true); - if (!l.check()) - return false; - if (l.size() != Size) - return false; - value_conv conv; - size_t ctr = 0; - for (auto it : l) { - if (!conv.load(it, convert)) - return false; - value[ctr++] = (Type) conv; - } - return true; - } - - static handle cast(const array_type &src, return_value_policy policy, handle parent) { - list l(Size); - size_t index = 0; - for (auto const &value: src) { - object value_ = object(value_conv::cast(value, policy, parent), false); - if (!value_) - return handle(); - PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference - } - return l.release(); - } - PYBIND11_TYPE_CASTER(array_type, _("list<") + value_conv::name() + _(">") + _("[") + _() + _("]")); -}; - -template struct type_caster> - : set_caster, Key> { }; - -template struct type_caster> - : set_caster, Key> { }; - -template struct type_caster> - : map_caster, Key, Value> { }; - -template struct type_caster> - : map_caster, Key, Value> { }; - -NAMESPACE_END(detail) - -inline std::ostream &operator<<(std::ostream &os, const handle &obj) { - os << (std::string) obj.str(); - return os; -} - -NAMESPACE_END(pybind11) - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif diff --git a/stormpy/resources/pybind11/include/pybind11/stl_bind.h b/stormpy/resources/pybind11/include/pybind11/stl_bind.h deleted file mode 100644 index a67f3ca0e..000000000 --- a/stormpy/resources/pybind11/include/pybind11/stl_bind.h +++ /dev/null @@ -1,353 +0,0 @@ -/* - pybind11/std_bind.h: Binding generators for STL data types - - Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include "common.h" -#include "operators.h" - -#include -#include -#include -#include - -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) - -/* SFINAE helper class used by 'is_comparable */ -template struct container_traits { - template static std::true_type test_comparable(decltype(std::declval() == std::declval())*); - template static std::false_type test_comparable(...); - template static std::true_type test_value(typename T2::value_type *); - template static std::false_type test_value(...); - template static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *); - template static std::false_type test_pair(...); - - static constexpr const bool is_comparable = std::is_same(nullptr))>::value; - static constexpr const bool is_pair = std::is_same(nullptr, nullptr))>::value; - static constexpr const bool is_vector = std::is_same(nullptr))>::value; - static constexpr const bool is_element = !is_pair && !is_vector; -}; - -/* Default: is_comparable -> std::false_type */ -template -struct is_comparable : std::false_type { }; - -/* For non-map data structures, check whether operator== can be instantiated */ -template -struct is_comparable< - T, typename std::enable_if::is_element && - container_traits::is_comparable>::type> - : std::true_type { }; - -/* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */ -template -struct is_comparable::is_vector>::type> { - static constexpr const bool value = - is_comparable::value; -}; - -/* For pairs, recursively check the two data types */ -template -struct is_comparable::is_pair>::type> { - static constexpr const bool value = - is_comparable::value && - is_comparable::value; -}; - -/* Fallback functions */ -template void vector_if_copy_constructible(const Args&...) { } -template void vector_if_equal_operator(const Args&...) { } -template void vector_if_insertion_operator(const Args&...) { } - -template::value, int>::type = 0> -void vector_if_copy_constructible(Class_ &cl) { - cl.def(pybind11::init(), - "Copy constructor"); -} - -template::value, int>::type = 0> -void vector_if_equal_operator(Class_ &cl) { - using T = typename Vector::value_type; - - cl.def(self == self); - cl.def(self != self); - - cl.def("count", - [](const Vector &v, const T &x) { - return std::count(v.begin(), v.end(), x); - }, - arg("x"), - "Return the number of times ``x`` appears in the list" - ); - - cl.def("remove", [](Vector &v, const T &x) { - auto p = std::find(v.begin(), v.end(), x); - if (p != v.end()) - v.erase(p); - else - throw pybind11::value_error(); - }, - arg("x"), - "Remove the first item from the list whose value is x. " - "It is an error if there is no such item." - ); - - cl.def("__contains__", - [](const Vector &v, const T &x) { - return std::find(v.begin(), v.end(), x) != v.end(); - }, - arg("x"), - "Return true the container contains ``x``" - ); -} - -template auto vector_if_insertion_operator(Class_ &cl, std::string const &name) - -> decltype(std::declval() << std::declval(), void()) { - using size_type = typename Vector::size_type; - - cl.def("__repr__", - [name](Vector &v) { - std::ostringstream s; - s << name << '['; - for (size_type i=0; i < v.size(); ++i) { - s << v[i]; - if (i != v.size() - 1) - s << ", "; - } - s << ']'; - return s.str(); - }, - "Return the canonical string representation of this list." - ); -} - -NAMESPACE_END(detail) - - -template , typename holder_type = std::unique_ptr>, typename... Args> -pybind11::class_, holder_type> bind_vector(pybind11::module &m, std::string const &name, Args&&... args) { - using Vector = std::vector; - using SizeType = typename Vector::size_type; - using DiffType = typename Vector::difference_type; - using ItType = typename Vector::iterator; - using Class_ = pybind11::class_; - - Class_ cl(m, name.c_str(), std::forward(args)...); - - cl.def(pybind11::init<>()); - - // Register copy constructor (if possible) - detail::vector_if_copy_constructible(cl); - - // Register comparison-related operators and functions (if possible) - detail::vector_if_equal_operator(cl); - - // Register stream insertion operator (if possible) - detail::vector_if_insertion_operator(cl, name); - - cl.def("__init__", [](Vector &v, iterable it) { - new (&v) Vector(); - try { - v.reserve(len(it)); - for (handle h : it) - v.push_back(h.cast()); - } catch (...) { - v.~Vector(); - throw; - } - }); - - cl.def("append", - [](Vector &v, const T &value) { v.push_back(value); }, - arg("x"), - "Add an item to the end of the list"); - - cl.def("extend", - [](Vector &v, Vector &src) { - v.reserve(v.size() + src.size()); - v.insert(v.end(), src.begin(), src.end()); - }, - arg("L"), - "Extend the list by appending all the items in the given list" - ); - - cl.def("insert", - [](Vector &v, SizeType i, const T &x) { - v.insert(v.begin() + (DiffType) i, x); - }, - arg("i") , arg("x"), - "Insert an item at a given position." - ); - - cl.def("pop", - [](Vector &v) { - if (v.empty()) - throw pybind11::index_error(); - T t = v.back(); - v.pop_back(); - return t; - }, - "Remove and return the last item" - ); - - cl.def("pop", - [](Vector &v, SizeType i) { - if (i >= v.size()) - throw pybind11::index_error(); - T t = v[i]; - v.erase(v.begin() + (DiffType) i); - return t; - }, - arg("i"), - "Remove and return the item at index ``i``" - ); - - cl.def("__bool__", - [](const Vector &v) -> bool { - return !v.empty(); - }, - "Check whether the list is nonempty" - ); - - cl.def("__getitem__", - [](const Vector &v, SizeType i) -> T { - if (i >= v.size()) - throw pybind11::index_error(); - return v[i]; - } - ); - - cl.def("__setitem__", - [](Vector &v, SizeType i, const T &t) { - if (i >= v.size()) - throw pybind11::index_error(); - v[i] = t; - } - ); - - cl.def("__delitem__", - [](Vector &v, SizeType i) { - if (i >= v.size()) - throw pybind11::index_error(); - v.erase(v.begin() + typename Vector::difference_type(i)); - }, - "Delete list elements using a slice object" - ); - - cl.def("__len__", &Vector::size); - - cl.def("__iter__", - [](Vector &v) { - return pybind11::make_iterator(v.begin(), v.end()); - }, - pybind11::keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */ - ); - - /// Slicing protocol - cl.def("__getitem__", - [](const Vector &v, slice slice) -> Vector * { - size_t start, stop, step, slicelength; - - if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) - throw pybind11::error_already_set(); - - Vector *seq = new Vector(); - seq->reserve((size_t) slicelength); - - for (size_t i=0; ipush_back(v[start]); - start += step; - } - return seq; - }, - arg("s"), - "Retrieve list elements using a slice object" - ); - - cl.def("__setitem__", - [](Vector &v, slice slice, const Vector &value) { - size_t start, stop, step, slicelength; - if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) - throw pybind11::error_already_set(); - - if (slicelength != value.size()) - throw std::runtime_error("Left and right hand size of slice assignment have different sizes!"); - - for (size_t i=0; i()); - - cl.def("resize", - (void (Vector::*) (size_type count)) & Vector::resize, - "changes the number of elements stored"); - - cl.def("erase", - [](Vector &v, SizeType i) { - if (i >= v.size()) - throw pybind11::index_error(); - v.erase(v.begin() + i); - }, "erases element at index ``i``"); - - cl.def("empty", &Vector::empty, "checks whether the container is empty"); - cl.def("size", &Vector::size, "returns the number of elements"); - cl.def("push_back", (void (Vector::*)(const T&)) &Vector::push_back, "adds an element to the end"); - cl.def("pop_back", &Vector::pop_back, "removes the last element"); - - cl.def("max_size", &Vector::max_size, "returns the maximum possible number of elements"); - cl.def("reserve", &Vector::reserve, "reserves storage"); - cl.def("capacity", &Vector::capacity, "returns the number of elements that can be held in currently allocated storage"); - cl.def("shrink_to_fit", &Vector::shrink_to_fit, "reduces memory usage by freeing unused memory"); - - cl.def("clear", &Vector::clear, "clears the contents"); - cl.def("swap", &Vector::swap, "swaps the contents"); - - cl.def("front", [](Vector &v) { - if (v.size()) return v.front(); - else throw pybind11::index_error(); - }, "access the first element"); - - cl.def("back", [](Vector &v) { - if (v.size()) return v.back(); - else throw pybind11::index_error(); - }, "access the last element "); - -#endif - - return cl; -} - -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/include/pybind11/typeid.h b/stormpy/resources/pybind11/include/pybind11/typeid.h deleted file mode 100644 index c903fb14c..000000000 --- a/stormpy/resources/pybind11/include/pybind11/typeid.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - pybind11/typeid.h: Compiler-independent access to type identifiers - - Copyright (c) 2016 Wenzel Jakob - - All rights reserved. Use of this source code is governed by a - BSD-style license that can be found in the LICENSE file. -*/ - -#pragma once - -#include -#include - -#if defined(__GNUG__) -#include -#endif - -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) -/// Erase all occurrences of a substring -inline void erase_all(std::string &string, const std::string &search) { - for (size_t pos = 0;;) { - pos = string.find(search, pos); - if (pos == std::string::npos) break; - string.erase(pos, search.length()); - } -} - -PYBIND11_NOINLINE inline void clean_type_id(std::string &name) { -#if defined(__GNUG__) - int status = 0; - std::unique_ptr res { - abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free }; - if (status == 0) - name = res.get(); -#else - detail::erase_all(name, "class "); - detail::erase_all(name, "struct "); - detail::erase_all(name, "enum "); -#endif - detail::erase_all(name, "pybind11::"); -} -NAMESPACE_END(detail) - -/// Return a string representation of a C++ type -template static std::string type_id() { - std::string name(typeid(T).name()); - detail::clean_type_id(name); - return name; -} - -NAMESPACE_END(pybind11) diff --git a/stormpy/resources/pybind11/pybind11/__init__.py b/stormpy/resources/pybind11/pybind11/__init__.py deleted file mode 100644 index dc0ddf6f3..000000000 --- a/stormpy/resources/pybind11/pybind11/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -from ._version import version_info, __version__ - - -def get_include(*args, **kwargs): - import os - try: - from pip import locations - return os.path.dirname( - locations.distutils_scheme('pybind11', *args, **kwargs)['headers']) - except ImportError: - return 'include' diff --git a/stormpy/resources/pybind11/pybind11/_version.py b/stormpy/resources/pybind11/pybind11/_version.py deleted file mode 100644 index be66f0732..000000000 --- a/stormpy/resources/pybind11/pybind11/_version.py +++ /dev/null @@ -1,2 +0,0 @@ -version_info = (1, 9, 'dev0') -__version__ = '.'.join(map(str, version_info)) diff --git a/stormpy/resources/pybind11/setup.cfg b/stormpy/resources/pybind11/setup.cfg deleted file mode 100644 index 3c6e79cf3..000000000 --- a/stormpy/resources/pybind11/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[bdist_wheel] -universal=1 diff --git a/stormpy/resources/pybind11/setup.py b/stormpy/resources/pybind11/setup.py deleted file mode 100644 index 07465bb67..000000000 --- a/stormpy/resources/pybind11/setup.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -# Setup script for PyPI; use CMakeFile.txt to build the example application - -from setuptools import setup -from pybind11 import __version__ - -setup( - name='pybind11', - version=__version__, - description='Seamless operability between C++11 and Python', - author='Wenzel Jakob', - author_email='wenzel.jakob@epfl.ch', - url='https://github.com/wjakob/pybind11', - download_url='https://github.com/wjakob/pybind11/tarball/v' + __version__, - packages=['pybind11'], - license='BSD', - headers=[ - 'include/pybind11/attr.h', - 'include/pybind11/cast.h', - 'include/pybind11/complex.h', - 'include/pybind11/descr.h', - 'include/pybind11/eigen.h', - 'include/pybind11/numpy.h', - 'include/pybind11/pybind11.h', - 'include/pybind11/stl.h', - 'include/pybind11/stl_bind.h', - 'include/pybind11/common.h', - 'include/pybind11/functional.h', - 'include/pybind11/operators.h', - 'include/pybind11/pytypes.h', - 'include/pybind11/typeid.h' - ], - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Utilities', - 'Programming Language :: C++', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'License :: OSI Approved :: BSD License', - ], - keywords='C++11, Python bindings', - long_description="""pybind11 is a lightweight header library that exposes -C++ types in Python and vice versa, mainly to create Python bindings of -existing C++ code. Its goals and syntax are similar to the excellent -Boost.Python library by David Abrahams: to minimize boilerplate code in -traditional extension modules by inferring type information using compile-time -introspection. - -The main issue with Boost.Python-and the reason for creating such a similar -project-is Boost. Boost is an enormously large and complex suite of utility -libraries that works with almost every C++ compiler in existence. This -compatibility has its cost: arcane template tricks and workarounds are -necessary to support the oldest and buggiest of compiler specimens. Now that -C++11-compatible compilers are widely available, this heavy machinery has -become an excessively large and unnecessary dependency. - -Think of this library as a tiny self-contained version of Boost.Python with -everything stripped away that isn't relevant for binding generation. Without -comments, the core header files only require ~2.5K lines of code and depend on -Python (2.7 or 3.x) and the C++ standard library. This compact implementation -was possible thanks to some of the new C++11 language features (specifically: -tuples, lambda functions and variadic templates). Since its creation, this -library has grown beyond Boost.Python in many ways, leading to dramatically -simpler binding code in many common situations.""") diff --git a/stormpy/resources/pybind11/tools/FindEigen3.cmake b/stormpy/resources/pybind11/tools/FindEigen3.cmake deleted file mode 100644 index 9c546a05d..000000000 --- a/stormpy/resources/pybind11/tools/FindEigen3.cmake +++ /dev/null @@ -1,81 +0,0 @@ -# - Try to find Eigen3 lib -# -# This module supports requiring a minimum version, e.g. you can do -# find_package(Eigen3 3.1.2) -# to require version 3.1.2 or newer of Eigen3. -# -# Once done this will define -# -# EIGEN3_FOUND - system has eigen lib with correct version -# EIGEN3_INCLUDE_DIR - the eigen include directory -# EIGEN3_VERSION - eigen version - -# Copyright (c) 2006, 2007 Montel Laurent, -# Copyright (c) 2008, 2009 Gael Guennebaud, -# Copyright (c) 2009 Benoit Jacob -# Redistribution and use is allowed according to the terms of the 2-clause BSD license. - -if(NOT Eigen3_FIND_VERSION) - if(NOT Eigen3_FIND_VERSION_MAJOR) - set(Eigen3_FIND_VERSION_MAJOR 2) - endif(NOT Eigen3_FIND_VERSION_MAJOR) - if(NOT Eigen3_FIND_VERSION_MINOR) - set(Eigen3_FIND_VERSION_MINOR 91) - endif(NOT Eigen3_FIND_VERSION_MINOR) - if(NOT Eigen3_FIND_VERSION_PATCH) - set(Eigen3_FIND_VERSION_PATCH 0) - endif(NOT Eigen3_FIND_VERSION_PATCH) - - set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}") -endif(NOT Eigen3_FIND_VERSION) - -macro(_eigen3_check_version) - file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) - - string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") - set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}") - set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}") - set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}") - - set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION}) - if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) - set(EIGEN3_VERSION_OK FALSE) - else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) - set(EIGEN3_VERSION_OK TRUE) - endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) - - if(NOT EIGEN3_VERSION_OK) - - message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, " - "but at least version ${Eigen3_FIND_VERSION} is required") - endif(NOT EIGEN3_VERSION_OK) -endmacro(_eigen3_check_version) - -if (EIGEN3_INCLUDE_DIR) - - # in cache already - _eigen3_check_version() - set(EIGEN3_FOUND ${EIGEN3_VERSION_OK}) - -else (EIGEN3_INCLUDE_DIR) - - find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library - PATHS - ${CMAKE_INSTALL_PREFIX}/include - ${KDE4_INCLUDE_DIR} - PATH_SUFFIXES eigen3 eigen - ) - - if(EIGEN3_INCLUDE_DIR) - _eigen3_check_version() - endif(EIGEN3_INCLUDE_DIR) - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) - - mark_as_advanced(EIGEN3_INCLUDE_DIR) - -endif(EIGEN3_INCLUDE_DIR) - diff --git a/stormpy/resources/pybind11/tools/mkdoc.py b/stormpy/resources/pybind11/tools/mkdoc.py deleted file mode 100644 index 400fb05da..000000000 --- a/stormpy/resources/pybind11/tools/mkdoc.py +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/env python3 -# -# Syntax: mkdoc.py [-I ..] [.. a list of header files ..] -# -# Extract documentation from C++ header files to use it in Python bindings -# - -import os -import sys -import platform -import re -import textwrap - -from clang import cindex -from clang.cindex import CursorKind -from collections import OrderedDict -from threading import Thread, Semaphore -from multiprocessing import cpu_count - -RECURSE_LIST = [ - CursorKind.TRANSLATION_UNIT, - CursorKind.NAMESPACE, - CursorKind.CLASS_DECL, - CursorKind.STRUCT_DECL, - CursorKind.ENUM_DECL, - CursorKind.CLASS_TEMPLATE -] - -PRINT_LIST = [ - CursorKind.CLASS_DECL, - CursorKind.STRUCT_DECL, - CursorKind.ENUM_DECL, - CursorKind.ENUM_CONSTANT_DECL, - CursorKind.CLASS_TEMPLATE, - CursorKind.FUNCTION_DECL, - CursorKind.FUNCTION_TEMPLATE, - CursorKind.CONVERSION_FUNCTION, - CursorKind.CXX_METHOD, - CursorKind.CONSTRUCTOR, - CursorKind.FIELD_DECL -] - -CPP_OPERATORS = { - '<=': 'le', '>=': 'ge', '==': 'eq', '!=': 'ne', '[]': 'array', - '+=': 'iadd', '-=': 'isub', '*=': 'imul', '/=': 'idiv', '%=': - 'imod', '&=': 'iand', '|=': 'ior', '^=': 'ixor', '<<=': 'ilshift', - '>>=': 'irshift', '++': 'inc', '--': 'dec', '<<': 'lshift', '>>': - 'rshift', '&&': 'land', '||': 'lor', '!': 'lnot', '~': 'bnot', - '&': 'band', '|': 'bor', '+': 'add', '-': 'sub', '*': 'mul', '/': - 'div', '%': 'mod', '<': 'lt', '>': 'gt', '=': 'assign', '()': 'call' -} - -CPP_OPERATORS = OrderedDict( - sorted(CPP_OPERATORS.items(), key=lambda t: -len(t[0]))) - -job_count = cpu_count() -job_semaphore = Semaphore(job_count) - -registered_names = dict() - - -def d(s): - return s.decode('utf8') - - -def sanitize_name(name): - global registered_names - name = re.sub(r'type-parameter-0-([0-9]+)', r'T\1', name) - for k, v in CPP_OPERATORS.items(): - name = name.replace('operator%s' % k, 'operator_%s' % v) - name = re.sub('<.*>', '', name) - name = ''.join([ch if ch.isalnum() else '_' for ch in name]) - name = re.sub('_$', '', re.sub('_+', '_', name)) - if name in registered_names: - registered_names[name] += 1 - name += '_' + str(registered_names[name]) - else: - registered_names[name] = 1 - return '__doc_' + name - - -def process_comment(comment): - result = '' - - # Remove C++ comment syntax - leading_spaces = float('inf') - for s in comment.expandtabs(tabsize=4).splitlines(): - s = s.strip() - if s.startswith('/*'): - s = s[2:].lstrip('*') - elif s.endswith('*/'): - s = s[:-2].rstrip('*') - elif s.startswith('///'): - s = s[3:] - if s.startswith('*'): - s = s[1:] - if len(s) > 0: - leading_spaces = min(leading_spaces, len(s) - len(s.lstrip())) - result += s + '\n' - - if leading_spaces != float('inf'): - result2 = "" - for s in result.splitlines(): - result2 += s[leading_spaces:] + '\n' - result = result2 - - # Doxygen tags - cpp_group = '([\w:]+)' - param_group = '([\[\w:\]]+)' - - s = result - s = re.sub(r'\\c\s+%s' % cpp_group, r'``\1``', s) - s = re.sub(r'\\a\s+%s' % cpp_group, r'*\1*', s) - s = re.sub(r'\\e\s+%s' % cpp_group, r'*\1*', s) - s = re.sub(r'\\em\s+%s' % cpp_group, r'*\1*', s) - s = re.sub(r'\\b\s+%s' % cpp_group, r'**\1**', s) - s = re.sub(r'\\ingroup\s+%s' % cpp_group, r'', s) - s = re.sub(r'\\param%s?\s+%s' % (param_group, cpp_group), - r'\n\n$Parameter ``\2``:\n\n', s) - s = re.sub(r'\\tparam%s?\s+%s' % (param_group, cpp_group), - r'\n\n$Template parameter ``\2``:\n\n', s) - - for in_, out_ in { - 'return': 'Returns', - 'author': 'Author', - 'authors': 'Authors', - 'copyright': 'Copyright', - 'date': 'Date', - 'remark': 'Remark', - 'sa': 'See also', - 'see': 'See also', - 'extends': 'Extends', - 'throw': 'Throws', - 'throws': 'Throws' - }.items(): - s = re.sub(r'\\%s\s*' % in_, r'\n\n$%s:\n\n' % out_, s) - - s = re.sub(r'\\details\s*', r'\n\n', s) - s = re.sub(r'\\brief\s*', r'', s) - s = re.sub(r'\\short\s*', r'', s) - s = re.sub(r'\\ref\s*', r'', s) - - s = re.sub(r'\\code\s?(.*?)\s?\\endcode', - r"```\n\1\n```\n", s, flags=re.DOTALL) - - # HTML/TeX tags - s = re.sub(r'(.*?)', r'``\1``', s, flags=re.DOTALL) - s = re.sub(r'
(.*?)
', r"```\n\1\n```\n", s, flags=re.DOTALL) - s = re.sub(r'(.*?)', r'*\1*', s, flags=re.DOTALL) - s = re.sub(r'(.*?)', r'**\1**', s, flags=re.DOTALL) - s = re.sub(r'\\f\$(.*?)\\f\$', r'$\1$', s, flags=re.DOTALL) - s = re.sub(r'
  • ', r'\n\n* ', s) - s = re.sub(r'', r'', s) - s = re.sub(r'
  • ', r'\n\n', s) - - s = s.replace('``true``', '``True``') - s = s.replace('``false``', '``False``') - - # Re-flow text - wrapper = textwrap.TextWrapper() - wrapper.expand_tabs = True - wrapper.replace_whitespace = True - wrapper.drop_whitespace = True - wrapper.width = 70 - wrapper.initial_indent = wrapper.subsequent_indent = '' - - result = '' - in_code_segment = False - for x in re.split(r'(```)', s): - if x == '```': - if not in_code_segment: - result += '```\n' - else: - result += '\n```\n\n' - in_code_segment = not in_code_segment - elif in_code_segment: - result += x.strip() - else: - for y in re.split(r'(?: *\n *){2,}', x): - wrapped = wrapper.fill(re.sub(r'\s+', ' ', y).strip()) - if len(wrapped) > 0 and wrapped[0] == '$': - result += wrapped[1:] + '\n' - wrapper.initial_indent = \ - wrapper.subsequent_indent = ' ' * 4 - else: - if len(wrapped) > 0: - result += wrapped + '\n\n' - wrapper.initial_indent = wrapper.subsequent_indent = '' - return result.rstrip().lstrip('\n') - - -def extract(filename, node, prefix, output): - num_extracted = 0 - if not (node.location.file is None or - os.path.samefile(d(node.location.file.name), filename)): - return 0 - if node.kind in RECURSE_LIST: - sub_prefix = prefix - if node.kind != CursorKind.TRANSLATION_UNIT: - if len(sub_prefix) > 0: - sub_prefix += '_' - sub_prefix += d(node.spelling) - for i in node.get_children(): - num_extracted += extract(filename, i, sub_prefix, output) - if num_extracted == 0: - return 0 - if node.kind in PRINT_LIST: - comment = d(node.raw_comment) if node.raw_comment is not None else '' - comment = process_comment(comment) - sub_prefix = prefix - if len(sub_prefix) > 0: - sub_prefix += '_' - if len(node.spelling) > 0: - name = sanitize_name(sub_prefix + d(node.spelling)) - output.append('\nstatic const char *%s =%sR"doc(%s)doc";' % - (name, '\n' if '\n' in comment else ' ', comment)) - num_extracted += 1 - return num_extracted - - -class ExtractionThread(Thread): - def __init__(self, filename, parameters, output): - Thread.__init__(self) - self.filename = filename - self.parameters = parameters - self.output = output - job_semaphore.acquire() - - def run(self): - print('Processing "%s" ..' % self.filename, file=sys.stderr) - try: - index = cindex.Index( - cindex.conf.lib.clang_createIndex(False, True)) - tu = index.parse(self.filename, self.parameters) - extract(self.filename, tu.cursor, '', self.output) - finally: - job_semaphore.release() - -if __name__ == '__main__': - parameters = ['-x', 'c++', '-std=c++11'] - filenames = [] - - if platform.system() == 'Darwin': - dev_path = '/Applications/Xcode.app/Contents/Developer/' - lib_dir = dev_path + 'Toolchains/XcodeDefault.xctoolchain/usr/lib/' - sdk_dir = dev_path + 'Platforms/MacOSX.platform/Developer/SDKs' - libclang = lib_dir + 'libclang.dylib' - - if os.path.exists(libclang): - cindex.Config.set_library_path(os.path.dirname(libclang)) - - if os.path.exists(sdk_dir): - sysroot_dir = os.path.join(sdk_dir, next(os.walk(sdk_dir))[1][0]) - parameters.append('-isysroot') - parameters.append(sysroot_dir) - - for item in sys.argv[1:]: - if item.startswith('-'): - parameters.append(item) - else: - filenames.append(item) - - if len(filenames) == 0: - print('Syntax: %s [.. a list of header files ..]' % sys.argv[0]) - exit(-1) - - print('''/* - This file contains docstrings for the Python bindings. - Do not edit! These were automatically extracted by mkdoc.py - */ - -#define __EXPAND(x) x -#define __COUNT(_1, _2, _3, _4, _5, _6, _7, COUNT, ...) COUNT -#define __VA_SIZE(...) __EXPAND(__COUNT(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1)) -#define __CAT1(a, b) a ## b -#define __CAT2(a, b) __CAT1(a, b) -#define __DOC1(n1) __doc_##n1 -#define __DOC2(n1, n2) __doc_##n1##_##n2 -#define __DOC3(n1, n2, n3) __doc_##n1##_##n2##_##n3 -#define __DOC4(n1, n2, n3, n4) __doc_##n1##_##n2##_##n3##_##n4 -#define __DOC5(n1, n2, n3, n4, n5) __doc_##n1##_##n2##_##n3##_##n4##_##n5 -#define __DOC6(n1, n2, n3, n4, n5, n6) __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6 -#define __DOC7(n1, n2, n3, n4, n5, n6, n7) __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6##_##n7 -#define DOC(...) __EXPAND(__EXPAND(__CAT2(__DOC, __VA_SIZE(__VA_ARGS__)))(__VA_ARGS__)) - -#if defined(__GNUG__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" -#endif -''') - - output = [] - for filename in filenames: - thr = ExtractionThread(filename, parameters, output) - thr.start() - - print('Waiting for jobs to finish ..', file=sys.stderr) - for i in range(job_count): - job_semaphore.acquire() - - output.sort() - for l in output: - print(l) - - print(''' -#if defined(__GNUG__) -#pragma GCC diagnostic pop -#endif -''') diff --git a/stormpy/setup.cfg.in b/stormpy/setup.cfg.in deleted file mode 100644 index b40a9a08e..000000000 --- a/stormpy/setup.cfg.in +++ /dev/null @@ -1,6 +0,0 @@ -[build_ext] -compile_flags=@STORMPY_COMPILE_ARGS@ -use-cln=@STORMPY_USE_CLN@ -include_dirs=@STORMPY_INCLUDE_DIRS@ -library_dirs=@STORMPY_LIBRARY_DIRS@ -rpath=@STORMPY_RPATH@ diff --git a/stormpy/setup.py b/stormpy/setup.py deleted file mode 100755 index c19855720..000000000 --- a/stormpy/setup.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python -from setuptools import setup -from distutils.core import Extension -from distutils.command.build_ext import build_ext as orig_build_ext -import os.path -import platform -from glob import glob - -PROJECT_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__))) - -# Glob source files for modules -core_sources = glob(os.path.join('src', 'core', '*.cpp')) -expressions_sources = glob(os.path.join('src', 'expressions', '*.cpp')) -logic_sources = glob(os.path.join('src', 'logic', '*.cpp')) -storage_sources = glob(os.path.join('src', 'storage', '*.cpp')) - -# Configuration shared between external modules follows -include_dirs = [PROJECT_DIR, os.path.join(PROJECT_DIR, 'src'), - os.path.join(PROJECT_DIR, 'resources', 'pybind11', 'include')] -libraries = ['storm'] -library_dirs = [] -extra_compile_args = [] -define_macros = [] -extra_link_args = [] - -ext_core = Extension( - name='core', - sources=['src/mod_core.cpp'] + core_sources, - include_dirs=include_dirs, - libraries=libraries, - library_dirs=library_dirs, - extra_compile_args=extra_compile_args, - define_macros=define_macros, - extra_link_args=extra_link_args -) - -ext_info = Extension( - name='info.info', - sources=['src/mod_info.cpp'], - include_dirs=include_dirs, - libraries=libraries, - library_dirs=library_dirs, - extra_compile_args=extra_compile_args, - define_macros=define_macros, - extra_link_args=extra_link_args -) - -ext_expressions = Extension( - name='expressions.expressions', - sources=['src/mod_expressions.cpp'] + expressions_sources, - include_dirs=include_dirs, - libraries=libraries, - library_dirs=library_dirs, - extra_compile_args=extra_compile_args, - define_macros=define_macros, - extra_link_args=extra_link_args -) - -ext_logic = Extension( - name='logic.logic', - sources=['src/mod_logic.cpp'] + logic_sources, - include_dirs=include_dirs, - libraries=libraries, - library_dirs=library_dirs, - extra_compile_args=extra_compile_args, - define_macros=define_macros, - extra_link_args=extra_link_args -) - -ext_storage = Extension( - name='storage.storage', - sources=['src/mod_storage.cpp'] + storage_sources, - include_dirs=include_dirs, - libraries=libraries, - library_dirs=library_dirs, - extra_compile_args=extra_compile_args, - define_macros=define_macros, - extra_link_args=extra_link_args -) - -class build_ext(orig_build_ext): - """Extend build_ext to provide CLN toggle option - """ - user_options = orig_build_ext.user_options + [ - ('use-cln', None, - "use cln numbers instead of gmpxx"), - ('compile-flags', None, - "compile flags for C++"), - ] - - boolean_options = orig_build_ext.boolean_options + ['use-cln'] - - def initialize_options (self): - super(build_ext, self).initialize_options() - self.use_cln = None - self.compile_flags = None - - def finalize_options(self): - super(build_ext, self).finalize_options() - - if self.use_cln: - self.libraries += ['cln'] - if not self.define: - self.define = [] - else: - self.define = list(self.define) - self.define += [('STORMPY_USE_CLN', 1)] - else: - self.libraries += ['gmp', 'gmpxx'] - if not self.undef: - self.undef = [] - self.undef += ['STORMPY_USE_CLN'] - - if self.library_dirs: - # Makes local storm library lookup that much easier - self.rpath += self.library_dirs - - if platform.system() == 'Darwin' and len(self.rpath) > 0: - for e in self.extensions: - # If rpath is used on OS X, set this option - e.extra_link_args.append('-Wl,-rpath,'+self.rpath[0]) - - for e in self.extensions: - e.extra_compile_args += self.compile_flags.split() - -setup(name="stormpy", - version="0.9", - author="M. Volk", - author_email="matthias.volk@cs.rwth-aachen.de", - maintainer="S. Junges", - maintainer_email="sebastian.junges@cs.rwth-aachen.de", - url="http://moves.rwth-aachen.de", - description="stormpy - Python Bindings for Storm", - packages=['stormpy', 'stormpy.info', 'stormpy.expressions', 'stormpy.logic', 'stormpy.storage'], - package_dir={'':'lib'}, - ext_package='stormpy', - ext_modules=[ext_core, ext_info, ext_expressions, ext_logic, ext_storage - ], - cmdclass={ - 'build_ext': build_ext, - } -) diff --git a/stormpy/src/CMakeLists.txt b/stormpy/src/CMakeLists.txt deleted file mode 100644 index 9882d8a91..000000000 --- a/stormpy/src/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -# This is a CMake example for Python - -INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src ${stormpy_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}) -INCLUDE_DIRECTORIES(${pybind11_incdir}) - -FILE(GLOB core_files "core/*.cpp") -#FILE(GLOB info_files "info/*.cpp") -#FILE(GLOB expressions_files "expressions/*.cpp") -FILE(GLOB storage_files "storage/*.cpp") -FILE(GLOB logic_files "logic/*.cpp") -ADD_LIBRARY(stormpy_core SHARED mod_core.cpp ${core_files}) -ADD_LIBRARY(stormpy_info SHARED mod_info.cpp) -ADD_LIBRARY(stormpy_expressions SHARED mod_expressions.cpp) -ADD_LIBRARY(stormpy_storage SHARED mod_storage.cpp ${storage_files}) -ADD_LIBRARY(stormpy_logic SHARED mod_logic.cpp ${logic_files}) - -SET_TARGET_PROPERTIES(stormpy_core PROPERTIES - OUTPUT_NAME core - PREFIX "" - SUFFIX ".so" - LIBRARY_OUTPUT_DIRECTORY ${STORMPY_OUTPUT_DIR}/ -) - -SET_TARGET_PROPERTIES(stormpy_info PROPERTIES - OUTPUT_NAME info - PREFIX "" - SUFFIX ".so" - LIBRARY_OUTPUT_DIRECTORY ${STORMPY_OUTPUT_DIR}/info -) - -SET_TARGET_PROPERTIES(stormpy_expressions PROPERTIES - OUTPUT_NAME expressions - PREFIX "" - SUFFIX ".so" - LIBRARY_OUTPUT_DIRECTORY ${STORMPY_OUTPUT_DIR}/expressions -) - -SET_TARGET_PROPERTIES(stormpy_storage PROPERTIES - OUTPUT_NAME storage - PREFIX "" - SUFFIX ".so" - LIBRARY_OUTPUT_DIRECTORY ${STORMPY_OUTPUT_DIR}/storage -) - -SET_TARGET_PROPERTIES(stormpy_logic PROPERTIES - OUTPUT_NAME logic - PREFIX "" - SUFFIX ".so" - LIBRARY_OUTPUT_DIRECTORY ${STORMPY_OUTPUT_DIR}/logic -) - -TARGET_LINK_LIBRARIES(stormpy_core storm ${PYTHON_LIBRARIES}) -TARGET_LINK_LIBRARIES(stormpy_info storm ${PYTHON_LIBRARIES}) -TARGET_LINK_LIBRARIES(stormpy_expressions storm ${PYTHON_LIBRARIES}) -TARGET_LINK_LIBRARIES(stormpy_storage storm ${PYTHON_LIBRARIES}) -TARGET_LINK_LIBRARIES(stormpy_logic storm ${PYTHON_LIBRARIES}) diff --git a/stormpy/src/common.h b/stormpy/src/common.h deleted file mode 100644 index e81b41784..000000000 --- a/stormpy/src/common.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * common.h - * - * Created on: 15 Apr 2016 - * Author: hbruintjes - */ - -#pragma once - -#include -#include -#include -#include - -namespace py = pybind11; - -#if PY_MAJOR_VERSION >= 3 -#define PY_DIV "__truediv__" -#define PY_RDIV "__rtruediv__" -#else -#define PY_DIV "__div__" -#define PY_RDIV "__rdiv__" -#endif - -PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) -PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr) - -namespace pybind11 { -namespace detail { -/** - * Dummy type caster for handle, so functions can return pybind11 handles directly - */ -/*template <> class type_caster { -public: - bool load(handle src, bool) { - value = handle(src).inc_ref(); - return true; - } - - static handle cast(handle src, return_value_policy policy, handle parent) { - switch(policy) { - case return_value_policy::automatic: - case return_value_policy::copy: - case return_value_policy::take_ownership: - return handle(src); - case return_value_policy::reference: - return handle(src).inc_ref(); - case return_value_policy::reference_internal: - parent.inc_ref(); - return handle(src); - } - return handle(src); - } - PYBIND11_TYPE_CASTER(handle, _("handle")); -};*/ -/* -template struct tuple_caster { - typedef TupleType type; - template - using type_conv = type_caster::type>; - - bool load(handle src, bool convert) { - pybind11::tuple tup(src, true); - if (!tup.check()) - return false; - - return loadItem<0, Keys...>(tup, convert); - } - - static handle cast(const type &src, return_value_policy policy, handle parent) { - pybind11::tuple tup(sizeof...(Keys)); - if (!castItem<0, Keys...>(tup, src, policy, parent)) { - return handle(); - } - - return tup.release(); - } - -private: - template - bool loadItem(pybind11::tuple& tup, bool convert) { - type_conv conv; - if (!conv.load(tup[N], convert)) - return false; - std::get(value) = static_cast(conv); - return loadItem(tup, convert); - } - - template - bool loadItem(pybind11::tuple& tup, bool convert) { - type_conv conv; - if (!conv.load(tup[N], convert)) - return false; - std::get(value) = static_cast(conv); - return true; - } - - template - static bool castItem(pybind11::tuple& tup, const type &src, return_value_policy policy, handle parent) { - auto obj = type_conv::cast(std::get(src), policy, parent); - object value_ = object(obj, false); - if (!obj) { - return false; - } - return castItem(tup, src, policy, parent); - } - - template - static bool castItem(pybind11::tuple& tu, const type &src, return_value_policy policy, handle parent) { - auto obj = type_conv::cast(std::get(src), policy, parent); - object value_ = object(obj, false); - if (!obj) { - return false; - } - return true; - } -}; - -template struct type_caster> - : tuple_caster, Types...> { }; - -template struct type_caster> - : tuple_caster, Type1, Type2> { }; -*/ - -} -} diff --git a/stormpy/src/core/bisimulation.cpp b/stormpy/src/core/bisimulation.cpp deleted file mode 100644 index 3eafc80d0..000000000 --- a/stormpy/src/core/bisimulation.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "bisimulation.h" - -// Thin wrapper for bisimulation -template -std::shared_ptr> performBisimulation(std::shared_ptr> const& model, std::shared_ptr const& formula, storm::storage::BisimulationType bisimulationType) { - return storm::performBisimulationMinimization>(model, formula, bisimulationType); -} - -// Define python bindings -void define_bisimulation(py::module& m) { - - // Bisimulation - m.def("_perform_bisimulation", &performBisimulation, "Perform bisimulation", py::arg("model"), py::arg("formula"), py::arg("bisimulation_type")); - m.def("_perform_parametric_bisimulation", &performBisimulation, "Perform bisimulation on parametric model", py::arg("model"), py::arg("formula"), py::arg("bisimulation_type")); - - // BisimulationType - py::enum_(m, "BisimulationType", "Types of bisimulation") - .value("STRONG", storm::storage::BisimulationType::Strong) - .value("WEAK", storm::storage::BisimulationType::Weak) - ; - -} diff --git a/stormpy/src/core/bisimulation.h b/stormpy/src/core/bisimulation.h deleted file mode 100644 index d444f40e9..000000000 --- a/stormpy/src/core/bisimulation.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PYTHON_CORE_BISIMULATION_H_ -#define PYTHON_CORE_BISIMULATION_H_ - -#include "common.h" - -void define_bisimulation(py::module& m); - -#endif /* PYTHON_CORE_BISIMULATION_H_ */ diff --git a/stormpy/src/core/common.h b/stormpy/src/core/common.h deleted file mode 100644 index e8466b2bd..000000000 --- a/stormpy/src/core/common.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "src/common.h" -#include "storm/utility/storm.h" -#include diff --git a/stormpy/src/core/core.cpp b/stormpy/src/core/core.cpp deleted file mode 100644 index 98d74dc80..000000000 --- a/stormpy/src/core/core.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "core.h" - -void define_core(py::module& m) { - // Init - m.def("set_up", [](std::string const& args) { - storm::utility::setUp(); - storm::settings::initializeAll("StoRM-Py", "stormpy"); - storm::settings::SettingsManager::manager().setFromString(args); - }, "Initialize Storm", py::arg("arguments")); -} - -void define_parse(py::module& m) { - // Parse formulas - m.def("parse_formulas", &storm::parseFormulasForExplicit, "Parse explicit formulas", py::arg("formula_string")); - m.def("parse_formulas_for_prism_program", &storm::parseFormulasForPrismProgram, "Parse formulas for prism program", py::arg("formula_string"), py::arg("prism_program")); - - // Pair - py::class_(m, "ModelFormulasPair", "Pair of model and formulas") - .def_property_readonly("model", [](storm::storage::ModelFormulasPair const& pair) { - return pair.model; - }, "The model") - .def_property_readonly("formulas", [](storm::storage::ModelFormulasPair const& pair) { - return pair.formulas; - }, "The formulas") - ; - - // Parse explicit models - m.def("parse_explicit_model", &storm::parser::AutoParser<>::parseModel, "Parse explicit model", py::arg("transition_file"), py::arg("labeling_file"), py::arg("state_reward_file") = "", py::arg("transition_reward_file") = "", py::arg("choice_labeling_file") = ""); -} - -// Thin wrapper for model building using one formula as argument -template -std::shared_ptr buildModel(storm::prism::Program const& program, std::shared_ptr const& formula) { - return storm::buildSymbolicModel(program, std::vector>(1,formula)); -} - -template -std::shared_ptr buildSparseModel(storm::prism::Program const& program, std::shared_ptr const& formula, bool onlyInitialStatesRelevant = false) { - return storm::buildSparseModel(program, std::vector>(1,formula), onlyInitialStatesRelevant); -} - -void define_build(py::module& m) { - // Build model - m.def("_build_model", &buildSparseModel, "Build the model", py::arg("program"), py::arg("formula"), py::arg("onlyInitialRelevant") = false); - m.def("_build_parametric_model", &buildSparseModel, "Build the parametric model", py::arg("program"), py::arg("formula"), py::arg("onlyInitialRelevant") = false); - m.def("build_model_from_prism_program", &storm::buildSparseModel, "Build the model", py::arg("program"), py::arg("formulas"), py::arg("onlyInitialRelevant") = false); - m.def("build_parametric_model_from_prism_program", &storm::buildSparseModel, "Build the parametric model", py::arg("program"), py::arg("formulas"), py::arg("onlyInitialRelevant") = false); - -} diff --git a/stormpy/src/core/core.h b/stormpy/src/core/core.h deleted file mode 100644 index ee3b3be7a..000000000 --- a/stormpy/src/core/core.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef PYTHON_CORE_CORE_H_ -#define PYTHON_CORE_CORE_H_ - -#include "common.h" - -void define_core(py::module& m); -void define_parse(py::module& m); -void define_build(py::module& m); - -#endif /* PYTHON_CORE_CORE_H_ */ diff --git a/stormpy/src/core/input.cpp b/stormpy/src/core/input.cpp deleted file mode 100644 index 8c9f915e4..000000000 --- a/stormpy/src/core/input.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "input.h" - -// Define python bindings -void define_input(py::module& m) { - - // Parse prism program - m.def("parse_prism_program", &storm::parseProgram, "Parse prism program", py::arg("path")); - - // PrismType - py::enum_(m, "PrismModelType", "Type of the prism model") - .value("DTMC", storm::prism::Program::ModelType::DTMC) - .value("CTMC", storm::prism::Program::ModelType::CTMC) - .value("MDP", storm::prism::Program::ModelType::MDP) - .value("CTMDP", storm::prism::Program::ModelType::CTMDP) - .value("MA", storm::prism::Program::ModelType::MA) - .value("UNDEFINED", storm::prism::Program::ModelType::UNDEFINED) - ; - - // PrismProgram - py::class_(m, "PrismProgram", "Prism program") - .def_property_readonly("nr_modules", &storm::prism::Program::getNumberOfModules, "Number of modules") - .def_property_readonly("model_type", &storm::prism::Program::getModelType, "Model type") - .def_property_readonly("has_undefined_constants", &storm::prism::Program::hasUndefinedConstants, "Flag if program has undefined constants") - ; - - // SymbolicModelDescription - py::class_(m, "SymbolicModelDescription", "Symbolic description of model") - .def(py::init(), "Construct from Prism program", py::arg("prism_program")) - .def_property_readonly("is_prism_program", &storm::storage::SymbolicModelDescription::isPrismProgram, "Flag if program is in Prism format") - ; - - // PrismProgram can be converted into SymbolicModelDescription - py::implicitly_convertible(); -} diff --git a/stormpy/src/core/input.h b/stormpy/src/core/input.h deleted file mode 100644 index 304dc9a9f..000000000 --- a/stormpy/src/core/input.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PYTHON_CORE_INPUT_H_ -#define PYTHON_CORE_INPUT_H_ - -#include "common.h" - -void define_input(py::module& m); - -#endif /* PYTHON_CORE_INPUT_H_ */ diff --git a/stormpy/src/core/modelchecking.cpp b/stormpy/src/core/modelchecking.cpp deleted file mode 100644 index dd00a281b..000000000 --- a/stormpy/src/core/modelchecking.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "modelchecking.h" - -// Class holding the model checking result -class PmcResult { - public: - storm::RationalFunction resultFunction; - std::unordered_set> constraintsWellFormed; - std::unordered_set> constraintsGraphPreserving; - - storm::RationalFunction getResultFunction() const { - return resultFunction; - } - - std::unordered_set> getConstraintsWellFormed() const { - return constraintsWellFormed; - } - - std::unordered_set> getConstraintsGraphPreserving() const { - return constraintsGraphPreserving; - } - - std::string toString() { - std::stringstream stream; - stream << resultFunction << std::endl; - stream << "Well formed constraints:" << std::endl; - for (auto constraint : constraintsWellFormed) { - stream << constraint << std::endl; - } - stream << "Graph preserving constraints:" << std::endl; - for (auto constraint : constraintsGraphPreserving) { - stream << constraint << std::endl; - } - return stream.str(); - } -}; - -// Thin wrapper for model checking -double modelChecking(std::shared_ptr> model, std::shared_ptr const& formula) { - std::unique_ptr checkResult = storm::verifySparseModel(model, formula); - return checkResult->asExplicitQuantitativeCheckResult()[*model->getInitialStates().begin()]; -} - -// Thin wrapper for model checking for all states -std::vector modelCheckingAll(std::shared_ptr> model, std::shared_ptr const& formula) { - std::unique_ptr checkResult = storm::verifySparseModel(model, formula); - return checkResult->asExplicitQuantitativeCheckResult().getValueVector(); -} - -// Thin wrapper for parametric model checking -std::shared_ptr parametricModelChecking(std::shared_ptr> model, std::shared_ptr const& formula) { - std::unique_ptr checkResult = storm::verifySparseModel(model, formula); - std::shared_ptr result = std::make_shared(); - result->resultFunction = checkResult->asExplicitQuantitativeCheckResult()[*model->getInitialStates().begin()]; - storm::models::sparse::Dtmc::ConstraintCollector constraintCollector(*(model->template as>())); - result->constraintsWellFormed = constraintCollector.getWellformedConstraints(); - result->constraintsGraphPreserving = constraintCollector.getGraphPreservingConstraints(); - return result; -} - -// Define python bindings -void define_modelchecking(py::module& m) { - - // Model checking - m.def("_model_checking", &modelChecking, "Perform model checking", py::arg("model"), py::arg("formula")); - m.def("model_checking_all", &modelCheckingAll, "Perform model checking for all states", py::arg("model"), py::arg("formula")); - m.def("_parametric_model_checking", ¶metricModelChecking, "Perform parametric model checking", py::arg("model"), py::arg("formula")); - - // PmcResult - py::class_>(m, "PmcResult", "Holds the results after parametric model checking") - .def("__str__", &PmcResult::toString) - .def_property_readonly("result_function", &PmcResult::getResultFunction, "Result as rational function") - .def_property_readonly("constraints_well_formed", &PmcResult::getConstraintsWellFormed, "Constraints ensuring well-formed probabilities") - .def_property_readonly("constraints_graph_preserving", &PmcResult::getConstraintsGraphPreserving, "Constraints ensuring graph preservation") - ; - -} diff --git a/stormpy/src/core/modelchecking.h b/stormpy/src/core/modelchecking.h deleted file mode 100644 index 06b1aad3c..000000000 --- a/stormpy/src/core/modelchecking.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PYTHON_CORE_MODELCHECKING_H_ -#define PYTHON_CORE_MODELCHECKING_H_ - -#include "common.h" - -void define_modelchecking(py::module& m); - -#endif /* PYTHON_CORE_MODELCHECKING_H_ */ diff --git a/stormpy/src/helpers.h b/stormpy/src/helpers.h deleted file mode 100644 index ffda72c19..000000000 --- a/stormpy/src/helpers.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * helpers.h - * - * Created on: 16 Apr 2016 - * Author: harold - */ - -#ifndef PYTHON_HELPERS_H_ -#define PYTHON_HELPERS_H_ - -#include -#include - -/** - * Helper function to get a string out of the stream operator. - * Used for __str__ functions. - */ -template -std::string streamToString(T const & t) { - std::stringstream ss; - ss << t; - return ss.str(); -} - -// Be warned: Enabling something like this will break everything about Monomial, -// as to Python the shared_ptr (Arg) IS the Monomial -// //PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr); - -#endif /* PYTHON_HELPERS_H_ */ diff --git a/stormpy/src/logic/formulae.cpp b/stormpy/src/logic/formulae.cpp deleted file mode 100644 index f6c892dfd..000000000 --- a/stormpy/src/logic/formulae.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "formulae.h" -#include "storm/logic/Formulas.h" - -void define_formulae(py::module& m) { - - py::enum_(m, "ComparisonType") - .value("LESS", storm::logic::ComparisonType::Less) - .value("LEQ", storm::logic::ComparisonType::LessEqual) - .value("GREATER", storm::logic::ComparisonType::Greater) - .value("GEQ", storm::logic::ComparisonType::GreaterEqual) - ; - - /*py::class_>, void, void>("FormulaVec", "Vector of formulas") - .def(vector_indexing_suite>, true>()) - ;*/ - - py::class_>(m, "Formula", "Generic Storm Formula") - .def("__str__", &storm::logic::Formula::toString) - ; - - // Path Formulae - py::class_>(m, "PathFormula", "Formula about the probability of a set of paths in an automaton", py::base()); - py::class_>(m, "UnaryPathFormula", "Path formula with one operand", py::base()); - py::class_>(m, "EventuallyFormula", "Formula for eventually", py::base()); - py::class_>(m, "GloballyFormula", "Formula for globally", py::base()); - py::class_>(m, "BinaryPathFormula", "Path formula with two operands", py::base()); - py::class_>(m, "BoundedUntilFormula", "Until Formula with either a step or a time bound.", py::base()); - py::class_>(m, "ConditionalFormula", "Formula with the right hand side being a condition.", py::base()); - py::class_>(m, "UntilFormula", "Path Formula for unbounded until", py::base()); - - // Reward Path Formulae - //py::class_(m, "RewardPathFormula", "Formula about the rewards of a set of paths in an automaton", py::base()); - py::class_>(m, "CumulativeRewardFormula", "Summed rewards over a the paths", py::base()); - py::class_>(m ,"InstantaneousRewardFormula", "Instantaneous reward", py::base()); - py::class_>(m, "LongRunAverageRewardFormula", "Long run average reward", py::base()); - //py::class_>(m, "ReachabilityRewardFormula", "Reachability reward", py::base()); - - - // State Formulae - py::class_>(m, "StateFormula", "Formula about a state of an automaton", py::base()); - py::class_>(m, "AtomicExpressionFormula", "Formula with an atomic expression", py::base()); - py::class_>(m, "AtomicLabelFormula", "Formula with an atomic label", py::base()); - py::class_>(m, "BooleanLiteralFormula", "Formula with a boolean literal", py::base()); - py::class_>(m, "UnaryStateFormula", "State formula with one operand", py::base()); - py::class_>(m, "UnaryBooleanStateFormula", "Unary boolean state formula", py::base()); - py::class_>(m, "OperatorFormula", "Operator formula", py::base()) - .def_property_readonly("has_bound", &storm::logic::OperatorFormula::hasBound, "Flag if formula is bounded") - .def_property("threshold", &storm::logic::OperatorFormula::getThreshold, &storm::logic::OperatorFormula::setThreshold, "Threshold of bound") - .def_property("comparison_type", &storm::logic::OperatorFormula::getComparisonType, &storm::logic::OperatorFormula::setComparisonType, "Comparison type of bound") - ; - py::class_>(m, "TimeOperator", "The time operator", py::base()); - py::class_>(m, "LongRunAvarageOperator", "Long run average operator", py::base()); - py::class_>(m, "ProbabilityOperator", "Probability operator", py::base()); - py::class_>(m, "RewardOperator", "Reward operator", py::base()); - py::class_>(m, "BinaryStateFormula", "State formula with two operands", py::base()); - py::class_>(m, "BooleanBinaryStateFormula", "Boolean binary state formula", py::base()); -} diff --git a/stormpy/src/logic/formulae.h b/stormpy/src/logic/formulae.h deleted file mode 100644 index d499685e7..000000000 --- a/stormpy/src/logic/formulae.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PYTHON_LOGIC_FORMULAE_H_ -#define PYTHON_LOGIC_FORMULAE_H_ - -#include "src/common.h" - -void define_formulae(py::module& m); - -#endif /* PYTHON_LOGIC_FORMULAE_H_ */ diff --git a/stormpy/src/mod_core.cpp b/stormpy/src/mod_core.cpp deleted file mode 100644 index b008e40d0..000000000 --- a/stormpy/src/mod_core.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "common.h" - -#include "core/core.h" -#include "core/modelchecking.h" -#include "core/bisimulation.h" -#include "core/input.h" - -PYBIND11_PLUGIN(core) { - py::module m("core"); - define_core(m); - define_parse(m); - define_build(m); - define_modelchecking(m); - define_bisimulation(m); - define_input(m); - return m.ptr(); -} diff --git a/stormpy/src/mod_expressions.cpp b/stormpy/src/mod_expressions.cpp deleted file mode 100644 index ef89106c8..000000000 --- a/stormpy/src/mod_expressions.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "common.h" -#include "helpers.h" -#include "storm/storage/expressions/ExpressionManager.h" - -PYBIND11_PLUGIN(expressions) { - py::module m("expressions", "Storm expressions"); - - py::class_>(m, "ExpressionManager", "Manages variables for expressions") - ; - - py::class_(m, "Expression", "Holds an expression") - .def("__str__", &storm::expressions::Expression::toString) - .def_property_readonly("contains_variables", &storm::expressions::Expression::containsVariables) - .def_property_readonly("has_boolean_type", &storm::expressions::Expression::hasBooleanType) - .def_property_readonly("has_integer_type", &storm::expressions::Expression::hasIntegerType) - .def_property_readonly("has_rational_type", &storm::expressions::Expression::hasRationalType) - - ; - - return m.ptr(); -} diff --git a/stormpy/src/mod_info.cpp b/stormpy/src/mod_info.cpp deleted file mode 100644 index 427b1f893..000000000 --- a/stormpy/src/mod_info.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "common.h" -#include "helpers.h" -#include "storm/utility/storm-version.h" - -PYBIND11_PLUGIN(info) { - py::module m("info", "Storm information"); - py::class_(m, "Version", "Version information for Storm") - .def_property_readonly("short", &storm::utility::StormVersion::shortVersionString, "Storm version in short representation") - .def_property_readonly("long", &storm::utility::StormVersion::longVersionString, "Storm version in long representation") - .def_property_readonly("build_info", &storm::utility::StormVersion::buildInfo, "Build info for Storm") - ; - return m.ptr(); -} diff --git a/stormpy/src/mod_logic.cpp b/stormpy/src/mod_logic.cpp deleted file mode 100644 index 98fcad102..000000000 --- a/stormpy/src/mod_logic.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "common.h" - -#include "logic/formulae.h" - -PYBIND11_PLUGIN(logic) { - py::module m("logic", "Logic module for Storm"); - define_formulae(m); - return m.ptr(); -} diff --git a/stormpy/src/mod_storage.cpp b/stormpy/src/mod_storage.cpp deleted file mode 100644 index 835f1e7b2..000000000 --- a/stormpy/src/mod_storage.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "common.h" - -#include "storage/model.h" -#include "storage/matrix.h" - -PYBIND11_PLUGIN(storage) { - py::module m("storage"); - define_model(m); - define_sparse_matrix(m); - return m.ptr(); -} diff --git a/stormpy/src/storage/common.h b/stormpy/src/storage/common.h deleted file mode 100644 index c9b9b0cb4..000000000 --- a/stormpy/src/storage/common.h +++ /dev/null @@ -1 +0,0 @@ -#include "src/common.h" diff --git a/stormpy/src/storage/matrix.cpp b/stormpy/src/storage/matrix.cpp deleted file mode 100644 index 887a86621..000000000 --- a/stormpy/src/storage/matrix.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include "matrix.h" -#include "storm/storage/SparseMatrix.h" - -typedef storm::storage::SparseMatrix::index_type entry_index; -typedef unsigned int row_index; -typedef storm::storage::SparseMatrix::index_type parametric_entry_index; -typedef unsigned int parametric_row_index; - -void define_sparse_matrix(py::module& m) { - - // MatrixEntry - py::class_>(m, "SparseMatrixEntry", "Entry of sparse matrix") - .def("__str__", [](storm::storage::MatrixEntry const& entry) { - std::stringstream stream; - stream << entry; - return stream.str(); - }) - //def_property threw "pointer being freed not allocated" after exiting - .def("value", &storm::storage::MatrixEntry::getValue, "Value") - .def("set_value", &storm::storage::MatrixEntry::setValue, py::arg("value"), "Set value") - .def_property_readonly("column", &storm::storage::MatrixEntry::getColumn, "Column") - ; - - py::class_>(m, "ParametricSparseMatrixEntry", "Entry of parametric sparse matrix") - .def("__str__", [](storm::storage::MatrixEntry const& entry) { - std::stringstream stream; - stream << entry; - return stream.str(); - }) - //def_property threw "pointer being freed not allocated" after exiting - .def("value", &storm::storage::MatrixEntry::getValue, "Value") - .def("set_value", &storm::storage::MatrixEntry::setValue, py::arg("value"), "Set value") - .def_property_readonly("column", &storm::storage::MatrixEntry::getColumn, "Column") - ; - - // SparseMatrix - py::class_>(m, "SparseMatrix", "Sparse matrix") - .def("__iter__", [](storm::storage::SparseMatrix& matrix) { - return py::make_iterator(matrix.begin(), matrix.end()); - }, py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */) - .def("__str__", [](storm::storage::SparseMatrix const& matrix) { - std::stringstream stream; - stream << matrix; - return stream.str(); - }) - .def_property_readonly("nr_rows", &storm::storage::SparseMatrix::getRowCount, "Number of rows") - .def_property_readonly("nr_columns", &storm::storage::SparseMatrix::getColumnCount, "Number of columns") - .def_property_readonly("nr_entries", &storm::storage::SparseMatrix::getEntryCount, "Number of non-zero entries") - .def_property_readonly("_row_group_indices", &storm::storage::SparseMatrix::getRowGroupIndices, "Starting rows of row groups") - .def("get_row", [](storm::storage::SparseMatrix& matrix, entry_index row) { - return matrix.getRows(row, row+1); - }, py::return_value_policy::reference, py::keep_alive<1, 0>(), py::arg("row"), "Get row") - .def("get_rows", [](storm::storage::SparseMatrix& matrix, entry_index start, entry_index end) { - return matrix.getRows(start, end); - }, py::return_value_policy::reference, py::keep_alive<1, 0>(), py::arg("row_start"), py::arg("row_end"), "Get rows from start to end") - .def("print_row", [](storm::storage::SparseMatrix const& matrix, entry_index row) { - std::stringstream stream; - auto rows = matrix.getRows(row, row+1); - for (auto transition : rows) { - stream << transition << ", "; - } - return stream.str(); - }, py::arg("row"), "Print row") - // Entry_index lead to problems - .def("row_iter", [](storm::storage::SparseMatrix& matrix, row_index start, row_index end) { - return py::make_iterator(matrix.begin(start), matrix.end(end)); - }, py::keep_alive<0, 1>() /* keep object alive while iterator exists */, py::arg("row_start"), py::arg("row_end"), "Get iterator from start to end") - ; - - py::class_>(m, "ParametricSparseMatrix", "Parametric sparse matrix") - .def("__iter__", [](storm::storage::SparseMatrix& matrix) { - return py::make_iterator(matrix.begin(), matrix.end()); - }, py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */) - .def("__str__", [](storm::storage::SparseMatrix const& matrix) { - std::stringstream stream; - stream << matrix; - return stream.str(); - }) - .def_property_readonly("nr_rows", &storm::storage::SparseMatrix::getRowCount, "Number of rows") - .def_property_readonly("nr_columns", &storm::storage::SparseMatrix::getColumnCount, "Number of columns") - .def_property_readonly("nr_entries", &storm::storage::SparseMatrix::getEntryCount, "Number of non-zero entries") - .def_property_readonly("_row_group_indices", &storm::storage::SparseMatrix::getRowGroupIndices, "Starting rows of row groups") - .def("get_row", [](storm::storage::SparseMatrix& matrix, parametric_entry_index row) { - return matrix.getRows(row, row+1); - }, py::return_value_policy::reference, py::keep_alive<1, 0>(), py::arg("row"), "Get row") - .def("get_rows", [](storm::storage::SparseMatrix& matrix, parametric_entry_index start, parametric_entry_index end) { - return matrix.getRows(start, end); - }, py::return_value_policy::reference, py::keep_alive<1, 0>(), py::arg("row_start"), py::arg("row_end"), "Get rows from start to end") - .def("print_row", [](storm::storage::SparseMatrix const& matrix, parametric_entry_index row) { - std::stringstream stream; - auto rows = matrix.getRows(row, row+1); - for (auto transition : rows) { - stream << transition << ", "; - } - return stream.str(); - }, py::arg("row"), "Print row") - // Entry_index lead to problems - .def("row_iter", [](storm::storage::SparseMatrix& matrix, parametric_row_index start, parametric_row_index end) { - return py::make_iterator(matrix.begin(start), matrix.end(end)); - }, py::keep_alive<0, 1>() /* keep object alive while iterator exists */, py::arg("row_start"), py::arg("row_end"), "Get iterator from start to end") - ; - - // Rows - py::class_::rows>(m, "SparseMatrixRows", "Set of rows in a sparse matrix") - .def("__iter__", [](storm::storage::SparseMatrix::rows& rows) { - return py::make_iterator(rows.begin(), rows.end()); - }, py::keep_alive<0, 1>()) - .def("__str__", [](storm::storage::SparseMatrix::const_rows& rows) { - std::stringstream stream; - for (auto transition : rows) { - stream << transition << ", "; - } - return stream.str(); - }) - ; - - py::class_::rows>(m, "ParametricSparseMatrixRows", "Set of rows in a parametric sparse matrix") - .def("__iter__", [](storm::storage::SparseMatrix::rows& rows) { - return py::make_iterator(rows.begin(), rows.end()); - }, py::keep_alive<0, 1>()) - .def("__str__", [](storm::storage::SparseMatrix::const_rows& rows) { - std::stringstream stream; - for (auto transition : rows) { - stream << transition << ", "; - } - return stream.str(); - }) - ; -} diff --git a/stormpy/src/storage/matrix.h b/stormpy/src/storage/matrix.h deleted file mode 100644 index 96e3df676..000000000 --- a/stormpy/src/storage/matrix.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PYTHON_STORAGE_MATRIX_H_ -#define PYTHON_STORAGE_MATRIX_H_ - -#include "common.h" - -void define_sparse_matrix(py::module& m); - -#endif /* PYTHON_STORAGE_MATRIX_H_ */ diff --git a/stormpy/src/storage/model.cpp b/stormpy/src/storage/model.cpp deleted file mode 100644 index 02f32a57a..000000000 --- a/stormpy/src/storage/model.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "model.h" -#include "storm/models/ModelBase.h" -#include "storm/models/sparse/Model.h" -#include "storm/models/sparse/Dtmc.h" -#include "storm/models/sparse/Mdp.h" -#include "storm/models/sparse/StandardRewardModel.h" - -// Thin wrapper for getting initial states -template -std::vector getInitialStates(storm::models::sparse::Model const& model) { - std::vector initialStates; - for (auto entry : model.getInitialStates()) { - initialStates.push_back(entry); - } - return initialStates; -} - -// Thin wrapper for getting transition matrix -template -storm::storage::SparseMatrix& getTransitionMatrix(storm::models::sparse::Model& model) { - return model.getTransitionMatrix(); -} - -// Define python bindings -void define_model(py::module& m) { - - // ModelType - py::enum_(m, "ModelType", "Type of the model") - .value("DTMC", storm::models::ModelType::Dtmc) - .value("MDP", storm::models::ModelType::Mdp) - .value("CTMC", storm::models::ModelType::Ctmc) - .value("MA", storm::models::ModelType::MarkovAutomaton) - ; - - // ModelBase - py::class_>(m, "ModelBase", "Base class for all models") - .def_property_readonly("nr_states", &storm::models::ModelBase::getNumberOfStates, "Number of states") - .def_property_readonly("nr_transitions", &storm::models::ModelBase::getNumberOfTransitions, "Number of transitions") - .def_property_readonly("model_type", &storm::models::ModelBase::getType, "Model type") - .def_property_readonly("supports_parameters", &storm::models::ModelBase::supportsParameters, "Flag whether model supports parameters") - .def_property_readonly("has_parameters", &storm::models::ModelBase::hasParameters, "Flag whether model has parameters") - .def_property_readonly("is_exact", &storm::models::ModelBase::isExact, "Flag whether model is exact") - .def("as_dtmc", &storm::models::ModelBase::as>, "Get model as DTMC") - .def("as_pdtmc", &storm::models::ModelBase::as>, "Get model as pDTMC") - .def("as_mdp", &storm::models::ModelBase::as>, "Get model as MDP") - .def("as_pmdp", &storm::models::ModelBase::as>, "Get model as pMDP") - ; - - // Models - py::class_, std::shared_ptr>>(m, "SparseModel", "A probabilistic model where transitions are represented by doubles and saved in a sparse matrix", py::base()) - .def_property_readonly("labels", [](storm::models::sparse::Model& model) { - return model.getStateLabeling().getLabels(); - }, "Labels") - .def("labels_state", &storm::models::sparse::Model::getLabelsOfState, py::arg("state"), "Get labels of state") - .def_property_readonly("initial_states", &getInitialStates, "Initial states") - .def_property_readonly("transition_matrix", &getTransitionMatrix, py::return_value_policy::reference, py::keep_alive<1, 0>(), "Transition matrix") - ; - py::class_, std::shared_ptr>>(m, "SparseDtmc", "DTMC in sparse representation", py::base>()) - ; - py::class_, std::shared_ptr>>(m, "SparseMdp", "MDP in sparse representation", py::base>()) - ; - - py::class_, std::shared_ptr>>(m, "SparseParametricModel", "A probabilistic model where transitions are represented by rational functions and saved in a sparse matrix", py::base()) - .def("collect_probability_parameters", &storm::models::sparse::getProbabilityParameters, "Collect parameters") - .def_property_readonly("labels", [](storm::models::sparse::Model& model) { - return model.getStateLabeling().getLabels(); - }, "Labels") - .def("labels_state", &storm::models::sparse::Model::getLabelsOfState, py::arg("state"), "Get labels of state") - .def_property_readonly("initial_states", &getInitialStates, "Initial states") - .def_property_readonly("transition_matrix", &getTransitionMatrix, py::return_value_policy::reference, py::keep_alive<1, 0>(), "Transition matrix") - ; - py::class_, std::shared_ptr>>(m, "SparseParametricDtmc", "pDTMC in sparse representation", py::base>()) - ; - py::class_, std::shared_ptr>>(m, "SparseParametricMdp", "pMDP in sparse representation", py::base>()) - ; - -} diff --git a/stormpy/src/storage/model.h b/stormpy/src/storage/model.h deleted file mode 100644 index c779f26e7..000000000 --- a/stormpy/src/storage/model.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PYTHON_STORAGE_MODEL_H_ -#define PYTHON_STORAGE_MODEL_H_ - -#include "common.h" - -void define_model(py::module& m); - -#endif /* PYTHON_STORAGE_MODEL_H_ */ diff --git a/stormpy/tests/.gitignore b/stormpy/tests/.gitignore deleted file mode 100644 index bee8a64b7..000000000 --- a/stormpy/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -__pycache__ diff --git a/stormpy/tests/conftest.py b/stormpy/tests/conftest.py deleted file mode 100644 index 5e85fe646..000000000 --- a/stormpy/tests/conftest.py +++ /dev/null @@ -1,3 +0,0 @@ -import sys -import os -sys.path.append(os.path.join(os.path.dirname(__file__), 'helpers')) diff --git a/stormpy/tests/core/test_bisimulation.py b/stormpy/tests/core/test_bisimulation.py deleted file mode 100644 index 3776f54d2..000000000 --- a/stormpy/tests/core/test_bisimulation.py +++ /dev/null @@ -1,39 +0,0 @@ -import stormpy -import stormpy.logic -from helpers.helper import get_example_path - -class TestBisimulation: - def test_bisimulation(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "crowds5_5.pm")) - assert program.nr_modules == 1 - assert program.model_type == stormpy.PrismModelType.DTMC - prop = "P=? [F \"observe0Greater1\"]" - formulas = stormpy.parse_formulas_for_prism_program(prop, program) - model = stormpy.build_model_from_prism_program(program, formulas) - assert model.nr_states == 7403 - assert model.nr_transitions == 13041 - assert model.model_type == stormpy.ModelType.DTMC - assert not model.supports_parameters - model_bisim = stormpy.perform_bisimulation(model, formulas[0], stormpy.BisimulationType.STRONG) - assert model_bisim.nr_states == 64 - assert model_bisim.nr_transitions == 104 - assert model_bisim.model_type == stormpy.ModelType.DTMC - assert not model_bisim.supports_parameters - - def test_parametric_bisimulation(self): - program = stormpy.parse_prism_program(get_example_path("pdtmc", "crowds3_5.pm")) - assert program.nr_modules == 1 - assert program.model_type == stormpy.PrismModelType.DTMC - assert program.has_undefined_constants - prop = "P=? [F \"observe0Greater1\"]" - formulas = stormpy.parse_formulas_for_prism_program(prop, program) - model = stormpy.build_parametric_model_from_prism_program(program, formulas) - assert model.nr_states == 1367 - assert model.nr_transitions == 2027 - assert model.model_type == stormpy.ModelType.DTMC - assert model.has_parameters - model_bisim = stormpy.perform_bisimulation(model, formulas[0], stormpy.BisimulationType.STRONG) - assert model_bisim.nr_states == 80 - assert model_bisim.nr_transitions == 120 - assert model_bisim.model_type == stormpy.ModelType.DTMC - assert model_bisim.has_parameters diff --git a/stormpy/tests/core/test_core.py b/stormpy/tests/core/test_core.py deleted file mode 100644 index cedd750eb..000000000 --- a/stormpy/tests/core/test_core.py +++ /dev/null @@ -1,14 +0,0 @@ - -class TestCore: - def test_init(self): - import stormpy - - def test_pycarl(self): - import stormpy - import pycarl - import pycarl.formula - import pycarl.parse - pol1 = pycarl.FactorizedPolynomial(32) - pol2 = pycarl.FactorizedPolynomial(2) - rat = pycarl.FactorizedRationalFunction(pol1, pol2) - assert str(rat) == "16" diff --git a/stormpy/tests/core/test_modelchecking.py b/stormpy/tests/core/test_modelchecking.py deleted file mode 100644 index 56ccdc93e..000000000 --- a/stormpy/tests/core/test_modelchecking.py +++ /dev/null @@ -1,45 +0,0 @@ -import stormpy -import stormpy.logic -from helpers.helper import get_example_path - -class TestModelChecking: - def test_model_checking_dtmc(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F \"one\" ]", program) - model = stormpy.build_model(program, formulas[0]) - assert model.nr_states == 13 - assert model.nr_transitions == 20 - result = stormpy.model_checking(model, formulas[0]) - assert result == 0.16666666666666663 - - def test_model_checking_all_dtmc(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F \"one\" ]", program) - model = stormpy.build_model(program, formulas[0]) - assert model.nr_states == 13 - assert model.nr_transitions == 20 - results = stormpy.model_checking_all(model, formulas[0]) - results_orig = [0.16666666666666663, 0.3333333333333333, 0, 0.6666666666666666, 0, 0, 0, 1, 0, 0, 0, 0, 0] - assert results == results_orig - - def test_parametric_state_elimination(self): - import pycarl - import pycarl.formula - program = stormpy.parse_prism_program(get_example_path("pdtmc", "brp16_2.pm")) - prop = "P=? [F s=5]" - formulas = stormpy.parse_formulas_for_prism_program(prop, program) - model = stormpy.build_parametric_model_from_prism_program(program, formulas) - assert model.nr_states == 613 - assert model.nr_transitions == 803 - assert model.model_type == stormpy.ModelType.DTMC - assert model.has_parameters - result = stormpy.model_checking(model, formulas[0]) - func = result.result_function - one = pycarl.FactorizedPolynomial(pycarl.Rational(1)) - assert func.denominator == one - constraints_well_formed = result.constraints_well_formed - for constraint in constraints_well_formed: - assert constraint.rel() == pycarl.formula.Relation.GEQ or constraint.rel() == pycarl.formula.Relation.LEQ - constraints_graph_preserving = result.constraints_graph_preserving - for constraint in constraints_graph_preserving: - assert constraint.rel() == pycarl.formula.Relation.GREATER diff --git a/stormpy/tests/core/test_parse.py b/stormpy/tests/core/test_parse.py deleted file mode 100644 index 83aff42e1..000000000 --- a/stormpy/tests/core/test_parse.py +++ /dev/null @@ -1,32 +0,0 @@ -import stormpy -import stormpy.logic -from helpers.helper import get_example_path - -class TestParse: - def test_parse_prism_program(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) - assert program.nr_modules == 1 - assert program.model_type == stormpy.PrismModelType.DTMC - assert not program.has_undefined_constants - - def test_parse_formula(self): - prop = "P=? [F \"one\"]" - formulas = stormpy.parse_formulas(prop) - assert len(formulas) == 1 - assert str(formulas[0]) == prop - - def test_parse_explicit_dtmc(self): - model = stormpy.parse_explicit_model(get_example_path("dtmc", "die.tra"), get_example_path("dtmc", "die.lab")) - assert model.nr_states == 13 - assert model.nr_transitions == 20 - assert model.model_type == stormpy.ModelType.DTMC - assert not model.supports_parameters - assert type(model) is stormpy.SparseDtmc - - def test_parse_explicit_mdp(self): - model = stormpy.parse_explicit_model(get_example_path("mdp", "two_dice.tra"), get_example_path("mdp", "two_dice.lab")) - assert model.nr_states == 169 - assert model.nr_transitions == 436 - assert model.model_type == stormpy.ModelType.MDP - assert not model.supports_parameters - assert type(model) is stormpy.SparseMdp diff --git a/stormpy/tests/expressions/test_expressions.py b/stormpy/tests/expressions/test_expressions.py deleted file mode 100644 index 823186d62..000000000 --- a/stormpy/tests/expressions/test_expressions.py +++ /dev/null @@ -1,9 +0,0 @@ -import stormpy -from stormpy.expressions import expressions - -class TestExpressions: - def test_expression_manager(self): - manager = expressions.ExpressionManager - - def test_expression(self): - expression = expressions.Expression diff --git a/stormpy/tests/helpers/helper.py b/stormpy/tests/helpers/helper.py deleted file mode 100644 index a7c2d295c..000000000 --- a/stormpy/tests/helpers/helper.py +++ /dev/null @@ -1,5 +0,0 @@ -import os -example_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, "resources", "examples", "testfiles")) - -def get_example_path(*paths): - return os.path.join(example_dir, *paths) diff --git a/stormpy/tests/info/test_info.py b/stormpy/tests/info/test_info.py deleted file mode 100644 index fd91d68d7..000000000 --- a/stormpy/tests/info/test_info.py +++ /dev/null @@ -1,8 +0,0 @@ -import stormpy -from stormpy.info import info - -class TestInfo: - def test_version(self): - s = info.Version.short - s = info.Version.long - s = info.Version.build_info diff --git a/stormpy/tests/logic/test_formulas.py b/stormpy/tests/logic/test_formulas.py deleted file mode 100644 index 1bb697ce3..000000000 --- a/stormpy/tests/logic/test_formulas.py +++ /dev/null @@ -1,51 +0,0 @@ -import pycarl -import stormpy -import stormpy.logic - -class TestFormulas: - - def test_probability_formula(self): - prop = "P=? [F \"one\"]" - formulas = stormpy.parse_formulas(prop) - formula = formulas[0] - assert type(formula) == stormpy.logic.ProbabilityOperator - assert len(formulas) == 1 - assert str(formula) == prop - - def test_reward_formula(self): - prop = "R=? [F \"one\"]" - formulas = stormpy.parse_formulas(prop) - formula = formulas[0] - assert type(formula) == stormpy.logic.RewardOperator - assert len(formulas) == 1 - assert str(formula) == "R[exp]=? [F \"one\"]" - - def test_formula_list(self): - formulas = [] - prop = "=? [F \"one\"]" - forms = stormpy.parse_formulas("P" + prop) - formulas.append(forms[0]) - forms = stormpy.parse_formulas("R" + prop) - formulas.append(forms[0]) - assert len(formulas) == 2 - assert str(formulas[0]) == "P" + prop - assert str(formulas[1]) == "R[exp]" + prop - - def test_bounds(self): - prop = "P=? [F \"one\"]" - formula = stormpy.parse_formulas(prop)[0] - assert not formula.has_bound - prop = "P<0.4 [F \"one\"]" - formula = stormpy.parse_formulas(prop)[0] - assert formula.has_bound - assert formula.threshold == pycarl.Rational("0.4") - assert formula.comparison_type == stormpy.logic.ComparisonType.LESS - - def test_set_bounds(self): - prop = "P<0.4 [F \"one\"]" - formula = stormpy.parse_formulas(prop)[0] - formula.threshold = pycarl.Rational("0.2") - formula.comparison_type = stormpy.logic.ComparisonType.GEQ - assert formula.threshold == pycarl.Rational("0.2") - assert formula.comparison_type == stormpy.logic.ComparisonType.GEQ - assert str(formula) == "P>=1/5 [F \"one\"]" diff --git a/stormpy/tests/storage/test_matrix.py b/stormpy/tests/storage/test_matrix.py deleted file mode 100644 index e6e2e6360..000000000 --- a/stormpy/tests/storage/test_matrix.py +++ /dev/null @@ -1,96 +0,0 @@ -import stormpy -from helpers.helper import get_example_path - -class TestMatrix: - def test_sparse_matrix(self): - model = stormpy.parse_explicit_model(get_example_path("dtmc", "die.tra"), get_example_path("dtmc", "die.lab")) - matrix = model.transition_matrix - assert type(matrix) is stormpy.storage.SparseMatrix - assert matrix.nr_rows == model.nr_states - assert matrix.nr_columns == model.nr_states - assert matrix.nr_entries == 27 #model.nr_transitions - for e in matrix: - assert e.value() == 0.5 or e.value() == 0 or (e.value() == 1 and e.column > 6) - - def test_change_sparse_matrix(self): - model = stormpy.parse_explicit_model(get_example_path("dtmc", "die.tra"), get_example_path("dtmc", "die.lab")) - matrix = model.transition_matrix - for e in matrix: - assert e.value() == 0.5 or e.value() == 0 or e.value() == 1 - i = 0 - for e in matrix: - e.set_value(i) - i += 0.1 - i = 0 - for e in matrix: - assert e.value() == i - i += 0.1 - - def test_change_sparse_matrix_modelchecking(self): - import stormpy.logic - model = stormpy.parse_explicit_model(get_example_path("dtmc", "die.tra"), get_example_path("dtmc", "die.lab")) - matrix = model.transition_matrix - # Check matrix - for e in matrix: - assert e.value() == 0.5 or e.value() == 0 or e.value() == 1 - # First model checking - formulas = stormpy.parse_formulas("P=? [ F \"one\" ]") - result = stormpy.model_checking(model, formulas[0]) - assert result == 0.16666666666666663 - - # Change probabilities - i = 0 - for e in matrix: - if e.value() == 0.5: - if i % 2 == 0: - e.set_value(0.3) - else: - e.set_value(0.7) - i += 1 - for e in matrix: - assert e.value() == 0.3 or e.value() == 0.7 or e.value() == 1 or e.value() == 0 - # Second model checking - result = stormpy.model_checking(model, formulas[0]) - assert result == 0.06923076923076932 - - # Change probabilities again - for state in stormpy.state.State(0, model): - for action in state.actions(): - for transition in action.transitions(): - if transition.value() == 0.3: - transition.set_value(0.8) - elif transition.value() == 0.7: - transition.set_value(0.2) - # Third model checking - result = stormpy.model_checking(model, formulas[0]) - assert result == 0.3555555555555556 or result == 0.3555555555555557 - - def test_change_parametric_sparse_matrix_modelchecking(self): - import stormpy.logic - import pycarl - program = stormpy.parse_prism_program(get_example_path("pdtmc", "brp16_2.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F s=5 ]", program) - model = stormpy.build_parametric_model(program, formulas[0]) - matrix = model.transition_matrix - # Check matrix - one_pol = pycarl.Rational(1) - one_pol = pycarl.FactorizedPolynomial(one_pol) - one = pycarl.FactorizedRationalFunction(one_pol, one_pol) - for e in matrix: - assert e.value() == one or len(e.value().gather_variables()) > 0 - # First model checking - result = stormpy.model_checking(model, formulas[0]) - assert len(result.result_function.gather_variables()) > 0 - - # Change probabilities - two_pol = pycarl.Rational(2) - two_pol = pycarl.FactorizedPolynomial(two_pol) - new_val = pycarl.FactorizedRationalFunction(one_pol, two_pol) - for e in matrix: - if len(e.value().gather_variables()) > 0: - e.set_value(new_val) - for e in matrix: - assert e.value() == new_val or e.value() == one - # Second model checking - result = stormpy.model_checking(model, formulas[0]) - assert len(result.result_function.gather_variables()) == 0 diff --git a/stormpy/tests/storage/test_model.py b/stormpy/tests/storage/test_model.py deleted file mode 100644 index 44a4c9c0e..000000000 --- a/stormpy/tests/storage/test_model.py +++ /dev/null @@ -1,96 +0,0 @@ -import stormpy -import stormpy.logic -from helpers.helper import get_example_path - -class TestModel: - def test_build_dtmc_from_prism_program(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) - prop = "P=? [F \"one\"]" - formulas = stormpy.parse_formulas_for_prism_program(prop, program) - model = stormpy.build_model_from_prism_program(program, formulas) - assert model.nr_states == 13 - assert model.nr_transitions == 20 - assert model.model_type == stormpy.ModelType.DTMC - assert not model.supports_parameters - assert type(model) is stormpy.SparseDtmc - - def test_build_parametric_dtmc_from_prism_program(self): - program = stormpy.parse_prism_program(get_example_path("pdtmc", "brp16_2.pm")) - assert program.nr_modules == 5 - assert program.model_type == stormpy.PrismModelType.DTMC - assert program.has_undefined_constants - prop = "P=? [F s=5]" - formulas = stormpy.parse_formulas_for_prism_program(prop, program) - model = stormpy.build_parametric_model_from_prism_program(program, formulas) - assert model.nr_states == 613 - assert model.nr_transitions == 803 - assert model.model_type == stormpy.ModelType.DTMC - assert model.supports_parameters - assert model.has_parameters - assert type(model) is stormpy.SparseParametricDtmc - - def test_build_dtmc(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F \"one\" ]", program) - model = stormpy.build_model(program, formulas[0]) - assert model.nr_states == 13 - assert model.nr_transitions == 20 - assert model.model_type == stormpy.ModelType.DTMC - assert not model.supports_parameters - assert type(model) is stormpy.SparseDtmc - - def test_build_parametric_dtmc(self): - program = stormpy.parse_prism_program(get_example_path("pdtmc", "brp16_2.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F s=5 ]", program) - model = stormpy.build_parametric_model(program, formulas[0]) - assert model.nr_states == 613 - assert model.nr_transitions == 803 - assert model.model_type == stormpy.ModelType.DTMC - assert model.supports_parameters - assert model.has_parameters - assert type(model) is stormpy.SparseParametricDtmc - - def test_build_dtmc_supporting_parameters(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F \"one\" ]", program) - model = stormpy.build_parametric_model(program, formulas[0]) - assert model.nr_states == 13 - assert model.nr_transitions == 20 - assert model.model_type == stormpy.ModelType.DTMC - assert model.supports_parameters - assert not model.has_parameters - assert type(model) is stormpy.SparseParametricDtmc - - def test_label(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F \"one\" ]", program) - model = stormpy.build_model(program, formulas[0]) - labels = model.labels - assert len(labels) == 3 - assert "init" in labels - assert "one" in labels - assert "init" in model.labels_state(0) - assert "one" in model.labels_state(7) - - def test_initial_states(self): - program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F \"one\" ]", program) - model = stormpy.build_model(program, formulas[0]) - initial_states = model.initial_states - assert len(initial_states) == 1 - assert 0 in initial_states - - def test_label_parametric(self): - program = stormpy.parse_prism_program(get_example_path("pdtmc", "brp16_2.pm")) - formulas = stormpy.parse_formulas_for_prism_program("P=? [ F s=5 ]", program) - model = stormpy.build_parametric_model(program, formulas[0]) - labels = model.labels - assert len(labels) == 3 - assert "init" in labels - assert "(s = 5)" in labels - assert "init" in model.labels_state(0) - assert "(s = 5)" in model.labels_state(28) - assert "(s = 5)" in model.labels_state(611) - initial_states = model.initial_states - assert len(initial_states) == 1 - assert 0 in initial_states diff --git a/stormpy/tests/storage/test_model_iterators.py b/stormpy/tests/storage/test_model_iterators.py deleted file mode 100644 index 8023b86d0..000000000 --- a/stormpy/tests/storage/test_model_iterators.py +++ /dev/null @@ -1,82 +0,0 @@ -import stormpy -from helpers.helper import get_example_path - -class TestModelIterators: - def test_states_dtmc(self): - model = stormpy.parse_explicit_model(get_example_path("dtmc", "die.tra"), get_example_path("dtmc", "die.lab")) - s = stormpy.state.State(0, model) - i = 0 - for state in stormpy.state.State(0, model): - assert state.id == i - i += 1 - assert i == model.nr_states - - def test_states_mdp(self): - model = stormpy.parse_explicit_model(get_example_path("mdp", "two_dice.tra"), get_example_path("mdp", "two_dice.lab")) - s = stormpy.state.State(0, model) - i = 0 - for state in stormpy.state.State(0, model): - assert state.id == i - i += 1 - assert i == model.nr_states - - def test_actions_dtmc(self): - model = stormpy.parse_explicit_model(get_example_path("dtmc", "die.tra"), get_example_path("dtmc", "die.lab")) - s = stormpy.state.State(0, model) - for state in stormpy.state.State(0, model): - for action in state.actions(): - assert action.row == 0 - - def test_actions_mdp(self): - model = stormpy.parse_explicit_model(get_example_path("mdp", "two_dice.tra"), get_example_path("mdp", "two_dice.lab")) - s = stormpy.state.State(0, model) - for state in stormpy.state.State(0, model): - for action in state.actions(): - assert action.row == 0 or action.row == 1 - - def test_transitions_dtmc(self): - transitions_orig = [(0, 0, 0), (0, 1, 0.5), (0, 2, 0.5), (1, 1, 0), (1, 3, 0.5), (1, 4, 0.5), - (2, 2, 0), (2, 5, 0.5), (2, 6, 0.5), (3, 1, 0.5), (3, 3, 0), (3, 7, 0.5), - (4, 4, 0), (4, 8, 0.5), (4, 9, 0.5), (5, 5, 0), (5, 10, 0.5), (5, 11, 0.5), - (6, 2, 0.5), (6, 6, 0), (6, 12, 0.5), (7, 7, 1), (8, 8, 1), - (9, 9, 1), (10, 10, 1), (11, 11, 1), (12, 12, 1) - ] - model = stormpy.parse_explicit_model(get_example_path("dtmc", "die.tra"), get_example_path("dtmc", "die.lab")) - s = stormpy.state.State(0, model) - i = 0 - for state in stormpy.state.State(0, model): - for action in state.actions(): - for transition in action.transitions(): - transition_orig = transitions_orig[i] - i += 1 - assert state.id == transition_orig[0] - assert transition.column == transition_orig[1] - assert transition.value() == transition_orig[2] - - def test_transitions_mdp(self): - model = stormpy.parse_explicit_model(get_example_path("mdp", "two_dice.tra"), get_example_path("mdp", "two_dice.lab")) - s = stormpy.state.State(0, model) - for state in stormpy.state.State(0, model): - i = 0 - for action in state.actions(): - i += 1 - for transition in action.transitions(): - assert transition.value() == 0.5 or transition.value() == 1 - assert i == 1 or i == 2 - - def test_row_iterator(self): - transitions_orig = [(0, 0, 0), (0, 1, 0.5), (0, 2, 0.5), (1, 1, 0), (1, 3, 0.5), (1, 4, 0.5), - (2, 2, 0), (2, 5, 0.5), (2, 6, 0.5), (3, 1, 0.5), (3, 3, 0), (3, 7, 0.5), - (4, 4, 0), (4, 8, 0.5), (4, 9, 0.5), (5, 5, 0), (5, 10, 0.5), (5, 11, 0.5), - (6, 2, 0.5), (6, 6, 0), (6, 12, 0.5), (7, 7, 1), (8, 8, 1), - (9, 9, 1), (10, 10, 1), (11, 11, 1), (12, 12, 1) - ] - model = stormpy.parse_explicit_model(get_example_path("dtmc", "die.tra"), get_example_path("dtmc", "die.lab")) - i = 0 - for state in stormpy.state.State(0, model): - for transition in model.transition_matrix.row_iter(state.id, state.id): - transition_orig = transitions_orig[i] - i += 1 - assert state.id == transition_orig[0] - assert transition.column == transition_orig[1] - assert transition.value() == transition_orig[2]