Browse Source

Merge remote-tracking branch 'origin' into menu_games

main
dehnert 9 years ago
parent
commit
4acb4fefdc
  1. 1
      .gitignore
  2. 30
      CMakeLists.txt
  3. 6
      doc/build.md
  4. 151
      resources/3rdparty/CMakeLists.txt
  5. 25
      resources/3rdparty/carl/CMakeLists.txt
  6. 4
      resources/3rdparty/include_cpptemplate.cmake
  7. 14
      resources/3rdparty/include_cudd.cmake
  8. 9
      resources/3rdparty/include_glpk.cmake
  9. 0
      resources/3rdparty/include_xerces.cmake.save
  10. 49
      resources/3rdparty/include_xerces.cmake.save.1
  11. 43
      resources/cmake/find_modules/FindCLN.cmake
  12. 54
      resources/cmake/find_modules/FindGiNaC.cmake
  13. 28
      resources/cmake/macros/export.cmake
  14. 59
      resources/cmake/macros/imported.cmake
  15. 21
      resources/cmake/stormConfig.cmake.in
  16. 2
      src/CMakeLists.txt
  17. 92
      src/storm-dft-cli/storm-dyftee.cpp
  18. 2
      src/storm-dft/CMakeLists.txt
  19. 1
      src/storm-dft/modelchecker/dft/DFTModelChecker.cpp
  20. 18
      src/storm-dft/parser/DFTGalileoParser.cpp
  21. 5
      src/storm-dft/parser/DFTGalileoParser.h
  22. 167
      src/storm-dft/parser/DFTJsonParser.cpp
  23. 48
      src/storm-dft/parser/DFTJsonParser.h
  24. 14
      src/storm-dft/settings/modules/DFTSettings.cpp
  25. 16
      src/storm-dft/settings/modules/DFTSettings.h
  26. 11
      src/storm-dft/storage/dft/DFT.cpp
  27. 19
      src/storm-dft/storage/dft/DFT.h
  28. 78
      src/storm-dft/storage/dft/DFTBuilder.cpp
  29. 63
      src/storm-dft/storage/dft/DFTBuilder.h
  30. 23
      src/storm-dft/storage/dft/DFTIsomorphism.h
  31. 15
      src/storm-dft/storage/dft/DFTLayoutInfo.h
  32. 14
      src/storm-dft/storage/dft/DFTState.cpp
  33. 3
      src/storm-dft/storage/dft/elements/DFTBE.h
  34. 46
      src/storm-dft/storage/dft/elements/DFTDependency.h
  35. 4
      src/storm-dft/storage/dft/elements/DFTElement.cpp
  36. 15
      src/storm-dft/storage/dft/elements/DFTPand.h
  37. 17
      src/storm-dft/storage/dft/elements/DFTPor.h
  38. 9
      src/storm-dft/storage/dft/elements/DFTRestriction.h
  39. 629
      src/storm-dft/transformations/DftToGspnTransformator.cpp
  40. 163
      src/storm-dft/transformations/DftToGspnTransformator.h
  41. 12
      src/storm-gspn-cli/storm-gspn.cpp
  42. 102
      src/storm-gspn/builder/JaniGSPNBuilder.h
  43. 66
      src/storm-gspn/storage/gspn/GSPN.cpp
  44. 37
      src/storm-gspn/storage/gspn/GSPN.h
  45. 49
      src/storm-gspn/storage/gspn/GspnBuilder.cpp
  46. 16
      src/storm-gspn/storage/gspn/GspnBuilder.h
  47. 17
      src/storm-gspn/storage/gspn/PlacementInfo.h
  48. 3
      src/storm-gspn/storage/gspn/Transition.h
  49. 18
      src/storm-gspn/storage/gspn/TransitionPartition.h
  50. 61
      src/storm-gspn/storm-gspn.h
  51. 5
      src/storm-pgcl-cli/storm-pgcl.cpp
  52. 18
      src/storm-pgcl/builder/JaniProgramGraphBuilder.h
  53. 7
      src/storm/CMakeLists.txt
  54. 11
      src/storm/cli/cli.cpp
  55. 2
      src/storm/generator/NextStateGenerator.cpp
  56. 2
      src/storm/logic/Formula.h
  57. 16
      src/storm/settings/modules/GSPNExportSettings.cpp
  58. 11
      src/storm/settings/modules/GSPNExportSettings.h
  59. 2
      src/storm/storage/BitVector.cpp
  60. 6
      src/storm/storage/expressions/Expression.cpp
  61. 15
      src/storm/storage/jani/JSONExporter.cpp
  62. 8
      src/storm/storage/jani/JSONExporter.h
  63. 9
      src/storm/storage/jani/OrderedAssignments.cpp
  64. 2
      src/storm/storage/jani/OrderedAssignments.h
  65. 11
      src/storm/utility/storm.cpp
  66. 10
      src/storm/utility/storm.h
  67. 2
      src/test/CMakeLists.txt
  68. 39
      stormpy/CMakeLists.txt
  69. 1
      stormpy/MANIFEST.in
  70. 3
      stormpy/lib/.gitignore
  71. 70
      stormpy/lib/stormpy/__init__.py
  72. 2
      stormpy/lib/stormpy/expressions/__init__.py
  73. 2
      stormpy/lib/stormpy/info/__init__.py
  74. 2
      stormpy/lib/stormpy/logic/__init__.py
  75. 3
      stormpy/lib/stormpy/storage/__init__.py
  76. 36
      stormpy/lib/stormpy/storage/action.py
  77. 34
      stormpy/lib/stormpy/storage/state.py
  78. 24
      stormpy/resources/pybind11/.appveyor.yml
  79. 33
      stormpy/resources/pybind11/.gitignore
  80. 3
      stormpy/resources/pybind11/.gitmodules
  81. 44
      stormpy/resources/pybind11/.travis.yml
  82. 170
      stormpy/resources/pybind11/CMakeLists.txt
  83. 37
      stormpy/resources/pybind11/CONTRIBUTING.md
  84. 36
      stormpy/resources/pybind11/LICENSE
  85. 1
      stormpy/resources/pybind11/MANIFEST.in
  86. 114
      stormpy/resources/pybind11/README.md
  87. 11
      stormpy/resources/pybind11/docs/_static/theme_overrides.css
  88. 1613
      stormpy/resources/pybind11/docs/advanced.rst
  89. 309
      stormpy/resources/pybind11/docs/basics.rst
  90. 90
      stormpy/resources/pybind11/docs/benchmark.py
  91. 96
      stormpy/resources/pybind11/docs/benchmark.rst
  92. 172
      stormpy/resources/pybind11/docs/changelog.rst
  93. 334
      stormpy/resources/pybind11/docs/classes.rst
  94. 53
      stormpy/resources/pybind11/docs/compiling.rst
  95. 308
      stormpy/resources/pybind11/docs/conf.py
  96. 208
      stormpy/resources/pybind11/docs/faq.rst
  97. 24
      stormpy/resources/pybind11/docs/index.rst
  98. 87
      stormpy/resources/pybind11/docs/intro.rst
  99. 23
      stormpy/resources/pybind11/docs/limitations.rst
  100. BIN
      stormpy/resources/pybind11/docs/pybind11-logo.png

1
.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

30
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)

6
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

151
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()

25
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")

4
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)

14
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}.")

9
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)

0
resources/3rdparty/include_xerces.cmake.save

49
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)

43
resources/cmake/find_modules/FindCLN.cmake

@ -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)

54
resources/cmake/find_modules/FindGiNaC.cmake

@ -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)

28
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
)

59
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)

21
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)

2
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)

92
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 <boost/lexical_cast.hpp>
#include <memory>
/*!
* 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 <typename ValueType>
void transformDFT(std::string filename) {
std::cout << "Transforming DFT from file " << filename << std::endl;
storm::parser::DFTGalileoParser<ValueType> parser;
storm::storage::DFT<ValueType> dft = parser.parseDFT(filename);
// TODO: activate again
//storm::transformations::dft::DftToGspnTransformator<ValueType> gspnTransformator(dft);
//gspnTransformator.transform();
}
/*!
* Initialize the settings manager.
@ -110,6 +98,11 @@ void initializeSettings() {
//storm::settings::addModule<storm::settings::modules::TopologicalValueIterationEquationSolverSettings>();
//storm::settings::addModule<storm::settings::modules::ParametricSettings>();
storm::settings::addModule<storm::settings::modules::EliminationSettings>();
// For translation into JANI via GSPN.
storm::settings::addModule<storm::settings::modules::GSPNSettings>();
storm::settings::addModule<storm::settings::modules::GSPNExportSettings>();
storm::settings::addModule<storm::settings::modules::JaniExportSettings>();
}
/*!
@ -132,13 +125,48 @@ int main(const int argc, const char** argv) {
storm::settings::modules::DFTSettings const& dftSettings = storm::settings::getModule<storm::settings::modules::DFTSettings>();
storm::settings::modules::GeneralSettings const& generalSettings = storm::settings::getModule<storm::settings::modules::GeneralSettings>();
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<double>(dftSettings.getDftFilename());
std::shared_ptr<storm::storage::DFT<double>> dft;
if (dftSettings.isDftJsonFileSet()) {
storm::parser::DFTJsonParser<double> parser;
dft = std::make_shared<storm::storage::DFT<double>>(parser.parseJson(dftSettings.getDftJsonFilename()));
} else {
storm::parser::DFTGalileoParser<double> parser(true, false);
dft = std::make_shared<storm::storage::DFT<double>>(parser.parseDFT(dftSettings.getDftFilename()));
}
storm::transformations::dft::DftToGspnTransformator<double> gspnTransformator(*dft);
gspnTransformator.transform();
storm::gspn::GSPN* gspn = gspnTransformator.obtainGSPN();
uint64_t toplevelFailedPlace = gspnTransformator.toplevelFailedPlaceId();
storm::handleGSPNExportSettings(*gspn);
std::shared_ptr<storm::expressions::ExpressionManager> 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<storm::logic::AtomicExpressionFormula>(targetExpression);
auto tbFormula = std::make_shared<storm::logic::BoundedUntilFormula>(std::make_shared<storm::logic::BooleanLiteralFormula>(true), evtlFormula, 0.0, 10.0);
auto tbUntil = std::make_shared<storm::logic::ProbabilityOperatorFormula>(tbFormula);
auto evFormula = std::make_shared<storm::logic::EventuallyFormula>(evtlFormula, storm::logic::FormulaContext::Time);
auto rewFormula = std::make_shared<storm::logic::TimeOperatorFormula>(evFormula, storm::logic::OperatorInformation(), storm::logic::RewardMeasureType::Expectation);
storm::settings::modules::JaniExportSettings const& janiSettings = storm::settings::getModule<storm::settings::modules::JaniExportSettings>();
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;
}

2
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})

1
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 {

18
src/storm-dft/parser/DFTGalileoParser.cpp

@ -4,6 +4,7 @@
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/replace.hpp>
#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<typename ValueType>
std::string DFTGalileoParser<ValueType>::parseNodeIdentifier(std::string const& name) {
return boost::replace_all_copy(name, "'", "__prime__");
}
template<typename ValueType>
void DFTGalileoParser<ValueType>::readFile(const std::string& filename) {
@ -84,11 +90,11 @@ namespace storm {
} else {
std::vector<std::string> tokens;
boost::split(tokens, line, boost::is_any_of(" "));
std::string name(stripQuotsFromName(tokens[0]));
std::string name(parseNodeIdentifier(stripQuotsFromName(tokens[0])));
std::vector<std::string> 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") {

5
src/storm-dft/parser/DFTGalileoParser.h

@ -26,7 +26,7 @@ namespace storm {
std::unordered_map<std::string, storm::expressions::Expression> 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<ValueType> 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;
};
}
}

167
src/storm-dft/parser/DFTJsonParser.cpp

@ -0,0 +1,167 @@
#include "DFTJsonParser.h"
#include <iostream>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/replace.hpp>
#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<typename ValueType>
storm::storage::DFT<ValueType> DFTJsonParser<ValueType>::parseJson(const std::string& filename) {
readFile(filename);
storm::storage::DFT<ValueType> dft = builder.build();
STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString());
STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString());
return dft;
}
template<typename ValueType>
std::string DFTJsonParser<ValueType>::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<typename ValueType>
std::string DFTJsonParser<ValueType>::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<typename ValueType>
std::string DFTJsonParser<ValueType>::parseNodeIdentifier(std::string const& name) {
return boost::replace_all_copy(name, "'", "__prime__");
}
template<typename ValueType>
void DFTJsonParser<ValueType>::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<std::string, std::string> 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<std::string> 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<ValueType>());
} 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<typename ValueType>
ValueType DFTJsonParser<ValueType>::parseRationalExpression(std::string const& expr) {
STORM_LOG_ASSERT(false, "Specialized method should be called.");
return 0;
}
template<>
double DFTJsonParser<double>::parseRationalExpression(std::string const& expr) {
return boost::lexical_cast<double>(expr);
}
// Explicitly instantiate the class.
template class DFTJsonParser<double>;
#ifdef STORM_HAVE_CARL
template<>
storm::RationalFunction DFTJsonParser<storm::RationalFunction>::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<RationalFunction>;
#endif
}
}

48
src/storm-dft/parser/DFTJsonParser.h

@ -0,0 +1,48 @@
#pragma once
#include <map>
#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<typename ValueType>
class DFTJsonParser {
storm::storage::DFTBuilder<ValueType> builder;
std::shared_ptr<storm::expressions::ExpressionManager> manager;
storm::parser::ExpressionParser parser;
storm::expressions::ExpressionEvaluator<ValueType> evaluator;
std::unordered_map<std::string, storm::expressions::Expression> identifierMapping;
public:
DFTJsonParser() : manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) {
}
storm::storage::DFT<ValueType> 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);
};
}
}

14
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();
}

16
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;

11
src/storm-dft/storage/dft/DFT.cpp

@ -174,7 +174,8 @@ namespace storm {
std::shared_ptr<DFTDependency<ValueType> 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<typename ValueType>
uint64_t DFT<ValueType>::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<typename ValueType>

19
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<size_t> mTopModule;
std::map<size_t, size_t> mRepresentants; // id element -> id representative
std::vector<std::vector<size_t>> mSymmetries;
std::map<size_t, DFTLayoutInfo> mLayoutInfo;
public:
DFT(DFTElementVector const& elements, DFTElementPointer const& tle);
@ -263,7 +264,19 @@ namespace storm {
std::vector<size_t> immediateFailureCauses(size_t index) const;
std::vector<size_t> 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<size_t>, std::vector<size_t>> getSortedParentAndOutDepIds(size_t index) const;

78
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<DFTGate<ValueType>>(mElements[dependency->nameTrigger()]);
STORM_LOG_ASSERT(mElements[dependency->nameDependent()]->isBasicElement(), "Dependent element is not BE.");
std::shared_ptr<DFTBE<ValueType>> dependentEvent = std::static_pointer_cast<DFTBE<ValueType>>(mElements[dependency->nameDependent()]);
dependency->initialize(triggerEvent, dependentEvent);
triggerEvent->addOutgoingDependency(dependency);
dependentEvent->addIngoingDependency(dependency);
for(auto& elem : mDependencyChildNames) {
bool first = true;
std::vector<std::shared_ptr<DFTBE<ValueType>>> 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<DFTBE<ValueType>>(childElement));
} else {
elem.first->setTriggerElement(std::static_pointer_cast<DFTGate<ValueType>>(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<ValueType>(elems, mElements[mTopLevelIdentifier]);
DFT<ValueType> 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<typename ValueType>
@ -144,10 +170,10 @@ namespace storm {
element = std::make_shared<DFTOr<ValueType>>(mNextId++, name);
break;
case DFTElementType::PAND:
element = std::make_shared<DFTPand<ValueType>>(mNextId++, name);
element = std::make_shared<DFTPand<ValueType>>(mNextId++, name, pandDefaultInclusive);
break;
case DFTElementType::POR:
element = std::make_shared<DFTPor<ValueType>>(mNextId++, name);
element = std::make_shared<DFTPor<ValueType>>(mNextId++, name, porDefaultInclusive);
break;
case DFTElementType::SPARE:
element = std::make_shared<DFTSpare<ValueType>>(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<DFTGate<ValueType>>(n)->children()) {
for (DFTElementPointer const& c : std::static_pointer_cast<DFTGate<ValueType>>(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<DFTRestriction<ValueType>>(n)->children()) {
topoVisit(c, visited, L);
}
}
if(n->isDependency()) {
visited[n] = topoSortColour::GREY;
for (DFTElementPointer const& c : std::static_pointer_cast<DFTDependency<ValueType>>(n)->dependentEvents()) {
topoVisit(c, visited, L);
}
topoVisit(std::static_pointer_cast<DFTDependency<ValueType>>(n)->triggerEvent(), visited, L);
}
visited[n] = topoSortColour::BLACK;
L.push_back(n);
}
@ -240,7 +280,9 @@ namespace storm {
{
DFTDependencyPointer dependency = std::static_pointer_cast<DFTDependency<ValueType>>(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;
}

63
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<std::string, DFTElementPointer> mElements;
std::unordered_map<DFTElementPointer, std::vector<std::string>> mChildNames;
std::unordered_map<DFTRestrictionPointer, std::vector<std::string>> mRestrictionChildNames;
std::unordered_map<DFTDependencyPointer, std::vector<std::string>> mDependencyChildNames;
std::vector<DFTDependencyPointer> mDependencies;
std::vector<DFTRestrictionPointer> mRestrictions;
std::unordered_map<std::string, DFTLayoutInfo> 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<std::string> 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<std::string> const& children) {
return addStandardGate(name, children, DFTElementType::POR);
}
bool addPorElement(std::string const& name, std::vector<std::string> 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<std::string> 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<ValueType>(), storm::utility::zero<ValueType>());
@ -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<DFTDependency<ValueType>>(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<DFTDependency<ValueType>>(mNextId++, nameDep, trigger, children[i], probability);
} else {
DFTDependencyPointer element = std::make_shared<DFTDependency<ValueType>>(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<DFTBE<ValueType>>(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;
};
}
}

23
src/storm-dft/storage/dft/DFTIsomorphism.h

@ -258,7 +258,8 @@ namespace storage {
}
void colourize(std::shared_ptr<const DFTDependency<ValueType>> const& dep) {
depColour[dep->id()] = std::pair<ValueType, ValueType>(dep->probability(), dep->dependentEvent()->activeFailureRate());
// TODO this can be improved for n-ary dependencies.
depColour[dep->id()] = std::pair<ValueType, ValueType>(dep->probability(), dep->dependentEvents()[0]->activeFailureRate());
}
void colourize(std::shared_ptr<const DFTRestriction<ValueType>> 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<size_t> dependenciesLeftMapped;
for (auto const& depEv : lDep->dependentEvents()) {
if (bleft.has(depEv->id())) {
dependenciesLeftMapped.insert(bijection.at(depEv->id()));
}
}
std::set<size_t> 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)) {

15
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;
};
}
}

14
src/storm-dft/storage/dft/DFTState.cpp

@ -57,7 +57,8 @@ namespace storm {
for (size_t dependencyId : mDft.getDependencies()) {
std::shared_ptr<DFTDependency<ValueType> 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<DFTDependency<ValueType> const> dependency = mDft.getDependency(mFailableDependencies[index]);
std::pair<std::shared_ptr<DFTBE<ValueType> const>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true);
assert(dependency->dependentEvents().size() == 1);
std::pair<std::shared_ptr<DFTBE<ValueType> const>,bool> res(mDft.getBasicElement(dependency->dependentEvents()[0]->id()), true);
mFailableDependencies.erase(mFailableDependencies.begin() + index);
setFailed(res.first->id());
setDependencySuccessful(dependency->id());

3
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;
}

46
src/storm-dft/storage/dft/elements/DFTDependency.h

@ -12,35 +12,28 @@ namespace storm {
using DFTBEPointer = std::shared_ptr<DFTBE<ValueType>>;
protected:
std::string mNameTrigger;
std::string mNameDependent;
ValueType mProbability;
DFTGatePointer mTriggerEvent;
DFTBEPointer mDependentEvent;
std::vector<DFTBEPointer> mDependentEvents;
public:
DFTDependency(size_t id, std::string const& name, std::string const& trigger, std::string const& dependent, ValueType probability) :
DFTElement<ValueType>(id, name), mNameTrigger(trigger), mNameDependent(dependent), mProbability(probability)
DFTDependency(size_t id, std::string const& name, ValueType probability) :
DFTElement<ValueType>(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<DFTBEPointer> 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<DFTBEPointer> 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<size_t> independentUnit() const override {
std::set<size_t> 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<size_t>(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;
}

4
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;
}
}

15
src/storm-dft/storage/dft/elements/DFTPand.h

@ -7,11 +7,13 @@ namespace storm {
class DFTPand : public DFTGate<ValueType> {
public:
DFTPand(size_t id, std::string const& name, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children = {}) :
DFTGate<ValueType>(id, name, children)
DFTPand(size_t id, std::string const& name, bool inclusive, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children = {}) :
DFTGate<ValueType>(id, name, children),
inclusive(inclusive)
{}
void checkFails(storm::storage::DFTState<ValueType>& state, DFTStateSpaceGenerationQueues<ValueType>& 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<ValueType>& state, DFTStateSpaceGenerationQueues<ValueType>& 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<typename ValueType>

17
src/storm-dft/storage/dft/elements/DFTPor.h

@ -6,12 +6,14 @@ namespace storm {
template<typename ValueType>
class DFTPor : public DFTGate<ValueType> {
public:
DFTPor(size_t id, std::string const& name, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children = {}) :
DFTGate<ValueType>(id, name, children)
DFTPor(size_t id, std::string const& name, bool inclusive, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children = {}) :
DFTGate<ValueType>(id, name, children),
inclusive(inclusive)
{}
void checkFails(storm::storage::DFTState<ValueType>& state, DFTStateSpaceGenerationQueues<ValueType>& 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<ValueType>& state, DFTStateSpaceGenerationQueues<ValueType>& 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<typename ValueType>

9
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;

629
src/storm-dft/transformations/DftToGspnTransformator.cpp

@ -0,0 +1,629 @@
#include "DftToGspnTransformator.h"
#include "storm/exceptions/NotImplementedException.h"
#include <memory>
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 <typename ValueType>
DftToGspnTransformator<ValueType>::DftToGspnTransformator(storm::storage::DFT<ValueType> const& dft) : mDft(dft) {
// Intentionally left empty.
}
template <typename ValueType>
void DftToGspnTransformator<ValueType>::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<typename ValueType>
uint64_t DftToGspnTransformator<ValueType>::toplevelFailedPlaceId() {
assert(failedNodes.size() > mDft.getTopLevelIndex());
return failedNodes[mDft.getTopLevelIndex()];
}
template <typename ValueType>
void DftToGspnTransformator<ValueType>::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<storm::storage::DFTAnd<ValueType> const>(dftElement), isRepresentative);
break;
case storm::storage::DFTElementType::OR:
drawOR(std::static_pointer_cast<storm::storage::DFTOr<ValueType> const>(dftElement), isRepresentative);
break;
case storm::storage::DFTElementType::VOT:
drawVOT(std::static_pointer_cast<storm::storage::DFTVot<ValueType> const>(dftElement), isRepresentative);
break;
case storm::storage::DFTElementType::PAND:
drawPAND(std::static_pointer_cast<storm::storage::DFTPand<ValueType> const>(dftElement), isRepresentative);
break;
case storm::storage::DFTElementType::SPARE:
drawSPARE(std::static_pointer_cast<storm::storage::DFTSpare<ValueType> const>(dftElement), isRepresentative);
break;
case storm::storage::DFTElementType::POR:
drawPOR(std::static_pointer_cast<storm::storage::DFTPor<ValueType> const>(dftElement), isRepresentative);
break;
case storm::storage::DFTElementType::SEQ:
drawSeq(std::static_pointer_cast<storm::storage::DFTSeq<ValueType> 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<storm::storage::DFTBE<ValueType> 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<storm::storage::DFTDependency<ValueType> const>(dftElement));
break;
default:
STORM_LOG_ASSERT(false, "DFT type unknown.");
break;
}
}
}
template <typename ValueType>
void DftToGspnTransformator<ValueType>::drawBE(std::shared_ptr<storm::storage::DFTBE<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawAND(std::shared_ptr<storm::storage::DFTAnd<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawOR(std::shared_ptr<storm::storage::DFTOr<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawVOT(std::shared_ptr<storm::storage::DFTVot<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawPAND(std::shared_ptr<storm::storage::DFTPand<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawPOR(std::shared_ptr<storm::storage::DFTPor<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawSPARE(std::shared_ptr<storm::storage::DFTSpare<ValueType> 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<uint64_t> cucNodes;
std::vector<uint64_t> considerNodes;
std::vector<uint64_t> nextclTransitions;
std::vector<uint64_t> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawCONSTF(std::shared_ptr<storm::storage::DFTElement<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawCONSTS(std::shared_ptr<storm::storage::DFTElement<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawPDEP(std::shared_ptr<storm::storage::DFTDependency<ValueType> 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 <typename ValueType>
void DftToGspnTransformator<ValueType>::drawSeq(std::shared_ptr<storm::storage::DFTSeq<ValueType> 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<typename ValueType>
uint64_t DftToGspnTransformator<ValueType>::addUnavailableNode(std::shared_ptr<storm::storage::DFTElement<ValueType> 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<typename ValueType>
uint64_t DftToGspnTransformator<ValueType>::addDisabledPlace(std::shared_ptr<const storm::storage::DFTBE<ValueType> > dftBe) {
uint64_t disabledNode = builder.addPlace(dftBe->nrRestrictions(), dftBe->nrRestrictions(), dftBe->name() + "_dabled");
disabledNodes.emplace(dftBe->id(), disabledNode);
return disabledNode;
}
//
template <typename ValueType>
bool DftToGspnTransformator<ValueType>::isBEActive(std::shared_ptr<storm::storage::DFTElement<ValueType> 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<bool> 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<storm::storage::DFTSpare<ValueType> 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 <typename ValueType>
uint64_t DftToGspnTransformator<ValueType>::getFailPriority(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftElement)
{
return mDft.maxRank() - dftElement->rank() + 2;
}
template <typename ValueType>
void DftToGspnTransformator<ValueType>::drawGSPNRestrictions() {
}
template <typename ValueType>
gspn::GSPN* DftToGspnTransformator<ValueType>::obtainGSPN() {
return builder.buildGspn();
}
// Explicitly instantiate the class.
template class DftToGspnTransformator<double>;
#ifdef STORM_HAVE_CARL
// template class DftToGspnTransformator<storm::RationalFunction>;
#endif
} // namespace dft
} // namespace transformations
} // namespace storm

163
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<typename ValueType>
class DftToGspnTransformator {
public:
/*!
* Constructor.
*
* @param dft DFT
*/
DftToGspnTransformator(storm::storage::DFT<ValueType> 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<storm::storage::DFTBE<ValueType> const> dftBE, bool isRepresentative);
/*
* Draw a Petri net AND.
*
* @param dftAnd The AND gate.
*/
void drawAND(std::shared_ptr<storm::storage::DFTAnd<ValueType> const> dftAnd, bool isRepresentative);
/*
* Draw a Petri net OR.
*
* @param dftOr The OR gate.
*/
void drawOR(std::shared_ptr<storm::storage::DFTOr<ValueType> const> dftOr, bool isRepresentative);
/*
* Draw a Petri net VOT.
*
* @param dftVot The VOT gate.
*/
void drawVOT(std::shared_ptr<storm::storage::DFTVot<ValueType> 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<storm::storage::DFTPand<ValueType> const> dftPand, bool isRepresentative);
/*
* Draw a Petri net SPARE.
*
* @param dftSpare The SPARE gate.
*/
void drawSPARE(std::shared_ptr<storm::storage::DFTSpare<ValueType> 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<storm::storage::DFTPor<ValueType> 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<storm::storage::DFTElement<ValueType> 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<storm::storage::DFTElement<ValueType> const> dftConstS, bool isRepresentative);
/*
* Draw a Petri net PDEP (FDEP is included with a firerate of 1).
*/
void drawPDEP(std::shared_ptr<storm::storage::DFTDependency<ValueType> const> dftDependency);
void drawSeq(std::shared_ptr<storm::storage::DFTSeq<ValueType> 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<storm::storage::DFTElement<ValueType> 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<storm::storage::DFTElement<ValueType> const> dFTElement);
uint64_t addUnavailableNode(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftElement, storm::gspn::LayoutInfo const& layoutInfo, bool initialAvailable = true);
uint64_t addDisabledPlace(std::shared_ptr<storm::storage::DFTBE<ValueType> const> dftBe);
storm::storage::DFT<ValueType> const& mDft;
storm::gspn::GspnBuilder builder;
std::vector<uint64_t> failedNodes;
std::map<uint64_t, uint64_t> unavailableNodes;
std::map<uint64_t, uint64_t> activeNodes;
std::map<uint64_t, uint64_t> 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.
};
}
}
}

12
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<std::string, uint64_t> parseCapacitiesList(std::string const&
}
void handleJani(storm::gspn::GSPN const& gspn) {
std::shared_ptr<storm::expressions::ExpressionManager> 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<storm::settings::modules::JaniExportSettings>().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<storm::settings::modules::JaniExportSettings>().isJaniFileSet()) {
handleJani(*gspn);
storm::jani::Model* model = storm::buildJani(*gspn);
storm::exportJaniModel(*model, {}, storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
delete model;
}

102
src/storm-gspn/builder/JaniGSPNBuilder.h

@ -9,17 +9,11 @@ namespace storm {
class JaniGSPNBuilder {
public:
JaniGSPNBuilder(storm::gspn::GSPN const& gspn, std::shared_ptr<storm::expressions::ExpressionManager> 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<storm::jani::Assignment> 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<storm::jani::EdgeDestination> 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<storm::jani::Assignment> 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<storm::jani::Assignment> 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<uint64_t, storm::jani::Variable*> vars;
std::map<uint64_t, storm::jani::Variable const*> vars;
std::shared_ptr<storm::expressions::ExpressionManager> expressionManager;
};

66
src/storm-gspn/storage/gspn/GSPN.cpp

@ -27,8 +27,8 @@ namespace storm {
return tId;
}
GSPN::GSPN(std::string const& name, std::vector<Place> const& places, std::vector<ImmediateTransition<WeightType>> const& itransitions, std::vector<TimedTransition<RateType>> const& ttransitions)
: name(name), places(places), immediateTransitions(itransitions), timedTransitions(ttransitions)
GSPN::GSPN(std::string const& name, std::vector<Place> const& places, std::vector<ImmediateTransition<WeightType>> const& itransitions, std::vector<TimedTransition<RateType>> const& ttransitions, std::vector<TransitionPartition> 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<storm::gspn::TimedTransition<GSPN::RateType>> const& GSPN::getTimedTransitions() const {
return this->timedTransitions;
@ -57,6 +65,10 @@ namespace storm {
return m;
}
std::vector<TransitionPartition> 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<uint64_t, LayoutInfo> const& placeLayout) const {
this->placeLayout = placeLayout;
}
void GSPN::setTransitionLayoutInfo(std::map<uint64_t, LayoutInfo> 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 << "<place marking=\"" << place.getNumberOfInitialTokens() <<"\" ";
stream << "name =\"" << place.getName() << "\" ";
stream << "x=\"" << x << "\" ";
stream << "y=\"1\" ";
if (placeLayout.count(place.getID()) > 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 << "<transition name=\"" << trans.getName() << "\" ";
stream << "type=\"EXP\" ";
stream << "nservers-x=\"" << trans.getRate() << "\" ";
stream << "x=\"" << x << "\" ";
stream << "y=\"4\" ";
if (transitionLayout.count(trans.getID()) > 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 << "<transition name=\"" << trans.getName() << "\" ";
stream << "type=\"IMM\" ";
stream << "x=\"" << x << "\" ";
stream << "y=\"4\" ";
stream << "priority=\"" << trans.getPriority() << "\" ";
if (transitionLayout.count(trans.getID()) > 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 << "</net>" << std::endl;
stream << "</pnml>" << 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;
}
}
}

37
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<Place> const& places, std::vector<ImmediateTransition<WeightType>> const& itransitions, std::vector<TimedTransition<RateType>> const& ttransitions);
GSPN(std::string const& name, std::vector<Place> const& places, std::vector<ImmediateTransition<WeightType>> const& itransitions,
std::vector<TimedTransition<RateType>> const& ttransitions, std::vector<TransitionPartition> 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<TransitionPartition> const& getPartitions() const;
/*!
* Returns the vector of timed transitions in this gspn.
*
@ -63,7 +75,6 @@ namespace storm {
*/
std::shared_ptr<storm::gspn::Marking> getInitialMarking(std::map<uint64_t, uint64_t>& 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<GSPN::RateType> 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<std::string, uint64_t> const& mapping);
void setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layout) const;
void setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layout) const;
void setPlaceLayoutInfo(std::map<uint64_t, LayoutInfo> const& placeLayout) const;
void setTransitionLayoutInfo(std::map<uint64_t, LayoutInfo> 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<storm::gspn::TimedTransition<RateType>> timedTransitions;
std::vector<storm::gspn::TransitionPartition> partitions;
mutable std::map<uint64_t, LayoutInfo> placeLayout;
mutable std::map<uint64_t, LayoutInfo> transitionLayout;
};
}
}

49
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<double>();
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<double>());
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<TransitionPartition> 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;
}
}
}

16
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<uint64_t, std::vector<storm::gspn::TransitionPartition>> partitions;
// set containing all immediate transitions
std::vector<storm::gspn::ImmediateTransition<WeightType>> immediateTransitions;
@ -110,6 +115,9 @@ namespace storm {
// set containing all places
std::vector<storm::gspn::Place> places;
std::map<uint64_t, LayoutInfo> placeLayout;
std::map<uint64_t, LayoutInfo> transitionLayout;
};
}
}

17
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;
};
}
}

3
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

18
src/storm-gspn/storage/gspn/TransitionPartition.h

@ -0,0 +1,18 @@
#pragma once
#include <vector>
namespace storm {
namespace gspn {
struct TransitionPartition {
std::vector<uint64_t> transitions;
uint64_t priority;
uint64_t nrTransitions() const {
return transitions.size();
}
};
}
}

61
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<storm::expressions::ExpressionManager> 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<storm::settings::modules::GSPNExportSettings>();
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();
}
}
}

5
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<storm::settings::modules::PGCLSettings>().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<storm::settings::modules::PGCLSettings>().isProgramVariableRestrictionSet()) {
// TODO More fine grained control
storm::storage::IntegerInterval restr = storm::storage::parseIntegerInterval(storm::settings::getModule<storm::settings::modules::PGCLSettings>().getProgramVariableRestrictions());
builder.restrictAllVariables(restr);
}
builder.restrictAllVariables(0, 120);
storm::jani::Model* model = builder.build();
delete progGraph;
handleJani(*model);

18
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<uint64_t, storm::storage::IntegerInterval> userVariableRestrictions;
/// Locations for variables that would have gone ot o
/// Locations for variables that would have gone out of bounds
std::map<uint64_t, uint64_t> varOutOfBoundsLocations;
std::map<storm::ppg::ProgramLocationIdentifier, uint64_t> janiLocId;
std::map<storm::ppg::ProgramVariableIdentifier, storm::jani::Variable*> variables;
@ -176,6 +178,8 @@ namespace storm {
std::shared_ptr<storm::expressions::ExpressionManager> expManager;
/// The program graph to be translated
storm::ppg::ProgramGraph const& programGraph;
/// Settings
JaniProgramGraphBuilderSetting pgbs;
};

7
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})

11
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<storm::settings::modules::JaniExportSettings>().isJaniFileSet()) {
STORM_LOG_TRACE("Exporting JANI model.");
if (storm::settings::getModule<storm::settings::modules::JaniExportSettings>().isExportAsStandardJaniSet()) {
storm::jani::Model normalisedModel = storm::jani::Model(model.asJaniModel());
normalisedModel.makeStandardJaniCompliant();
storm::jani::JsonExporter::toFile(normalisedModel, formulasInProperties(properties), storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
} else {
storm::jani::JsonExporter::toFile(model.asJaniModel(), formulasInProperties(properties), storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
}
exportJaniModel(model.asJaniModel(), properties, storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
}
if (ioSettings.isNoBuildModelSet()) {

2
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;

2
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<Formula const> {
class Formula : public std::enable_shared_from_this<Formula> {
public:
// Make the destructor virtual to allow deletion of objects of subclasses via a pointer to this class.
virtual ~Formula() {

16
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() {
}

11
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;
};

2
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;

6
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<BaseExpression>(new BinaryBooleanFunctionExpression(first.getBaseExpression().getManager(), first.getType().logicalConnective(second.getType()), first.getBaseExpressionPointer(), second.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::And)));
}

15
src/storm/storage/jani/JSONExporter.cpp

@ -516,7 +516,7 @@ namespace storm {
void JsonExporter::toFile(storm::jani::Model const& janiModel, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, std::string const& filepath, bool checkValid) {
void JsonExporter::toFile(storm::jani::Model const& janiModel, std::vector<storm::jani::Property> 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<std::shared_ptr<storm::logic::Formula const>> const& formulas, std::ostream& os, bool checkValid) {
void JsonExporter::toStream(storm::jani::Model const& janiModel, std::vector<storm::jani::Property> const& formulas, std::ostream& os, bool checkValid) {
if(checkValid) {
janiModel.checkValid();
}
@ -650,6 +650,7 @@ namespace storm {
}
modernjson::json buildDestinations(std::vector<EdgeDestination> const& destinations, std::map<uint64_t, std::string> const& locationNames) {
assert(destinations.size() > 0);
std::vector<modernjson::json> destDeclarations;
for(auto const& destination : destinations) {
modernjson::json destEntry;
@ -664,6 +665,10 @@ namespace storm {
modernjson::json buildEdges(std::vector<Edge> const& edges , std::map<uint64_t, std::string> const& actionNames, std::map<uint64_t, std::string> const& locationNames) {
std::vector<modernjson::json> 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<std::shared_ptr<storm::logic::Formula const>> const& formulas, storm::jani::Model const& model) {
void JsonExporter::convertProperties( std::vector<storm::jani::Property> const& formulas, storm::jani::Model const& model) {
std::vector<modernjson::json> 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);
}

8
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<std::shared_ptr<storm::logic::Formula const>> const& formulas, std::string const& filepath, bool checkValid = true);
static void toStream(storm::jani::Model const& janiModel, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, std::ostream& ostream, bool checkValid = false);
static void toFile(storm::jani::Model const& janiModel, std::vector<storm::jani::Property> const& formulas, std::string const& filepath, bool checkValid = true);
static void toStream(storm::jani::Model const& janiModel, std::vector<storm::jani::Property> const& formulas, std::ostream& ostream, bool checkValid = false);
private:
void convertModel(storm::jani::Model const& model);
void convertProperties(std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, storm::jani::Model const& model);
void convertProperties(std::vector<storm::jani::Property> const& formulas, storm::jani::Model const& model);
void appendVariableDeclaration(storm::jani::Variable const& variable);
modernjson::json finalize() {

9
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;
}
}
}

2
src/storm/storage/jani/OrderedAssignments.h

@ -119,6 +119,8 @@ namespace storm {
*/
void changeAssignmentVariables(std::map<Variable const*, std::reference_wrapper<Variable const>> const& remapping);
friend std::ostream& operator<<(std::ostream& stream, OrderedAssignments const& assignments);
private:
static std::vector<std::shared_ptr<Assignment>>::const_iterator lowerBound(Assignment const& assignment, std::vector<std::shared_ptr<Assignment>> const& assignments);

11
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<storm::jani::Property> const& properties, std::string const& filepath) {
STORM_LOG_TRACE("Exporting JANI model.");
if (storm::settings::getModule<storm::settings::modules::JaniExportSettings>().isExportAsStandardJaniSet()) {
storm::jani::Model normalisedModel = model;
normalisedModel.makeStandardJaniCompliant();
storm::jani::JsonExporter::toFile(normalisedModel, properties, filepath);
} else {
storm::jani::JsonExporter::toFile(model, properties, filepath);
}
}
/**
* Helper

10
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<storm::models::ModelBase> preprocessModel(std::shared_ptr<storm::models::ModelBase> model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
if (model->getType() == storm::models::ModelType::MarkovAutomaton && model->isSparseModel()) {
std::shared_ptr<storm::models::sparse::MarkovAutomaton<typename ModelType::ValueType>> ma = model->template as<storm::models::sparse::MarkovAutomaton<typename ModelType::ValueType>>();
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<storm::jani::Property> const& properties, std::string const& filepath);
template<typename ValueType>
void exportMatrixToFile(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::string const& filepath) {
STORM_LOG_THROW(model->getType() != storm::models::ModelType::Ctmc, storm::exceptions::NotImplementedException, "This functionality is not yet implemented." );

2
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 ()

39
stormpy/CMakeLists.txt

@ -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
)

1
stormpy/MANIFEST.in

@ -1 +0,0 @@
recursive-include src *.h

3
stormpy/lib/.gitignore

@ -1,3 +0,0 @@
*.so
__pycache__/
stormpy.egg-info/

70
stormpy/lib/stormpy/__init__.py

@ -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)

2
stormpy/lib/stormpy/expressions/__init__.py

@ -1,2 +0,0 @@
from . import expressions
from .expressions import *

2
stormpy/lib/stormpy/info/__init__.py

@ -1,2 +0,0 @@
from . import info
from .info import *

2
stormpy/lib/stormpy/logic/__init__.py

@ -1,2 +0,0 @@
from . import logic
from .logic import *

3
stormpy/lib/stormpy/storage/__init__.py

@ -1,3 +0,0 @@
from . import storage
from .storage import *
from . import state,action

36
stormpy/lib/stormpy/storage/action.py

@ -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)

34
stormpy/lib/stormpy/storage/state.py

@ -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)

24
stormpy/resources/pybind11/.appveyor.yml

@ -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%

33
stormpy/resources/pybind11/.gitignore

@ -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

3
stormpy/resources/pybind11/.gitmodules

@ -1,3 +0,0 @@
[submodule "tools/clang"]
path = tools/clang
url = https://github.com/wjakob/clang-cindex-python3

44
stormpy/resources/pybind11/.travis.yml

@ -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

170
stormpy/resources/pybind11/CMakeLists.txt

@ -1,170 +0,0 @@
# CMakeLists.txt -- Build system for the pybind11 examples
#
# Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
#
# 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(<name> 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 $<TARGET_FILE:${target_name}>)
else()
add_custom_command(TARGET ${target_name} POST_BUILD
COMMAND ${CMAKE_STRIP} $<TARGET_FILE:${target_name}>)
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 $<$<NOT:$<CONFIG:Debug>>:/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 $<CONFIGURATION> 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()

37
stormpy/resources/pybind11/CONTRIBUTING.md

@ -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.

36
stormpy/resources/pybind11/LICENSE

@ -1,36 +0,0 @@
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, 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.

1
stormpy/resources/pybind11/MANIFEST.in

@ -1 +0,0 @@
include include/pybind11/*.h

114
stormpy/resources/pybind11/README.md

@ -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.

11
stormpy/resources/pybind11/docs/_static/theme_overrides.css

@ -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;
}

1613
stormpy/resources/pybind11/docs/advanced.rst
File diff suppressed because it is too large
View File

309
stormpy/resources/pybind11/docs/basics.rst

@ -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 <pybind11/pybind11.h>
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 <path-to-pybind11>/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<T1, T2>`` | 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<T>`` | Complex numbers | :file:`pybind11/complex.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
+---------------------------------+--------------------------+-------------------------------+
| ``std::unordered_set<T>`` | 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.

90
stormpy/resources/pybind11/docs/benchmark.py

@ -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_<cl%03i>(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 <pybind11/pybind11.h>\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>("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<py::manage_new_object>())\n' % \
(fn, cl, fn)
decl += "};\n\n"
bindings += ' ;\n'
result = "#include <boost/python.hpp>\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 ("}")

96
stormpy/resources/pybind11/docs/benchmark.rst

@ -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_<cl034>(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

172
stormpy/resources/pybind11/docs/changelog.rst

@ -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

334
stormpy/resources/pybind11/docs/classes.rst

@ -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 <pybind11/pybind11.h>
namespace py = pybind11;
PYBIND11_PLUGIN(example) {
py::module m("example", "pybind11 example plugin");
py::class_<Pet>(m, "Pet")
.def(py::init<const std::string &>())
.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)
<example.Pet object at 0x10cd98060>
>>> 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)
<example.Pet object at 0x10cd98060>
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_<Pet>(m, "Pet")
.def(py::init<const std::string &>())
.def("setName", &Pet::setName)
.def("getName", &Pet::getName)
.def("__repr__",
[](const Pet &a) {
return "<example.Pet named '" + a.name + "'>";
}
);
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)
<example.Pet named 'Molly'>
.. _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_<Pet>(m, "Pet")
.def(py::init<const std::string &>())
.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_<Pet>(m, "Pet")
.def(py::init<const std::string &>())
.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_<Pet>(m, "Pet")
.def(py::init<const std::string &>())
.def_readwrite("name", &Pet::name);
py::class_<Dog>(m, "Dog", py::base<Pet>() /* <- specify C++ parent type */)
.def(py::init<const std::string &>())
.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> pet(m, "Pet");
pet.def(py::init<const std::string &>())
.def_readwrite("name", &Pet::name);
py::class_<Dog>(m, "Dog", pet /* <- specify Python parent type */)
.def(py::init<const std::string &>())
.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_<Pet>(m, "Pet")
.def(py::init<const std::string &, int>())
.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> pet(m, "Pet");
pet.def(py::init<const std::string &, Pet::Kind>())
.def_readwrite("name", &Pet::name)
.def_readwrite("type", &Pet::type);
py::enum_<Pet::Kind>(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.

53
stormpy/resources/pybind11/docs/compiling.rst

@ -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(<name> 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

308
stormpy/resources/pybind11/docs/conf.py

@ -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
# "<project> v<release> 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 <link> 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'

208
stormpy/resources/pybind11/docs/faq.rst

@ -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=<path-to-python-executable> .
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<void, Example2, std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&, pybind11::name, pybind11::sibling, pybind11::is_method, char [28]>(void (Example2::*)(std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&), 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.

24
stormpy/resources/pybind11/docs/index.rst

@ -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

87
stormpy/resources/pybind11/docs/intro.rst

@ -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

23
stormpy/resources/pybind11/docs/limitations.rst

@ -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.

BIN
stormpy/resources/pybind11/docs/pybind11-logo.png

Before

Width: 1131  |  Height: 336  |  Size: 57 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save