diff --git a/CMakeLists.txt b/CMakeLists.txt index 13ccb71fc..f2621cf4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ include(ExternalProject) ## CMake options of StoRM ## ############################################################# -option(STORM_DEBUG "Sets whether the DEBUG mode is used" ON) +option(STORM_DEVELOPER "Sets whether the development mode is used" OFF) option(STORM_USE_POPCNT "Sets whether the popcnt instruction is going to be used." ON) option(USE_BOOST_STATIC_LIBRARIES "Sets whether the Boost libraries should be linked statically." ON) option(STORM_USE_INTELTBB "Sets whether the Intel TBB libraries should be used." OFF) @@ -40,11 +40,11 @@ set(MSAT_ROOT "" CACHE STRING "The hint to the root directory of MathSAT (option set(ADDITIONAL_INCLUDE_DIRS "" CACHE STRING "Additional directories added to the include directories.") set(ADDITIONAL_LINK_DIRS "" CACHE STRING "Additional directories added to the link directories.") -# If the DEBUG option was turned on, we will target a debug version and a release version otherwise. -if (STORM_DEBUG) - set (CMAKE_BUILD_TYPE "DEBUG") -else() - set (CMAKE_BUILD_TYPE "RELEASE") +# If the STORM_DEVELOPER option was turned on, we will target a debug version. +if (STORM_DEVELOPER) + message(STATUS "StoRM - Using development mode") + set(CMAKE_BUILD_TYPE "DEBUG" CACHE STRING "Set the build type" FORCE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTORM_DEV") endif() message(STATUS "StoRM - Building ${CMAKE_BUILD_TYPE} version.") diff --git a/examples/dft/and.dft b/examples/dft/and.dft new file mode 100644 index 000000000..2b06cbe95 --- /dev/null +++ b/examples/dft/and.dft @@ -0,0 +1,4 @@ +toplevel "A"; +"A" and "B" "C"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/and_param.dft b/examples/dft/and_param.dft new file mode 100644 index 000000000..8c95a0f2a --- /dev/null +++ b/examples/dft/and_param.dft @@ -0,0 +1,5 @@ +param x; +toplevel "A"; +"A" and "B" "C"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=x dorm=0.3; diff --git a/examples/dft/be_nonfail.dft b/examples/dft/be_nonfail.dft new file mode 100644 index 000000000..d53dca551 --- /dev/null +++ b/examples/dft/be_nonfail.dft @@ -0,0 +1,4 @@ +toplevel "A"; +"A" and "B" "C"; +"B" lambda=0 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/cardiac.dft b/examples/dft/cardiac.dft new file mode 100644 index 000000000..505f002b1 --- /dev/null +++ b/examples/dft/cardiac.dft @@ -0,0 +1,21 @@ +toplevel "SYSTEM"; +"SYSTEM" or "FDEP" "CPU" "MOTOR" "PUMPS"; +"FDEP" fdep "TRIGGER" "P" "B"; +"TRIGGER" or "CS" "SS"; +"CPU" wsp "P" "B"; +"MOTOR" or "SWITCH" "MOTORS"; +"SWITCH" pand "MS" "MA"; +"MOTORS" csp "MA" "MB"; +"PUMPS" and "PUMP1" "PUMP2"; +"PUMP1" csp "PA" "PS"; +"PUMP2" csp "PB" "PS"; +"P" lambda=5.0e-5 dorm=0; +"B" lambda=5.0e-5 dorm=0.5; +"CS" lambda=2.0e-5 dorm=0; +"SS" lambda=2.0e-5 dorm=0; +"MS" lambda=1.0e-6 dorm=0; +"MA" lambda=1.0e-4 dorm=0; +"MB" lambda=1.0e-4 dorm=0; +"PA" lambda=1.0e-4 dorm=0; +"PB" lambda=1.0e-4 dorm=0; +"PS" lambda=1.0e-4 dorm=0; diff --git a/examples/dft/cas.dft b/examples/dft/cas.dft new file mode 100644 index 000000000..812a3f30a --- /dev/null +++ b/examples/dft/cas.dft @@ -0,0 +1,24 @@ +toplevel "System"; +"System" or "CPUfdep" "CPUunit" "Motorunit" "Pumpunit"; + +"CPUfdep" fdep "trigger" "P" "B"; +"trigger" or "CS" "SS"; +"CS" lambda=0.2 dorm=0; +"SS" lambda=0.2 dorm=0; +"CPUunit" wsp "P" "B"; +"P" lambda=0.5 dorm=0; +"B" lambda=0.5 dorm=0.5; + +"Motorunit" or "MP" "Motors"; +"MP" pand "MS" "MA"; +"Motors" csp "MA" "MB"; +"MS" lambda=0.01 dorm=0; +"MA" lambda=1 dorm=0; +"MB" lambda=1 dorm=0; + +"Pumpunit" and "PumpA" "PumpB"; +"PumpA" csp "PA" "PS"; +"PumpB" csp "PB" "PS"; +"PA" lambda=1 dorm=0; +"PB" lambda=1 dorm=0; +"PS" lambda=1 dorm=0; diff --git a/examples/dft/cm2.dft b/examples/dft/cm2.dft new file mode 100644 index 000000000..89a1a8eba --- /dev/null +++ b/examples/dft/cm2.dft @@ -0,0 +1,22 @@ +toplevel "System"; +"System" or "BUS" "CM"; +"CM" and "CM1" "CM2"; +"CM1" or "DISK1" "POWER1" "MEMORY1"; +"CM2" or "DISK2" "POWER2" "MEMORY2"; +"DISK1" wsp "D11" "D12"; +"DISK2" wsp "D21" "D22"; +"POWER1" or "P1" "PS"; +"POWER2" or "P2" "PS"; +"MEMORY1" wsp "M1" "M3"; +"MEMORY2" wsp "M2" "M3"; +"BUS" lambda=0.0002 dorm=0; +"P1" lambda=0.05 dorm=0; +"P2" lambda=0.05 dorm=0; +"PS" lambda=0.6 dorm=0; +"D11" lambda=8.0 dorm=0; +"D12" lambda=8.0 dorm=0.5; +"D21" lambda=8.0 dorm=0; +"D22" lambda=8.0 dorm=0.5; +"M1" lambda=0.003 dorm=0; +"M2" lambda=0.003 dorm=0; +"M3" lambda=0.003 dorm=0.5; diff --git a/examples/dft/cm4.dft b/examples/dft/cm4.dft new file mode 100644 index 000000000..deb8a7fb7 --- /dev/null +++ b/examples/dft/cm4.dft @@ -0,0 +1,41 @@ +toplevel "System"; +"System" or "BUS" "CM"; +"CM" and "CM1" "CM2" "CM3" "CM4"; +"CM1" or "DISK1" "POWER1" "MEMORY1"; +"CM2" or "DISK2" "POWER2" "MEMORY2"; +"CM3" or "DISK3" "POWER3" "MEMORY3"; +"CM4" or "DISK4" "POWER4" "MEMORY4"; +"DISK1" wsp "D11" "D12"; +"DISK2" wsp "D21" "D22"; +"DISK3" wsp "D31" "D32"; +"DISK4" wsp "D41" "D42"; +"POWER1" or "P1" "PS"; +"POWER2" or "P2" "PS"; +"POWER3" or "P3" "PS2"; +"POWER4" or "P4" "PS2"; +"MEMORY1" wsp "M1" "M3" "M4"; +"MEMORY2" wsp "M2" "M3" "M4"; +"MEMORY3" wsp "M31" "M3"; +"MEMORY4" wsp "M41" "M4"; +"BUS" lambda=0.0002 dorm=0; +"P1" lambda=0.05 dorm=0; +"P2" lambda=0.05 dorm=0; +"P3" lambda=0.05 dorm=0; +"P4" lambda=0.05 dorm=0; +"PS" lambda=0.6 dorm=0; +"PS2" lambda=0.6 dorm=0; +"D11" lambda=8.0 dorm=0; +"D12" lambda=8.0 dorm=0.5; +"D21" lambda=8.0 dorm=0; +"D22" lambda=8.0 dorm=0.5; +"D31" lambda=8.0 dorm=0; +"D32" lambda=8.0 dorm=0.5; +"D41" lambda=8.0 dorm=0; +"D42" lambda=8.0 dorm=0.5; +"M1" lambda=0.003 dorm=0; +"M2" lambda=0.003 dorm=0; +"M31" lambda=0.003 dorm=0; +"M41" lambda=0.003 dorm=0; +"M3" lambda=0.003 dorm=0.5; +"M4" lambda=0.003 dorm=0.5; + diff --git a/examples/dft/cps.dft b/examples/dft/cps.dft new file mode 100644 index 000000000..9ee386740 --- /dev/null +++ b/examples/dft/cps.dft @@ -0,0 +1,26 @@ +toplevel "System"; + +"System" pand "A" "B"; + +"A" and "AA" "AB" "AC" "AD"; + +"B" pand "C" "D"; + +"C" and "CA" "CB" "CC" "CD"; + +"D" and "DA" "DB" "DC" "DD"; + +"AA" lambda=1 dorm=0; +"AB" lambda=1 dorm=0; +"AC" lambda=1 dorm=0; +"AD" lambda=1 dorm=0; + +"CA" lambda=1 dorm=0; +"CB" lambda=1 dorm=0; +"CC" lambda=1 dorm=0; +"CD" lambda=1 dorm=0; + +"DA" lambda=1 dorm=0; +"DB" lambda=1 dorm=0; +"DC" lambda=1 dorm=0; +"DD" lambda=1 dorm=0; diff --git a/examples/dft/deathegg.dft b/examples/dft/deathegg.dft new file mode 100644 index 000000000..618684c4e --- /dev/null +++ b/examples/dft/deathegg.dft @@ -0,0 +1,16 @@ +toplevel "DeathEgg"; +"DeathEgg" or "DeathEggProxy" "DeathEggServer" "CampusPowerDependency" "ProxyPowerDependency"; +"DeathEggServer" or "CampusNET" "DES_Disks"; +"DES_Disks" and "DES_Disks_RAID1" "DES_Disks_RAID2"; +"DES_Disks_RAID1" and "DES_Disk_1" "DES_Disk_2"; +"DES_Disks_RAID2" and "DES_Disk_3" "DES_Disk_4"; +"DeathEggProxy" lambda=0.01 dorm=0; +"DES_Disk_1" lambda=0.01 dorm=0; +"DES_Disk_2" lambda=0.01 dorm=0; +"DES_Disk_3" lambda=0.01 dorm=0; +"DES_Disk_4" lambda=0.01 dorm=0; +"CampusPowerDependency" fdep "CampusPower" "DeathEggServer"; +"ProxyPowerDependency" fdep "ProxyPower" "DeathEggProxy"; +"CampusPower" lambda=0.01 dorm=0; +"CampusNET" lambda=0.01 dorm=0; +"ProxyPower" lambda=0.01 dorm=0; \ No newline at end of file diff --git a/examples/dft/fdep.dft b/examples/dft/fdep.dft new file mode 100644 index 000000000..e597c46ce --- /dev/null +++ b/examples/dft/fdep.dft @@ -0,0 +1,8 @@ +toplevel "System"; +"System" or "Power" "Machine"; +"Power" fdep "B_Power" "P" "B"; +"Machine" or "P" "B"; + +"B_Power" lambda=0.5 dorm=0; +"P" lambda=0.5 dorm=0; +"B" lambda=0.5 dorm=0.5; diff --git a/examples/dft/fdep2.dft b/examples/dft/fdep2.dft new file mode 100644 index 000000000..a444ed4be --- /dev/null +++ b/examples/dft/fdep2.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" and "B" "C"; +"F" fdep "B" "C"; +"B" lambda=0.5 dorm=0; +"C" lambda=0.5 dorm=0; diff --git a/examples/dft/fdep3.dft b/examples/dft/fdep3.dft new file mode 100644 index 000000000..3815c9973 --- /dev/null +++ b/examples/dft/fdep3.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" and "B" "C" "F"; +"F" fdep "B" "C"; +"B" lambda=0.4 dorm=0; +"C" lambda=0.8 dorm=0; diff --git a/examples/dft/ftpp_complex.dft b/examples/dft/ftpp_complex.dft new file mode 100644 index 000000000..1b836ee6b --- /dev/null +++ b/examples/dft/ftpp_complex.dft @@ -0,0 +1,129 @@ +toplevel "System"; +"System" or "triadA" "triadB" "triadC" "triadD" "fA" "fB" "fC" "fD"; + +"triadA" 2of3 "aA" "bA" "cA"; +"aA" csp "TAA" "TAS"; +"bA" csp "TAB" "TAS"; +"cA" csp "TAC" "TAS"; + +"triadB" 2of3 "aB" "bB" "cB"; +"aB" csp "TBA" "TBS"; +"bB" csp "TBB" "TBS"; +"cB" csp "TBC" "TBS"; + +"triadC" 2of3 "aC" "bC" "cC"; +"aC" csp "TCA" "TCS"; +"bC" csp "TCB" "TCS"; +"cC" csp "TCC" "TCS"; + +"triadD" 2of3 "aD" "bD" "cD"; +"aD" csp "TDA" "TDS"; +"bD" csp "TDB" "TDS"; +"cD" csp "TDC" "TDS"; + +"fA" fdep "NEA" "TAA" "TBA" "TCA" "TDA"; +"fB" fdep "NEB" "TAB" "TBB" "TCB" "TDB"; +"fC" fdep "NEC" "TAC" "TBC" "TCC" "TDC"; +"fD" fdep "NED" "TAS" "TBS" "TCS" "TDS"; + + +"NEA" lambda=0.017 dorm=1; +"NEB" lambda=0.017 dorm=1; +"NEC" lambda=0.017 dorm=1; +"NED" lambda=0.017 dorm=1; + +"TAA" or "cpuAA" "memAA"; +"memAA" csp "memAA1" "memAA2"; +"cpuAA" lambda=0.11 dorm=0; +"memAA1" lambda=0.11 dorm=0; +"memAA2" lambda=0.11 dorm=0; + +"TAB" or "cpuAB" "memAB"; +"memAB" csp "memAB1" "memAB2"; +"cpuAB" lambda=0.11 dorm=0; +"memAB1" lambda=0.11 dorm=0; +"memAB2" lambda=0.11 dorm=0; + +"TAC" or "cpuAC" "memAC"; +"memAC" csp "memAC1" "memAC2"; +"cpuAC" lambda=0.11 dorm=0; +"memAC1" lambda=0.11 dorm=0; +"memAC2" lambda=0.11 dorm=0; + +"TAS" or "cpuAS" "memAS"; +"memAS" csp "memAS1" "memAS2"; +"cpuAS" lambda=0.11 dorm=0; +"memAS1" lambda=0.11 dorm=0; +"memAS2" lambda=0.11 dorm=0; + +"TBA" or "cpuBA" "memBA"; +"memBA" csp "memBA1" "memBA2"; +"cpuBA" lambda=0.11 dorm=0; +"memBA1" lambda=0.11 dorm=0; +"memBA2" lambda=0.11 dorm=0; + +"TBB" or "cpuBB" "memBB"; +"memBB" csp "memBB1" "memBB2"; +"cpuBB" lambda=0.11 dorm=0; +"memBB1" lambda=0.11 dorm=0; +"memBB2" lambda=0.11 dorm=0; + +"TBC" or "cpuBC" "memBC"; +"memBC" csp "memBC1" "memBC2"; +"cpuBC" lambda=0.11 dorm=0; +"memBC1" lambda=0.11 dorm=0; +"memBC2" lambda=0.11 dorm=0; + +"TBS" or "cpuBS" "memBS"; +"memBS" csp "memBS1" "memBS2"; +"cpuBS" lambda=0.11 dorm=0; +"memBS1" lambda=0.11 dorm=0; +"memBS2" lambda=0.11 dorm=0; + +"TCA" or "cpuCA" "memCA"; +"memCA" csp "memCA1" "memCA2"; +"cpuCA" lambda=0.11 dorm=0; +"memCA1" lambda=0.11 dorm=0; +"memCA2" lambda=0.11 dorm=0; + +"TCB" or "cpuCB" "memCB"; +"memCB" csp "memCB1" "memCB2"; +"cpuCB" lambda=0.11 dorm=0; +"memCB1" lambda=0.11 dorm=0; +"memCB2" lambda=0.11 dorm=0; + +"TCC" or "cpuCC" "memCC"; +"memCC" csp "memCC1" "memCC2"; +"cpuCC" lambda=0.11 dorm=0; +"memCC1" lambda=0.11 dorm=0; +"memCC2" lambda=0.11 dorm=0; + +"TCS" or "cpuCS" "memCS"; +"memCS" csp "memCS1" "memCS2"; +"cpuCS" lambda=0.11 dorm=0; +"memCS1" lambda=0.11 dorm=0; +"memCS2" lambda=0.11 dorm=0; + +"TDA" or "cpuDA" "memDA"; +"memDA" csp "memDA1" "memDA2"; +"cpuDA" lambda=0.11 dorm=0; +"memDA1" lambda=0.11 dorm=0; +"memDA2" lambda=0.11 dorm=0; + +"TDB" or "cpuDB" "memDB"; +"memDB" csp "memDB1" "memDB2"; +"cpuDB" lambda=0.11 dorm=0; +"memDB1" lambda=0.11 dorm=0; +"memDB2" lambda=0.11 dorm=0; + +"TDC" or "cpuDC" "memDC"; +"memDC" csp "memDC1" "memDC2"; +"cpuDC" lambda=0.11 dorm=0; +"memDC1" lambda=0.11 dorm=0; +"memDC2" lambda=0.11 dorm=0; + +"TDS" or "cpuDS" "memDS"; +"memDS" csp "memDS1" "memDS2"; +"cpuDS" lambda=0.11 dorm=0; +"memDS1" lambda=0.11 dorm=0; +"memDS2" lambda=0.11 dorm=0; diff --git a/examples/dft/ftpp_large.dft b/examples/dft/ftpp_large.dft new file mode 100644 index 000000000..cdc8032e7 --- /dev/null +++ b/examples/dft/ftpp_large.dft @@ -0,0 +1,63 @@ +toplevel "System"; +"System" or "triadA" "triadB" "triadC" "triadD" "fA" "fB" "fC" "fD" "fE"; + +"triadA" 3of4 "aA" "bA" "cA" "dA"; +"aA" csp "TAA" "TAS"; +"bA" csp "TAB" "TAS"; +"cA" csp "TAC" "TAS"; +"dA" csp "TAD" "TAS"; + +"triadB" 3of4 "aB" "bB" "cB" "dB"; +"aB" csp "TBA" "TBS"; +"bB" csp "TBB" "TBS"; +"cB" csp "TBC" "TBS"; +"dB" csp "TBD" "TBS"; + +"triadC" 3of4 "aC" "bC" "cC" "dC"; +"aC" csp "TCA" "TCS"; +"bC" csp "TCB" "TCS"; +"cC" csp "TCC" "TCS"; +"dC" csp "TCD" "TCS"; + +"triadD" 3of4 "aD" "bD" "cD" "dD"; +"aD" csp "TDA" "TDS"; +"bD" csp "TDB" "TDS"; +"cD" csp "TDC" "TDS"; +"dD" csp "TDD" "TDS"; + +"fA" fdep "NEA" "TAA" "TBA" "TCA" "TDA"; +"fB" fdep "NEB" "TAB" "TBB" "TCB" "TDB"; +"fC" fdep "NEC" "TAC" "TBC" "TCC" "TDC"; +"fD" fdep "NED" "TAD" "TBD" "TCD" "TDD"; +"fE" fdep "NEE" "TAS" "TBS" "TCS" "TDS"; + + +"NEA" lambda=0.017 dorm=1; +"NEB" lambda=0.017 dorm=1; +"NEC" lambda=0.017 dorm=1; +"NED" lambda=0.017 dorm=1; +"NEE" lambda=0.017 dorm=1; + +"TAA" lambda=0.11 dorm=0; +"TAB" lambda=0.11 dorm=0; +"TAC" lambda=0.11 dorm=0; +"TAD" lambda=0.11 dorm=0; +"TAS" lambda=0.11 dorm=0; + +"TBA" lambda=0.11 dorm=0; +"TBB" lambda=0.11 dorm=0; +"TBC" lambda=0.11 dorm=0; +"TBD" lambda=0.11 dorm=0; +"TBS" lambda=0.11 dorm=0; + +"TCA" lambda=0.11 dorm=0; +"TCB" lambda=0.11 dorm=0; +"TCC" lambda=0.11 dorm=0; +"TCD" lambda=0.11 dorm=0; +"TCS" lambda=0.11 dorm=0; + +"TDA" lambda=0.11 dorm=0; +"TDB" lambda=0.11 dorm=0; +"TDC" lambda=0.11 dorm=0; +"TDD" lambda=0.11 dorm=0; +"TDS" lambda=0.11 dorm=0; diff --git a/examples/dft/ftpp_standard.dft b/examples/dft/ftpp_standard.dft new file mode 100644 index 000000000..9eaa7720e --- /dev/null +++ b/examples/dft/ftpp_standard.dft @@ -0,0 +1,53 @@ +toplevel "System"; +"System" or "triadA" "triadB" "triadC" "triadD" "fA" "fB" "fC" "fD"; + +"triadA" 2of3 "aA" "bA" "cA"; +"aA" csp "TAA" "TAS"; +"bA" csp "TAB" "TAS"; +"cA" csp "TAC" "TAS"; + +"triadB" 2of3 "aB" "bB" "cB"; +"aB" csp "TBA" "TBS"; +"bB" csp "TBB" "TBS"; +"cB" csp "TBC" "TBS"; + +"triadC" 2of3 "aC" "bC" "cC"; +"aC" csp "TCA" "TCS"; +"bC" csp "TCB" "TCS"; +"cC" csp "TCC" "TCS"; + +"triadD" 2of3 "aD" "bD" "cD"; +"aD" csp "TDA" "TDS"; +"bD" csp "TDB" "TDS"; +"cD" csp "TDC" "TDS"; + +"fA" fdep "NEA" "TAA" "TBA" "TCA" "TDA"; +"fB" fdep "NEB" "TAB" "TBB" "TCB" "TDB"; +"fC" fdep "NEC" "TAC" "TBC" "TCC" "TDC"; +"fD" fdep "NED" "TAS" "TBS" "TCS" "TDS"; + + +"NEA" lambda=0.017 dorm=1; +"NEB" lambda=0.017 dorm=1; +"NEC" lambda=0.017 dorm=1; +"NED" lambda=0.017 dorm=1; + +"TAA" lambda=0.11 dorm=0; +"TAB" lambda=0.11 dorm=0; +"TAC" lambda=0.11 dorm=0; +"TAS" lambda=0.11 dorm=0; + +"TBA" lambda=0.11 dorm=0; +"TBB" lambda=0.11 dorm=0; +"TBC" lambda=0.11 dorm=0; +"TBS" lambda=0.11 dorm=0; + +"TCA" lambda=0.11 dorm=0; +"TCB" lambda=0.11 dorm=0; +"TCC" lambda=0.11 dorm=0; +"TCS" lambda=0.11 dorm=0; + +"TDA" lambda=0.11 dorm=0; +"TDB" lambda=0.11 dorm=0; +"TDC" lambda=0.11 dorm=0; +"TDS" lambda=0.11 dorm=0; diff --git a/examples/dft/mcs.dft b/examples/dft/mcs.dft new file mode 100644 index 000000000..733a7a599 --- /dev/null +++ b/examples/dft/mcs.dft @@ -0,0 +1,22 @@ +toplevel "n12"; +"n12" or "n1" "n103" "n7"; +"n103" wsp "n106" "n14"; +"n7" and "n18" "n26"; +"n26" or "n28" "n19" "n23"; +"n19" wsp "n16" "n13"; +"n23" wsp "n0" "n17"; +"n18" or "n15" "n9" "n3"; +"n3" wsp "n2" "n17"; +"n9" wsp "n8" "n27"; +"n16" lambda=8.0 dorm=0.0; +"n0" lambda=0.003 dorm=0.0; +"n13" lambda=8.0 dorm=0.5; +"n2" lambda=0.003 dorm=0.0; +"n17" lambda=0.003 dorm=0.5; +"n15" lambda=0.05 dorm=0.0; +"n106" lambda=1.2 dorm=0.0; +"n14" lambda=0.6 dorm=0.0; +"n1" lambda=2.0E-4 dorm=0.0; +"n27" lambda=8.0 dorm=0.5; +"n8" lambda=8.0 dorm=0.0; +"n28" lambda=0.05 dorm=0.0; diff --git a/examples/dft/mdcs.dft b/examples/dft/mdcs.dft new file mode 100644 index 000000000..450217a4c --- /dev/null +++ b/examples/dft/mdcs.dft @@ -0,0 +1,26 @@ +toplevel "System"; + +"System" or "S" "N"; + +"N" lambda=2e-5 dorm=0; + +"S" and "CMA" "CMB"; + +"CMA" or "DiskA" "PA" "MemA"; +"DiskA" wsp "DAA" "DAB"; +"PA" lambda=500e-5 dorm=0; +"MemA" wsp "MA" "MC"; +"DAA" lambda=80000e-5 dorm=0.5; +"DAB" lambda=80000e-5 dorm=0.5; +"MA" lambda=30e-5 dorm=0; + +"CMB" or "DiskB" "PB" "MemB"; +"DiskB" wsp "DBA" "DBB"; +"PB" lambda=500e-5 dorm=0; +"MemB" wsp "MB" "MC"; +"DBA" lambda=80000e-5 dorm=0.5; +"DBB" lambda=80000e-5 dorm=0.5; +"MB" lambda=30e-5 dorm=0; + +"MC" lambda=30e-5 dorm=0.5; + diff --git a/examples/dft/mdcs2.dft b/examples/dft/mdcs2.dft new file mode 100644 index 000000000..5a376a7b8 --- /dev/null +++ b/examples/dft/mdcs2.dft @@ -0,0 +1,19 @@ +toplevel "System"; +"System" or "S" "N"; +"N" lambda=0.0000200000 dorm=0.0000000000; +"S" and "CMA" "CMB"; +"CMA" or "DiskA" "PA" "MemA"; +"DiskA" wsp "DAA" "DAB"; +"PA" lambda=0.0049999999 dorm=0.0000000000; +"MemA" wsp "MA" "MC"; +"DAA" lambda=0.8000000119 dorm=0.5000000000; +"DAB" lambda=0.8000000119 dorm=0.5000000000; +"MA" lambda=0.0003000000 dorm=0.0000000000; +"CMB" or "DiskB" "PB" "MemB"; +"DiskB" wsp "DBA" "DBB"; +"PB" lambda=0.0049999999 dorm=0.0000000000; +"MemB" wsp "MB" "MC"; +"DBA" lambda=0.8000000119 dorm=0.5000000000; +"DBB" lambda=0.8000000119 dorm=0.5000000000; +"MB" lambda=0.0003000000 dorm=0.0000000000; +"MC" lambda=0.0003000000 dorm=0.5000000000; diff --git a/examples/dft/mp.dft b/examples/dft/mp.dft new file mode 100644 index 000000000..a2e769420 --- /dev/null +++ b/examples/dft/mp.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" or "B" "C"; +"B" or "D" "E"; +"C" or "F" "E"; +"D" lambda=0.1 dorm=0; +"E" lambda=0.2 dorm=0; +"F" lambda=0.3 dorm=0; diff --git a/examples/dft/nonmonoton_param.dft b/examples/dft/nonmonoton_param.dft new file mode 100644 index 000000000..e83f3b012 --- /dev/null +++ b/examples/dft/nonmonoton_param.dft @@ -0,0 +1,8 @@ +param x; +param y; +toplevel "A"; +"A" or "B" "Z"; +"B" pand "D" "S"; +"Z" lambda=y dorm=0; +"D" lambda=100 dorm=0; +"S" lambda=100*x dorm=0; diff --git a/examples/dft/or.dft b/examples/dft/or.dft new file mode 100644 index 000000000..b1003da11 --- /dev/null +++ b/examples/dft/or.dft @@ -0,0 +1,4 @@ +toplevel "A"; +"A" or "B" "C"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/pand.dft b/examples/dft/pand.dft new file mode 100644 index 000000000..d752517b4 --- /dev/null +++ b/examples/dft/pand.dft @@ -0,0 +1,4 @@ +toplevel "A"; +"A" pand "B" "C"; +"B" lambda=0.4 dorm=0.3; +"C" lambda=0.2 dorm=0.3; diff --git a/examples/dft/pand_param.dft b/examples/dft/pand_param.dft new file mode 100644 index 000000000..9a0b3d211 --- /dev/null +++ b/examples/dft/pand_param.dft @@ -0,0 +1,6 @@ +param x; +param y; +toplevel "A"; +"A" pand "B" "C"; +"B" lambda=x dorm=0.3; +"C" lambda=y dorm=0.3; diff --git a/examples/dft/pdep.dft b/examples/dft/pdep.dft new file mode 100644 index 000000000..f8cb0382b --- /dev/null +++ b/examples/dft/pdep.dft @@ -0,0 +1,12 @@ +// From Junges2015 +// Example 3.19 + +toplevel "SF"; +"SF" or "A" "B" "PDEP"; +"A" pand "S" "MA"; +"B" and "MA" "MB"; +"PDEP" pdep=0.2 "MA" "S"; + +"S" lambda=0.5 dorm=0; +"MA" lambda=0.5 dorm=0; +"MB" lambda=0.5 dorm=0; diff --git a/examples/dft/pdep2.dft b/examples/dft/pdep2.dft new file mode 100644 index 000000000..ab1c7a9b8 --- /dev/null +++ b/examples/dft/pdep2.dft @@ -0,0 +1,9 @@ +toplevel "SF"; +"SF" or "A" "B" "PDEP"; +"A" pand "S" "MA"; +"B" and "MA" "MB"; +"PDEP" pdep=0.2 "MA" "S" "MB"; + +"S" lambda=0.5 dorm=0; +"MA" lambda=0.5 dorm=0; +"MB" lambda=0.5 dorm=0; diff --git a/examples/dft/pdep3.dft b/examples/dft/pdep3.dft new file mode 100644 index 000000000..a9a73f472 --- /dev/null +++ b/examples/dft/pdep3.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" and "B" "C" "F"; +"F" pdep=0.3 "B" "C"; +"B" lambda=0.4 dorm=0; +"C" lambda=0.8 dorm=0; diff --git a/examples/dft/pdep4.dft b/examples/dft/pdep4.dft new file mode 100644 index 000000000..eace91847 --- /dev/null +++ b/examples/dft/pdep4.dft @@ -0,0 +1,7 @@ +toplevel "SF"; +"SF" pand "S" "A" "B"; +"PDEP" pdep=0.2 "S" "A" "B"; + +"S" lambda=0.5 dorm=0; +"A" lambda=0.5 dorm=0; +"B" lambda=0.5 dorm=0; diff --git a/examples/dft/pdep_symmetry.dft b/examples/dft/pdep_symmetry.dft new file mode 100644 index 000000000..5c9254aa5 --- /dev/null +++ b/examples/dft/pdep_symmetry.dft @@ -0,0 +1,11 @@ +toplevel "A"; +"A" and "B" "B'"; +"B" and "C" "D" "PDEP"; +"B'" and "C'" "D'" "PDEP'"; +"PDEP" pdep=0.6 "C" "D"; +"PDEP'" pdep=0.6 "C'" "D'"; +"C" lambda=0.5 dorm=0; +"D" lambda=0.5 dorm=0; +"C'" lambda=0.5 dorm=0; +"D'" lambda=0.5 dorm=0; + diff --git a/examples/dft/por.dft b/examples/dft/por.dft new file mode 100644 index 000000000..020687f62 --- /dev/null +++ b/examples/dft/por.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" por "B" "C" "D"; +"B" lambda=0.4 dorm=0.0; +"C" lambda=0.2 dorm=0.0; +"D" lambda=0.2 dorm=0.0; diff --git a/examples/dft/seq.dft b/examples/dft/seq.dft new file mode 100644 index 000000000..6fd99bc3b --- /dev/null +++ b/examples/dft/seq.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" and "B" "C"; +"X" seq "B" "C" +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq2.dft b/examples/dft/seq2.dft new file mode 100644 index 000000000..408d4c26d --- /dev/null +++ b/examples/dft/seq2.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" and "B" "C" "D"; +"X" seq "B" "C" "D"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; +"D" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq3.dft b/examples/dft/seq3.dft new file mode 100644 index 000000000..b22b9e8b6 --- /dev/null +++ b/examples/dft/seq3.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" and "C" "D"; +"X" seq "B" "C" "D"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; +"D" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq4.dft b/examples/dft/seq4.dft new file mode 100644 index 000000000..60bf149af --- /dev/null +++ b/examples/dft/seq4.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" and "T1" "B3"; +"T1" or "B1" "B2"; +"X" seq "B1" "B2" "B3"; +"B1" lambda=0.5 dorm=0.3; +"B2" lambda=0.5 dorm=0.3; +"B3" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq5.dft b/examples/dft/seq5.dft new file mode 100644 index 000000000..77b13ddeb --- /dev/null +++ b/examples/dft/seq5.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" and "T1" "T2"; +"T1" pand "B1" "B2"; +"T2" pand "B3" "B4"; +"X" seq "B4" "B3"; +"B1" lambda=0.7 dorm=0.3; +"B2" lambda=0.5 dorm=0.3; +"B3" lambda=0.5 dorm=0.3; +"B4" lambda=0.7 dorm=0.3; diff --git a/examples/dft/spare.dft b/examples/dft/spare.dft new file mode 100644 index 000000000..4c5d44ff4 --- /dev/null +++ b/examples/dft/spare.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" wsp "I" "M"; +"I" lambda=0.5 dorm=0.3; +"M" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/spare2.dft b/examples/dft/spare2.dft new file mode 100644 index 000000000..21b40cf73 --- /dev/null +++ b/examples/dft/spare2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" or "B" "C"; +"B" wsp "I" "J"; +"C" wsp "M" "J"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"M" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/spare3.dft b/examples/dft/spare3.dft new file mode 100644 index 000000000..ba0ac01d4 --- /dev/null +++ b/examples/dft/spare3.dft @@ -0,0 +1,10 @@ +toplevel "A"; +"A" or "B" "C" "D"; +"B" wsp "I" "M"; +"C" wsp "J" "M"; +"D" wsp "K" "M"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"K" lambda=0.5 dorm=0.3; +"M" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/spare4.dft b/examples/dft/spare4.dft new file mode 100644 index 000000000..a217c6e43 --- /dev/null +++ b/examples/dft/spare4.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" and "B" "C"; +"B" wsp "I" "J" "K"; +"C" wsp "M" "J"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"K" lambda=0.5 dorm=0.3; +"M" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/spare5.dft b/examples/dft/spare5.dft new file mode 100644 index 000000000..0cd15bf0e --- /dev/null +++ b/examples/dft/spare5.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" wsp "I" "B"; +"B" or "C" "J"; +"C" or "K" "L"; +"I" lambda=0.5 dorm=0; +"J" lambda=0.5 dorm=0; +"K" lambda=0.5 dorm=0; +"L" lambda=0.5 dorm=0; + diff --git a/examples/dft/spare6.dft b/examples/dft/spare6.dft new file mode 100644 index 000000000..d5f2b270b --- /dev/null +++ b/examples/dft/spare6.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" or "I" "B"; +"B" wsp "J" "M"; +"I" lambda=0.5 dorm=0.5; +"J" lambda=0.5 dorm=0.5; +"M" lambda=0.5 dorm=0.5; + diff --git a/examples/dft/spare7.dft b/examples/dft/spare7.dft new file mode 100644 index 000000000..a16429e6f --- /dev/null +++ b/examples/dft/spare7.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" wsp "K" "J" "I"; +"I" lambda=0.5 dorm=0.5; +"J" lambda=1 dorm=0.5; +"K" lambda=0.5 dorm=0.5; diff --git a/examples/dft/spare8.dft b/examples/dft/spare8.dft new file mode 100644 index 000000000..c67eaf022 --- /dev/null +++ b/examples/dft/spare8.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" wsp "I" "B"; +"B" wsp "J" "K"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"K" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/spare_cold.dft b/examples/dft/spare_cold.dft new file mode 100644 index 000000000..d01174bd5 --- /dev/null +++ b/examples/dft/spare_cold.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" wsp "I" "M"; +"I" lambda=0.5 dorm=0.0; +"M" lambda=0.5 dorm=0.0; + diff --git a/examples/dft/spare_param.dft b/examples/dft/spare_param.dft new file mode 100644 index 000000000..5378b13d2 --- /dev/null +++ b/examples/dft/spare_param.dft @@ -0,0 +1,9 @@ +param x; +param y; +toplevel "SF"; +"SF" or "FW" "BW"; +"FW" wsp "W1" "WS"; +"BW" wsp "W2" "WS"; +"W1" lambda=x dorm=0; +"W2" lambda=1 dorm=0; +"WS" lambda=y dorm=0; diff --git a/examples/dft/spare_symmetry.dft b/examples/dft/spare_symmetry.dft new file mode 100644 index 000000000..04b5c253b --- /dev/null +++ b/examples/dft/spare_symmetry.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" and "B" "C"; +"B" wsp "I" "J"; +"C" wsp "K" "L"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"K" lambda=0.5 dorm=0.3; +"L" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/symmetry.dft b/examples/dft/symmetry.dft new file mode 100644 index 000000000..6f4031d0b --- /dev/null +++ b/examples/dft/symmetry.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" and "B" "B'"; +"B" and "C" "D"; +"B'" and "C'" "D'"; +"C" lambda=0.5 dorm=0; +"D" lambda=0.5 dorm=0; +"C'" lambda=0.5 dorm=0; +"D'" lambda=0.5 dorm=0; diff --git a/examples/dft/symmetry2.dft b/examples/dft/symmetry2.dft new file mode 100644 index 000000000..6d04021bb --- /dev/null +++ b/examples/dft/symmetry2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" and "B" "B'"; +"B" and "C" "D"; +"B'" and "C'" "D'"; +"C" lambda=0.5 dorm=0; +"D" lambda=2 dorm=0; +"C'" lambda=0.5 dorm=0; +"D'" lambda=2 dorm=0; diff --git a/examples/dft/symmetry3.dft b/examples/dft/symmetry3.dft new file mode 100644 index 000000000..edda963f9 --- /dev/null +++ b/examples/dft/symmetry3.dft @@ -0,0 +1,12 @@ +toplevel "A"; +"A" and "B" "B'" "B''"; +"B" and "C" "D"; +"B'" and "C'" "D'"; +"B''" and "C''" "D''"; +"C" lambda=0.5 dorm=0; +"D" lambda=0.5 dorm=0; +"C'" lambda=0.5 dorm=0; +"D'" lambda=0.5 dorm=0; +"C''" lambda=0.5 dorm=0; +"D''" lambda=0.5 dorm=0; + diff --git a/examples/dft/symmetry4.dft b/examples/dft/symmetry4.dft new file mode 100644 index 000000000..f401fc241 --- /dev/null +++ b/examples/dft/symmetry4.dft @@ -0,0 +1,12 @@ +toplevel "A"; +"A" and "B" "B'" "C" "C'"; +"B" and "D" "E"; +"B'" and "D'" "E'"; +"C" or "F"; +"C'" or "F'"; +"D" lambda=0.5 dorm=0; +"E" lambda=0.5 dorm=0; +"D'" lambda=0.5 dorm=0; +"E'" lambda=0.5 dorm=0; +"F" lambda=0.5 dorm=0; +"F'" lambda=0.5 dorm=0; diff --git a/examples/dft/symmetry5.dft b/examples/dft/symmetry5.dft new file mode 100644 index 000000000..18f700bb2 --- /dev/null +++ b/examples/dft/symmetry5.dft @@ -0,0 +1,21 @@ +toplevel "A"; +"A" and "BA" "BB" "BC" "BD" "BE" "BF"; +"BA" and "CA" "DA"; +"BB" and "CB" "DB"; +"BC" and "CC" "DC"; +"BD" and "CD" "DD"; +"BE" and "CE" "DE"; +"BF" and "CF" "DF"; +"CA" lambda=0.5 dorm=0; +"DA" lambda=0.5 dorm=0; +"CB" lambda=0.5 dorm=0; +"DB" lambda=0.5 dorm=0; +"CC" lambda=0.5 dorm=0; +"DC" lambda=0.5 dorm=0; +"CD" lambda=0.5 dorm=0; +"DD" lambda=0.5 dorm=0; +"CE" lambda=0.5 dorm=0; +"DE" lambda=0.5 dorm=0; +"CF" lambda=0.5 dorm=0; +"DF" lambda=0.5 dorm=0; + diff --git a/examples/dft/symmetry_param.dft b/examples/dft/symmetry_param.dft new file mode 100644 index 000000000..412968c80 --- /dev/null +++ b/examples/dft/symmetry_param.dft @@ -0,0 +1,10 @@ +param x; +param y; +toplevel "A"; +"A" and "B" "B'"; +"B" and "C" "D"; +"B'" and "C'" "D'"; +"C" lambda=x dorm=0; +"D" lambda=y dorm=0; +"C'" lambda=x dorm=0; +"D'" lambda=y dorm=0; diff --git a/examples/dft/symmetry_shared.dft b/examples/dft/symmetry_shared.dft new file mode 100644 index 000000000..73ebed519 --- /dev/null +++ b/examples/dft/symmetry_shared.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" and "B" "B'"; +"B" wsp "C" "D"; +"B'" wsp "C'" "D"; +"C" lambda=0.5 dorm=0; +"D" lambda=0.5 dorm=0; +"C'" lambda=0.5 dorm=0; diff --git a/examples/dft/tripple_and1.dft b/examples/dft/tripple_and1.dft new file mode 100644 index 000000000..b6f1c04b2 --- /dev/null +++ b/examples/dft/tripple_and1.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" and "B" "C"; +"B" and "BE1" "BE2"; +"C" and "BE3" "BE4"; +"BE1" lambda=0.5 dorm=0.3; +"BE2" lambda=0.5 dorm=0.3; +"BE3" lambda=0.5 dorm=0.3; +"BE4" lambda=0.5 dorm=0.3; diff --git a/examples/dft/tripple_and2.dft b/examples/dft/tripple_and2.dft new file mode 100644 index 000000000..382c1657d --- /dev/null +++ b/examples/dft/tripple_and2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" and "B" "C"; +"B" and "BE1" "BE2"; +"C" and "BE2" "BE3"; +"BE1" lambda=0.5 dorm=0.3; +"BE2" lambda=0.5 dorm=0.3; +"BE3" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/tripple_and2_c.dft b/examples/dft/tripple_and2_c.dft new file mode 100644 index 000000000..edfde4144 --- /dev/null +++ b/examples/dft/tripple_and2_c.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" and "BE1" "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_and_c.dft b/examples/dft/tripple_and_c.dft new file mode 100644 index 000000000..72b384c98 --- /dev/null +++ b/examples/dft/tripple_and_c.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" and "BE1" "BE2" "BE3" "BE4"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_or.dft b/examples/dft/tripple_or.dft new file mode 100644 index 000000000..9dbd0e377 --- /dev/null +++ b/examples/dft/tripple_or.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" or "B" "C"; +"B" or "BE1" "BE2"; +"C" or "BE3" "BE4"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_or2.dft b/examples/dft/tripple_or2.dft new file mode 100644 index 000000000..32bc0ff8f --- /dev/null +++ b/examples/dft/tripple_or2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" or "B" "C"; +"B" or "BE1" "BE2"; +"C" or "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_or2_c.dft b/examples/dft/tripple_or2_c.dft new file mode 100644 index 000000000..40747fbc8 --- /dev/null +++ b/examples/dft/tripple_or2_c.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" or "BE1" "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_or_c.dft b/examples/dft/tripple_or_c.dft new file mode 100644 index 000000000..378b29630 --- /dev/null +++ b/examples/dft/tripple_or_c.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" or "BE1" "BE2" "BE3" "BE4"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_pand.dft b/examples/dft/tripple_pand.dft new file mode 100644 index 000000000..7b38cf0f1 --- /dev/null +++ b/examples/dft/tripple_pand.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" pand "B" "BE4"; +"B" pand "C" "BE3"; +"C" pand "BE1" "BE2"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_pand2.dft b/examples/dft/tripple_pand2.dft new file mode 100644 index 000000000..4e6ef460f --- /dev/null +++ b/examples/dft/tripple_pand2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" pand "B" "C"; +"B" pand "BE1" "BE2"; +"C" pand "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_pand2_c.dft b/examples/dft/tripple_pand2_c.dft new file mode 100644 index 000000000..1c6001ea4 --- /dev/null +++ b/examples/dft/tripple_pand2_c.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" pand "BE1" "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_pand_c.dft b/examples/dft/tripple_pand_c.dft new file mode 100644 index 000000000..bfb8daa1c --- /dev/null +++ b/examples/dft/tripple_pand_c.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" pand "BE1" "BE2" "BE3" "BE4"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/voting.dft b/examples/dft/voting.dft new file mode 100644 index 000000000..5c648d424 --- /dev/null +++ b/examples/dft/voting.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" 1of3 "B" "C" "D"; +"B" lambda=0.1 dorm=0; +"C" lambda=0.2 dorm=0; +"D" lambda=0.3 dorm=0; diff --git a/examples/dft/voting2.dft b/examples/dft/voting2.dft new file mode 100644 index 000000000..9cdf299f3 --- /dev/null +++ b/examples/dft/voting2.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" 1of3 "B" "C" "D"; +"B" lambda=0.3 dorm=0; +"C" lambda=0.4 dorm=0; +"D" lambda=1 dorm=0; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d75204355..34b3cf77b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,7 @@ file(GLOB_RECURSE STORM_HEADERS_CLI ${PROJECT_SOURCE_DIR}/src/cli/*.h) file(GLOB_RECURSE STORM_SOURCES_WITHOUT_MAIN ${PROJECT_SOURCE_DIR}/src/*/*.cpp) file(GLOB_RECURSE STORM_SOURCES_CLI ${PROJECT_SOURCE_DIR}/src/cli/*.cpp) file(GLOB_RECURSE STORM_MAIN_FILE ${PROJECT_SOURCE_DIR}/src/storm.cpp) +file(GLOB_RECURSE STORM_DFT_MAIN_FILE ${PROJECT_SOURCE_DIR}/src/storm-dyftee.cpp) file(GLOB_RECURSE STORM_ADAPTERS_FILES ${PROJECT_SOURCE_DIR}/src/adapters/*.h ${PROJECT_SOURCE_DIR}/src/adapters/*.cpp) file(GLOB_RECURSE STORM_BUILDER_FILES ${PROJECT_SOURCE_DIR}/src/builder/*.h ${PROJECT_SOURCE_DIR}/src/builder/*.cpp) file(GLOB_RECURSE STORM_GENERATOR_FILES ${PROJECT_SOURCE_DIR}/src/generator/*.h ${PROJECT_SOURCE_DIR}/src/generator/*.cpp) @@ -33,10 +34,13 @@ file(GLOB STORM_PARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/*.h ${PROJECT_SOUR file(GLOB_RECURSE STORM_PARSER_PRISMPARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/prismparser/*.h ${PROJECT_SOURCE_DIR}/src/parser/prismparser/*.cpp) file(GLOB STORM_SETTINGS_FILES ${PROJECT_SOURCE_DIR}/src/settings/*.h ${PROJECT_SOURCE_DIR}/src/settings/*.cpp) file(GLOB STORM_SETTINGS_MODULES_FILES ${PROJECT_SOURCE_DIR}/src/settings/modules/*.h ${PROJECT_SOURCE_DIR}/src/settings/modules/*.cpp) -file(GLOB_RECURSE STORM_SOLVER_FILES ${PROJECT_SOURCE_DIR}/src/solver/*.h ${PROJECT_SOURCE_DIR}/src/solver/*.cpp) +file(GLOB STORM_SOLVER_FILES ${PROJECT_SOURCE_DIR}/src/solver/*.h ${PROJECT_SOURCE_DIR}/src/solver/*.cpp) +file(GLOB STORM_SOLVER_STATEELIMINATION_FILES ${PROJECT_SOURCE_DIR}/src/solver/stateelimination/*.h ${PROJECT_SOURCE_DIR}/src/solver/stateelimination/*.cpp) file(GLOB STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SOURCE_DIR}/src/storage/*.cpp) file(GLOB STORM_STORAGE_BISIMULATION_FILES ${PROJECT_SOURCE_DIR}/src/storage/bisimulation/*.h ${PROJECT_SOURCE_DIR}/src/storage/bisimulation/*.cpp) file(GLOB STORM_STORAGE_DD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/*.cpp) +file(GLOB STORM_STORAGE_DFT_FILES ${PROJECT_SOURCE_DIR}/src/storage/dft/*.h ${PROJECT_SOURCE_DIR}/src/storage/dft/*.cpp) +file(GLOB STORM_STORAGE_DFT_ELEMENTS_FILES ${PROJECT_SOURCE_DIR}/src/storage/dft/elements/*.h ${PROJECT_SOURCE_DIR}/src/storage/dft/elements/*.cpp) file(GLOB_RECURSE STORM_STORAGE_DD_CUDD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/cudd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/cudd/*.cpp) file(GLOB_RECURSE STORM_STORAGE_DD_SYLVAN_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/sylvan/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/sylvan/*.cpp) file(GLOB_RECURSE STORM_STORAGE_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.h ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.cpp) @@ -53,10 +57,12 @@ list(REMOVE_ITEM STORM_LIB_SOURCES ${STORM_SOURCES_CLI}) set(STORM_LIB_HEADERS ${STORM_HEADERS}) list(REMOVE_ITEM STORM_LIB_HEADERS ${STORM_HEADERS_CLI}) set(STORM_MAIN_SOURCES ${STORM_SOURCES_CLI} ${STORM_MAIN_FILE}) +set(STORM_DFT_MAIN_SOURCES ${STORM_SOURCES_CLI} ${STORM_DFT_MAIN_FILE}) set(STORM_MAIN_HEADERS ${STORM_HEADERS_CLI}) # Group the headers and sources source_group(main FILES ${STORM_MAIN_FILE}) +source_group(dft FILES ${STORM_DYFTTEE_FILE}) source_group(adapters FILES ${STORM_ADAPTERS_FILES}) source_group(builder FILES ${STORM_BUILDER_FILES}) source_group(generator FILES ${STORM_GENERATOR_FILES}) @@ -83,6 +89,7 @@ source_group(parser\\prismparser FILES ${STORM_PARSER_PRISMPARSER_FILES}) source_group(settings FILES ${STORM_SETTINGS_FILES}) source_group(settings\\modules FILES ${STORM_SETTINGS_MODULES_FILES}) source_group(solver FILES ${STORM_SOLVER_FILES}) +source_group(solver\\stateelimination FILES ${STORM_SOLVER_STATEELIMINATION_FILES}) source_group(storage FILES ${STORM_STORAGE_FILES}) source_group(storage\\bisimulation FILES ${STORM_STORAGE_BISIMULATION_FILES}) source_group(storage\\dd FILES ${STORM_STORAGE_DD_FILES}) @@ -91,6 +98,8 @@ source_group(storage\\dd\\sylvan FILES ${STORM_STORAGE_DD_SYLVAN_FILES}) source_group(storage\\expressions FILES ${STORM_STORAGE_EXPRESSIONS_FILES}) source_group(storage\\prism FILES ${STORM_STORAGE_PRISM_FILES}) source_group(storage\\sparse FILES ${STORM_STORAGE_SPARSE_FILES}) +source_group(storage\\dft FILES ${STORM_STORAGE_DFT_FILES}) +source_group(storage\\dft\\elements FILES ${STORM_STORAGE_DFT_ELEMENTS_FILES}) source_group(utility FILES ${STORM_UTILITY_FILES}) # Add custom additional include or link directories @@ -117,6 +126,9 @@ add_executable(storm-main ${STORM_MAIN_SOURCES} ${STORM_MAIN_HEADERS}) target_link_libraries(storm-main storm) # Adding headers for xcode set_target_properties(storm-main PROPERTIES OUTPUT_NAME "storm") +add_executable(storm-dft-main ${STORM_DFT_MAIN_SOURCES} ${STORM_MAIN_HEADERS}) +target_link_libraries(storm-dft-main storm) # Adding headers for xcode +set_target_properties(storm-dft-main PROPERTIES OUTPUT_NAME "storm-dft") target_link_libraries(storm ${STORM_LINK_LIBRARIES}) diff --git a/src/adapters/CarlAdapter.h b/src/adapters/CarlAdapter.h index 5956c0aaa..5b7225a15 100644 --- a/src/adapters/CarlAdapter.h +++ b/src/adapters/CarlAdapter.h @@ -4,6 +4,8 @@ // Include config to know whether CARL is available or not. #include "storm-config.h" +#include + #ifdef STORM_HAVE_CARL #include @@ -39,6 +41,14 @@ namespace carl { std::hash> h; return h(i); } + +} + +namespace cln { + inline size_t hash_value(cl_RA const& n) { + std::hash h; + return h(n); + } } namespace storm { diff --git a/src/builder/DdPrismModelBuilder.cpp b/src/builder/DdPrismModelBuilder.cpp index a9230dbcb..2bb3328cd 100644 --- a/src/builder/DdPrismModelBuilder.cpp +++ b/src/builder/DdPrismModelBuilder.cpp @@ -20,7 +20,7 @@ #include "src/storage/dd/cudd/CuddAddIterator.h" #include "src/storage/dd/Bdd.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" namespace storm { namespace builder { @@ -1081,7 +1081,7 @@ namespace storm { if (!deadlockStates.isZero()) { // If we need to fix deadlocks, we do so now. - if (!storm::settings::generalSettings().isDontFixDeadlocksSet()) { + if (!storm::settings::getModule().isDontFixDeadlocksSet()) { STORM_LOG_INFO("Fixing deadlocks in " << deadlockStates.getNonZeroCount() << " states. The first three of these states are: "); uint_fast64_t count = 0; diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp new file mode 100644 index 000000000..4fb6131df --- /dev/null +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -0,0 +1,474 @@ +#include "src/builder/ExplicitDFTModelBuilder.h" +#include +#include +#include +#include +#include +#include + +namespace storm { + namespace builder { + + template + ExplicitDFTModelBuilder::ModelComponents::ModelComponents() : transitionMatrix(), stateLabeling(), markovianStates(), exitRates(), choiceLabeling() { + // Intentionally left empty. + } + + template + ExplicitDFTModelBuilder::ExplicitDFTModelBuilder(storm::storage::DFT const& dft, storm::storage::DFTIndependentSymmetries const& symmetries, bool enableDC) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, INITIAL_BUCKETSIZE), enableDC(enableDC) { + // stateVectorSize is bound for size of bitvector + + mStateGenerationInfo = std::make_shared(mDft.buildStateGenerationInfo(symmetries)); + } + + + template + std::shared_ptr> ExplicitDFTModelBuilder::buildModel(LabelOptions const& labelOpts) { + // Initialize + bool deterministicModel = false; + size_t rowOffset = 0; + ModelComponents modelComponents; + std::vector tmpMarkovianStates; + storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, false, !deterministicModel, 0); + + if(mergeFailedStates) { + // Introduce explicit fail state + failedIndex = newIndex; + newIndex++; + transitionMatrixBuilder.newRowGroup(failedIndex); + transitionMatrixBuilder.addNextValue(failedIndex, failedIndex, storm::utility::one()); + STORM_LOG_TRACE("Introduce fail state with id: " << failedIndex); + modelComponents.exitRates.push_back(storm::utility::one()); + tmpMarkovianStates.push_back(failedIndex); + } + + // Explore state space + DFTStatePointer state = std::make_shared>(mDft, *mStateGenerationInfo, newIndex); + auto exploreResult = exploreStates(state, rowOffset, transitionMatrixBuilder, tmpMarkovianStates, modelComponents.exitRates); + initialStateIndex = exploreResult.first; + bool deterministic = exploreResult.second; + + // Before ending the exploration check for pseudo states which are not initialized yet + for (auto & pseudoStatePair : mPseudoStatesMapping) { + if (pseudoStatePair.first == 0) { + // Create state from pseudo state and explore + STORM_LOG_ASSERT(mStates.contains(pseudoStatePair.second), "Pseudo state not contained."); + STORM_LOG_ASSERT(mStates.getValue(pseudoStatePair.second) >= OFFSET_PSEUDO_STATE, "State is no pseudo state."); + STORM_LOG_TRACE("Create pseudo state from bit vector " << pseudoStatePair.second); + DFTStatePointer pseudoState = std::make_shared>(pseudoStatePair.second, mDft, *mStateGenerationInfo, newIndex); + STORM_LOG_ASSERT(pseudoStatePair.second == pseudoState->status(), "Pseudo states do not coincide."); + STORM_LOG_TRACE("Explore pseudo state " << mDft.getStateString(pseudoState) << " with id " << pseudoState->getId()); + auto exploreResult = exploreStates(pseudoState, rowOffset, transitionMatrixBuilder, tmpMarkovianStates, modelComponents.exitRates); + deterministic &= exploreResult.second; + STORM_LOG_ASSERT(pseudoStatePair.first == pseudoState->getId(), "Pseudo state ids do not coincide"); + STORM_LOG_ASSERT(pseudoState->getId() == exploreResult.first, "Pseudo state ids do not coincide."); + } + } + + // Replace pseudo states in matrix + std::vector pseudoStatesVector; + for (auto const& pseudoStatePair : mPseudoStatesMapping) { + pseudoStatesVector.push_back(pseudoStatePair.first); + } + STORM_LOG_ASSERT(std::find(pseudoStatesVector.begin(), pseudoStatesVector.end(), 0) == pseudoStatesVector.end(), "Unexplored pseudo state still contained."); + transitionMatrixBuilder.replaceColumns(pseudoStatesVector, OFFSET_PSEUDO_STATE); + + STORM_LOG_DEBUG("Generated " << mStates.size() + (mergeFailedStates ? 1 : 0) << " states"); + STORM_LOG_DEBUG("Model is " << (deterministic ? "deterministic" : "non-deterministic")); + + size_t stateSize = mStates.size() + (mergeFailedStates ? 1 : 0); + // Build Markov Automaton + modelComponents.markovianStates = storm::storage::BitVector(stateSize, tmpMarkovianStates); + // Build transition matrix + modelComponents.transitionMatrix = transitionMatrixBuilder.build(stateSize, stateSize); + if (stateSize <= 15) { + STORM_LOG_TRACE("Transition matrix: " << std::endl << modelComponents.transitionMatrix); + } else { + STORM_LOG_TRACE("Transition matrix: too big to print"); + } + STORM_LOG_TRACE("Exit rates: " << modelComponents.exitRates); + STORM_LOG_TRACE("Markovian states: " << modelComponents.markovianStates); + + // Build state labeling + modelComponents.stateLabeling = storm::models::sparse::StateLabeling(mStates.size() + (mergeFailedStates ? 1 : 0)); + // Initial state is always first state without any failure + modelComponents.stateLabeling.addLabel("init"); + modelComponents.stateLabeling.addLabelToState("init", initialStateIndex); + // Label all states corresponding to their status (failed, failsafe, failed BE) + if(labelOpts.buildFailLabel) { + modelComponents.stateLabeling.addLabel("failed"); + } + if(labelOpts.buildFailSafeLabel) { + modelComponents.stateLabeling.addLabel("failsafe"); + } + + // Collect labels for all BE + std::vector>> basicElements = mDft.getBasicElements(); + for (std::shared_ptr> elem : basicElements) { + if(labelOpts.beLabels.count(elem->name()) > 0) { + modelComponents.stateLabeling.addLabel(elem->name() + "_fail"); + } + } + + if(mergeFailedStates) { + modelComponents.stateLabeling.addLabelToState("failed", failedIndex); + } + for (auto const& stateIdPair : mStates) { + storm::storage::BitVector state = stateIdPair.first; + size_t stateId = stateIdPair.second; + if (!mergeFailedStates && labelOpts.buildFailLabel && mDft.hasFailed(state, *mStateGenerationInfo)) { + modelComponents.stateLabeling.addLabelToState("failed", stateId); + } + if (labelOpts.buildFailSafeLabel && mDft.isFailsafe(state, *mStateGenerationInfo)) { + modelComponents.stateLabeling.addLabelToState("failsafe", stateId); + }; + // Set fail status for each BE + for (std::shared_ptr> elem : basicElements) { + if (labelOpts.beLabels.count(elem->name()) > 0 && storm::storage::DFTState::hasFailed(state, mStateGenerationInfo->getStateIndex(elem->id())) ) { + modelComponents.stateLabeling.addLabelToState(elem->name() + "_fail", stateId); + } + } + } + + std::shared_ptr> model; + + if (deterministic) { + // Turn the probabilities into rates by multiplying each row with the exit rate of the state. + // TODO Matthias: avoid transforming back and forth + storm::storage::SparseMatrix rateMatrix(modelComponents.transitionMatrix); + for (uint_fast64_t row = 0; row < rateMatrix.getRowCount(); ++row) { + STORM_LOG_ASSERT(row < modelComponents.markovianStates.size(), "Row exceeds no. of markovian states."); + if (modelComponents.markovianStates.get(row)) { + for (auto& entry : rateMatrix.getRow(row)) { + entry.setValue(entry.getValue() * modelComponents.exitRates[row]); + } + } + } + model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.exitRates), std::move(modelComponents.stateLabeling)); + } else { + std::shared_ptr> ma = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates), true); + if (ma->hasOnlyTrivialNondeterminism()) { + // Markov automaton can be converted into CTMC + model = ma->convertToCTMC(); + } else { + model = ma; + } + } + + return model; + } + + template + std::pair ExplicitDFTModelBuilder::exploreStates(DFTStatePointer const& state, size_t& rowOffset, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates) { + STORM_LOG_TRACE("Explore state: " << mDft.getStateString(state)); + + auto explorePair = checkForExploration(state); + if (!explorePair.first) { + // State does not need any exploration + return std::make_pair(explorePair.second, true); + } + + + // Initialization + // TODO Matthias: set Markovian states directly as bitvector? + std::map outgoingRates; + std::vector> outgoingProbabilities; + bool hasDependencies = state->nrFailableDependencies() > 0; + size_t failableCount = hasDependencies ? state->nrFailableDependencies() : state->nrFailableBEs(); + size_t smallest = 0; + ValueType exitRate = storm::utility::zero(); + bool deterministic = !hasDependencies; + + // Absorbing state + if (mDft.hasFailed(state) || mDft.isFailsafe(state) || state->nrFailableBEs() == 0) { + uint_fast64_t stateId = addState(state); + STORM_LOG_ASSERT(stateId == state->getId(), "Ids do not coincide."); + + // Add self loop + transitionMatrixBuilder.newRowGroup(stateId + rowOffset); + transitionMatrixBuilder.addNextValue(stateId + rowOffset, stateId, storm::utility::one()); + STORM_LOG_TRACE("Added self loop for " << stateId); + exitRates.push_back(storm::utility::one()); + STORM_LOG_ASSERT(exitRates.size()-1 == stateId, "No. of considered states does not match state id."); + markovianStates.push_back(stateId); + // No further exploration required + return std::make_pair(stateId, true); + } + + // Let BE fail + while (smallest < failableCount) { + STORM_LOG_ASSERT(!mDft.hasFailed(state), "Dft has failed."); + + // Construct new state as copy from original one + DFTStatePointer newState = std::make_shared>(*state); + std::pair const>, bool> nextBEPair = newState->letNextBEFail(smallest++); + std::shared_ptr const>& nextBE = nextBEPair.first; + STORM_LOG_ASSERT(nextBE, "NextBE is null."); + STORM_LOG_ASSERT(nextBEPair.second == hasDependencies, "Failure due to dependencies does not match."); + STORM_LOG_TRACE("With the failure of: " << nextBE->name() << " [" << nextBE->id() << "] in " << mDft.getStateString(state)); + + // Propagate failures + storm::storage::DFTStateSpaceGenerationQueues queues; + + for (DFTGatePointer parent : nextBE->parents()) { + if (newState->isOperational(parent->id())) { + queues.propagateFailure(parent); + } + } + for (DFTRestrictionPointer restr : nextBE->restrictions()) { + queues.checkRestrictionLater(restr); + } + + while (!queues.failurePropagationDone()) { + DFTGatePointer next = queues.nextFailurePropagation(); + next->checkFails(*newState, queues); + newState->updateFailableDependencies(next->id()); + } + + while(!queues.restrictionChecksDone()) { + DFTRestrictionPointer next = queues.nextRestrictionCheck(); + next->checkFails(*newState, queues); + newState->updateFailableDependencies(next->id()); + } + + if(newState->isInvalid()) { + continue; + } + bool dftFailed = newState->hasFailed(mDft.getTopLevelIndex()); + + while (!dftFailed && !queues.failsafePropagationDone()) { + DFTGatePointer next = queues.nextFailsafePropagation(); + next->checkFailsafe(*newState, queues); + } + + while (!dftFailed && enableDC && !queues.dontCarePropagationDone()) { + DFTElementPointer next = queues.nextDontCarePropagation(); + next->checkDontCareAnymore(*newState, queues); + } + + // Update failable dependencies + if (!dftFailed) { + newState->updateFailableDependencies(nextBE->id()); + newState->updateDontCareDependencies(nextBE->id()); + } + + uint_fast64_t newStateId; + if(dftFailed && mergeFailedStates) { + newStateId = failedIndex; + } else { + // Explore new state recursively + auto explorePair = exploreStates(newState, rowOffset, transitionMatrixBuilder, markovianStates, exitRates); + newStateId = explorePair.first; + deterministic &= explorePair.second; + } + + // Set transitions + if (hasDependencies) { + // Failure is due to dependency -> add non-deterministic choice + std::map choiceProbabilities; + std::shared_ptr const> dependency = mDft.getDependency(state->getDependencyId(smallest-1)); + choiceProbabilities.insert(std::make_pair(newStateId, dependency->probability())); + STORM_LOG_TRACE("Added transition to " << newStateId << " with probability " << dependency->probability()); + + if (!storm::utility::isOne(dependency->probability())) { + // Add transition to state where dependency was unsuccessful + DFTStatePointer unsuccessfulState = std::make_shared>(*state); + unsuccessfulState->letDependencyBeUnsuccessful(smallest-1); + auto explorePair = exploreStates(unsuccessfulState, rowOffset, transitionMatrixBuilder, markovianStates, exitRates); + uint_fast64_t unsuccessfulStateId = explorePair.first; + deterministic &= explorePair.second; + ValueType remainingProbability = storm::utility::one() - dependency->probability(); + choiceProbabilities.insert(std::make_pair(unsuccessfulStateId, remainingProbability)); + STORM_LOG_TRACE("Added transition to " << unsuccessfulStateId << " with remaining probability " << remainingProbability); + } + outgoingProbabilities.push_back(choiceProbabilities); + } else { + // Set failure rate according to activation + bool isActive = true; + if (mDft.hasRepresentant(nextBE->id())) { + // Active must be checked for the state we are coming from as this state is responsible for the + // rate and not the new state we are going to + isActive = state->isActive(mDft.getRepresentant(nextBE->id())->id()); + } + ValueType rate = isActive ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); + STORM_LOG_ASSERT(!storm::utility::isZero(rate), "Rate is 0."); + auto resultFind = outgoingRates.find(newStateId); + if (resultFind != outgoingRates.end()) { + // Add to existing transition + resultFind->second += rate; + STORM_LOG_TRACE("Updated transition to " << resultFind->first << " with " << (isActive ? "active" : "passive") << " rate " << rate << " to new rate " << resultFind->second); + } else { + // Insert new transition + outgoingRates.insert(std::make_pair(newStateId, rate)); + STORM_LOG_TRACE("Added transition to " << newStateId << " with " << (isActive ? "active" : "passive") << " rate " << rate); + } + exitRate += rate; + } + + } // end while failing BE + + // Add state + uint_fast64_t stateId = addState(state); + STORM_LOG_ASSERT(stateId == state->getId(), "Ids do not match."); + STORM_LOG_ASSERT(stateId == newIndex-1, "Id does not match no. of states."); + + if (hasDependencies) { + // Add all probability transitions + STORM_LOG_ASSERT(outgoingRates.empty(), "Outgoing transitions not empty."); + transitionMatrixBuilder.newRowGroup(stateId + rowOffset); + for (size_t i = 0; i < outgoingProbabilities.size(); ++i, ++rowOffset) { + STORM_LOG_ASSERT(outgoingProbabilities[i].size() == 1 || outgoingProbabilities[i].size() == 2, "No. of outgoing transitions is not valid."); + for (auto it = outgoingProbabilities[i].begin(); it != outgoingProbabilities[i].end(); ++it) + { + STORM_LOG_TRACE("Set transition from " << stateId << " to " << it->first << " with probability " << it->second); + transitionMatrixBuilder.addNextValue(stateId + rowOffset, it->first, it->second); + } + } + rowOffset--; // One increment too many + } else { + // Try to merge pseudo states with their instantiation + // TODO Matthias: improve? + for (auto it = outgoingRates.begin(); it != outgoingRates.end(); ) { + if (it->first >= OFFSET_PSEUDO_STATE) { + uint_fast64_t newId = it->first - OFFSET_PSEUDO_STATE; + STORM_LOG_ASSERT(newId < mPseudoStatesMapping.size(), "Id is not valid."); + if (mPseudoStatesMapping[newId].first > 0) { + // State exists already + newId = mPseudoStatesMapping[newId].first; + auto itFind = outgoingRates.find(newId); + if (itFind != outgoingRates.end()) { + // Add probability from pseudo state to instantiation + itFind->second += it->second; + STORM_LOG_TRACE("Merged pseudo state " << newId << " adding rate " << it->second << " to total rate of " << itFind->second); + } else { + // Only change id + outgoingRates.emplace(newId, it->second); + STORM_LOG_TRACE("Instantiated pseudo state " << newId << " with rate " << it->second); + } + // Remove pseudo state + it = outgoingRates.erase(it); + } else { + ++it; + } + } else { + ++it; + } + } + + // Add all rate transitions + STORM_LOG_ASSERT(outgoingProbabilities.empty(), "Outgoing probabilities not empty."); + transitionMatrixBuilder.newRowGroup(state->getId() + rowOffset); + STORM_LOG_TRACE("Exit rate for " << state->getId() << ": " << exitRate); + for (auto it = outgoingRates.begin(); it != outgoingRates.end(); ++it) + { + ValueType probability = it->second / exitRate; // Transform rate to probability + STORM_LOG_TRACE("Set transition from " << state->getId() << " to " << it->first << " with rate " << it->second); + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, it->first, probability); + } + + markovianStates.push_back(state->getId()); + } + + STORM_LOG_TRACE("Finished exploring state: " << mDft.getStateString(state)); + exitRates.push_back(exitRate); + STORM_LOG_ASSERT(exitRates.size()-1 == state->getId(), "Id does not match no. of states."); + return std::make_pair(state->getId(), deterministic); + } + + template + std::pair ExplicitDFTModelBuilder::checkForExploration(DFTStatePointer const& state) { + bool changed = false; + if (mStateGenerationInfo->hasSymmetries()) { + // Order state by symmetry + STORM_LOG_TRACE("Check for symmetry: " << mDft.getStateString(state)); + changed = state->orderBySymmetry(); + STORM_LOG_TRACE("State " << (changed ? "changed to " : "did not change") << (changed ? mDft.getStateString(state) : "")); + } + + if (mStates.contains(state->status())) { + // State already exists + uint_fast64_t stateId = mStates.getValue(state->status()); + STORM_LOG_TRACE("State " << mDft.getStateString(state) << " with id " << stateId << " already exists"); + + if (changed || stateId < OFFSET_PSEUDO_STATE) { + // State is changed or an explored "normal" state + return std::make_pair(false, stateId); + } + + stateId -= OFFSET_PSEUDO_STATE; + STORM_LOG_ASSERT(stateId < mPseudoStatesMapping.size(), "Id not valid."); + if (mPseudoStatesMapping[stateId].first > 0) { + // Pseudo state already explored + return std::make_pair(false, mPseudoStatesMapping[stateId].first); + } + + STORM_LOG_ASSERT(mPseudoStatesMapping[stateId].second == state->status(), "States do not coincide."); + STORM_LOG_TRACE("Pseudo state " << mDft.getStateString(state) << " can be explored now"); + return std::make_pair(true, stateId); + } else { + // State does not exists + if (changed) { + // Remember state for later creation + state->setId(mPseudoStatesMapping.size() + OFFSET_PSEUDO_STATE); + mPseudoStatesMapping.push_back(std::make_pair(0, state->status())); + mStates.findOrAdd(state->status(), state->getId()); + STORM_LOG_TRACE("Remember state for later creation: " << mDft.getStateString(state)); + return std::make_pair(false, state->getId()); + } else { + // State needs exploration + return std::make_pair(true, 0); + } + } + } + + template + uint_fast64_t ExplicitDFTModelBuilder::addState(DFTStatePointer const& state) { + uint_fast64_t stateId; + // TODO remove + bool changed = state->orderBySymmetry(); + STORM_LOG_ASSERT(!changed, "State to add has changed by applying symmetry."); + + // Check if state already exists + if (mStates.contains(state->status())) { + // State already exists + stateId = mStates.getValue(state->status()); + STORM_LOG_TRACE("State " << mDft.getStateString(state) << " with id " << stateId << " already exists"); + + // Check if possible pseudo state can be created now + STORM_LOG_ASSERT(stateId >= OFFSET_PSEUDO_STATE, "State is no pseudo state."); + stateId -= OFFSET_PSEUDO_STATE; + STORM_LOG_ASSERT(stateId < mPseudoStatesMapping.size(), "Pseudo state not known."); + if (mPseudoStatesMapping[stateId].first == 0) { + // Create pseudo state now + STORM_LOG_ASSERT(mPseudoStatesMapping[stateId].second == state->status(), "Pseudo states do not coincide."); + state->setId(newIndex++); + mPseudoStatesMapping[stateId].first = state->getId(); + stateId = state->getId(); + mStates.setOrAdd(state->status(), stateId); + STORM_LOG_TRACE("Now create state " << mDft.getStateString(state) << " with id " << stateId); + return stateId; + } else { + STORM_LOG_ASSERT(false, "Pseudo state already created."); + return 0; + } + } else { + // Create new state + state->setId(newIndex++); + stateId = mStates.findOrAdd(state->status(), state->getId()); + STORM_LOG_TRACE("New state: " << mDft.getStateString(state)); + return stateId; + } + } + + + // Explicitly instantiate the class. + template class ExplicitDFTModelBuilder; + +#ifdef STORM_HAVE_CARL + template class ExplicitDFTModelBuilder; +#endif + + } // namespace builder +} // namespace storm + + diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h new file mode 100644 index 000000000..3e78180d1 --- /dev/null +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -0,0 +1,97 @@ +#ifndef EXPLICITDFTMODELBUILDER_H +#define EXPLICITDFTMODELBUILDER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace storm { + namespace builder { + + template + class ExplicitDFTModelBuilder { + + using DFTElementPointer = std::shared_ptr>; + using DFTElementCPointer = std::shared_ptr const>; + using DFTGatePointer = std::shared_ptr>; + using DFTStatePointer = std::shared_ptr>; + using DFTRestrictionPointer = std::shared_ptr>; + + + // A structure holding the individual components of a model. + struct ModelComponents { + ModelComponents(); + + // The transition matrix. + storm::storage::SparseMatrix transitionMatrix; + + // The state labeling. + storm::models::sparse::StateLabeling stateLabeling; + + // The Markovian states. + storm::storage::BitVector markovianStates; + + // The exit rates. + std::vector exitRates; + + // A vector that stores a labeling for each choice. + boost::optional>> choiceLabeling; + }; + + const size_t INITIAL_BUCKETSIZE = 20000; + const uint_fast64_t OFFSET_PSEUDO_STATE = UINT_FAST64_MAX / 2; + + storm::storage::DFT const& mDft; + std::shared_ptr mStateGenerationInfo; + storm::storage::BitVectorHashMap mStates; + std::vector> mPseudoStatesMapping; // vector of (id to concrete state, bitvector) + size_t newIndex = 0; + bool mergeFailedStates = true; + bool enableDC = true; + size_t failedIndex = 0; + size_t initialStateIndex = 0; + + public: + struct LabelOptions { + bool buildFailLabel = true; + bool buildFailSafeLabel = false; + std::set beLabels = {}; + }; + + ExplicitDFTModelBuilder(storm::storage::DFT const& dft, storm::storage::DFTIndependentSymmetries const& symmetries, bool enableDC); + + std::shared_ptr> buildModel(LabelOptions const& labelOpts); + + private: + std::pair exploreStates(DFTStatePointer const& state, size_t& rowOffset, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates); + + /*! + * Adds a state to the explored states and handles pseudo states. + * + * @param state The state to add. + * @return Id of added state. + */ + uint_fast64_t addState(DFTStatePointer const& state); + + /*! + * Check if state needs an exploration and remember pseudo states for later creation. + * + * @param state State which might need exploration. + * @return Pair of flag indicating whether the state needs exploration now and the state id if the state already + * exists. + */ + std::pair checkForExploration(DFTStatePointer const& state); + + }; + } +} + +#endif /* EXPLICITDFTMODELBUILDER_H */ diff --git a/src/builder/ExplicitPrismModelBuilder.cpp b/src/builder/ExplicitPrismModelBuilder.cpp index 687e9fb41..b94cb9f47 100644 --- a/src/builder/ExplicitPrismModelBuilder.cpp +++ b/src/builder/ExplicitPrismModelBuilder.cpp @@ -9,7 +9,8 @@ #include "src/storage/expressions/ExpressionManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" +#include "src/settings/modules/IOSettings.h" #include "src/generator/PrismNextStateGenerator.h" #include "src/generator/PrismStateLabelingGenerator.h" @@ -69,17 +70,17 @@ namespace storm { } template - ExplicitPrismModelBuilder::Options::Options() : explorationOrder(storm::settings::generalSettings().getExplorationOrder()), buildCommandLabels(false), buildAllRewardModels(true), buildStateValuations(false), rewardModelsToBuild(), constantDefinitions(), buildAllLabels(true), labelsToBuild(), expressionLabels(), terminalStates(), negatedTerminalStates() { + ExplicitPrismModelBuilder::Options::Options() : explorationOrder(storm::settings::getModule().getExplorationOrder()), buildCommandLabels(false), buildAllRewardModels(true), buildStateValuations(false), rewardModelsToBuild(), constantDefinitions(), buildAllLabels(true), labelsToBuild(), expressionLabels(), terminalStates(), negatedTerminalStates() { // Intentionally left empty. } template - ExplicitPrismModelBuilder::Options::Options(storm::logic::Formula const& formula) : explorationOrder(storm::settings::generalSettings().getExplorationOrder()), buildCommandLabels(false), buildAllRewardModels(false), buildStateValuations(false), rewardModelsToBuild(), constantDefinitions(), buildAllLabels(false), labelsToBuild(std::set()), expressionLabels(std::vector()), terminalStates(), negatedTerminalStates() { + ExplicitPrismModelBuilder::Options::Options(storm::logic::Formula const& formula) : explorationOrder(storm::settings::getModule().getExplorationOrder()), buildCommandLabels(false), buildAllRewardModels(false), buildStateValuations(false), rewardModelsToBuild(), constantDefinitions(), buildAllLabels(false), labelsToBuild(std::set()), expressionLabels(std::vector()), terminalStates(), negatedTerminalStates() { this->preserveFormula(formula); } template - ExplicitPrismModelBuilder::Options::Options(std::vector> const& formulas) : explorationOrder(storm::settings::generalSettings().getExplorationOrder()), buildCommandLabels(false), buildAllRewardModels(false), buildStateValuations(false), rewardModelsToBuild(), constantDefinitions(), buildAllLabels(false), labelsToBuild(), expressionLabels(), terminalStates(), negatedTerminalStates() { + ExplicitPrismModelBuilder::Options::Options(std::vector> const& formulas) : explorationOrder(storm::settings::getModule().getExplorationOrder()), buildCommandLabels(false), buildAllRewardModels(false), buildStateValuations(false), rewardModelsToBuild(), constantDefinitions(), buildAllLabels(false), labelsToBuild(), expressionLabels(), terminalStates(), negatedTerminalStates() { if (formulas.empty()) { this->buildAllRewardModels = true; this->buildAllLabels = true; @@ -304,7 +305,7 @@ namespace storm { // If there is no behavior, we might have to introduce a self-loop. if (behavior.empty()) { - if (!storm::settings::generalSettings().isDontFixDeadlocksSet() || !behavior.wasExpanded()) { + if (!storm::settings::getModule().isDontFixDeadlocksSet() || !behavior.wasExpanded()) { if (options.buildCommandLabels) { // Insert empty choice labeling for added self-loop transitions. choiceLabels.get().push_back(boost::container::flat_set()); diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 3b5a5fcc2..8fd9120cb 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -4,6 +4,8 @@ #include "../utility/storm.h" #include "src/settings/modules/DebugSettings.h" +#include "src/settings/modules/IOSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/exceptions/OptionParserException.h" #include "src/utility/storm-version.h" @@ -41,9 +43,9 @@ namespace storm { return (GetCurrentDir(temp, 512 - 1) ? std::string(temp) : std::string("")); } - void printHeader(const int argc, const char* argv[]) { - std::cout << "StoRM" << std::endl; - std::cout << "--------" << std::endl << std::endl; + void printHeader(const std::string name, const int argc, const char* argv[]) { + std::cout << name << std::endl; + std::cout << "---------------" << std::endl << std::endl; std::cout << storm::utility::StormVersion::longVersionString() << std::endl; @@ -166,59 +168,56 @@ namespace storm { } bool parseOptions(const int argc, const char* argv[]) { - storm::settings::SettingsManager& manager = storm::settings::mutableManager(); try { - manager.setFromCommandLine(argc, argv); + storm::settings::mutableManager().setFromCommandLine(argc, argv); } catch (storm::exceptions::OptionParserException& e) { - manager.printHelp(); + storm::settings::manager().printHelp(); throw e; return false; } - if (storm::settings::generalSettings().isHelpSet()) { - storm::settings::manager().printHelp(storm::settings::generalSettings().getHelpModuleName()); + if (storm::settings::getModule().isHelpSet()) { + storm::settings::manager().printHelp(storm::settings::getModule().getHelpModuleName()); return false; } - if (storm::settings::generalSettings().isVersionSet()) { + if (storm::settings::getModule().isVersionSet()) { storm::settings::manager().printVersion(); return false; } - if (storm::settings::generalSettings().isVerboseSet()) { + if (storm::settings::getModule().isVerboseSet()) { STORM_GLOBAL_LOGLEVEL_INFO(); } - if (storm::settings::debugSettings().isDebugSet()) { + if (storm::settings::getModule().isDebugSet()) { STORM_GLOBAL_LOGLEVEL_DEBUG(); } - if (storm::settings::debugSettings().isTraceSet()) { + if (storm::settings::getModule().isTraceSet()) { STORM_GLOBAL_LOGLEVEL_TRACE(); } - if (storm::settings::debugSettings().isLogfileSet()) { + if (storm::settings::getModule().isLogfileSet()) { storm::utility::initializeFileLogging(); } return true; } void processOptions() { - if (storm::settings::debugSettings().isLogfileSet()) { + if (storm::settings::getModule().isLogfileSet()) { storm::utility::initializeFileLogging(); } - storm::settings::modules::GeneralSettings const& settings = storm::settings::generalSettings(); - // If we have to build the model from a symbolic representation, we need to parse the representation first. boost::optional program; - if (settings.isSymbolicSet()) { - std::string const& programFile = settings.getSymbolicModelFilename(); + if (storm::settings::getModule().isSymbolicSet()) { + std::string const& programFile = storm::settings::getModule().getSymbolicModelFilename(); program = storm::parseProgram(programFile); } // Then proceed to parsing the property (if given), since the model we are building may depend on the property. std::vector> parsedFormulas; - if (settings.isPropertySet()) { - std::string properties = settings.getProperty(); + if (storm::settings::getModule().isPropertySet()) { + std::string properties = storm::settings::getModule().getProperty(); if(program) { parsedFormulas = storm::parseFormulasForProgram(properties, program.get()); @@ -229,9 +228,9 @@ namespace storm { } std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); - if (settings.isSymbolicSet()) { + if (storm::settings::getModule().isSymbolicSet()) { #ifdef STORM_HAVE_CARL - if (settings.isParametricSet()) { + if (storm::settings::getModule().isParametricSet()) { buildAndCheckSymbolicModel(program.get(), formulas, true); } else { #endif @@ -239,7 +238,8 @@ namespace storm { #ifdef STORM_HAVE_CARL } #endif - } else if (settings.isExplicitSet()) { + } else if (storm::settings::getModule().isExplicitSet()) { + STORM_LOG_THROW(storm::settings::getModule().getEngine() == storm::settings::modules::MarkovChainSettings::Engine::Sparse, storm::exceptions::InvalidSettingsException, "Cannot use explicit input models with this engine."); buildAndCheckExplicitModel(formulas, true); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "No input model."); diff --git a/src/cli/cli.h b/src/cli/cli.h index 896b7bee2..db2ab11bf 100644 --- a/src/cli/cli.h +++ b/src/cli/cli.h @@ -6,23 +6,22 @@ namespace storm { namespace cli { - std::string getCurrentWorkingDirectory(); + std::string getCurrentWorkingDirectory(); - void printHeader(const int argc, const char* argv[]); + void printHeader(std::string name, const int argc, const char* argv[]); - void printUsage(); + void printUsage(); + + /*! + * Parses the given command line arguments. + * + * @param argc The argc argument of main(). + * @param argv The argv argument of main(). + * @return True iff the program should continue to run after parsing the options. + */ + bool parseOptions(const int argc, const char* argv[]); - /*! - * Parses the given command line arguments. - * - * @param argc The argc argument of main(). - * @param argv The argv argument of main(). - * @return True iff the program should continue to run after parsing the options. - */ - bool parseOptions(const int argc, const char* argv[]); - - - void processOptions(); + void processOptions(); } } diff --git a/src/cli/entrypoints.h b/src/cli/entrypoints.h index c1f88a9b4..b8352ae49 100644 --- a/src/cli/entrypoints.h +++ b/src/cli/entrypoints.h @@ -29,7 +29,7 @@ namespace storm { inline void verifySparseModel(std::shared_ptr> model, std::vector> const& formulas, bool onlyInitialStatesRelevant) { for (auto const& formula : formulas) { - STORM_LOG_THROW(model->getType() == storm::models::ModelType::Dtmc, storm::exceptions::InvalidSettingsException, "Currently parametric verification is only available for DTMCs."); + STORM_LOG_THROW(model->getType() == storm::models::ModelType::Dtmc || model->getType() == storm::models::ModelType::Ctmc, storm::exceptions::InvalidSettingsException, "Currently parametric verification is only available for DTMCs and CTMCs."); std::cout << std::endl << "Model checking property: " << *formula << " ..."; std::unique_ptr result(storm::verifySparseModel(model, formula, onlyInitialStatesRelevant)); if (result) { @@ -41,9 +41,8 @@ namespace storm { std::cout << " skipped, because the modelling formalism is currently unsupported." << std::endl; } - storm::settings::modules::ParametricSettings const& parametricSettings = storm::settings::parametricSettings(); - if (parametricSettings.exportResultToFile()) { - exportParametricResultToFile(result->asExplicitQuantitativeCheckResult()[*model->getInitialStates().begin()], storm::models::sparse::Dtmc::ConstraintCollector(*(model->template as>())), parametricSettings.exportResultPath()); + if (storm::settings::getModule().exportResultToFile()) { + exportParametricResultToFile(result->asExplicitQuantitativeCheckResult()[*model->getInitialStates().begin()], storm::models::sparse::Dtmc::ConstraintCollector(*(model->template as>())), storm::settings::getModule().exportResultPath()); } } } @@ -61,7 +60,7 @@ namespace storm { STORM_LOG_THROW(program.getModelType() == storm::prism::Program::ModelType::DTMC || program.getModelType() == storm::prism::Program::ModelType::MDP, storm::exceptions::InvalidSettingsException, "Currently exploration-based verification is only available for DTMCs and MDPs."); std::cout << std::endl << "Model checking property: " << *formula << " ..."; storm::modelchecker::CheckTask task(*formula, onlyInitialStatesRelevant); - storm::modelchecker::SparseExplorationModelChecker checker(program, storm::utility::prism::parseConstantDefinitionString(program, storm::settings::generalSettings().getConstantDefinitionString())); + storm::modelchecker::SparseExplorationModelChecker checker(program, storm::utility::prism::parseConstantDefinitionString(program, storm::settings::getModule().getConstantDefinitionString())); std::unique_ptr result; if (checker.canHandle(task)) { result = checker.check(task); @@ -147,11 +146,9 @@ namespace storm { template void buildAndCheckSymbolicModel(storm::prism::Program const& program, std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { - storm::settings::modules::GeneralSettings const& settings = storm::settings::generalSettings(); - - if (settings.getEngine() == storm::settings::modules::GeneralSettings::Engine::AbstractionRefinement) { + if (storm::settings::getModule().getEngine() == storm::settings::modules::MarkovChainSettings::Engine::AbstractionRefinement) { verifySymbolicModelWithAbstractionRefinementEngine(program, formulas, onlyInitialStatesRelevant); - } else if (settings.getEngine() == storm::settings::modules::GeneralSettings::Engine::Exploration) { + } else if (storm::settings::getModule().getEngine() == storm::settings::modules::MarkovChainSettings::Engine::Exploration) { verifySymbolicModelWithExplorationEngine(program, formulas, onlyInitialStatesRelevant); } else { storm::storage::ModelFormulasPair modelFormulasPair = buildSymbolicModel(program, formulas); @@ -167,7 +164,7 @@ namespace storm { // Verify the model, if a formula was given. if (!formulas.empty()) { if (modelFormulasPair.model->isSparseModel()) { - if (storm::settings::generalSettings().isCounterexampleSet()) { + if (storm::settings::getModule().isCounterexampleSet()) { // If we were requested to generate a counterexample, we now do so for each formula. for (auto const& formula : modelFormulasPair.formulas) { generateCounterexample(program, modelFormulasPair.model->as>(), formula); @@ -176,7 +173,7 @@ namespace storm { verifySparseModel(modelFormulasPair.model->as>(), modelFormulasPair.formulas, onlyInitialStatesRelevant); } } else if (modelFormulasPair.model->isSymbolicModel()) { - if (storm::settings::generalSettings().getEngine() == storm::settings::modules::GeneralSettings::Engine::Hybrid) { + if (storm::settings::getModule().getEngine() == storm::settings::modules::MarkovChainSettings::Engine::Hybrid) { verifySymbolicModelWithHybridEngine(modelFormulasPair.model->as>(), modelFormulasPair.formulas, onlyInitialStatesRelevant); } else { @@ -192,16 +189,16 @@ namespace storm { template void buildAndCheckSymbolicModel(storm::prism::Program const& program, std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { - if (storm::settings::generalSettings().getDdLibraryType() == storm::dd::DdType::CUDD) { + if (storm::settings::getModule().getDdLibraryType() == storm::dd::DdType::CUDD) { buildAndCheckSymbolicModel(program, formulas, onlyInitialStatesRelevant); - } else if (storm::settings::generalSettings().getDdLibraryType() == storm::dd::DdType::Sylvan) { + } else if (storm::settings::getModule().getDdLibraryType() == storm::dd::DdType::Sylvan) { buildAndCheckSymbolicModel(program, formulas, onlyInitialStatesRelevant); } } template void buildAndCheckExplicitModel(std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { - storm::settings::modules::GeneralSettings const& settings = storm::settings::generalSettings(); + storm::settings::modules::IOSettings const& settings = storm::settings::getModule(); STORM_LOG_THROW(settings.isExplicitSet(), storm::exceptions::InvalidStateException, "Unable to build explicit model without model files."); std::shared_ptr model = buildExplicitModel(settings.getTransitionFilename(), settings.getLabelingFilename(), settings.isStateRewardsSet() ? boost::optional(settings.getStateRewardsFilename()) : boost::none, settings.isTransitionRewardsSet() ? boost::optional(settings.getTransitionRewardsFilename()) : boost::none, settings.isChoiceLabelingSet() ? boost::optional(settings.getChoiceLabelingFilename()) : boost::none); diff --git a/src/counterexamples/MILPMinimalLabelSetGenerator.h b/src/counterexamples/MILPMinimalLabelSetGenerator.h index 3c805d7fe..4f30ea41d 100644 --- a/src/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/counterexamples/MILPMinimalLabelSetGenerator.h @@ -1015,7 +1015,7 @@ namespace storm { // Delegate the actual computation work to the function of equal name. auto startTime = std::chrono::high_resolution_clock::now(); - boost::container::flat_set usedLabelSet = getMinimalLabelSet(probabilityOperator.getSubformula(), labeledMdp, phiStates, psiStates, threshold, strictBound, true, storm::settings::counterexampleGeneratorSettings().isUseSchedulerCutsSet()); + boost::container::flat_set usedLabelSet = getMinimalLabelSet(probabilityOperator.getSubformula(), labeledMdp, phiStates, psiStates, threshold, strictBound, true, storm::settings::getModule().isUseSchedulerCutsSet()); auto endTime = std::chrono::high_resolution_clock::now(); std::cout << std::endl << "Computed minimal label set of size " << usedLabelSet.size() << " in " << std::chrono::duration_cast(endTime - startTime).count() << "ms." << std::endl; diff --git a/src/counterexamples/SMTMinimalCommandSetGenerator.h b/src/counterexamples/SMTMinimalCommandSetGenerator.h index 6cf9e9e8a..ee0613fca 100644 --- a/src/counterexamples/SMTMinimalCommandSetGenerator.h +++ b/src/counterexamples/SMTMinimalCommandSetGenerator.h @@ -12,7 +12,7 @@ #include "src/modelchecker/results/ExplicitQuantitativeCheckResult.h" #include "src/solver/GmmxxMinMaxLinearEquationSolver.h" #include "src/settings/SettingsManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/utility/counterexamples.h" #include "src/utility/prism.h" @@ -1729,7 +1729,7 @@ namespace storm { // Compute and emit the time measurements if the corresponding flag was set. totalTime = std::chrono::high_resolution_clock::now() - totalClock; - if (storm::settings::generalSettings().isShowStatisticsSet()) { + if (storm::settings::getModule().isShowStatisticsSet()) { std::cout << std::endl; std::cout << "Time breakdown:" << std::endl; std::cout << " * time for setup: " << std::chrono::duration_cast(totalSetupTime).count() << "ms" << std::endl; @@ -1793,7 +1793,7 @@ namespace storm { // Delegate the actual computation work to the function of equal name. auto startTime = std::chrono::high_resolution_clock::now(); - auto labelSet = getMinimalCommandSet(probabilityOperator.getSubformula(), program, constantDefinitionString, labeledMdp, phiStates, psiStates, threshold, strictBound, true, storm::settings::counterexampleGeneratorSettings().isEncodeReachabilitySet()); + auto labelSet = getMinimalCommandSet(probabilityOperator.getSubformula(), program, constantDefinitionString, labeledMdp, phiStates, psiStates, threshold, strictBound, true, storm::settings::getModule().isEncodeReachabilitySet()); auto endTime = std::chrono::high_resolution_clock::now(); std::cout << std::endl << "Computed minimal label set of size " << labelSet.size() << " in " << std::chrono::duration_cast(endTime - startTime).count() << "ms." << std::endl; diff --git a/src/modelchecker/AbstractModelChecker.cpp b/src/modelchecker/AbstractModelChecker.cpp index 850cae65d..4fd86a13e 100644 --- a/src/modelchecker/AbstractModelChecker.cpp +++ b/src/modelchecker/AbstractModelChecker.cpp @@ -241,4 +241,4 @@ namespace storm { return subResult; } } -} \ No newline at end of file +} diff --git a/src/modelchecker/DFTAnalyser.h b/src/modelchecker/DFTAnalyser.h new file mode 100644 index 000000000..24c1068ba --- /dev/null +++ b/src/modelchecker/DFTAnalyser.h @@ -0,0 +1,191 @@ +#pragma once + +#include "logic/Formula.h" +#include "parser/DFTGalileoParser.h" +#include "builder/ExplicitDFTModelBuilder.h" +#include "modelchecker/results/CheckResult.h" +#include "utility/storm.h" +#include "storage/dft/DFTIsomorphism.h" +#include "utility/bitoperations.h" + + +#include + +template +class DFTAnalyser { + + std::chrono::duration buildingTime = std::chrono::duration::zero(); + std::chrono::duration explorationTime = std::chrono::duration::zero(); + std::chrono::duration bisimulationTime = std::chrono::duration::zero(); + std::chrono::duration modelCheckingTime = std::chrono::duration::zero(); + std::chrono::duration totalTime = std::chrono::duration::zero(); + ValueType checkResult = storm::utility::zero(); +public: + void check(storm::storage::DFT const& origDft , std::shared_ptr const& formula, bool symred = true, bool allowModularisation = true, bool enableDC = true) { + + // Building DFT + std::chrono::high_resolution_clock::time_point totalStart = std::chrono::high_resolution_clock::now(); + + + // Optimizing DFT + storm::storage::DFT dft = origDft.optimize(); + checkResult = checkHelper(dft, formula, symred, allowModularisation, enableDC); + totalTime = std::chrono::high_resolution_clock::now() - totalStart; + + + + } + +private: + ValueType checkHelper(storm::storage::DFT const& dft , std::shared_ptr const& formula, bool symred = true, bool allowModularisation = true, bool enableDC = true) { + STORM_LOG_TRACE("Check helper called"); + bool invResults = false; + std::vector> dfts = {dft}; + std::vector res; + size_t nrK = 0; // K out of M + size_t nrM = 0; // K out of M + + if(allowModularisation) { + if(dft.topLevelType() == storm::storage::DFTElementType::AND) { + STORM_LOG_TRACE("top modularisation called AND"); + dfts = dft.topModularisation(); + STORM_LOG_TRACE("Modularsation into " << dfts.size() << " submodules."); + nrK = dfts.size(); + nrM = dfts.size(); + } + if(dft.topLevelType() == storm::storage::DFTElementType::OR) { + STORM_LOG_TRACE("top modularisation called OR"); + dfts = dft.topModularisation(); + STORM_LOG_TRACE("Modularsation into " << dfts.size() << " submodules."); + nrK = 0; + nrM = dfts.size(); + invResults = true; + } + if(dft.topLevelType() == storm::storage::DFTElementType::VOT) { + STORM_LOG_TRACE("top modularisation called VOT"); + dfts = dft.topModularisation(); + STORM_LOG_TRACE("Modularsation into " << dfts.size() << " submodules."); + nrK = std::static_pointer_cast const>(dft.getTopLevelGate())->threshold(); + nrM = dfts.size(); + if(nrK <= nrM/2) { + nrK -= 1; + invResults = true; + } + } + if(dfts.size() > 1) { + STORM_LOG_TRACE("Recursive CHECK Call"); + for(auto const ft : dfts) { + res.push_back(checkHelper(ft, formula, symred, allowModularisation)); + } + } + } + if(res.empty()) { + // Model based modularisation. + auto const& models = buildMarkovModels(dfts, formula, symred, enableDC); + + + for (auto const& model : models) { + // Model checking + STORM_LOG_INFO("Model checking..."); + std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); + std::unique_ptr result(storm::verifySparseModel(model, formula)); + STORM_LOG_INFO("Model checking done."); + STORM_LOG_ASSERT(result, "Result does not exist."); + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + modelCheckingTime += std::chrono::high_resolution_clock::now() - modelCheckingStart; + res.push_back(result->asExplicitQuantitativeCheckResult().getValueMap().begin()->second); + } + } + if(nrM <= 1) { + // No modularisation done. + STORM_LOG_ASSERT(res.size()==1, "Result size not 1."); + return res[0]; + } + + STORM_LOG_TRACE("Combining all results... K=" << nrK << "; M=" << nrM << "; invResults=" << (invResults?"On":"Off")); + ValueType result = storm::utility::zero(); + int limK = invResults ? -1 : nrM+1; + int chK = invResults ? -1 : 1; + for(int cK = nrK; cK != limK; cK += chK ) { + STORM_LOG_ASSERT(cK >= 0, "ck negative."); + size_t permutation = smallestIntWithNBitsSet(static_cast(cK)); + do { + STORM_LOG_TRACE("Permutation="<(); + for(size_t i = 0; i < res.size(); ++i) { + if(permutation & (1 << i)) { + permResult *= res[i]; + } else { + permResult *= storm::utility::one() - res[i]; + } + } + STORM_LOG_TRACE("Result for permutation:"<() - result; + } + return result; + } + + + std::vector>> buildMarkovModels(std::vector> const& dfts, std::shared_ptr const& formula, bool symred, bool enableDC) { + std::vector>> models; + for(auto& dft : dfts) { + std::chrono::high_resolution_clock::time_point buildingStart = std::chrono::high_resolution_clock::now(); + + std::map>> emptySymmetry; + storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); + if(symred) { + auto colouring = dft.colourDFT(); + symmetries = dft.findSymmetries(colouring); + STORM_LOG_INFO("Found " << symmetries.groups.size() << " symmetries."); + STORM_LOG_TRACE("Symmetries: " << std::endl << symmetries); + } + std::chrono::high_resolution_clock::time_point buildingEnd = std::chrono::high_resolution_clock::now(); + buildingTime += buildingEnd - buildingStart; + + // Building Markov Automaton + STORM_LOG_INFO("Building Model..."); + storm::builder::ExplicitDFTModelBuilder builder(dft, symmetries, enableDC); + typename storm::builder::ExplicitDFTModelBuilder::LabelOptions labeloptions; // TODO initialize this with the formula + std::shared_ptr> model = builder.buildModel(labeloptions); + //model->printModelInformationToStream(std::cout); + STORM_LOG_INFO("No. states (Explored): " << model->getNumberOfStates()); + STORM_LOG_INFO("No. transitions (Explored): " << model->getNumberOfTransitions()); + std::chrono::high_resolution_clock::time_point explorationEnd = std::chrono::high_resolution_clock::now(); + explorationTime += explorationEnd -buildingEnd; + + // Bisimulation + if (model->isOfType(storm::models::ModelType::Ctmc) && storm::settings::getModule().isBisimulationSet()) { + STORM_LOG_INFO("Bisimulation..."); + model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), {formula}, storm::storage::BisimulationType::Weak)->template as>(); + //model->printModelInformationToStream(std::cout); + } + STORM_LOG_INFO("No. states (Bisimulation): " << model->getNumberOfStates()); + STORM_LOG_INFO("No. transitions (Bisimulation): " << model->getNumberOfTransitions()); + bisimulationTime += std::chrono::high_resolution_clock::now() - explorationEnd; + models.push_back(model); + } + return models; + } + +public: + void printTimings(std::ostream& os = std::cout) { + os << "Times:" << std::endl; + os << "Building:\t" << buildingTime.count() << std::endl; + os << "Exploration:\t" << explorationTime.count() << std::endl; + os << "Bisimulation:\t" << bisimulationTime.count() << std::endl; + os << "Modelchecking:\t" << modelCheckingTime.count() << std::endl; + os << "Total:\t\t" << totalTime.count() << std::endl; + } + + void printResult(std::ostream& os = std::cout) { + + os << "Result: ["; + os << checkResult << "]" << std::endl; + } + +}; diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp index 7a85682df..8356620c1 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -34,7 +34,7 @@ namespace storm { template bool SparseCtmcCslModelChecker::canHandle(CheckTask const& checkTask) const { storm::logic::Formula const& formula = checkTask.getFormula(); - return formula.isInFragment(storm::logic::csrl().setGloballyFormulasAllowed(false).setLongRunAverageRewardFormulasAllowed(false).setLongRunAverageProbabilitiesAllowed(true)); + return formula.isInFragment(storm::logic::csrl().setGloballyFormulasAllowed(false).setLongRunAverageRewardFormulasAllowed(false).setLongRunAverageProbabilitiesAllowed(true).setTimeAllowed(true)); } template @@ -111,10 +111,20 @@ namespace storm { storm::storage::SparseMatrix probabilityMatrix = storm::modelchecker::helper::SparseCtmcCslHelper::computeProbabilityMatrix(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(probabilityMatrix, subResult.getTruthValuesVector(), &this->getModel().getExitRateVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); - } - + } + + template + std::unique_ptr SparseCtmcCslModelChecker::computeReachabilityTimes(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) { + storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); + std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); + ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), this->getModel().getInitialStates(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); + return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); + } + // Explicitly instantiate the model checker. template class SparseCtmcCslModelChecker>; } // namespace modelchecker -} // namespace storm \ No newline at end of file +} // namespace storm diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.h b/src/modelchecker/csl/SparseCtmcCslModelChecker.h index f6cee6ae4..802841dee 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.h +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.h @@ -28,6 +28,7 @@ namespace storm { virtual std::unique_ptr computeInstantaneousRewards(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; virtual std::unique_ptr computeReachabilityRewards(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityTimes(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; private: // An object that is used for solving linear equations and performing matrix-vector multiplication. diff --git a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index 7cd7e12ac..ab3e8f32f 100644 --- a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -45,7 +45,6 @@ namespace storm { STORM_LOG_THROW(this->getModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute time-bounded reachability probabilities in non-closed Markov automaton."); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - double lowerBound = 0; double upperBound = 0; if (!pathFormula.hasDiscreteTimeBound()) { @@ -111,4 +110,4 @@ namespace storm { template class SparseMarkovAutomatonCslModelChecker>; } -} \ No newline at end of file +} diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index a4724da46..b4c01d13a 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -1,6 +1,7 @@ #include "src/modelchecker/csl/helper/SparseCtmcCslHelper.h" #include "src/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h" +#include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h" #include "src/models/sparse/StandardRewardModel.h" @@ -11,6 +12,8 @@ #include "src/storage/StronglyConnectedComponentDecomposition.h" +#include "src/adapters/CarlAdapter.h" + #include "src/utility/macros.h" #include "src/utility/vector.h" #include "src/utility/graph.h" @@ -192,6 +195,12 @@ namespace storm { return SparseDtmcPrctlHelper::computeUntilProbabilities(computeProbabilityMatrix(rateMatrix, exitRateVector), backwardTransitions, phiStates, psiStates, qualitative, linearEquationSolverFactory); } + template + std::vector SparseCtmcCslHelper::computeUntilProbabilitiesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative) { + // Use "normal" function again, if RationalFunction finally is supported. + return storm::modelchecker::SparseDtmcEliminationModelChecker>::computeUntilProbabilities(computeProbabilityMatrix(rateMatrix, exitRateVector), backwardTransitions, initialStates, phiStates, psiStates, false); + } + template std::vector SparseCtmcCslHelper::computeNextProbabilities(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { return SparseDtmcPrctlHelper::computeNextProbabilities(computeProbabilityMatrix(rateMatrix, exitRateVector), nextStates, linearEquationSolverFactory); @@ -236,7 +245,7 @@ namespace storm { } // Use Fox-Glynn to get the truncation points and the weights. - std::tuple> foxGlynnResult = storm::utility::numerical::getFoxGlynnCutoff(lambda, 1e-300, 1e+300, storm::settings::generalSettings().getPrecision() / 8.0); + std::tuple> foxGlynnResult = storm::utility::numerical::getFoxGlynnCutoff(lambda, 1e-300, 1e+300, storm::settings::getModule().getPrecision() / 8.0); STORM_LOG_DEBUG("Fox-Glynn cutoff points: left=" << std::get<0>(foxGlynnResult) << ", right=" << std::get<1>(foxGlynnResult)); // Scale the weights so they add up to one. @@ -645,12 +654,58 @@ namespace storm { return result; } + + template + std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + // Compute expected time on CTMC by reduction to DTMC with rewards. + storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); + + // Initialize rewards. + std::vector totalRewardVector; + for (size_t i = 0; i < exitRateVector.size(); ++i) { + if (targetStates[i] || storm::utility::isZero(exitRateVector[i])) { + // Set reward for target states or states without outgoing transitions to 0. + totalRewardVector.push_back(storm::utility::zero()); + } else { + // Reward is (1 / exitRate). + totalRewardVector.push_back(storm::utility::one() / exitRateVector[i]); + } + } + + return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); + } + + template + std::vector SparseCtmcCslHelper::computeReachabilityTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative) { + // Use "normal" function again, if RationalFunction finally is supported. + // Compute expected time on CTMC by reduction to DTMC with rewards. + storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); + + // Initialize rewards. + std::vector totalRewardVector; + for (size_t i = 0; i < exitRateVector.size(); ++i) { + if (targetStates[i] || storm::utility::isZero(exitRateVector[i])) { + // Set reward for target states or states without outgoing transitions to 0. + totalRewardVector.push_back(storm::utility::zero()); + } else { + // Reward is (1 / exitRate). + totalRewardVector.push_back(storm::utility::one() / exitRateVector[i]); + } + } + + return storm::modelchecker::SparseDtmcEliminationModelChecker>::computeReachabilityRewards(probabilityMatrix, backwardTransitions, initialStates, targetStates, totalRewardVector, false); + } + template class SparseCtmcCslHelper; template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); +#ifdef STORM_HAVE_CARL + template std::vector SparseCtmcCslHelper::computeUntilProbabilitiesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); + template std::vector SparseCtmcCslHelper::computeReachabilityTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative); +#endif } } -} \ No newline at end of file +} diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h index fb4f7e74f..2b4dd6043 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h @@ -16,6 +16,7 @@ namespace storm { static std::vector computeNextProbabilities(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); static std::vector computeUntilProbabilities(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeUntilProbabilitiesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); template static std::vector computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); @@ -28,6 +29,9 @@ namespace storm { static std::vector computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeReachabilityTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative); + /*! * Computes the matrix representing the transitions of the uniformized CTMC. * @@ -78,4 +82,4 @@ namespace storm { } } -#endif /* STORM_MODELCHECKER_SPARSE_CTMC_CSL_MODELCHECKER_HELPER_H_ */ \ No newline at end of file +#endif /* STORM_MODELCHECKER_SPARSE_CTMC_CSL_MODELCHECKER_HELPER_H_ */ diff --git a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp index 71564b929..0c55b6556 100644 --- a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp @@ -122,17 +122,17 @@ namespace storm { std::vector SparseMarkovAutomatonCslHelper::computeBoundedUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, std::pair const& boundsPair, storm::utility::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { uint_fast64_t numberOfStates = transitionMatrix.getRowGroupCount(); - + // 'Unpack' the bounds to make them more easily accessible. double lowerBound = boundsPair.first; double upperBound = boundsPair.second; - + // (1) Compute the accuracy we need to achieve the required error bound. ValueType maxExitRate = 0; for (auto value : exitRateVector) { maxExitRate = std::max(maxExitRate, value); } - ValueType delta = (2 * storm::settings::generalSettings().getPrecision()) / (upperBound * maxExitRate * maxExitRate); + ValueType delta = (2 * storm::settings::getModule().getPrecision()) / (upperBound * maxExitRate * maxExitRate); // (2) Compute the number of steps we need to make for the interval. uint_fast64_t numberOfSteps = static_cast(std::ceil((upperBound - lowerBound) / delta)); @@ -408,33 +408,35 @@ namespace storm { infinityStates = storm::storage::BitVector(numberOfStates); } } - // Now we identify the states for which values need to be computed. storm::storage::BitVector maybeStates = ~(goalStates | infinityStates); - - // Then, we can eliminate the rows and columns for all states whose values are already known to be 0. - std::vector x(maybeStates.getNumberOfSetBits()); - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates); - - // Now prepare the expected reward values for all states so they can be used as the right-hand side of the equation system. - std::vector rewardValues(stateRewards); - for (auto state : markovianStates) { - rewardValues[state] = rewardValues[state] / exitRateVector[state]; - } - - // Finally, prepare the actual right-hand side. - std::vector b(submatrix.getRowCount()); - storm::utility::vector::selectVectorValuesRepeatedly(b, maybeStates, transitionMatrix.getRowGroupIndices(), rewardValues); - - // Solve the corresponding system of equations. - std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(submatrix); - solver->solveEquationSystem(dir, x, b); - + // Create resulting vector. std::vector result(numberOfStates); - // Set values of resulting vector according to previous result and return the result. - storm::utility::vector::setVectorValues(result, maybeStates, x); + if (!maybeStates.empty()) { + // Then, we can eliminate the rows and columns for all states whose values are already known. + std::vector x(maybeStates.getNumberOfSetBits()); + storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates); + + // Now prepare the expected reward values for all states so they can be used as the right-hand side of the equation system. + std::vector rewardValues(stateRewards); + for (auto state : markovianStates) { + rewardValues[state] = rewardValues[state] / exitRateVector[state]; + } + + // Finally, prepare the actual right-hand side. + std::vector b(submatrix.getRowCount()); + storm::utility::vector::selectVectorValuesRepeatedly(b, maybeStates, transitionMatrix.getRowGroupIndices(), rewardValues); + + // Solve the corresponding system of equations. + std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(submatrix); + solver->solveEquationSystem(dir, x, b); + + // Set values of resulting vector according to previous result and return the result. + storm::utility::vector::setVectorValues(result, maybeStates, x); + } + storm::utility::vector::setVectorValues(result, goalStates, storm::utility::zero()); storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::infinity()); @@ -508,4 +510,4 @@ namespace storm { } } -} \ No newline at end of file +} diff --git a/src/modelchecker/exploration/ExplorationInformation.cpp b/src/modelchecker/exploration/ExplorationInformation.cpp index 756fd57d9..0e63f4dcc 100644 --- a/src/modelchecker/exploration/ExplorationInformation.cpp +++ b/src/modelchecker/exploration/ExplorationInformation.cpp @@ -12,7 +12,7 @@ namespace storm { template ExplorationInformation::ExplorationInformation(storm::OptimizationDirection const& direction, ActionType const& unexploredMarker) : unexploredMarker(unexploredMarker), optimizationDirection(direction), localPrecomputation(false), numberOfExplorationStepsUntilPrecomputation(100000), numberOfSampledPathsUntilPrecomputation(), nextStateHeuristic(storm::settings::modules::ExplorationSettings::NextStateHeuristic::DifferenceProbabilitySum) { - storm::settings::modules::ExplorationSettings const& settings = storm::settings::explorationSettings(); + storm::settings::modules::ExplorationSettings const& settings = storm::settings::getModule(); localPrecomputation = settings.isLocalPrecomputationSet(); numberOfExplorationStepsUntilPrecomputation = settings.getNumberOfExplorationStepsUntilPrecomputation(); if (settings.isNumberOfSampledPathsUntilPrecomputationSet()) { @@ -224,4 +224,4 @@ namespace storm { template class ExplorationInformation; } } -} \ No newline at end of file +} diff --git a/src/modelchecker/exploration/SparseExplorationModelChecker.cpp b/src/modelchecker/exploration/SparseExplorationModelChecker.cpp index 322af7999..580097119 100644 --- a/src/modelchecker/exploration/SparseExplorationModelChecker.cpp +++ b/src/modelchecker/exploration/SparseExplorationModelChecker.cpp @@ -19,7 +19,8 @@ #include "src/models/sparse/StandardRewardModel.h" #include "src/settings/SettingsManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" +#include "src/settings/modules/ExplorationSettings.h" #include "src/utility/macros.h" #include "src/utility/constants.h" @@ -34,7 +35,7 @@ namespace storm { namespace modelchecker { template - SparseExplorationModelChecker::SparseExplorationModelChecker(storm::prism::Program const& program, boost::optional> const& constantDefinitions) : program(storm::utility::prism::preprocessProgram(program, constantDefinitions)), variableInformation(this->program), randomGenerator(std::chrono::system_clock::now().time_since_epoch().count()), comparator(storm::settings::explorationSettings().getPrecision()) { + SparseExplorationModelChecker::SparseExplorationModelChecker(storm::prism::Program const& program, boost::optional> const& constantDefinitions) : program(storm::utility::prism::preprocessProgram(program, constantDefinitions)), variableInformation(this->program), randomGenerator(std::chrono::system_clock::now().time_since_epoch().count()), comparator(storm::settings::getModule().getPrecision()) { // Intentionally left empty. } @@ -112,7 +113,7 @@ namespace storm { } // Show statistics if required. - if (storm::settings::generalSettings().isShowStatisticsSet()) { + if (storm::settings::getModule().isShowStatisticsSet()) { stats.printToStream(std::cout, explorationInformation); } @@ -684,4 +685,4 @@ namespace storm { template class SparseExplorationModelChecker; } -} \ No newline at end of file +} diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index dcde3c480..5a6045f66 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -7,7 +7,7 @@ #include "src/adapters/CarlAdapter.h" #include "src/settings/modules/SparseDtmcEliminationModelCheckerSettings.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/settings/SettingsManager.h" #include "src/storage/StronglyConnectedComponentDecomposition.h" @@ -27,6 +27,10 @@ #include "src/exceptions/InvalidSettingsException.h" #include "src/exceptions/IllegalArgumentException.h" +#include "src/solver/stateelimination/LongRunAverageEliminator.h" +#include "src/solver/stateelimination/ConditionalEliminator.h" +#include "src/solver/stateelimination/PrioritizedEliminator.h" + namespace storm { namespace modelchecker { @@ -221,15 +225,15 @@ namespace storm { std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now(); // Then, we convert the reduced matrix to a more flexible format to be able to perform state elimination more easily. - FlexibleSparseMatrix flexibleMatrix = getFlexibleSparseMatrix(transitionMatrix); - flexibleMatrix.filter(maybeStates, maybeStates); - FlexibleSparseMatrix flexibleBackwardTransitions = getFlexibleSparseMatrix(backwardTransitions); - flexibleBackwardTransitions.filter(maybeStates, maybeStates); + storm::storage::FlexibleSparseMatrix flexibleMatrix(transitionMatrix); + flexibleMatrix.createSubmatrix(maybeStates, maybeStates); + storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(backwardTransitions); + flexibleBackwardTransitions.createSubmatrix(maybeStates, maybeStates); auto conversionEnd = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); - storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationOrder(); + storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule().getEliminationOrder(); boost::optional> distanceBasedPriorities; if (eliminationOrderNeedsDistances(order)) { distanceBasedPriorities = getDistanceBasedPriorities(transitionMatrix, backwardTransitions, initialStates, stateValues, @@ -261,30 +265,15 @@ namespace storm { std::vector averageTimeInStates(stateValues.size(), storm::utility::one()); // First, we eliminate all states in BSCCs (except for the representative states). - { - std::unique_ptr priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs); - - ValueUpdateCallback valueUpdateCallback = [&stateValues,&averageTimeInStates] (storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { - stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]); - averageTimeInStates[state] = storm::utility::simplify(loopProbability * averageTimeInStates[state]); - }; - - PredecessorUpdateCallback predecessorCallback = [&stateValues,&averageTimeInStates] (storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { - stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state])); - averageTimeInStates[predecessor] = storm::utility::simplify(averageTimeInStates[predecessor] + storm::utility::simplify(probability * averageTimeInStates[state])); - }; - - boost::optional priorityUpdateCallback = PriorityUpdateCallback([&flexibleMatrix,&flexibleBackwardTransitions,&stateValues,&priorityQueue] (storm::storage::sparse::state_type const& state) { - priorityQueue->update(state, flexibleMatrix, flexibleBackwardTransitions, stateValues); - }); - - boost::optional predecessorFilterCallback = boost::none; - - while (priorityQueue->hasNextState()) { - storm::storage::sparse::state_type state = priorityQueue->popNextState(); - eliminateState(state, flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorCallback, priorityUpdateCallback, predecessorFilterCallback, true); - STORM_LOG_ASSERT(checkConsistent(flexibleMatrix, flexibleBackwardTransitions), "The forward and backward transition matrices became inconsistent."); - } + std::shared_ptr> priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs); + storm::solver::stateelimination::LongRunAverageEliminator stateEliminator(flexibleMatrix, flexibleBackwardTransitions, priorityQueue, stateValues, averageTimeInStates); + + while (priorityQueue->hasNextState()) { + storm::storage::sparse::state_type state = priorityQueue->popNextState(); + stateEliminator.eliminateState(state, true); +#ifdef STORM_DEV + STORM_LOG_ASSERT(checkConsistent(flexibleMatrix, flexibleBackwardTransitions), "The forward and backward transition matrices became inconsistent."); +#endif } // Now, we set the values of all states in BSCCs to that of the representative value (and clear the @@ -306,11 +295,11 @@ namespace storm { stateValues[*representativeIt] = bsccValue; } - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::row_type& representativeForwardRow = flexibleMatrix.getRow(*representativeIt); + FlexibleRowType& representativeForwardRow = flexibleMatrix.getRow(*representativeIt); representativeForwardRow.clear(); representativeForwardRow.shrink_to_fit(); - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::row_type& representativeBackwardRow = flexibleBackwardTransitions.getRow(*representativeIt); + FlexibleRowType& representativeBackwardRow = flexibleBackwardTransitions.getRow(*representativeIt); auto it = representativeBackwardRow.begin(), ite = representativeBackwardRow.end(); for (; it != ite; ++it) { if (it->getColumn() == *representativeIt) { @@ -343,7 +332,7 @@ namespace storm { std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point totalTimeEnd = std::chrono::high_resolution_clock::now(); - if (storm::settings::generalSettings().isShowStatisticsSet()) { + if (storm::settings::getModule().isShowStatisticsSet()) { std::chrono::high_resolution_clock::duration sccDecompositionTime = sccDecompositionEnd - sccDecompositionStart; std::chrono::milliseconds sccDecompositionTimeInMilliseconds = std::chrono::duration_cast(sccDecompositionTime); std::chrono::high_resolution_clock::duration conversionTime = conversionEnd - conversionStart; @@ -482,46 +471,56 @@ namespace storm { std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - + + std::vector result = computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, checkTask.isOnlyInitialStatesRelevantSet()); + + // Construct check result. + std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); + return checkResult; + } + + template + std::vector SparseDtmcEliminationModelChecker::computeUntilProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool computeForInitialStatesOnly) { + // Then, compute the subset of states that has a probability of 0 or 1, respectively. - std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->getModel(), phiStates, psiStates); + std::pair statesWithProbability01 = storm::utility::graph::performProb01(backwardTransitions, phiStates, psiStates); storm::storage::BitVector statesWithProbability0 = statesWithProbability01.first; storm::storage::BitVector statesWithProbability1 = statesWithProbability01.second; storm::storage::BitVector maybeStates = ~(statesWithProbability0 | statesWithProbability1); // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (checkTask.isOnlyInitialStatesRelevantSet() && this->getModel().getInitialStates().isDisjointFrom(maybeStates)) { + if (computeForInitialStatesOnly && initialStates.isDisjointFrom(maybeStates)) { STORM_LOG_DEBUG("The probability for all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } else if (maybeStates.empty()) { STORM_LOG_DEBUG("The probability for all states was found in a preprocessing step."); furtherComputationNeeded = false; } - + std::vector result(maybeStates.size()); if (furtherComputationNeeded) { // If we compute the results for the initial states only, we can cut off all maybe state that are not // reachable from them. - if (checkTask.isOnlyInitialStatesRelevantSet()) { + if (computeForInitialStatesOnly) { // Determine the set of states that is reachable from the initial state without jumping over a target state. - storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), maybeStates, statesWithProbability1); + storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(probabilityMatrix, initialStates, maybeStates, statesWithProbability1); // Subtract from the maybe states the set of states that is not reachable (on a path from the initial to a target state). maybeStates &= reachableStates; } - + // Create a vector for the probabilities to go to a state with probability 1 in one step. - std::vector oneStepProbabilities = this->getModel().getTransitionMatrix().getConstrainedRowSumVector(maybeStates, statesWithProbability1); - + std::vector oneStepProbabilities = probabilityMatrix.getConstrainedRowSumVector(maybeStates, statesWithProbability1); + // Determine the set of initial states of the sub-model. - storm::storage::BitVector newInitialStates = this->getModel().getInitialStates() % maybeStates; - + storm::storage::BitVector newInitialStates = initialStates % maybeStates; + // We then build the submatrix that only has the transitions of the maybe states. - storm::storage::SparseMatrix submatrix = this->getModel().getTransitionMatrix().getSubmatrix(false, maybeStates, maybeStates); + storm::storage::SparseMatrix submatrix = probabilityMatrix.getSubmatrix(false, maybeStates, maybeStates); storm::storage::SparseMatrix submatrixTransposed = submatrix.transpose(); - - std::vector subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates, checkTask.isOnlyInitialStatesRelevantSet(), phiStates, psiStates, oneStepProbabilities); + + std::vector subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates, computeForInitialStatesOnly, phiStates, psiStates, oneStepProbabilities); storm::utility::vector::setVectorValues(result, maybeStates, subresult); } @@ -529,14 +528,12 @@ namespace storm { storm::utility::vector::setVectorValues(result, statesWithProbability0, storm::utility::zero()); storm::utility::vector::setVectorValues(result, statesWithProbability1, storm::utility::one()); - // Construct check result based on whether we have computed values for all states or just the initial states. - std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (checkTask.isOnlyInitialStatesRelevantSet()) { + if (computeForInitialStatesOnly) { // If we computed the results for the initial (and prob 0 and prob1) states only, we need to filter the // result to only communicate these results. - checkResult->filter(ExplicitQualitativeCheckResult(~maybeStates | this->getModel().getInitialStates())); + result = storm::utility::vector::filterVector(result, ~maybeStates | initialStates); } - return checkResult; + return result; } template @@ -545,27 +542,54 @@ namespace storm { // Retrieve the appropriate bitvectors by model checking the subformulas. std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); - storm::storage::BitVector phiStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); + storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Do some sanity checks to establish some required properties. RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); + STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException, "Input model does not have a reward model."); + std::vector result = computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), targetStates, + [&] (uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates); + }, + checkTask.isOnlyInitialStatesRelevantSet()); + + // Construct check result. + std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); + return checkResult; + } + + template + std::vector SparseDtmcEliminationModelChecker::computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector& stateRewardValues, bool computeForInitialStatesOnly) { + return computeReachabilityRewards(probabilityMatrix, backwardTransitions, initialStates, targetStates, + [&] (uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + std::vector result(numberOfRows); + storm::utility::vector::selectVectorValues(result, maybeStates, stateRewardValues); + return result; + }, + computeForInitialStatesOnly); + } + + template + std::vector SparseDtmcEliminationModelChecker::computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, bool computeForInitialStatesOnly) { + + uint_fast64_t numberOfStates = probabilityMatrix.getRowCount(); - // Then, compute the subset of states that has a reachability reward less than infinity. - storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(this->getModel().getBackwardTransitions(), trueStates, psiStates); + // Compute the subset of states that has a reachability reward less than infinity. + storm::storage::BitVector trueStates(numberOfStates, true); + storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(backwardTransitions, trueStates, targetStates); infinityStates.complement(); - storm::storage::BitVector maybeStates = ~psiStates & ~infinityStates; + storm::storage::BitVector maybeStates = ~targetStates & ~infinityStates; // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (checkTask.isOnlyInitialStatesRelevantSet()) { - if (this->getModel().getInitialStates().isSubsetOf(infinityStates)) { + if (computeForInitialStatesOnly) { + if (initialStates.isSubsetOf(infinityStates)) { STORM_LOG_DEBUG("The reward of all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } - if (this->getModel().getInitialStates().isSubsetOf(psiStates)) { + if (initialStates.isSubsetOf(targetStates)) { STORM_LOG_DEBUG("The reward of all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } @@ -575,40 +599,37 @@ namespace storm { if (furtherComputationNeeded) { // If we compute the results for the initial states only, we can cut off all maybe state that are not // reachable from them. - if (checkTask.isOnlyInitialStatesRelevantSet()) { + if (computeForInitialStatesOnly) { // Determine the set of states that is reachable from the initial state without jumping over a target state. - storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), maybeStates, psiStates); + storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(probabilityMatrix, initialStates, maybeStates, targetStates); // Subtract from the maybe states the set of states that is not reachable (on a path from the initial to a target state). maybeStates &= reachableStates; } // Determine the set of initial states of the sub-model. - storm::storage::BitVector newInitialStates = this->getModel().getInitialStates() % maybeStates; + storm::storage::BitVector newInitialStates = initialStates % maybeStates; // We then build the submatrix that only has the transitions of the maybe states. - storm::storage::SparseMatrix submatrix = this->getModel().getTransitionMatrix().getSubmatrix(false, maybeStates, maybeStates); + storm::storage::SparseMatrix submatrix = probabilityMatrix.getSubmatrix(false, maybeStates, maybeStates); storm::storage::SparseMatrix submatrixTransposed = submatrix.transpose(); // Project the state reward vector to all maybe-states. - std::vector stateRewardValues = rewardModel.getTotalRewardVector(maybeStates.getNumberOfSetBits(), this->getModel().getTransitionMatrix(), maybeStates); + std::vector stateRewardValues = totalStateRewardVectorGetter(submatrix.getRowCount(), probabilityMatrix, maybeStates); - std::vector subresult = computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, checkTask.isOnlyInitialStatesRelevantSet(), phiStates, psiStates, this->getModel().getTransitionMatrix().getConstrainedRowSumVector(maybeStates, psiStates)); + std::vector subresult = computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly, trueStates, targetStates, probabilityMatrix.getConstrainedRowSumVector(maybeStates, targetStates)); storm::utility::vector::setVectorValues(result, maybeStates, subresult); } // Construct full result. storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::infinity()); - storm::utility::vector::setVectorValues(result, psiStates, storm::utility::zero()); - - // Construct check result based on whether we have computed values for all states or just the initial states. - std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (checkTask.isOnlyInitialStatesRelevantSet()) { + storm::utility::vector::setVectorValues(result, targetStates, storm::utility::zero()); + if (computeForInitialStatesOnly) { // If we computed the results for the initial (and inf) states only, we need to filter the result to // only communicate these results. - checkResult->filter(ExplicitQualitativeCheckResult(~maybeStates | this->getModel().getInitialStates())); + result = storm::utility::vector::filterVector(result, ~maybeStates | initialStates); } - return checkResult; + return result; } template @@ -626,7 +647,7 @@ namespace storm { storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); // Do some sanity checks to establish some required properties. - // STORM_LOG_WARN_COND(storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::State, "The chosen elimination method is not available for computing conditional probabilities. Falling back to regular state elimination."); + // STORM_LOG_WARN_COND(storm::settings::getModule().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::State, "The chosen elimination method is not available for computing conditional probabilities. Falling back to regular state elimination."); STORM_LOG_THROW(this->getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException, "Input model is required to have exactly one initial state."); STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::IllegalArgumentException, "Cannot compute conditional probabilities for all states."); storm::storage::sparse::state_type initialState = *this->getModel().getInitialStates().begin(); @@ -687,28 +708,28 @@ namespace storm { // Before starting the model checking process, we assign priorities to states so we can use them to // impose ordering constraints later. boost::optional> distanceBasedPriorities; - storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationOrder(); + storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule().getEliminationOrder(); if (eliminationOrderNeedsDistances(order)) { distanceBasedPriorities = getDistanceBasedPriorities(submatrix, submatrixTransposed, newInitialStates, oneStepProbabilities, eliminationOrderNeedsForwardDistances(order), eliminationOrderNeedsReversedDistances(order)); } - FlexibleSparseMatrix flexibleMatrix = getFlexibleSparseMatrix(submatrix); - FlexibleSparseMatrix flexibleBackwardTransitions = getFlexibleSparseMatrix(submatrixTransposed, true); + storm::storage::FlexibleSparseMatrix flexibleMatrix(submatrix); + storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(submatrixTransposed, true); - std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); + std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); + + STORM_LOG_INFO("Computing conditional probilities." << std::endl); + uint_fast64_t numberOfStatesToEliminate = statePriorities->size(); + STORM_LOG_INFO("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl); performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->getModel().getInitialStates(), true); - // Prepare some callbacks for the elimination procedure. - ValueUpdateCallback valueUpdateCallback = [&oneStepProbabilities] (storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { oneStepProbabilities[state] = storm::utility::simplify(loopProbability * oneStepProbabilities[state]); }; - PredecessorUpdateCallback predecessorUpdateCallback = [&oneStepProbabilities] (storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { oneStepProbabilities[predecessor] = storm::utility::simplify(oneStepProbabilities[predecessor] * storm::utility::simplify(probability * oneStepProbabilities[state])); }; - boost::optional phiFilterCallback = PredecessorFilterCallback([&phiStates] (storm::storage::sparse::state_type const& state) { return phiStates.get(state); }); - boost::optional psiFilterCallback = PredecessorFilterCallback([&psiStates] (storm::storage::sparse::state_type const& state) { return psiStates.get(state); }); + storm::solver::stateelimination::ConditionalEliminator stateEliminator = storm::solver::stateelimination::ConditionalEliminator(flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, phiStates, psiStates); // Eliminate the transitions going into the initial state (if there are any). if (!flexibleBackwardTransitions.getRow(*newInitialStates.begin()).empty()) { - eliminateState(*newInitialStates.begin(), flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorUpdateCallback, boost::none, boost::none, false); + stateEliminator.eliminateState(*newInitialStates.begin(), false); } // Now we need to basically eliminate all chains of not-psi states after phi states and chains of not-phi @@ -739,11 +760,13 @@ namespace storm { for (auto const& element : currentRow) { // If any of the successors is a phi state, we eliminate it (wrt. all its phi predecessors). if (!psiStates.get(element.getColumn())) { - typename FlexibleSparseMatrix::row_type const& successorRow = flexibleMatrix.getRow(element.getColumn()); + FlexibleRowType const& successorRow = flexibleMatrix.getRow(element.getColumn()); // Eliminate the successor only if there possibly is a psi state reachable through it. if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) { STORM_LOG_TRACE("Found non-psi successor " << element.getColumn() << " that needs to be eliminated."); - eliminateState(element.getColumn(), flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorUpdateCallback, boost::none, phiFilterCallback, false); + stateEliminator.setStatePhi(); + stateEliminator.eliminateState(element.getColumn(), false); + stateEliminator.clearState(); hasNonPsiSuccessor = true; } } @@ -769,10 +792,12 @@ namespace storm { for (auto const& element : currentRow) { // If any of the successors is a psi state, we eliminate it (wrt. all its psi predecessors). if (!phiStates.get(element.getColumn())) { - typename FlexibleSparseMatrix::row_type const& successorRow = flexibleMatrix.getRow(element.getColumn()); + FlexibleRowType const& successorRow = flexibleMatrix.getRow(element.getColumn()); if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) { STORM_LOG_TRACE("Found non-phi successor " << element.getColumn() << " that needs to be eliminated."); - eliminateState(element.getColumn(), flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorUpdateCallback, boost::none, psiFilterCallback, false); + stateEliminator.setStatePsi(); + stateEliminator.eliminateState(element.getColumn(), false); + stateEliminator.clearState(); hasNonPhiSuccessor = true; } } @@ -819,12 +844,12 @@ namespace storm { } template - std::unique_ptr::StatePriorityQueue> SparseDtmcEliminationModelChecker::createStatePriorityQueue(boost::optional> const& distanceBasedStatePriorities, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states) { + std::shared_ptr> SparseDtmcEliminationModelChecker::createStatePriorityQueue(boost::optional> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states) { STORM_LOG_TRACE("Creating state priority queue for states " << states); // Get the settings to customize the priority queue. - storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationOrder(); + storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule().getEliminationOrder(); std::vector sortedStates(states.begin(), states.end()); @@ -859,37 +884,36 @@ namespace storm { } } } - STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Illlegal elimination order selected."); + STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Illegal elimination order selected."); } template - std::unique_ptr::StatePriorityQueue> SparseDtmcEliminationModelChecker::createNaivePriorityQueue(storm::storage::BitVector const& states) { + std::shared_ptr> SparseDtmcEliminationModelChecker::createNaivePriorityQueue(storm::storage::BitVector const& states) { std::vector sortedStates(states.begin(), states.end()); - return std::unique_ptr(new StaticStatePriorityQueue(sortedStates)); + return std::shared_ptr>(new StaticStatePriorityQueue(sortedStates)); } template - void SparseDtmcEliminationModelChecker::performPrioritizedStateElimination(std::unique_ptr& priorityQueue, FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) { + void SparseDtmcEliminationModelChecker::performPrioritizedStateElimination(std::shared_ptr>& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) { - ValueUpdateCallback valueUpdateCallback = [&values] (storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { values[state] = storm::utility::simplify(loopProbability * values[state]); }; - PredecessorUpdateCallback predecessorCallback = [&values] (storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { values[predecessor] = storm::utility::simplify(values[predecessor] + storm::utility::simplify(probability * values[state])); }; - boost::optional priorityUpdateCallback = PriorityUpdateCallback([&transitionMatrix,&backwardTransitions,&values,&priorityQueue] (storm::storage::sparse::state_type const& state) { priorityQueue->update(state, transitionMatrix, backwardTransitions, values); }); - boost::optional predecessorFilterCallback = boost::none; + storm::solver::stateelimination::PrioritizedEliminator stateEliminator(transitionMatrix, backwardTransitions, priorityQueue, values); while (priorityQueue->hasNextState()) { storm::storage::sparse::state_type state = priorityQueue->popNextState(); bool removeForwardTransitions = computeResultsForInitialStatesOnly && !initialStates.get(state); - eliminateState(state, transitionMatrix, backwardTransitions, valueUpdateCallback, predecessorCallback, priorityUpdateCallback, predecessorFilterCallback, removeForwardTransitions); + stateEliminator.eliminateState(state, removeForwardTransitions); if (removeForwardTransitions) { values[state] = storm::utility::zero(); } +#ifdef STORM_DEV STORM_LOG_ASSERT(checkConsistent(transitionMatrix, backwardTransitions), "The forward and backward transition matrices became inconsistent."); +#endif } } template - void SparseDtmcEliminationModelChecker::performOrdinaryStateElimination(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { - std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem); + void SparseDtmcEliminationModelChecker::performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { + std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem); std::size_t numberOfStatesToEliminate = statePriorities->size(); STORM_LOG_DEBUG("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl); @@ -898,17 +922,17 @@ namespace storm { } template - uint_fast64_t SparseDtmcEliminationModelChecker::performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { + uint_fast64_t SparseDtmcEliminationModelChecker::performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { // When using the hybrid technique, we recursively treat the SCCs up to some size. std::vector entryStateQueue; STORM_LOG_DEBUG("Eliminating " << subsystem.size() << " states using the hybrid elimination technique." << std::endl); - uint_fast64_t maximalDepth = treatScc(transitionMatrix, values, initialStates, subsystem, initialStates, forwardTransitions, backwardTransitions, false, 0, storm::settings::sparseDtmcEliminationModelCheckerSettings().getMaximalSccSize(), entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities); + uint_fast64_t maximalDepth = treatScc(transitionMatrix, values, initialStates, subsystem, initialStates, forwardTransitions, backwardTransitions, false, 0, storm::settings::getModule().getMaximalSccSize(), entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities); // If the entry states were to be eliminated last, we need to do so now. - if (storm::settings::sparseDtmcEliminationModelCheckerSettings().isEliminateEntryStatesLastSet()) { + if (storm::settings::getModule().isEliminateEntryStatesLastSet()) { STORM_LOG_DEBUG("Eliminating " << entryStateQueue.size() << " entry states as a last step."); std::vector sortedStates(entryStateQueue.begin(), entryStateQueue.end()); - std::unique_ptr queuePriorities = std::unique_ptr(new StaticStatePriorityQueue(sortedStates)); + std::shared_ptr> queuePriorities = std::shared_ptr>(new StaticStatePriorityQueue(sortedStates)); performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); } STORM_LOG_DEBUG("Eliminated " << subsystem.size() << " states." << std::endl); @@ -918,10 +942,10 @@ namespace storm { template std::vector::ValueType> SparseDtmcEliminationModelChecker::computeReachabilityValues(storm::storage::SparseMatrix const& transitionMatrix, std::vector& values, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& oneStepProbabilitiesToTarget) { // Then, we convert the reduced matrix to a more flexible format to be able to perform state elimination more easily. - FlexibleSparseMatrix flexibleMatrix = getFlexibleSparseMatrix(transitionMatrix); - FlexibleSparseMatrix flexibleBackwardTransitions = getFlexibleSparseMatrix(backwardTransitions); - - storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationOrder(); + storm::storage::FlexibleSparseMatrix flexibleMatrix(transitionMatrix); + storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(backwardTransitions); + + storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::getModule().getEliminationOrder(); boost::optional> distanceBasedPriorities; if (eliminationOrderNeedsDistances(order)) { distanceBasedPriorities = getDistanceBasedPriorities(transitionMatrix, backwardTransitions, initialStates, oneStepProbabilitiesToTarget, @@ -932,9 +956,9 @@ namespace storm { storm::storage::BitVector subsystem = storm::storage::BitVector(transitionMatrix.getRowCount(), true); uint_fast64_t maximalDepth = 0; - if (storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::State) { + if (storm::settings::getModule().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::State) { performOrdinaryStateElimination(flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates, computeResultsForInitialStatesOnly, values, distanceBasedPriorities); - } else if (storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::Hybrid) { + } else if (storm::settings::getModule().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::Hybrid) { maximalDepth = performHybridStateElimination(transitionMatrix, flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates, computeResultsForInitialStatesOnly, values, distanceBasedPriorities); } @@ -950,7 +974,7 @@ namespace storm { } template - uint_fast64_t SparseDtmcEliminationModelChecker::treatScc(FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities) { + uint_fast64_t SparseDtmcEliminationModelChecker::treatScc(storm::storage::FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities) { uint_fast64_t maximalDepth = level; // If the SCCs are large enough, we try to split them further. @@ -966,7 +990,7 @@ namespace storm { storm::storage::BitVector remainingSccs(decomposition.size(), true); // First, get rid of the trivial SCCs. - storm::storage::BitVector statesInTrivialSccs(matrix.getNumberOfRows()); + storm::storage::BitVector statesInTrivialSccs(matrix.getRowCount()); for (uint_fast64_t sccIndex = 0; sccIndex < decomposition.size(); ++sccIndex) { storm::storage::StronglyConnectedComponent const& scc = decomposition.getBlock(sccIndex); if (scc.isTrivial()) { @@ -976,7 +1000,7 @@ namespace storm { } } - std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs); + std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs); STORM_LOG_TRACE("Eliminating " << statePriorities->size() << " trivial SCCs."); performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated all trivial SCCs."); @@ -1000,13 +1024,13 @@ namespace storm { } // Recursively descend in SCC-hierarchy. - uint_fast64_t depth = treatScc(matrix, values, entryStates, newSccAsBitVector, initialStates, forwardTransitions, backwardTransitions, eliminateEntryStates || !storm::settings::sparseDtmcEliminationModelCheckerSettings().isEliminateEntryStatesLastSet(), level + 1, maximalSccSize, entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities); + uint_fast64_t depth = treatScc(matrix, values, entryStates, newSccAsBitVector, initialStates, forwardTransitions, backwardTransitions, eliminateEntryStates || !storm::settings::getModule().isEliminateEntryStatesLastSet(), level + 1, maximalSccSize, entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities); maximalDepth = std::max(maximalDepth, depth); } } else { // In this case, we perform simple state elimination in the current SCC. STORM_LOG_TRACE("SCC of size " << scc.getNumberOfSetBits() << " is small enough to be eliminated directly."); - std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates); + std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates); performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated all states of SCC."); } @@ -1014,7 +1038,7 @@ namespace storm { // Finally, eliminate the entry states (if we are required to do so). if (eliminateEntryStates) { STORM_LOG_TRACE("Finally, eliminating entry states."); - std::unique_ptr naivePriorities = createNaivePriorityQueue(entryStates); + std::shared_ptr> naivePriorities = createNaivePriorityQueue(entryStates); performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated/added entry states."); } else { @@ -1027,229 +1051,6 @@ namespace storm { return maximalDepth; } - template - void SparseDtmcEliminationModelChecker::eliminateState(storm::storage::sparse::state_type state, FlexibleSparseMatrix& matrix, FlexibleSparseMatrix& backwardTransitions, - ValueUpdateCallback const& callback, PredecessorUpdateCallback const& predecessorCallback, - boost::optional const& priorityUpdateCallback, - boost::optional const& predecessorFilterCallback, bool removeForwardTransitions) { - - STORM_LOG_TRACE("Eliminating state " << state << "."); - - // Start by finding loop probability. - bool hasSelfLoop = false; - ValueType loopProbability = storm::utility::zero(); - typename FlexibleSparseMatrix::row_type& currentStateSuccessors = matrix.getRow(state); - for (auto entryIt = currentStateSuccessors.begin(), entryIte = currentStateSuccessors.end(); entryIt != entryIte; ++entryIt) { - if (entryIt->getColumn() >= state) { - if (entryIt->getColumn() == state) { - loopProbability = entryIt->getValue(); - hasSelfLoop = true; - - // If we do not clear the forward transitions completely, we need to remove the self-loop, - // because we scale all the other outgoing transitions with it anyway. - if (!removeForwardTransitions) { - currentStateSuccessors.erase(entryIt); - } - } - break; - } - } - - // Scale all entries in this row with (1 / (1 - loopProbability)) only in case there was a self-loop. - STORM_LOG_TRACE((hasSelfLoop ? "State has self-loop." : "State does not have a self-loop.")); - if (hasSelfLoop) { - STORM_LOG_ASSERT(loopProbability != storm::utility::one(), "Must not eliminate state with probability 1 self-loop."); - loopProbability = storm::utility::simplify(storm::utility::one() / (storm::utility::one() - loopProbability)); - for (auto& entry : matrix.getRow(state)) { - // Only scale the non-diagonal entries. - if (entry.getColumn() != state) { - entry.setValue(storm::utility::simplify(entry.getValue() * loopProbability)); - } - } - callback(state, loopProbability); - } - - // Now connect the predecessors of the state being eliminated with its successors. - typename FlexibleSparseMatrix::row_type& currentStatePredecessors = backwardTransitions.getRow(state); - - // In case we have a constrained elimination, we need to keep track of the new predecessors. - typename FlexibleSparseMatrix::row_type newCurrentStatePredecessors; - - std::vector newBackwardProbabilities(currentStateSuccessors.size()); - for (auto& backwardProbabilities : newBackwardProbabilities) { - backwardProbabilities.reserve(currentStatePredecessors.size()); - } - - // Now go through the predecessors and eliminate the ones (satisfying the constraint if given). - for (auto const& predecessorEntry : currentStatePredecessors) { - uint_fast64_t predecessor = predecessorEntry.getColumn(); - STORM_LOG_TRACE("Found predecessor " << predecessor << "."); - - // Skip the state itself as one of its predecessors. - if (predecessor == state) { - assert(hasSelfLoop); - continue; - } - - // Skip the state if the elimination is constrained, but the predecessor is not in the constraint. - if (predecessorFilterCallback && !predecessorFilterCallback.get()(predecessor)) { - newCurrentStatePredecessors.emplace_back(predecessorEntry); - STORM_LOG_TRACE("Not eliminating predecessor " << predecessor << ", because it does not fit the filter."); - continue; - } - STORM_LOG_TRACE("Eliminating predecessor " << predecessor << "."); - - // First, find the probability with which the predecessor can move to the current state, because - // the forward probabilities of the state to be eliminated need to be scaled with this factor. - typename FlexibleSparseMatrix::row_type& predecessorForwardTransitions = matrix.getRow(predecessor); - typename FlexibleSparseMatrix::row_type::iterator multiplyElement = std::find_if(predecessorForwardTransitions.begin(), predecessorForwardTransitions.end(), [&](storm::storage::MatrixEntry const& a) { return a.getColumn() == state; }); - - // Make sure we have found the probability and set it to zero. - STORM_LOG_THROW(multiplyElement != predecessorForwardTransitions.end(), storm::exceptions::InvalidStateException, "No probability for successor found."); - ValueType multiplyFactor = multiplyElement->getValue(); - multiplyElement->setValue(storm::utility::zero()); - - // At this point, we need to update the (forward) transitions of the predecessor. - typename FlexibleSparseMatrix::row_type::iterator first1 = predecessorForwardTransitions.begin(); - typename FlexibleSparseMatrix::row_type::iterator last1 = predecessorForwardTransitions.end(); - typename FlexibleSparseMatrix::row_type::iterator first2 = currentStateSuccessors.begin(); - typename FlexibleSparseMatrix::row_type::iterator last2 = currentStateSuccessors.end(); - - typename FlexibleSparseMatrix::row_type newSuccessors; - newSuccessors.reserve((last1 - first1) + (last2 - first2)); - std::insert_iterator result(newSuccessors, newSuccessors.end()); - - uint_fast64_t successorOffsetInNewBackwardTransitions = 0; - // Now we merge the two successor lists. (Code taken from std::set_union and modified to suit our needs). - for (; first1 != last1; ++result) { - // Skip the transitions to the state that is currently being eliminated. - if (first1->getColumn() == state || (first2 != last2 && first2->getColumn() == state)) { - if (first1->getColumn() == state) { - ++first1; - } - if (first2 != last2 && first2->getColumn() == state) { - ++first2; - } - continue; - } - - if (first2 == last2) { - std::copy_if(first1, last1, result, [&] (storm::storage::MatrixEntry const& a) { return a.getColumn() != state; } ); - break; - } - if (first2->getColumn() < first1->getColumn()) { - auto successorEntry = storm::utility::simplify(std::move(*first2 * multiplyFactor)); - *result = successorEntry; - newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, successorEntry.getValue()); - ++first2; - ++successorOffsetInNewBackwardTransitions; - } else if (first1->getColumn() < first2->getColumn()) { - *result = *first1; - ++first1; - } else { - auto probability = storm::utility::simplify(first1->getValue() + storm::utility::simplify(multiplyFactor * first2->getValue())); - *result = storm::storage::MatrixEntry(first1->getColumn(), probability); - newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, probability); - ++first1; - ++first2; - ++successorOffsetInNewBackwardTransitions; - } - } - for (; first2 != last2; ++first2) { - if (first2->getColumn() != state) { - auto stateProbability = storm::utility::simplify(std::move(*first2 * multiplyFactor)); - *result = stateProbability; - newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, stateProbability.getValue()); - ++successorOffsetInNewBackwardTransitions; - } - } - - // Now move the new transitions in place. - predecessorForwardTransitions = std::move(newSuccessors); - STORM_LOG_TRACE("Fixed new next-state probabilities of predecessor state " << predecessor << "."); - - predecessorCallback(predecessor, multiplyFactor, state); - - if (priorityUpdateCallback) { - STORM_LOG_TRACE("Updating priority of predecessor."); - priorityUpdateCallback.get()(predecessor); - } - } - - // Finally, we need to add the predecessor to the set of predecessors of every successor. - uint_fast64_t successorOffsetInNewBackwardTransitions = 0; - for (auto const& successorEntry : currentStateSuccessors) { - if (successorEntry.getColumn() == state) { - continue; - } - - typename FlexibleSparseMatrix::row_type& successorBackwardTransitions = backwardTransitions.getRow(successorEntry.getColumn()); - - // Delete the current state as a predecessor of the successor state only if we are going to remove the - // current state's forward transitions. - if (removeForwardTransitions) { - typename FlexibleSparseMatrix::row_type::iterator elimIt = std::find_if(successorBackwardTransitions.begin(), successorBackwardTransitions.end(), [&](storm::storage::MatrixEntry const& a) { return a.getColumn() == state; }); - STORM_LOG_ASSERT(elimIt != successorBackwardTransitions.end(), "Expected a proper backward transition from " << successorEntry.getColumn() << " to " << state << ", but found none."); - successorBackwardTransitions.erase(elimIt); - } - - typename FlexibleSparseMatrix::row_type::iterator first1 = successorBackwardTransitions.begin(); - typename FlexibleSparseMatrix::row_type::iterator last1 = successorBackwardTransitions.end(); - typename FlexibleSparseMatrix::row_type::iterator first2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].begin(); - typename FlexibleSparseMatrix::row_type::iterator last2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].end(); - - typename FlexibleSparseMatrix::row_type newPredecessors; - newPredecessors.reserve((last1 - first1) + (last2 - first2)); - std::insert_iterator result(newPredecessors, newPredecessors.end()); - - for (; first1 != last1; ++result) { - if (first2 == last2) { - std::copy(first1, last1, result); - break; - } - if (first2->getColumn() < first1->getColumn()) { - if (first2->getColumn() != state) { - *result = *first2; - } - ++first2; - } else if (first1->getColumn() == first2->getColumn()) { - if (estimateComplexity(first1->getValue()) > estimateComplexity(first2->getValue())) { - *result = *first1; - } else { - *result = *first2; - } - ++first1; - ++first2; - } else { - *result = *first1; - ++first1; - } - } - if (predecessorFilterCallback) { - std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry const& a) { return a.getColumn() != state && predecessorFilterCallback.get()(a.getColumn()); }); - } else { - std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry const& a) { return a.getColumn() != state; }); - } - - // Now move the new predecessors in place. - successorBackwardTransitions = std::move(newPredecessors); - ++successorOffsetInNewBackwardTransitions; - } - STORM_LOG_TRACE("Fixed predecessor lists of successor states."); - - if (removeForwardTransitions) { - // Clear the eliminated row to reduce memory consumption. - currentStateSuccessors.clear(); - currentStateSuccessors.shrink_to_fit(); - } - if (predecessorFilterCallback) { - currentStatePredecessors = std::move(newCurrentStatePredecessors); - } else { - currentStatePredecessors.clear(); - currentStatePredecessors.shrink_to_fit(); - } - } - template std::vector SparseDtmcEliminationModelChecker::getDistanceBasedPriorities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector const& oneStepProbabilities, bool forward, bool reverse) { std::vector statePriorities(transitionMatrix.getRowCount()); @@ -1259,8 +1060,8 @@ namespace storm { } std::vector distances = getStateDistances(transitionMatrix, transitionMatrixTransposed, initialStates, oneStepProbabilities, - storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationOrder() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward || - storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationOrder() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed); + storm::settings::getModule().getEliminationOrder() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::Forward || + storm::settings::getModule().getEliminationOrder() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder::ForwardReversed); // In case of the forward or backward ordering, we can sort the states according to the distances. if (forward ^ reverse) { @@ -1298,111 +1099,7 @@ namespace storm { } template - SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::FlexibleSparseMatrix(index_type rows) : data(rows) { - // Intentionally left empty. - } - - template - void SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::reserveInRow(index_type row, index_type numberOfElements) { - this->data[row].reserve(numberOfElements); - } - - template - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::row_type& SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::getRow(index_type index) { - return this->data[index]; - } - - template - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::row_type const& SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::getRow(index_type index) const { - return this->data[index]; - } - - template - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::index_type SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::getNumberOfRows() const { - return this->data.size(); - } - - template - bool SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::hasSelfLoop(storm::storage::sparse::state_type state) { - for (auto const& entry : this->getRow(state)) { - if (entry.getColumn() < state) { - continue; - } else if (entry.getColumn() > state) { - return false; - } else if (entry.getColumn() == state) { - return true; - } - } - return false; - } - - template - void SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::print() const { - for (uint_fast64_t index = 0; index < this->data.size(); ++index) { - std::cout << index << " - "; - for (auto const& element : this->getRow(index)) { - std::cout << "(" << element.getColumn() << ", " << element.getValue() << ") "; - } - std::cout << std::endl; - } - } - - template - bool SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::empty() const { - for (auto const& row : this->data) { - if (!row.empty()) { - return false; - } - } - return true; - } - - template - void SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::filter(storm::storage::BitVector const& rowFilter, storm::storage::BitVector const& columnFilter) { - for (uint_fast64_t rowIndex = 0; rowIndex < this->data.size(); ++rowIndex) { - auto& row = this->data[rowIndex]; - if (!rowFilter.get(rowIndex)) { - row.clear(); - row.shrink_to_fit(); - continue; - } - row_type newRow; - for (auto const& element : row) { - if (columnFilter.get(element.getColumn())) { - newRow.push_back(element); - } - } - row = std::move(newRow); - } - } - - template - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix SparseDtmcEliminationModelChecker::getFlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) { - FlexibleSparseMatrix flexibleMatrix(matrix.getRowCount()); - - for (typename FlexibleSparseMatrix::index_type rowIndex = 0; rowIndex < matrix.getRowCount(); ++rowIndex) { - typename storm::storage::SparseMatrix::const_rows row = matrix.getRow(rowIndex); - flexibleMatrix.reserveInRow(rowIndex, row.getNumberOfEntries()); - - for (auto const& element : row) { - // If the probability is zero, we skip this entry. - if (storm::utility::isZero(element.getValue())) { - continue; - } - - if (setAllValuesToOne) { - flexibleMatrix.getRow(rowIndex).emplace_back(element.getColumn(), storm::utility::one()); - } else { - flexibleMatrix.getRow(rowIndex).emplace_back(element); - } - } - } - - return flexibleMatrix; - } - - template - uint_fast64_t SparseDtmcEliminationModelChecker::computeStatePenalty(storm::storage::sparse::state_type const& state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + uint_fast64_t SparseDtmcEliminationModelChecker::computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { uint_fast64_t penalty = 0; bool hasParametricSelfLoop = false; @@ -1429,17 +1126,17 @@ namespace storm { } template - uint_fast64_t SparseDtmcEliminationModelChecker::computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + uint_fast64_t SparseDtmcEliminationModelChecker::computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { return backwardTransitions.getRow(state).size() * transitionMatrix.getRow(state).size(); } - template - void SparseDtmcEliminationModelChecker::StatePriorityQueue::update(storm::storage::sparse::state_type, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + template + void StatePriorityQueue::update(storm::storage::sparse::state_type, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { // Intentionally left empty. } template - SparseDtmcEliminationModelChecker::StaticStatePriorityQueue::StaticStatePriorityQueue(std::vector const& sortedStates) : StatePriorityQueue(), sortedStates(sortedStates), currentPosition(0) { + SparseDtmcEliminationModelChecker::StaticStatePriorityQueue::StaticStatePriorityQueue(std::vector const& sortedStates) : StatePriorityQueue(), sortedStates(sortedStates), currentPosition(0) { // Intentionally left empty. } @@ -1460,7 +1157,7 @@ namespace storm { } template - SparseDtmcEliminationModelChecker::DynamicPenaltyStatePriorityQueue::DynamicPenaltyStatePriorityQueue(std::vector> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction) : StatePriorityQueue(), priorityQueue(), stateToPriorityMapping(), penaltyFunction(penaltyFunction) { + SparseDtmcEliminationModelChecker::DynamicPenaltyStatePriorityQueue::DynamicPenaltyStatePriorityQueue(std::vector> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction) : StatePriorityQueue(), priorityQueue(), stateToPriorityMapping(), penaltyFunction(penaltyFunction) { // Insert all state-penalty pairs into our priority queue. for (auto const& statePenalty : sortedStatePenaltyPairs) { priorityQueue.insert(priorityQueue.end(), statePenalty); @@ -1487,7 +1184,7 @@ namespace storm { } template - void SparseDtmcEliminationModelChecker::DynamicPenaltyStatePriorityQueue::update(storm::storage::sparse::state_type state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + void SparseDtmcEliminationModelChecker::DynamicPenaltyStatePriorityQueue::update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { // First, we need to find the priority until now. auto priorityIt = stateToPriorityMapping.find(state); @@ -1516,8 +1213,8 @@ namespace storm { } template - bool SparseDtmcEliminationModelChecker::checkConsistent(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions) { - for (uint_fast64_t forwardIndex = 0; forwardIndex < transitionMatrix.getNumberOfRows(); ++forwardIndex) { + bool SparseDtmcEliminationModelChecker::checkConsistent(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions) { + for (uint_fast64_t forwardIndex = 0; forwardIndex < transitionMatrix.getRowCount(); ++forwardIndex) { for (auto const& forwardEntry : transitionMatrix.getRow(forwardIndex)) { if (forwardEntry.getColumn() == forwardIndex) { continue; @@ -1538,9 +1235,13 @@ namespace storm { return true; } + template class StatePriorityQueue; template class SparseDtmcEliminationModelChecker>; - + template uint_fast64_t estimateComplexity(double const& value); + + #ifdef STORM_HAVE_CARL + template class StatePriorityQueue; template class SparseDtmcEliminationModelChecker>; #endif } // namespace modelchecker diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index 25b4c12d4..7359ac93f 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -2,6 +2,7 @@ #define STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCELIMINATIONMODELCHECKER_H_ #include "src/storage/sparse/StateType.h" +#include "src/storage/FlexibleSparseMatrix.h" #include "src/models/sparse/Dtmc.h" #include "src/modelchecker/propositional/SparsePropositionalModelChecker.h" #include "src/utility/constants.h" @@ -9,12 +10,26 @@ namespace storm { namespace modelchecker { + template + uint_fast64_t estimateComplexity(ValueType const& value); + + template + class StatePriorityQueue { + public: + virtual bool hasNextState() const = 0; + virtual storm::storage::sparse::state_type popNextState() = 0; + virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); + virtual std::size_t size() const = 0; + }; + template class SparseDtmcEliminationModelChecker : public SparsePropositionalModelChecker { public: typedef typename SparseDtmcModelType::ValueType ValueType; typedef typename SparseDtmcModelType::RewardModelType RewardModelType; - + typedef typename storm::storage::FlexibleSparseMatrix::row_type FlexibleRowType; + typedef typename FlexibleRowType::iterator FlexibleRowIterator; + /*! * Creates an elimination-based model checker for the given model. * @@ -30,53 +45,15 @@ namespace storm { virtual std::unique_ptr computeLongRunAverageRewards(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; virtual std::unique_ptr computeConditionalProbabilities(CheckTask const& checkTask) override; virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; + + // Static helper methods + static std::vector computeUntilProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool computeForInitialStatesOnly); + + static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector& stateRewardValues, bool computeForInitialStatesOnly); private: - class FlexibleSparseMatrix { - public: - typedef uint_fast64_t index_type; - typedef ValueType value_type; - typedef std::vector> row_type; - typedef typename row_type::iterator iterator; - typedef typename row_type::const_iterator const_iterator; - - FlexibleSparseMatrix() = default; - FlexibleSparseMatrix(index_type rows); - - void reserveInRow(index_type row, index_type numberOfElements); - - row_type& getRow(index_type); - row_type const& getRow(index_type) const; - - index_type getNumberOfRows() const; - - void print() const; - - bool empty() const; - - void filter(storm::storage::BitVector const& rowFilter, storm::storage::BitVector const& columnFilter); - - /*! - * Checks whether the given state has a self-loop with an arbitrary probability in the probability matrix. - * - * @param state The state for which to check whether it possesses a self-loop. - * @return True iff the given state has a self-loop with an arbitrary probability in the probability matrix. - */ - bool hasSelfLoop(storm::storage::sparse::state_type state); - - private: - std::vector data; - }; - class StatePriorityQueue { - public: - virtual bool hasNextState() const = 0; - virtual storm::storage::sparse::state_type popNextState() = 0; - virtual void update(storm::storage::sparse::state_type state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); - virtual std::size_t size() const = 0; - }; - - class StaticStatePriorityQueue : public StatePriorityQueue { + class StaticStatePriorityQueue : public StatePriorityQueue { public: StaticStatePriorityQueue(std::vector const& sortedStates); @@ -95,15 +72,15 @@ namespace storm { } }; - typedef std::function const& oneStepProbabilities)> PenaltyFunctionType; + typedef std::function const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities)> PenaltyFunctionType; - class DynamicPenaltyStatePriorityQueue : public StatePriorityQueue { + class DynamicPenaltyStatePriorityQueue : public StatePriorityQueue { public: DynamicPenaltyStatePriorityQueue(std::vector> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction); virtual bool hasNextState() const override; virtual storm::storage::sparse::state_type popNextState() override; - virtual void update(storm::storage::sparse::state_type state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) override; + virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) override; virtual std::size_t size() const override; private: @@ -114,40 +91,33 @@ namespace storm { static std::vector computeLongRunValues(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& maybeStates, bool computeResultsForInitialStatesOnly, std::vector& stateValues); + static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, bool computeForInitialStatesOnly); + static std::vector computeReachabilityValues(storm::storage::SparseMatrix const& transitionMatrix, std::vector& values, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& oneStepProbabilitiesToTarget); - static std::unique_ptr createStatePriorityQueue(boost::optional> const& stateDistances, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); + static std::shared_ptr> createStatePriorityQueue(boost::optional> const& stateDistances, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); - static std::unique_ptr createNaivePriorityQueue(storm::storage::BitVector const& states); + static std::shared_ptr> createNaivePriorityQueue(storm::storage::BitVector const& states); - static void performPrioritizedStateElimination(std::unique_ptr& priorityQueue, FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly); + static void performPrioritizedStateElimination(std::shared_ptr>& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly); - static void performOrdinaryStateElimination(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional>& additionalStateValues, boost::optional> const& distanceBasedPriorities); + static void performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional>& additionalStateValues, boost::optional> const& distanceBasedPriorities); - static void performOrdinaryStateElimination(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); - - static uint_fast64_t performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); + static void performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); - static uint_fast64_t treatScc(FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities = boost::none); - - static FlexibleSparseMatrix getFlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne = false); - - typedef std::function ValueUpdateCallback; - typedef std::function PredecessorUpdateCallback; - typedef std::function PriorityUpdateCallback; - typedef std::function PredecessorFilterCallback; - - static void eliminateState(storm::storage::sparse::state_type state, FlexibleSparseMatrix& matrix, FlexibleSparseMatrix& backwardTransitions, ValueUpdateCallback const& valueUpdateCallback, PredecessorUpdateCallback const& predecessorCallback, boost::optional const& priorityUpdateCallback = boost::none, boost::optional const& predecessorFilterCallback = boost::none, bool removeForwardTransitions = true); + static uint_fast64_t performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); + static uint_fast64_t treatScc(storm::storage::FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities = boost::none); + static std::vector getDistanceBasedPriorities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector const& oneStepProbabilities, bool forward, bool reverse); static std::vector getStateDistances(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector const& oneStepProbabilities, bool forward); - static uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); + static uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); - static uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); + static uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); - static bool checkConsistent(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions); + static bool checkConsistent(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions); }; diff --git a/src/models/sparse/Ctmc.cpp b/src/models/sparse/Ctmc.cpp index 62347c81b..1d07c48a9 100644 --- a/src/models/sparse/Ctmc.cpp +++ b/src/models/sparse/Ctmc.cpp @@ -24,6 +24,13 @@ namespace storm { exitRates = createExitRateVector(this->getTransitionMatrix()); } + template + Ctmc::Ctmc(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRates, storm::models::sparse::StateLabeling const& stateLabeling, + std::unordered_map const& rewardModels, + boost::optional> const& optionalChoiceLabeling) + : DeterministicModel(storm::models::ModelType::Ctmc, std::move(rateMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)), exitRates(exitRates) { + } + template std::vector const& Ctmc::getExitRateVector() const { return exitRates; diff --git a/src/models/sparse/Ctmc.h b/src/models/sparse/Ctmc.h index 716b80373..fc933ae7d 100644 --- a/src/models/sparse/Ctmc.h +++ b/src/models/sparse/Ctmc.h @@ -38,6 +38,20 @@ namespace storm { std::unordered_map&& rewardModels = std::unordered_map(), boost::optional>&& optionalChoiceLabeling = boost::optional>()); + /*! + * Constructs a model from the given data. + * + * @param rateMatrix The matrix representing the transitions in the model. + * @param exitRates The exit rates of all states. + * @param stateLabeling The labeling of the states. + * @param rewardModels A mapping of reward model names to reward models. + * @param optionalChoiceLabeling A vector that represents the labels associated with the choices of each state. + */ + Ctmc(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRates, storm::models::sparse::StateLabeling const& stateLabeling, + std::unordered_map const& rewardModels = std::unordered_map(), + boost::optional> const& optionalChoiceLabeling = boost::optional>()); + + Ctmc(Ctmc const& ctmc) = default; Ctmc& operator=(Ctmc const& ctmc) = default; diff --git a/src/models/sparse/MarkovAutomaton.cpp b/src/models/sparse/MarkovAutomaton.cpp index 993cc4aa9..b3b416cfc 100644 --- a/src/models/sparse/MarkovAutomaton.cpp +++ b/src/models/sparse/MarkovAutomaton.cpp @@ -3,6 +3,10 @@ #include "src/exceptions/InvalidArgumentException.h" #include "src/utility/constants.h" #include "src/adapters/CarlAdapter.h" +#include "src/storage/FlexibleSparseMatrix.h" +#include "src/models/sparse/Dtmc.h" +#include "src/solver/stateelimination/MAEliminator.h" +#include "src/utility/vector.h" namespace storm { namespace models { @@ -30,6 +34,19 @@ namespace storm { this->turnRatesToProbabilities(); } + template + MarkovAutomaton::MarkovAutomaton(storm::storage::SparseMatrix&& transitionMatrix, + storm::models::sparse::StateLabeling&& stateLabeling, + storm::storage::BitVector const& markovianStates, + std::vector const& exitRates, + bool probabilities, + std::unordered_map&& rewardModels, + boost::optional>&& optionalChoiceLabeling) + : NondeterministicModel(storm::models::ModelType::MarkovAutomaton, std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)), markovianStates(markovianStates), exitRates(std::move(exitRates)), closed(this->checkIsClosed()) { + assert(probabilities); + assert(this->getTransitionMatrix().isProbabilistic()); + } + template bool MarkovAutomaton::isClosed() const { return closed; @@ -220,6 +237,23 @@ namespace storm { } } + template + bool MarkovAutomaton::hasOnlyTrivialNondeterminism() const { + // Check every state + for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) { + // Get number of choices in current state + uint_fast64_t numberChoices = this->getTransitionMatrix().getRowGroupIndices()[state + 1] - this->getTransitionMatrix().getRowGroupIndices()[state]; + if (isMarkovianState(state)) { + assert(numberChoices == 1); + } + if (numberChoices > 1) { + assert(isProbabilisticState(state)); + return false; + } + } + return true; + } + template bool MarkovAutomaton::checkIsClosed() const { for (auto state : markovianStates) { @@ -230,6 +264,62 @@ namespace storm { return true; } + template + std::shared_ptr> MarkovAutomaton::convertToCTMC() { + STORM_LOG_TRACE("MA matrix:" << std::endl << this->getTransitionMatrix()); + STORM_LOG_TRACE("Markovian states: " << getMarkovianStates()); + + // Eliminate all probabilistic states by state elimination + // Initialize + storm::storage::FlexibleSparseMatrix flexibleMatrix(this->getTransitionMatrix()); + storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(this->getTransitionMatrix().transpose()); + storm::solver::stateelimination::MAEliminator> stateEliminator(flexibleMatrix, flexibleBackwardTransitions); + + for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) { + assert(!this->isHybridState(state)); + if (this->isProbabilisticState(state)) { + // Eliminate this probabilistic state + stateEliminator.eliminateState(state, true); + STORM_LOG_TRACE("Flexible matrix after eliminating state " << state << ":" << std::endl << flexibleMatrix); + } + } + + // Create the rate matrix for the CTMC + storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, false, false); + // Remember state to keep + storm::storage::BitVector keepStates(this->getNumberOfStates(), true); + for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) { + if (storm::utility::isZero(flexibleMatrix.getRowSum(state))) { + // State is eliminated and can be discarded + keepStates.set(state, false); + } else { + assert(this->isMarkovianState(state)); + // Copy transitions + for (uint_fast64_t row = flexibleMatrix.getRowGroupIndices()[state]; row < flexibleMatrix.getRowGroupIndices()[state + 1]; ++row) { + for (auto const& entry : flexibleMatrix.getRow(row)) { + // Convert probabilities into rates + transitionMatrixBuilder.addNextValue(state, entry.getColumn(), entry.getValue() * exitRates[state]); + } + } + } + } + + storm::storage::SparseMatrix rateMatrix = transitionMatrixBuilder.build(); + rateMatrix = rateMatrix.getSubmatrix(false, keepStates, keepStates, false); + STORM_LOG_TRACE("New CTMC matrix:" << std::endl << rateMatrix); + // Construct CTMC + storm::models::sparse::StateLabeling stateLabeling = this->getStateLabeling().getSubLabeling(keepStates); + boost::optional> optionalChoiceLabeling = this->getOptionalChoiceLabeling(); + if (optionalChoiceLabeling) { + optionalChoiceLabeling = storm::utility::vector::filterVector(optionalChoiceLabeling.get(), keepStates); + } + //TODO update reward models according to kept states + std::unordered_map rewardModels = this->getRewardModels(); + + return std::make_shared>(std::move(rateMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)); + } + + template class MarkovAutomaton; // template class MarkovAutomaton; @@ -241,4 +331,4 @@ namespace storm { } // namespace sparse } // namespace models -} // namespace storm \ No newline at end of file +} // namespace storm diff --git a/src/models/sparse/MarkovAutomaton.h b/src/models/sparse/MarkovAutomaton.h index 3ffb59e70..9864f4f85 100644 --- a/src/models/sparse/MarkovAutomaton.h +++ b/src/models/sparse/MarkovAutomaton.h @@ -2,6 +2,7 @@ #define STORM_MODELS_SPARSE_MARKOVAUTOMATON_H_ #include "src/models/sparse/NondeterministicModel.h" +#include "src/models/sparse/Ctmc.h" #include "src/utility/OsDetection.h" namespace storm { @@ -48,6 +49,25 @@ namespace storm { std::unordered_map&& rewardModels = std::unordered_map(), boost::optional>&& optionalChoiceLabeling = boost::optional>()); + /*! + * Constructs a model by moving the given data. + * + * @param transitionMatrix The matrix representing the transitions in the model in terms of rates. + * @param stateLabeling The labeling of the states. + * @param markovianStates A bit vector indicating the Markovian states of the automaton. + * @param exitRates A vector storing the exit rates of the states. + * @param probabilities Flag if transitions matrix contains probabilities or rates + * @param rewardModels A mapping of reward model names to reward models. + * @param optionalChoiceLabeling A vector that represents the labels associated with the choices of each state. + */ + MarkovAutomaton(storm::storage::SparseMatrix&& transitionMatrix, + storm::models::sparse::StateLabeling&& stateLabeling, + storm::storage::BitVector const& markovianStates, + std::vector const& exitRates, + bool probabilities, + std::unordered_map&& rewardModels = std::unordered_map(), + boost::optional>&& optionalChoiceLabeling = boost::optional>()); + MarkovAutomaton(MarkovAutomaton const& other) = default; MarkovAutomaton& operator=(MarkovAutomaton const& other) = default; @@ -128,6 +148,10 @@ namespace storm { */ void close(); + bool hasOnlyTrivialNondeterminism() const; + + std::shared_ptr> convertToCTMC(); + virtual void writeDotToStream(std::ostream& outStream, bool includeLabeling = true, storm::storage::BitVector const* subsystem = nullptr, std::vector const* firstValue = nullptr, std::vector const* secondValue = nullptr, std::vector const* stateColoring = nullptr, std::vector const* colors = nullptr, std::vector* scheduler = nullptr, bool finalizeOutput = true) const; std::size_t getSizeInBytes() const; diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp new file mode 100644 index 000000000..2cdda4929 --- /dev/null +++ b/src/parser/DFTGalileoParser.cpp @@ -0,0 +1,160 @@ +#include "DFTGalileoParser.h" + +#include +#include +#include +#include +#include "src/storage/expressions/ExpressionManager.h" +#include "src/exceptions/NotImplementedException.h" +#include "src/exceptions/FileIoException.h" +#include "src/exceptions/NotSupportedException.h" +#include "src/utility/macros.h" + +namespace storm { + namespace parser { + + template + storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { + readFile(filename); + storm::storage::DFT dft = builder.build(); + STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString()); + STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString()); + return dft; + } + + template + std::string DFTGalileoParser::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 + void DFTGalileoParser::readFile(const std::string& filename) { + // constants + std::string toplevelToken = "toplevel"; + std::string toplevelId; + std::string parametricToken = "param"; + + 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 ); + + std::string line; + while(std::getline(file, line)) { + bool success = true; + STORM_LOG_TRACE("Parsing: " << line); + size_t commentstarts = line.find("//"); + line = line.substr(0, commentstarts); + size_t firstsemicolon = line.find(";"); + line = line.substr(0, firstsemicolon); + if (line.find_first_not_of(' ') == std::string::npos) { + // Only whitespace + continue; + } + + // Top level indicator. + if(boost::starts_with(line, toplevelToken)) { + toplevelId = stripQuotsFromName(line.substr(toplevelToken.size() + 1)); + } + else if (boost::starts_with(line, parametricToken)) { + STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, "Parameters only allowed when using rational functions."); + std::string parameter = stripQuotsFromName(line.substr(parametricToken.size() + 1)); + storm::expressions::Variable var = manager->declareRationalVariable(parameter); + identifierMapping.emplace(var.getName(), var); + parser.setIdentifierMapping(identifierMapping); + STORM_LOG_TRACE("Added parameter: " << var.getName()); + } else { + std::vector tokens; + boost::split(tokens, line, boost::is_any_of(" ")); + std::string name(stripQuotsFromName(tokens[0])); + + std::vector childNames; + for(unsigned i = 2; i < tokens.size(); ++i) { + childNames.push_back(stripQuotsFromName(tokens[i])); + } + if(tokens[1] == "and") { + success = builder.addAndElement(name, childNames); + } else if (tokens[1] == "or") { + success = builder.addOrElement(name, childNames); + } else if (boost::starts_with(tokens[1], "vot")) { + success = builder.addVotElement(name, boost::lexical_cast(tokens[1].substr(3)), childNames); + } else if (tokens[1].find("of") != std::string::npos) { + size_t pos = tokens[1].find("of"); + unsigned threshold = boost::lexical_cast(tokens[1].substr(0, pos)); + unsigned count = boost::lexical_cast(tokens[1].substr(pos + 2)); + STORM_LOG_THROW(count == childNames.size(), storm::exceptions::FileIoException, "Voting gate does not correspond to number of children."); + success = builder.addVotElement(name, threshold, childNames); + } else if (tokens[1] == "pand") { + success = builder.addPandElement(name, childNames); + } else if (tokens[1] == "por") { + success = builder.addPorElement(name, childNames); + } else if (tokens[1] == "wsp" || tokens[1] == "csp") { + success = builder.addSpareElement(name, childNames); + } else if (tokens[1] == "seq") { + success = builder.addSequenceEnforcer(name, childNames); + } else if (tokens[1] == "fdep") { + success = builder.addDepElement(name, childNames, storm::utility::one()); + } else if (boost::starts_with(tokens[1], "pdep=")) { + ValueType probability = parseRationalExpression(tokens[1].substr(5)); + success = builder.addDepElement(name, childNames, probability); + } else if (boost::starts_with(tokens[1], "lambda=")) { + ValueType failureRate = parseRationalExpression(tokens[1].substr(7)); + ValueType dormancyFactor = parseRationalExpression(tokens[2].substr(5)); + success = builder.addBasicElement(name, failureRate, dormancyFactor); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " << tokens[1] << " not recognized."); + success = false; + } + STORM_LOG_THROW(success, storm::exceptions::FileIoException, "Error while adding element '" << name << "' of line '" << line << "'."); + } + } + if(!builder.setTopLevel(toplevelId)) { + STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Top level id unknown."); + } + file.close(); + } + + template + ValueType DFTGalileoParser::parseRationalExpression(std::string const& expr) { + STORM_LOG_ASSERT(false, "Specialized method should be called."); + return 0; + } + + template<> + double DFTGalileoParser::parseRationalExpression(std::string const& expr) { + return boost::lexical_cast(expr); + } + + // Explicitly instantiate the class. + template class DFTGalileoParser; + +#ifdef STORM_HAVE_CARL + template<> + storm::RationalFunction DFTGalileoParser::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 DFTGalileoParser; +#endif + + } +} diff --git a/src/parser/DFTGalileoParser.h b/src/parser/DFTGalileoParser.h new file mode 100644 index 000000000..fc64ee80e --- /dev/null +++ b/src/parser/DFTGalileoParser.h @@ -0,0 +1,44 @@ +#ifndef DFTGALILEOPARSER_H +#define DFTGALILEOPARSER_H + +#include "src/storage/dft/DFT.h" +#include "src/storage/dft/DFTBuilder.h" +#include "src/storage/expressions/ExpressionManager.h" +#include "src/parser/ExpressionParser.h" +#include "src/storage/expressions/ExpressionEvaluator.h" + +#include + +namespace storm { + namespace parser { + + template + class DFTGalileoParser { + storm::storage::DFTBuilder builder; + + std::shared_ptr manager; + + storm::parser::ExpressionParser parser; + + storm::expressions::ExpressionEvaluator evaluator; + + std::unordered_map identifierMapping; + + public: + DFTGalileoParser() : manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) { + } + + storm::storage::DFT parseDFT(std::string const& filename); + + private: + void readFile(std::string const& filename); + + std::string stripQuotsFromName(std::string const& name); + + ValueType parseRationalExpression(std::string const& expr); + }; + } +} + +#endif /* DFTGALILEOPARSER_H */ + diff --git a/src/parser/DeterministicSparseTransitionParser.cpp b/src/parser/DeterministicSparseTransitionParser.cpp index da200fe2e..db63f509f 100644 --- a/src/parser/DeterministicSparseTransitionParser.cpp +++ b/src/parser/DeterministicSparseTransitionParser.cpp @@ -14,7 +14,7 @@ #include "src/exceptions/WrongFormatException.h" #include "src/exceptions/InvalidArgumentException.h" #include "src/settings/SettingsManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/adapters/CarlAdapter.h" #include "src/utility/macros.h" @@ -88,7 +88,7 @@ namespace storm { uint_fast64_t row, col, lastRow = 0; double val; - bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet(); + bool dontFixDeadlocks = storm::settings::getModule().isDontFixDeadlocksSet(); bool hadDeadlocks = false; bool rowHadDiagonalEntry = false; diff --git a/src/parser/ExpressionParser.cpp b/src/parser/ExpressionParser.cpp index 7054e26ef..20982bd20 100644 --- a/src/parser/ExpressionParser.cpp +++ b/src/parser/ExpressionParser.cpp @@ -134,9 +134,23 @@ namespace storm { this->identifiers_ = nullptr; } } - + + void ExpressionParser::setIdentifierMapping(std::unordered_map const& identifierMapping) { + unsetIdentifierMapping(); + this->createExpressions = true; + this->identifiers_ = new qi::symbols(); + for (auto const& identifierExpressionPair : identifierMapping) { + this->identifiers_->add(identifierExpressionPair.first, identifierExpressionPair.second); + } + deleteIdentifierMapping = true; + } + void ExpressionParser::unsetIdentifierMapping() { this->createExpressions = false; + if (deleteIdentifierMapping) { + delete this->identifiers_; + deleteIdentifierMapping = false; + } this->identifiers_ = nullptr; } @@ -352,5 +366,25 @@ namespace storm { } return true; } + + storm::expressions::Expression ExpressionParser::parseFromString(std::string const& expressionString) const { + PositionIteratorType first(expressionString.begin()); + PositionIteratorType iter = first; + PositionIteratorType last(expressionString.end()); + + // Create empty result; + storm::expressions::Expression result; + + try { + // Start parsing. + bool succeeded = qi::phrase_parse(iter, last, *this, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - (qi::eol | qi::eoi)) >> (qi::eol | qi::eoi), result); + STORM_LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Could not parse expression."); + STORM_LOG_DEBUG("Parsed expression successfully."); + } catch (qi::expectation_failure const& e) { + STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, e.what_); + } + + return result; + } } -} \ No newline at end of file +} diff --git a/src/parser/ExpressionParser.h b/src/parser/ExpressionParser.h index 94d4c8249..66d851707 100644 --- a/src/parser/ExpressionParser.h +++ b/src/parser/ExpressionParser.h @@ -26,7 +26,7 @@ namespace storm { * points it would typically allow. This can, for example, be used to prevent errors if the outer grammar * also parses boolean conjuncts that are erroneously consumed by the expression parser. */ - ExpressionParser(storm::expressions::ExpressionManager const& manager, qi::symbols const& invalidIdentifiers_, bool enableErrorHandling = true, bool allowBacktracking = false); + ExpressionParser(storm::expressions::ExpressionManager const& manager, qi::symbols const& invalidIdentifiers_ = qi::symbols(), bool enableErrorHandling = true, bool allowBacktracking = false); ExpressionParser(ExpressionParser const& other) = default; ExpressionParser& operator=(ExpressionParser const& other) = default; @@ -39,6 +39,15 @@ namespace storm { * @param identifiers_ A pointer to a mapping from identifiers to expressions. */ void setIdentifierMapping(qi::symbols const* identifiers_); + + /*! + * Sets an identifier mapping that is used to determine valid variables in the expression. The mapped-to + * expressions will be substituted wherever the key value appears in the parsed expression. After setting + * this, the parser will generate expressions. + * + * @param identifierMapping A mapping from identifiers to expressions. + */ + void setIdentifierMapping(std::unordered_map const& identifierMapping); /*! * Unsets a previously set identifier mapping. This will make the parser not generate expressions any more @@ -52,7 +61,9 @@ namespace storm { * @param flag If set to true, double literals are accepted. */ void setAcceptDoubleLiterals(bool flag); - + + storm::expressions::Expression parseFromString(std::string const& expressionString) const; + private: struct orOperatorStruct : qi::symbols { orOperatorStruct() { @@ -195,12 +206,15 @@ namespace storm { // A flag that indicates whether double literals are accepted. bool acceptDoubleLiterals; + // A flag that indicates whether the mapping must be deleted on unsetting. + bool deleteIdentifierMapping; + // The currently used mapping of identifiers to expressions. This is used if the parser is set to create // expressions. qi::symbols const* identifiers_; // The symbol table of invalid identifiers. - qi::symbols const& invalidIdentifiers_; + qi::symbols invalidIdentifiers_; // Rules for parsing a composed expression. qi::rule expression; @@ -248,4 +262,4 @@ namespace storm { } // namespace parser } // namespace storm -#endif /* STORM_PARSER_EXPRESSIONPARSER_H_ */ \ No newline at end of file +#endif /* STORM_PARSER_EXPRESSIONPARSER_H_ */ diff --git a/src/parser/FormulaParser.cpp b/src/parser/FormulaParser.cpp index 80aa2f421..db6e8a1ea 100644 --- a/src/parser/FormulaParser.cpp +++ b/src/parser/FormulaParser.cpp @@ -280,7 +280,7 @@ namespace storm { booleanLiteralFormula = (qi::lit("true")[qi::_a = true] | qi::lit("false")[qi::_a = false])[qi::_val = phoenix::bind(&FormulaParserGrammar::createBooleanLiteralFormula, phoenix::ref(*this), qi::_a)]; booleanLiteralFormula.name("boolean literal formula"); - operatorFormula = probabilityOperator | rewardOperator | longRunAverageOperator; + operatorFormula = probabilityOperator | rewardOperator | longRunAverageOperator | timeOperator; operatorFormula.name("operator formulas"); atomicStateFormula = booleanLiteralFormula | labelFormula | expressionFormula | (qi::lit("(") > stateFormula > qi::lit(")")) | operatorFormula; @@ -346,8 +346,8 @@ namespace storm { start = qi::eps > (stateFormula % +(qi::char_("\n;"))) >> qi::skip(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - (qi::eol | qi::eoi)))[qi::eps] >> qi::eoi; start.name("start"); - /*! - * Enable the following lines to print debug output for most the rules. + //Enable the following lines to print debug output for most the rules. + /* debug(start); debug(stateFormula); debug(orStateFormula); @@ -355,6 +355,7 @@ namespace storm { debug(probabilityOperator); debug(rewardOperator); debug(longRunAverageOperator); + debug(timeOperator); debug(pathFormulaWithoutUntil); debug(pathFormula); // debug(conditionalFormula); @@ -378,6 +379,7 @@ namespace storm { qi::on_error(probabilityOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(rewardOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(longRunAverageOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error(timeOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(operatorInformation, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(pathFormulaWithoutUntil, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(pathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); diff --git a/src/parser/MarkovAutomatonSparseTransitionParser.cpp b/src/parser/MarkovAutomatonSparseTransitionParser.cpp index a49fa3996..43f8aed64 100644 --- a/src/parser/MarkovAutomatonSparseTransitionParser.cpp +++ b/src/parser/MarkovAutomatonSparseTransitionParser.cpp @@ -1,7 +1,7 @@ #include "MarkovAutomatonSparseTransitionParser.h" #include "src/settings/SettingsManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/exceptions/WrongFormatException.h" #include "src/exceptions/FileIoException.h" #include "src/parser/MappedFile.h" @@ -18,7 +18,7 @@ namespace storm { typename MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTransitionParser::firstPass(char const* buf) { MarkovAutomatonSparseTransitionParser::FirstPassResult result; - bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet(); + bool dontFixDeadlocks = storm::settings::getModule().isDontFixDeadlocksSet(); // Skip the format hint if it is there. buf = trimWhitespaces(buf); @@ -171,7 +171,7 @@ namespace storm { typename MarkovAutomatonSparseTransitionParser::Result MarkovAutomatonSparseTransitionParser::secondPass(char const* buf, FirstPassResult const& firstPassResult) { Result result(firstPassResult); - bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet(); + bool dontFixDeadlocks = storm::settings::getModule().isDontFixDeadlocksSet(); // Skip the format hint if it is there. buf = trimWhitespaces(buf); diff --git a/src/parser/NondeterministicSparseTransitionParser.cpp b/src/parser/NondeterministicSparseTransitionParser.cpp index e89fe76e2..2186b4929 100644 --- a/src/parser/NondeterministicSparseTransitionParser.cpp +++ b/src/parser/NondeterministicSparseTransitionParser.cpp @@ -4,7 +4,7 @@ #include "src/parser/MappedFile.h" #include "src/settings/SettingsManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/exceptions/FileIoException.h" #include "src/exceptions/OutOfRangeException.h" @@ -96,7 +96,7 @@ namespace storm { // Initialize variables for the parsing run. uint_fast64_t source = 0, target = 0, lastSource = 0, choice = 0, lastChoice = 0, curRow = 0; double val = 0.0; - bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet(); + bool dontFixDeadlocks = storm::settings::getModule().isDontFixDeadlocksSet(); bool hadDeadlocks = false; // The first state already starts a new row group of the matrix. diff --git a/src/settings/ArgumentValidators.h b/src/settings/ArgumentValidators.h index 6e1b4aa02..60a36b55b 100644 --- a/src/settings/ArgumentValidators.h +++ b/src/settings/ArgumentValidators.h @@ -46,6 +46,26 @@ namespace storm { return rangeValidatorExcluding(lowerBound, upperBound); } + /*! + * Creates a validation function that checks whether an integer is greater than or equal to the given threshold. + * + * @param threshold The threshold. + * @return The resulting validation function. + */ + static std::function integerGreaterValidatorIncluding(int_fast64_t threshold) { + return greaterValidatorIncluding(threshold); + } + + /*! + * Creates a validation function that checks whether an integer is greater than the given threshold. + * + * @param threshold The threshold. + * @return The resulting validation function. + */ + static std::function integerGreaterValidatorExcluding(int_fast64_t threshold) { + return greaterValidatorExcluding(threshold); + } + /*! * Creates a validation function that checks whether an unsigned integer is in the given range (including the bounds). * @@ -67,6 +87,26 @@ namespace storm { static std::function unsignedIntegerRangeValidatorExcluding(uint_fast64_t lowerBound, uint_fast64_t upperBound) { return rangeValidatorExcluding(lowerBound, upperBound); } + + /*! + * Creates a validation function that checks whether an unsigned integer is greater than or equal to the given threshold. + * + * @param threshold The threshold. + * @return The resulting validation function. + */ + static std::function unsignedIntegerGreaterValidatorIncluding(uint_fast64_t threshold) { + return greaterValidatorIncluding(threshold); + } + + /*! + * Creates a validation function that checks whether an unsigned integer is greater than the given threshold. + * + * @param threshold The threshold. + * @return The resulting validation function. + */ + static std::function unsignedIntegerGreaterValidatorExcluding(uint_fast64_t threshold) { + return greaterValidatorExcluding(threshold); + } /*! * Creates a validation function that checks whether a double is in the given range (including the bounds). @@ -89,6 +129,26 @@ namespace storm { static std::function doubleRangeValidatorExcluding(double lowerBound, double upperBound) { return rangeValidatorExcluding(lowerBound, upperBound); } + + /*! + * Creates a validation function that checks whether a double is greater than or equal to the given threshold. + * + * @param threshold The threshold. + * @return The resulting validation function. + */ + static std::function doubleGreaterValidatorIncluding(double threshold) { + return greaterValidatorIncluding(threshold); + } + + /*! + * Creates a validation function that checks whether a double is greater than the given threshold. + * + * @param threshold The threshold. + * @return The resulting validation function. + */ + static std::function doubleGreaterValidatorExcluding(double threshold) { + return greaterValidatorExcluding(threshold); + } /*! * Creates a validation function that checks whether a given string corresponds to an existing and readable @@ -141,7 +201,7 @@ namespace storm { template static std::function rangeValidatorIncluding(T lowerBound, T upperBound) { return std::bind([](T lowerBound, T upperBound, T value) -> bool { - STORM_LOG_THROW(lowerBound <= value && value <= upperBound, storm::exceptions::InvalidArgumentException, "Value " << value << " is out range."); + STORM_LOG_THROW(lowerBound <= value && value <= upperBound, storm::exceptions::InvalidArgumentException, "Value " << value << " is out of range."); return true; }, lowerBound, upperBound, std::placeholders::_1); } @@ -156,10 +216,38 @@ namespace storm { template static std::function rangeValidatorExcluding(T lowerBound, T upperBound) { return std::bind([](T lowerBound, T upperBound, T value) -> bool { - STORM_LOG_THROW(lowerBound < value && value < upperBound, storm::exceptions::InvalidArgumentException, "Value " << value << " is out range."); + STORM_LOG_THROW(lowerBound < value && value < upperBound, storm::exceptions::InvalidArgumentException, "Value " << value << " is out of range."); return true; }, lowerBound, upperBound, std::placeholders::_1); } + + /*! + * Creates a validation function that checks whether its argument is greater than the given threshold. + * + * @param threshold The threshold. + * @return The resulting validation function. + */ + template + static std::function greaterValidatorExcluding(T threshold) { + return std::bind([](T threshold, T value) -> bool { + STORM_LOG_THROW(threshold < value, storm::exceptions::InvalidArgumentException, "Value " << value << " is out of range."); + return true; + }, threshold, std::placeholders::_1); + } + + /*! + * Creates a validation function that checks whether its argument is greater than or equal to the given threshold. + * + * @param threshold The threshold. + * @return The resulting validation function. + */ + template + static std::function greaterValidatorIncluding(T threshold) { + return std::bind([](T threshold, T value) -> bool { + STORM_LOG_THROW(threshold <= value, storm::exceptions::InvalidArgumentException, "Value " << value << " is out of range."); + return true; + }, threshold, std::placeholders::_1); + } }; } } diff --git a/src/settings/SettingsManager.cpp b/src/settings/SettingsManager.cpp index a13adb9e4..8e79c5457 100644 --- a/src/settings/SettingsManager.cpp +++ b/src/settings/SettingsManager.cpp @@ -14,6 +14,8 @@ #include "src/exceptions/OptionParserException.h" #include "src/utility/storm-version.h" #include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" +#include "src/settings/modules/IOSettings.h" #include "src/settings/modules/DebugSettings.h" #include "src/settings/modules/CounterexampleGeneratorSettings.h" #include "src/settings/modules/CuddSettings.h" @@ -35,21 +37,6 @@ namespace storm { namespace settings { SettingsManager::SettingsManager() : modules(), longNameToOptions(), shortNameToOptions(), moduleOptions() { - // Register all known settings modules. - this->addModule(std::unique_ptr(new modules::GeneralSettings(*this))); - this->addModule(std::unique_ptr(new modules::DebugSettings(*this))); - this->addModule(std::unique_ptr(new modules::CounterexampleGeneratorSettings(*this))); - this->addModule(std::unique_ptr(new modules::CuddSettings(*this))); - this->addModule(std::unique_ptr(new modules::SylvanSettings(*this))); - this->addModule(std::unique_ptr(new modules::GmmxxEquationSolverSettings(*this))); - this->addModule(std::unique_ptr(new modules::NativeEquationSolverSettings(*this))); - this->addModule(std::unique_ptr(new modules::BisimulationSettings(*this))); - this->addModule(std::unique_ptr(new modules::GlpkSettings(*this))); - this->addModule(std::unique_ptr(new modules::GurobiSettings(*this))); - this->addModule(std::unique_ptr(new modules::TopologicalValueIterationEquationSolverSettings(*this))); - this->addModule(std::unique_ptr(new modules::ParametricSettings(*this))); - this->addModule(std::unique_ptr(new modules::SparseDtmcEliminationModelCheckerSettings(*this))); - this->addModule(std::unique_ptr(new modules::ExplorationSettings(*this))); } SettingsManager::~SettingsManager() { @@ -61,6 +48,12 @@ namespace storm { return settingsManager; } + void SettingsManager::setName(std::string const& name, std::string const& executableName) { + this->name = name; + this->executableName = executableName; + } + + void SettingsManager::setFromCommandLine(int const argc, char const * const argv[]) { // We convert the arguments to a vector of strings and strip off the first element since it refers to the // name of the program. @@ -137,8 +130,8 @@ namespace storm { } // Include the options from a possibly specified configuration file, but don't overwrite existing settings. - if (storm::settings::generalSettings().isConfigSet()) { - this->setFromConfigurationFile(storm::settings::generalSettings().getConfigFilename()); + if (storm::settings::getModule().isConfigSet()) { + this->setFromConfigurationFile(storm::settings::getModule().getConfigFilename()); } // Finally, check whether all modules are okay with the current settings. @@ -172,7 +165,7 @@ namespace storm { } void SettingsManager::printHelp(std::string const& hint) const { - STORM_PRINT("usage: storm [options]" << std::endl << std::endl); + STORM_PRINT("usage: " << executableName << " [options]" << std::endl << std::endl); if (hint == "all") { // Find longest option name. @@ -495,64 +488,35 @@ namespace storm { return SettingsManager::manager(); } - storm::settings::modules::GeneralSettings const& generalSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::GeneralSettings::moduleName)); - } - - storm::settings::modules::GeneralSettings& mutableGeneralSettings() { - return dynamic_cast(storm::settings::SettingsManager::manager().getModule(storm::settings::modules::GeneralSettings::moduleName)); - } - - storm::settings::modules::DebugSettings const& debugSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::DebugSettings::moduleName)); - } - - storm::settings::modules::CounterexampleGeneratorSettings const& counterexampleGeneratorSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::CounterexampleGeneratorSettings::moduleName)); - } - - storm::settings::modules::CuddSettings const& cuddSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::CuddSettings::moduleName)); - } - - storm::settings::modules::SylvanSettings const& sylvanSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::SylvanSettings::moduleName)); + storm::settings::modules::MarkovChainSettings& mutableMarkovChainSettings() { + return dynamic_cast(mutableManager().getModule(storm::settings::modules::MarkovChainSettings::moduleName)); } - storm::settings::modules::GmmxxEquationSolverSettings const& gmmxxEquationSolverSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::GmmxxEquationSolverSettings::moduleName)); + storm::settings::modules::IOSettings& mutableIOSettings() { + return dynamic_cast(mutableManager().getModule(storm::settings::modules::IOSettings::moduleName)); } - storm::settings::modules::NativeEquationSolverSettings const& nativeEquationSolverSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::NativeEquationSolverSettings::moduleName)); - } - - storm::settings::modules::BisimulationSettings const& bisimulationSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::BisimulationSettings::moduleName)); - } - - storm::settings::modules::GlpkSettings const& glpkSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::GlpkSettings::moduleName)); - } - - storm::settings::modules::GurobiSettings const& gurobiSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::GurobiSettings::moduleName)); - } - - storm::settings::modules::TopologicalValueIterationEquationSolverSettings const& topologicalValueIterationEquationSolverSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::TopologicalValueIterationEquationSolverSettings::moduleName)); - } - - storm::settings::modules::ParametricSettings const& parametricSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::ParametricSettings::moduleName)); + void initializeAll(std::string const& name, std::string const& executableName) { + storm::settings::mutableManager().setName(name, executableName); + + // Register all known settings modules. + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); + storm::settings::addModule(); } - storm::settings::modules::SparseDtmcEliminationModelCheckerSettings const& sparseDtmcEliminationModelCheckerSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::moduleName)); - } - - storm::settings::modules::ExplorationSettings const& explorationSettings() { - return dynamic_cast(manager().getModule(storm::settings::modules::ExplorationSettings::moduleName)); - } } } diff --git a/src/settings/SettingsManager.h b/src/settings/SettingsManager.h index f6a1779d1..0efdcd2fd 100644 --- a/src/settings/SettingsManager.h +++ b/src/settings/SettingsManager.h @@ -12,20 +12,8 @@ namespace storm { namespace settings { namespace modules { - class GeneralSettings; - class DebugSettings; - class CounterexampleGeneratorSettings; - class CuddSettings; - class SylvanSettings; - class GmmxxEquationSolverSettings; - class NativeEquationSolverSettings; - class BisimulationSettings; - class GlpkSettings; - class GurobiSettings; - class TopologicalValueIterationEquationSolverSettings; - class ParametricSettings; - class SparseDtmcEliminationModelCheckerSettings; - class ExplorationSettings; + class MarkovChainSettings; + class IOSettings; class ModuleSettings; } class Option; @@ -37,6 +25,11 @@ namespace storm { */ class SettingsManager { public: + + // Explicitely delete copy constructor + SettingsManager(SettingsManager const&) = delete; + void operator=(SettingsManager const&) = delete; + /*! * This function parses the given command line arguments and sets all registered options accordingly. If the * command line cannot be matched using the known options, an exception is thrown. @@ -99,6 +92,13 @@ namespace storm { */ static SettingsManager& manager(); + /*! + * Sets the name of the tool. + * @param name Name of the tool. + * @param executableName Filename of the executable. + */ + void setName(std::string const& name, std::string const& executableName); + /*! * Adds a new module with the given name. If the module could not be successfully added, an exception is * thrown. @@ -135,6 +135,10 @@ namespace storm { */ virtual ~SettingsManager(); + // The name of the tool + std::string name; + std::string executableName; + // The registered modules. std::vector moduleNames; std::unordered_map> modules; @@ -235,110 +239,49 @@ namespace storm { SettingsManager& mutableManager(); /*! - * Retrieves the general settings. - * - * @return An object that allows accessing the general settings. - */ - storm::settings::modules::GeneralSettings const& generalSettings(); - - /*! - * Retrieves the general settings in a mutable form. This is only meant to be used for debug purposes or very - * rare cases where it is necessary. - * - * @return An object that allows accessing and modifying the general settings. - */ - storm::settings::modules::GeneralSettings& mutableGeneralSettings(); - - /*! - * Retrieves the debug settings. - * - * @return An object that allows accessing the debug settings. - */ - storm::settings::modules::DebugSettings const& debugSettings(); - - /*! - * Retrieves the counterexample generator settings. - * - * @return An object that allows accessing the counterexample generator settings. - */ - storm::settings::modules::CounterexampleGeneratorSettings const& counterexampleGeneratorSettings(); - - /*! - * Retrieves the CUDD settings. - * - * @return An object that allows accessing the CUDD settings. - */ - storm::settings::modules::CuddSettings const& cuddSettings(); - - /*! - * Retrieves the Sylvan settings. - * - * @return An object that allows accessing the Sylvan settings. - */ - storm::settings::modules::SylvanSettings const& sylvanSettings(); - - /*! - * Retrieves the settings of the gmm++-based equation solver. - * - * @return An object that allows accessing the settings of the gmm++-based equation solver. + * Add new module to use for the settings. The new module is given as a template argument. */ - storm::settings::modules::GmmxxEquationSolverSettings const& gmmxxEquationSolverSettings(); + template + void addModule() { + static_assert(std::is_base_of::value, "Template argument must be derived from ModuleSettings"); + mutableManager().addModule(std::unique_ptr(new SettingsType())); + } /*! - * Retrieves the settings of the native equation solver. - * - * @return An object that allows accessing the settings of the native equation solver. - */ - storm::settings::modules::NativeEquationSolverSettings const& nativeEquationSolverSettings(); - - /*! - * Retrieves the settings of the native equation solver. - * - * @return An object that allows accessing the settings of the native equation solver. + * Initialize the settings manager with all available modules. + * @param name Name of the tool. + * @param executableName Filename of the executable. */ - storm::settings::modules::BisimulationSettings const& bisimulationSettings(); + void initializeAll(std::string const& name, std::string const& executableName); /*! - * Retrieves the settings of glpk. + * Get module. The type of the module is given as a template argument. * - * @return An object that allows accessing the settings of glpk. + * @return The module. */ - storm::settings::modules::GlpkSettings const& glpkSettings(); + template + SettingsType getModule() { + static_assert(std::is_base_of::value, "Template argument must be derived from ModuleSettings"); + return dynamic_cast(manager().getModule(SettingsType::moduleName)); + } /*! - * Retrieves the settings of Gurobi. + * Retrieves the markov chain settings in a mutable form. This is only meant to be used for debug purposes or very + * rare cases where it is necessary. * - * @return An object that allows accessing the settings of Gurobi. + * @return An object that allows accessing and modifying the markov chain settings. */ - storm::settings::modules::GurobiSettings const& gurobiSettings(); - - /*! - * Retrieves the settings of the topological value iteration-based equation solver. - * - * @return An object that allows accessing the settings of the topological value iteration-based equation solver. - */ - storm::settings::modules::TopologicalValueIterationEquationSolverSettings const& topologicalValueIterationEquationSolverSettings(); + storm::settings::modules::MarkovChainSettings& mutableMarkovChainSettings(); /*! - * Retrieves the settings for parametric model checking. - * - * @return An object that allows accessing the settings for parameteric model checking. - */ - storm::settings::modules::ParametricSettings const& parametricSettings(); - - /* Retrieves the settings of the elimination-based DTMC model checker. - * - * @return An object that allows accessing the settings of the elimination-based DTMC model checker. - */ - storm::settings::modules::SparseDtmcEliminationModelCheckerSettings const& sparseDtmcEliminationModelCheckerSettings(); - - /* Retrieves the settings of the exploration engine. + * Retrieves the IO settings in a mutable form. This is only meant to be used for debug purposes or very + * rare cases where it is necessary. * - * @return An object that allows accessing the settings of the exploration engine. + * @return An object that allows accessing and modifying the IO settings. */ - storm::settings::modules::ExplorationSettings const& explorationSettings(); + storm::settings::modules::IOSettings& mutableIOSettings(); } // namespace settings } // namespace storm -#endif /* STORM_SETTINGS_SETTINGSMANAGER_H_ */ \ No newline at end of file +#endif /* STORM_SETTINGS_SETTINGSMANAGER_H_ */ diff --git a/src/settings/modules/BisimulationSettings.cpp b/src/settings/modules/BisimulationSettings.cpp index db3bdce9e..3e57b292c 100644 --- a/src/settings/modules/BisimulationSettings.cpp +++ b/src/settings/modules/BisimulationSettings.cpp @@ -13,7 +13,7 @@ namespace storm { const std::string BisimulationSettings::moduleName = "bisimulation"; const std::string BisimulationSettings::typeOptionName = "type"; - BisimulationSettings::BisimulationSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + BisimulationSettings::BisimulationSettings() : ModuleSettings(moduleName) { std::vector types = { "strong", "weak" }; this->addOption(storm::settings::OptionBuilder(moduleName, typeOptionName, true, "Sets the kind of bisimulation quotienting used. Available are: { strong, weak }.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the type to use.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(types)).setDefaultValueString("strong").build()).build()); } @@ -34,7 +34,7 @@ namespace storm { bool BisimulationSettings::check() const { bool optionsSet = this->getOption(typeOptionName).getHasOptionBeenSet(); - STORM_LOG_WARN_COND(storm::settings::generalSettings().isBisimulationSet() || !optionsSet, "Bisimulation minimization is not selected, so setting options for bisimulation has no effect."); + STORM_LOG_WARN_COND(storm::settings::getModule().isBisimulationSet() || !optionsSet, "Bisimulation minimization is not selected, so setting options for bisimulation has no effect."); return true; } } // namespace modules diff --git a/src/settings/modules/BisimulationSettings.h b/src/settings/modules/BisimulationSettings.h index 3e2d1efe7..7bace55ce 100644 --- a/src/settings/modules/BisimulationSettings.h +++ b/src/settings/modules/BisimulationSettings.h @@ -16,11 +16,9 @@ namespace storm { enum class BisimulationType { Strong, Weak }; /*! - * Creates a new set of bisimulation settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of bisimulation settings. */ - BisimulationSettings(storm::settings::SettingsManager& settingsManager); + BisimulationSettings(); /*! * Retrieves whether strong bisimulation is to be used. diff --git a/src/settings/modules/CounterexampleGeneratorSettings.cpp b/src/settings/modules/CounterexampleGeneratorSettings.cpp index e4f8d2a32..b2dbb0ddc 100644 --- a/src/settings/modules/CounterexampleGeneratorSettings.cpp +++ b/src/settings/modules/CounterexampleGeneratorSettings.cpp @@ -6,7 +6,7 @@ #include "src/settings/OptionBuilder.h" #include "src/settings/ArgumentBuilder.h" #include "src/settings/Argument.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/IOSettings.h" namespace storm { namespace settings { @@ -17,7 +17,7 @@ namespace storm { const std::string CounterexampleGeneratorSettings::encodeReachabilityOptionName = "encreach"; const std::string CounterexampleGeneratorSettings::schedulerCutsOptionName = "schedcuts"; - CounterexampleGeneratorSettings::CounterexampleGeneratorSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + CounterexampleGeneratorSettings::CounterexampleGeneratorSettings() : ModuleSettings(moduleName) { std::vector techniques = {"maxsat", "milp"}; this->addOption(storm::settings::OptionBuilder(moduleName, minimalCommandSetOptionName, true, "Computes a counterexample for the given model in terms of a minimal command set. Note that this requires the model to be given in a symbolic format.") .addArgument(storm::settings::ArgumentBuilder::createStringArgument("method", "Sets which technique is used to derive the counterexample. Available are {milp, maxsat}").setDefaultValueString("maxsat").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(techniques)).build()).build()); @@ -48,7 +48,7 @@ namespace storm { bool CounterexampleGeneratorSettings::check() const { // Ensure that the model was given either symbolically or explicitly. - STORM_LOG_THROW(!isMinimalCommandSetGenerationSet() || storm::settings::generalSettings().isSymbolicSet(), storm::exceptions::InvalidSettingsException, "For the generation of a minimal command set, the model has to be specified symbolically."); + STORM_LOG_THROW(!isMinimalCommandSetGenerationSet() || storm::settings::getModule().isSymbolicSet(), storm::exceptions::InvalidSettingsException, "For the generation of a minimal command set, the model has to be specified symbolically."); if (isMinimalCommandSetGenerationSet()) { STORM_LOG_WARN_COND(isUseMaxSatBasedMinimalCommandSetGenerationSet() || !isEncodeReachabilitySet(), "Encoding reachability is only available for the MaxSat-based minimal command set generation, so selecting it has no effect."); diff --git a/src/settings/modules/CounterexampleGeneratorSettings.h b/src/settings/modules/CounterexampleGeneratorSettings.h index 049747183..6103f0102 100644 --- a/src/settings/modules/CounterexampleGeneratorSettings.h +++ b/src/settings/modules/CounterexampleGeneratorSettings.h @@ -13,11 +13,9 @@ namespace storm { class CounterexampleGeneratorSettings : public ModuleSettings { public: /*! - * Creates a new set of counterexample settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of counterexample settings. */ - CounterexampleGeneratorSettings(storm::settings::SettingsManager& settingsManager); + CounterexampleGeneratorSettings(); /*! * Retrieves whether the option to generate a minimal command set was set. diff --git a/src/settings/modules/CuddSettings.cpp b/src/settings/modules/CuddSettings.cpp index 1cd54d011..bf15d1cc6 100644 --- a/src/settings/modules/CuddSettings.cpp +++ b/src/settings/modules/CuddSettings.cpp @@ -16,7 +16,7 @@ namespace storm { const std::string CuddSettings::maximalMemoryOptionName = "maxmem"; const std::string CuddSettings::reorderOptionName = "reorder"; - CuddSettings::CuddSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + CuddSettings::CuddSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, precisionOptionName, true, "Sets the precision used by Cudd.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision up to which to constants are considered to be different.").setDefaultValueDouble(1e-15).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, maximalMemoryOptionName, true, "Sets the upper bound of memory available to Cudd in MB.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("value", "The memory available to Cudd (0 means unlimited).").setDefaultValueUnsignedInteger(4096).build()).build()); diff --git a/src/settings/modules/CuddSettings.h b/src/settings/modules/CuddSettings.h index db59ddc77..8aaa8f007 100644 --- a/src/settings/modules/CuddSettings.h +++ b/src/settings/modules/CuddSettings.h @@ -16,11 +16,9 @@ namespace storm { enum class ReorderingTechnique { None, Random, RandomPivot, Sift, SiftConv, SymmetricSift, SymmetricSiftConv, GroupSift, GroupSiftConv, Win2, Win2Conv, Win3, Win3Conv, Win4, Win4Conv, Annealing, Genetic, Exact }; /*! - * Creates a new set of CUDD settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of CUDD settings. */ - CuddSettings(storm::settings::SettingsManager& settingsManager); + CuddSettings(); /*! * Retrieves the precision that CUDD is supposed to use for distinguishing constants. diff --git a/src/settings/modules/DFTSettings.cpp b/src/settings/modules/DFTSettings.cpp new file mode 100644 index 000000000..365ba0271 --- /dev/null +++ b/src/settings/modules/DFTSettings.cpp @@ -0,0 +1,107 @@ +#include "src/settings/modules/DFTSettings.h" + +#include "src/settings/SettingsManager.h" +#include "src/settings/SettingMemento.h" +#include "src/settings/Option.h" +#include "src/settings/OptionBuilder.h" +#include "src/settings/ArgumentBuilder.h" +#include "src/settings/Argument.h" + +#include "src/exceptions/InvalidSettingsException.h" + + +namespace storm { + namespace settings { + namespace modules { + + const std::string DFTSettings::moduleName = "dft"; + const std::string DFTSettings::dftFileOptionName = "dftfile"; + const std::string DFTSettings::dftFileOptionShortName = "dft"; + const std::string DFTSettings::symmetryReductionOptionName = "symmetryreduction"; + const std::string DFTSettings::symmetryReductionOptionShortName = "symred"; + const std::string DFTSettings::modularisationOptionName = "modularisation"; + const std::string DFTSettings::disableDCOptionName = "disabledc"; + const std::string DFTSettings::propExpectedTimeOptionName = "expectedtime"; + const std::string DFTSettings::propExpectedTimeOptionShortName = "mttf"; + const std::string DFTSettings::propProbabilityOptionName = "probability"; + const std::string DFTSettings::propTimeBoundOptionName = "timebound"; + const std::string DFTSettings::minValueOptionName = "min"; + const std::string DFTSettings::maxValueOptionName = "max"; + + 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, 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()); + this->addOption(storm::settings::OptionBuilder(moduleName, propExpectedTimeOptionName, false, "Compute expected time of system failure.").setShortName(propExpectedTimeOptionShortName).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, propProbabilityOptionName, false, "Compute probability of system failure.").build()); + this->addOption(storm::settings::OptionBuilder(moduleName, propTimeBoundOptionName, false, "Compute probability of system failure up to given timebound.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("time", "The timebound to use.").addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleGreaterValidatorExcluding(0.0)).build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, minValueOptionName, false, "Compute minimal value in case of non-determinism.").build()); + this->addOption(storm::settings::OptionBuilder(moduleName, maxValueOptionName, false, "Compute maximal value in case of non-determinism.").build()); + } + + bool DFTSettings::isDftFileSet() const { + return this->getOption(dftFileOptionName).getHasOptionBeenSet(); + } + + std::string DFTSettings::getDftFilename() const { + return this->getOption(dftFileOptionName).getArgumentByName("filename").getValueAsString(); + } + + bool DFTSettings::useSymmetryReduction() const { + return this->getOption(symmetryReductionOptionName).getHasOptionBeenSet(); + } + + bool DFTSettings::useModularisation() const { + return this->getOption(modularisationOptionName).getHasOptionBeenSet(); + } + + bool DFTSettings::isDisableDC() const { + return this->getOption(disableDCOptionName).getHasOptionBeenSet(); + } + + bool DFTSettings::usePropExpectedTime() const { + return this->getOption(propExpectedTimeOptionName).getHasOptionBeenSet(); + } + + bool DFTSettings::usePropProbability() const { + return this->getOption(propProbabilityOptionName).getHasOptionBeenSet(); + } + + bool DFTSettings::usePropTimebound() const { + return this->getOption(propTimeBoundOptionName).getHasOptionBeenSet(); + } + + double DFTSettings::getPropTimebound() const { + return this->getOption(propTimeBoundOptionName).getArgumentByName("time").getValueAsDouble(); + } + + bool DFTSettings::isComputeMinimalValue() const { + return this->getOption(minValueOptionName).getHasOptionBeenSet(); + } + + bool DFTSettings::isComputeMaximalValue() const { + return this->getOption(maxValueOptionName).getHasOptionBeenSet(); + } + + void DFTSettings::finalize() { + + } + + bool DFTSettings::check() const { + // Ensure that only one property is given. + if (usePropExpectedTime()) { + STORM_LOG_THROW(!usePropProbability() && !usePropTimebound(), storm::exceptions::InvalidSettingsException, "More than one property given."); + } else if (usePropProbability()) { + STORM_LOG_THROW(!usePropTimebound(), storm::exceptions::InvalidSettingsException, "More than one property given."); + } + + // Ensure that at most one of min or max is set + STORM_LOG_THROW(!isComputeMinimalValue() || !isComputeMaximalValue(), storm::exceptions::InvalidSettingsException, "Min and max can not both be set."); + return true; + } + + } // namespace modules + } // namespace settings +} // namespace storm \ No newline at end of file diff --git a/src/settings/modules/DFTSettings.h b/src/settings/modules/DFTSettings.h new file mode 100644 index 000000000..844953c2c --- /dev/null +++ b/src/settings/modules/DFTSettings.h @@ -0,0 +1,129 @@ +#ifndef STORM_SETTINGS_MODULES_DFTSETTINGS_H_ +#define STORM_SETTINGS_MODULES_DFTSETTINGS_H_ + +#include "storm-config.h" +#include "src/settings/modules/ModuleSettings.h" + +namespace storm { + namespace settings { + namespace modules { + + /*! + * This class represents the settings for DFT model checking. + */ + class DFTSettings : public ModuleSettings { + public: + + /*! + * Creates a new set of DFT settings. + */ + DFTSettings(); + + /*! + * Retrieves whether the dft file option was set. + * + * @return True if the dft file option was set. + */ + bool isDftFileSet() const; + + /*! + * Retrieves the name of the file that contains the dft specification. + * + * @return The name of the file that contains the dft specification. + */ + std::string getDftFilename() const; + + //expectedtime, probability, timebound, prob + //min, max + + /*! + * Retrieves whether the option to use symmetry reduction is set. + * + * @return True iff the option was set. + */ + bool useSymmetryReduction() const; + + /*! + * Retrieves whether the option to use modularisation is set. + * + * @return True iff the option was set. + */ + bool useModularisation() const; + + /*! + * Retrieves whether the option to disable Dont Care propagation is set. + * + * @return True iff the option was set. + */ + bool isDisableDC() const; + + /*! + * Retrieves whether the property expected time should be used. + * + * @return True iff the option was set. + */ + bool usePropExpectedTime() const; + + /*! + * Retrieves whether the property probability should be used. + * + * @return True iff the option was set. + */ + bool usePropProbability() const; + + /*! + * Retrieves whether the property timebound should be used. + * + * @return True iff the option was set. + */ + bool usePropTimebound() const; + + /*! + * Retrieves whether the minimal value should be computed for non-determinism. + * + * @return True iff the option was set. + */ + bool isComputeMinimalValue() const; + + /*! + * Retrieves whether the maximal value should be computed for non-determinism. + * + * @return True iff the option was set. + */ + bool isComputeMaximalValue() const; + + /*! + * Retrieves the timebound for the timebound property. + * + * @return The timebound. + */ + double getPropTimebound() const; + + bool check() const override; + void finalize() override; + + // The name of the module. + static const std::string moduleName; + + private: + // Define the string names of the options as constants. + static const std::string dftFileOptionName; + static const std::string dftFileOptionShortName; + static const std::string symmetryReductionOptionName; + static const std::string symmetryReductionOptionShortName; + static const std::string modularisationOptionName; + static const std::string disableDCOptionName; + static const std::string propExpectedTimeOptionName; + static const std::string propExpectedTimeOptionShortName; + static const std::string propProbabilityOptionName; + static const std::string propTimeBoundOptionName; + static const std::string minValueOptionName; + static const std::string maxValueOptionName; + + }; + + } // namespace modules + } // namespace settings +} // namespace storm + +#endif /* STORM_SETTINGS_MODULES_DFTSETTINGS_H_ */ diff --git a/src/settings/modules/DebugSettings.cpp b/src/settings/modules/DebugSettings.cpp index cf2867181..0f37e7ce7 100644 --- a/src/settings/modules/DebugSettings.cpp +++ b/src/settings/modules/DebugSettings.cpp @@ -15,12 +15,14 @@ namespace storm { const std::string DebugSettings::traceOptionName = "trace"; const std::string DebugSettings::logfileOptionName = "logfile"; const std::string DebugSettings::logfileOptionShortName = "l"; + const std::string DebugSettings::testOptionName = "test"; - DebugSettings::DebugSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + DebugSettings::DebugSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, debugOptionName, false, "Print debug output.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, traceOptionName, false, "Print even more debug output.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, logfileOptionName, false, "If specified, the log output will also be written to this file.").setShortName(logfileOptionShortName) .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file to write the log.").build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, testOptionName, false, "Activate a test setting.").build()); } bool DebugSettings::isDebugSet() const { @@ -39,6 +41,10 @@ namespace storm { return this->getOption(traceOptionName).getArgumentByName("filename").getValueAsString(); } + bool DebugSettings::isTestSet() const { + return this->getOption(testOptionName).getHasOptionBeenSet(); + } + } // namespace modules } // namespace settings } // namespace storm \ No newline at end of file diff --git a/src/settings/modules/DebugSettings.h b/src/settings/modules/DebugSettings.h index 024246b68..438017307 100644 --- a/src/settings/modules/DebugSettings.h +++ b/src/settings/modules/DebugSettings.h @@ -13,11 +13,9 @@ namespace storm { class DebugSettings : public ModuleSettings { public: /*! - * Creates a new set of debug settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of debug settings. */ - DebugSettings(storm::settings::SettingsManager& settingsManager); + DebugSettings(); /*! * Retrieves whether the debug option was set. @@ -47,6 +45,14 @@ namespace storm { */ std::string getLogfilename() const; + /*! + * Retrieves whether the test option was set. This is a general option which can be + * used for quick testing purposes to activate/decactivate a certain setting. + * + * @return True iff the test option was set. + */ + bool isTestSet() const; + // The name of the module. static const std::string moduleName; @@ -56,6 +62,7 @@ namespace storm { static const std::string traceOptionName; static const std::string logfileOptionName; static const std::string logfileOptionShortName; + static const std::string testOptionName; }; } // namespace modules diff --git a/src/settings/modules/ExplorationSettings.cpp b/src/settings/modules/ExplorationSettings.cpp index 688f4e6b6..c7fb3140c 100644 --- a/src/settings/modules/ExplorationSettings.cpp +++ b/src/settings/modules/ExplorationSettings.cpp @@ -1,5 +1,5 @@ #include "src/settings/modules/ExplorationSettings.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/settings/Option.h" #include "src/settings/OptionBuilder.h" #include "src/settings/ArgumentBuilder.h" @@ -18,7 +18,7 @@ namespace storm { const std::string ExplorationSettings::precisionOptionName = "precision"; const std::string ExplorationSettings::precisionOptionShortName = "eps"; - ExplorationSettings::ExplorationSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + ExplorationSettings::ExplorationSettings() : ModuleSettings(moduleName) { std::vector types = { "local", "global" }; this->addOption(storm::settings::OptionBuilder(moduleName, precomputationTypeOptionName, true, "Sets the kind of precomputation used. Available are: { local, global }.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the type to use.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(types)).setDefaultValueString("global").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, numberOfExplorationStepsUntilPrecomputationOptionName, true, "Sets the number of exploration steps to perform until a precomputation is triggered.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count", "The number of exploration steps to perform.").setDefaultValueUnsignedInteger(100000).build()).build()); @@ -88,9 +88,9 @@ namespace storm { this->getOption(numberOfExplorationStepsUntilPrecomputationOptionName).getHasOptionBeenSet() || this->getOption(numberOfSampledPathsUntilPrecomputationOptionName).getHasOptionBeenSet() || this->getOption(nextStateHeuristicOptionName).getHasOptionBeenSet(); - STORM_LOG_WARN_COND(storm::settings::generalSettings().getEngine() == storm::settings::modules::GeneralSettings::Engine::Exploration || !optionsSet, "Exploration engine is not selected, so setting options for it has no effect."); + STORM_LOG_WARN_COND(storm::settings::getModule().getEngine() == storm::settings::modules::MarkovChainSettings::Engine::Exploration || !optionsSet, "Exploration engine is not selected, so setting options for it has no effect."); return true; } } // namespace modules } // namespace settings -} // namespace storm \ No newline at end of file +} // namespace storm diff --git a/src/settings/modules/ExplorationSettings.h b/src/settings/modules/ExplorationSettings.h index 8f72785eb..fae91aeb8 100644 --- a/src/settings/modules/ExplorationSettings.h +++ b/src/settings/modules/ExplorationSettings.h @@ -19,11 +19,9 @@ namespace storm { enum class NextStateHeuristic { DifferenceProbabilitySum, Probability, Uniform }; /*! - * Creates a new set of exploration settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of exploration settings. */ - ExplorationSettings(storm::settings::SettingsManager& settingsManager); + ExplorationSettings(); /*! * Retrieves whether local precomputation is to be used. diff --git a/src/settings/modules/GeneralSettings.cpp b/src/settings/modules/GeneralSettings.cpp index a5e878f0b..91620e09e 100644 --- a/src/settings/modules/GeneralSettings.cpp +++ b/src/settings/modules/GeneralSettings.cpp @@ -24,114 +24,35 @@ namespace storm { const std::string GeneralSettings::verboseOptionShortName = "v"; const std::string GeneralSettings::precisionOptionName = "precision"; const std::string GeneralSettings::precisionOptionShortName = "eps"; - const std::string GeneralSettings::exportDotOptionName = "exportdot"; - const std::string GeneralSettings::exportMatOptionName = "exportmat"; const std::string GeneralSettings::configOptionName = "config"; const std::string GeneralSettings::configOptionShortName = "c"; - const std::string GeneralSettings::explicitOptionName = "explicit"; - const std::string GeneralSettings::explicitOptionShortName = "exp"; - const std::string GeneralSettings::symbolicOptionName = "symbolic"; - const std::string GeneralSettings::symbolicOptionShortName = "s"; - const std::string GeneralSettings::explorationOrderOptionName = "explorder"; - const std::string GeneralSettings::explorationOrderOptionShortName = "eo"; const std::string GeneralSettings::propertyOptionName = "prop"; const std::string GeneralSettings::propertyOptionShortName = "prop"; - const std::string GeneralSettings::transitionRewardsOptionName = "transrew"; - const std::string GeneralSettings::stateRewardsOptionName = "staterew"; - const std::string GeneralSettings::choiceLabelingOptionName = "choicelab"; - const std::string GeneralSettings::counterexampleOptionName = "counterexample"; - const std::string GeneralSettings::counterexampleOptionShortName = "cex"; - const std::string GeneralSettings::dontFixDeadlockOptionName = "nofixdl"; - const std::string GeneralSettings::dontFixDeadlockOptionShortName = "ndl"; const std::string GeneralSettings::timeoutOptionName = "timeout"; const std::string GeneralSettings::timeoutOptionShortName = "t"; - const std::string GeneralSettings::eqSolverOptionName = "eqsolver"; - const std::string GeneralSettings::lpSolverOptionName = "lpsolver"; - const std::string GeneralSettings::smtSolverOptionName = "smtsolver"; - const std::string GeneralSettings::constantsOptionName = "constants"; - const std::string GeneralSettings::constantsOptionShortName = "const"; - const std::string GeneralSettings::statisticsOptionName = "statistics"; - const std::string GeneralSettings::statisticsOptionShortName = "stats"; const std::string GeneralSettings::bisimulationOptionName = "bisimulation"; const std::string GeneralSettings::bisimulationOptionShortName = "bisim"; - const std::string GeneralSettings::engineOptionName = "engine"; - const std::string GeneralSettings::engineOptionShortName = "e"; - const std::string GeneralSettings::ddLibraryOptionName = "ddlib"; - const std::string GeneralSettings::cudaOptionName = "cuda"; - const std::string GeneralSettings::prismCompatibilityOptionName = "prismcompat"; - const std::string GeneralSettings::prismCompatibilityOptionShortName = "pc"; - const std::string GeneralSettings::minMaxEquationSolvingTechniqueOptionName = "minMaxEquationSolvingTechnique"; #ifdef STORM_HAVE_CARL const std::string GeneralSettings::parametricOptionName = "parametric"; #endif - GeneralSettings::GeneralSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, helpOptionName, false, "Shows all available options, arguments and descriptions.").setShortName(helpOptionShortName) .addArgument(storm::settings::ArgumentBuilder::createStringArgument("hint", "A regular expression to show help for all matching entities or 'all' for the complete help.").setDefaultValueString("all").build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, prismCompatibilityOptionName, false, "Enables PRISM compatibility. This may be necessary to process some PRISM models.").setShortName(prismCompatibilityOptionShortName).build()); this->addOption(storm::settings::OptionBuilder(moduleName, versionOptionName, false, "Prints the version information.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, verboseOptionName, false, "Enables more verbose output.").setShortName(verboseOptionShortName).build()); this->addOption(storm::settings::OptionBuilder(moduleName, precisionOptionName, false, "The internally used precision.").setShortName(precisionOptionShortName) .addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to use.").setDefaultValueDouble(1e-06).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, exportDotOptionName, "", "If given, the loaded model will be written to the specified file in the dot format.") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file to which the model is to be written.").build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, exportMatOptionName, "", "If given, the loaded model will be written to the specified file in the mat format.") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "the name of the file to which the model is to be writen.").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, configOptionName, false, "If given, this file will be read and parsed for additional configuration settings.").setShortName(configOptionShortName) .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file from which to read the configuration.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, explicitOptionName, false, "Parses the model given in an explicit (sparse) representation.").setShortName(explicitOptionShortName) - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("transition filename", "The name of the file from which to read the transitions.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()) - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("labeling filename", "The name of the file from which to read the state labeling.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, symbolicOptionName, false, "Parses the model given in a symbolic representation.").setShortName(symbolicOptionShortName) - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file from which to read the symbolic model.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); - - std::vector explorationOrders = {"dfs", "bfs"}; - this->addOption(storm::settings::OptionBuilder(moduleName, explorationOrderOptionName, false, "Sets which exploration order to use.").setShortName(explorationOrderOptionShortName) - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the exploration order to choose. Available are: dfs and bfs.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(explorationOrders)).setDefaultValueString("bfs").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, propertyOptionName, false, "Specifies the formulas to be checked on the model.").setShortName(propertyOptionShortName) .addArgument(storm::settings::ArgumentBuilder::createStringArgument("formula or filename", "The formula or the file containing the formulas.").build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, counterexampleOptionName, false, "Generates a counterexample for the given PRCTL formulas if not satisfied by the model") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file to which the counterexample is to be written.").setDefaultValueString("-").setIsOptional(true).build()).setShortName(counterexampleOptionShortName).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, bisimulationOptionName, false, "Sets whether to perform bisimulation minimization.").setShortName(bisimulationOptionShortName).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, transitionRewardsOptionName, false, "If given, the transition rewards are read from this file and added to the explicit model. Note that this requires the model to be given as an explicit model (i.e., via --" + explicitOptionName + ").") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the transition rewards.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, stateRewardsOptionName, false, "If given, the state rewards are read from this file and added to the explicit model. Note that this requires the model to be given as an explicit model (i.e., via --" + explicitOptionName + ").") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the state rewards.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, choiceLabelingOptionName, false, "If given, the choice labels are read from this file and added to the explicit model. Note that this requires the model to be given as an explicit model (i.e., via --" + explicitOptionName + ").") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the choice labels.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, dontFixDeadlockOptionName, false, "If the model contains deadlock states, they need to be fixed by setting this option.").setShortName(dontFixDeadlockOptionShortName).build()); - - std::vector engines = {"sparse", "hybrid", "dd", "expl", "abs"}; - this->addOption(storm::settings::OptionBuilder(moduleName, engineOptionName, false, "Sets which engine is used for model building and model checking.").setShortName(engineOptionShortName) - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the engine to use. Available are {sparse, hybrid, dd, expl, abs}.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(engines)).setDefaultValueString("sparse").build()).build()); - - std::vector linearEquationSolver = {"gmm++", "native"}; - this->addOption(storm::settings::OptionBuilder(moduleName, eqSolverOptionName, false, "Sets which solver is preferred for solving systems of linear equations.") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the solver to prefer. Available are: gmm++ and native.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(linearEquationSolver)).setDefaultValueString("gmm++").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, timeoutOptionName, false, "If given, computation will abort after the timeout has been reached.").setShortName(timeoutOptionShortName) .addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("time", "The number of seconds after which to timeout.").setDefaultValueUnsignedInteger(0).build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, bisimulationOptionName, false, "Sets whether to perform bisimulation minimization.").setShortName(bisimulationOptionShortName).build()); - std::vector ddLibraries = {"cudd", "sylvan"}; - this->addOption(storm::settings::OptionBuilder(moduleName, ddLibraryOptionName, false, "Sets which library is preferred for decision-diagram operations.") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the library to prefer. Available are: cudd and sylvan.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(ddLibraries)).setDefaultValueString("cudd").build()).build()); - - std::vector lpSolvers = {"gurobi", "glpk"}; - this->addOption(storm::settings::OptionBuilder(moduleName, lpSolverOptionName, false, "Sets which LP solver is preferred.") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of an LP solver. Available are: gurobi and glpk.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(lpSolvers)).setDefaultValueString("glpk").build()).build()); - std::vector smtSolvers = {"z3", "mathsat"}; - this->addOption(storm::settings::OptionBuilder(moduleName, smtSolverOptionName, false, "Sets which SMT solver is preferred.") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of an SMT solver. Available are: z3 and mathsat.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(smtSolvers)).setDefaultValueString("z3").build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, constantsOptionName, false, "Specifies the constant replacements to use in symbolic models. Note that Note that this requires the model to be given as an symbolic model (i.e., via --" + symbolicOptionName + ").").setShortName(constantsOptionShortName) - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("values", "A comma separated list of constants and their value, e.g. a=1,b=2,c=3.").setDefaultValueString("").build()).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, statisticsOptionName, false, "Sets whether to display statistics if available.").setShortName(statisticsOptionShortName).build()); - this->addOption(storm::settings::OptionBuilder(moduleName, cudaOptionName, false, "Sets whether to use CUDA to speed up computation time.").build()); - - std::vector minMaxSolvingTechniques = {"policyIteration", "valueIteration"}; - this->addOption(storm::settings::OptionBuilder(moduleName, minMaxEquationSolvingTechniqueOptionName, false, "Sets which min/max linear equation solving technique is preferred.") - .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of a min/max linear equation solving technique. Available are: valueIteration and policyIteration.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(minMaxSolvingTechniques)).setDefaultValueString("valueIteration").build()).build()); - #ifdef STORM_HAVE_CARL this->addOption(storm::settings::OptionBuilder(moduleName, parametricOptionName, false, "Sets whether to use the parametric engine.").build()); #endif @@ -157,14 +78,6 @@ namespace storm { return this->getOption(precisionOptionName).getArgumentByName("value").getValueAsDouble(); } - bool GeneralSettings::isExportDotSet() const { - return this->getOption(exportDotOptionName).getHasOptionBeenSet(); - } - - std::string GeneralSettings::getExportDotFilename() const { - return this->getOption(exportDotOptionName).getArgumentByName("filename").getValueAsString(); - } - bool GeneralSettings::isConfigSet() const { return this->getOption(configOptionName).getHasOptionBeenSet(); } @@ -173,40 +86,6 @@ namespace storm { return this->getOption(configOptionName).getArgumentByName("filename").getValueAsString(); } - bool GeneralSettings::isExplicitSet() const { - return this->getOption(explicitOptionName).getHasOptionBeenSet(); - } - - std::string GeneralSettings::getTransitionFilename() const { - return this->getOption(explicitOptionName).getArgumentByName("transition filename").getValueAsString(); - } - - std::string GeneralSettings::getLabelingFilename() const { - return this->getOption(explicitOptionName).getArgumentByName("labeling filename").getValueAsString(); - } - - bool GeneralSettings::isSymbolicSet() const { - return this->getOption(symbolicOptionName).getHasOptionBeenSet(); - } - - std::string GeneralSettings::getSymbolicModelFilename() const { - return this->getOption(symbolicOptionName).getArgumentByName("filename").getValueAsString(); - } - - bool GeneralSettings::isExplorationOrderSet() const { - return this->getOption(explorationOrderOptionName).getHasOptionBeenSet(); - } - - storm::builder::ExplorationOrder GeneralSettings::getExplorationOrder() const { - std::string explorationOrderAsString = this->getOption(explorationOrderOptionName).getArgumentByName("name").getValueAsString(); - if (explorationOrderAsString == "dfs") { - return storm::builder::ExplorationOrder::Dfs; - } else if (explorationOrderAsString == "bfs") { - return storm::builder::ExplorationOrder::Bfs; - } - STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown exploration order '" << explorationOrderAsString << "'."); - } - bool GeneralSettings::isPropertySet() const { return this->getOption(propertyOptionName).getHasOptionBeenSet(); } @@ -215,50 +94,6 @@ namespace storm { return this->getOption(propertyOptionName).getArgumentByName("formula or filename").getValueAsString(); } - bool GeneralSettings::isTransitionRewardsSet() const { - return this->getOption(transitionRewardsOptionName).getHasOptionBeenSet(); - } - - std::string GeneralSettings::getTransitionRewardsFilename() const { - return this->getOption(transitionRewardsOptionName).getArgumentByName("filename").getValueAsString(); - } - - bool GeneralSettings::isStateRewardsSet() const { - return this->getOption(stateRewardsOptionName).getHasOptionBeenSet(); - } - - std::string GeneralSettings::getStateRewardsFilename() const { - return this->getOption(stateRewardsOptionName).getArgumentByName("filename").getValueAsString(); - } - - bool GeneralSettings::isChoiceLabelingSet() const { - return this->getOption(choiceLabelingOptionName).getHasOptionBeenSet(); - } - - std::string GeneralSettings::getChoiceLabelingFilename() const { - return this->getOption(choiceLabelingOptionName).getArgumentByName("filename").getValueAsString(); - } - - bool GeneralSettings::isCounterexampleSet() const { - return this->getOption(counterexampleOptionName).getHasOptionBeenSet(); - } - - std::string GeneralSettings::getCounterexampleFilename() const { - return this->getOption(counterexampleOptionName).getArgumentByName("filename").getValueAsString(); - } - - bool GeneralSettings::isDontFixDeadlocksSet() const { - return this->getOption(dontFixDeadlockOptionName).getHasOptionBeenSet(); - } - - std::unique_ptr GeneralSettings::overrideDontFixDeadlocksSet(bool stateToSet) { - return this->overrideOption(dontFixDeadlockOptionName, stateToSet); - } - - std::unique_ptr GeneralSettings::overridePrismCompatibilityMode(bool stateToSet) { - return this->overrideOption(prismCompatibilityOptionName, stateToSet); - } - bool GeneralSettings::isTimeoutSet() const { return this->getOption(timeoutOptionName).getHasOptionBeenSet(); } @@ -267,91 +102,10 @@ namespace storm { return this->getOption(timeoutOptionName).getArgumentByName("time").getValueAsUnsignedInteger(); } - storm::solver::EquationSolverType GeneralSettings::getEquationSolver() const { - std::string equationSolverName = this->getOption(eqSolverOptionName).getArgumentByName("name").getValueAsString(); - if (equationSolverName == "gmm++") { - return storm::solver::EquationSolverType::Gmmxx; - } else if (equationSolverName == "native") { - return storm::solver::EquationSolverType::Native; - } - STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown equation solver '" << equationSolverName << "'."); - } - - bool GeneralSettings::isEquationSolverSet() const { - return this->getOption(eqSolverOptionName).getHasOptionBeenSet(); - } - - storm::solver::LpSolverType GeneralSettings::getLpSolver() const { - std::string lpSolverName = this->getOption(lpSolverOptionName).getArgumentByName("name").getValueAsString(); - if (lpSolverName == "gurobi") { - return storm::solver::LpSolverType::Gurobi; - } else if (lpSolverName == "glpk") { - return storm::solver::LpSolverType::Glpk; - } - STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown LP solver '" << lpSolverName << "'."); - } - - storm::solver::SmtSolverType GeneralSettings::getSmtSolver() const { - std::string smtSolverName = this->getOption(smtSolverOptionName).getArgumentByName("name").getValueAsString(); - if (smtSolverName == "z3") { - return storm::solver::SmtSolverType::Z3; - } else if (smtSolverName == "mathsat") { - return storm::solver::SmtSolverType::Mathsat; - } - STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown SMT solver '" << smtSolverName << "'."); - } - - storm::dd::DdType GeneralSettings::getDdLibraryType() const { - std::string ddLibraryAsString = this->getOption(ddLibraryOptionName).getArgumentByName("name").getValueAsString(); - if (ddLibraryAsString == "sylvan") { - return storm::dd::DdType::Sylvan; - } else { - return storm::dd::DdType::CUDD; - } - } - - bool GeneralSettings::isConstantsSet() const { - return this->getOption(constantsOptionName).getHasOptionBeenSet(); - } - - std::string GeneralSettings::getConstantDefinitionString() const { - return this->getOption(constantsOptionName).getArgumentByName("values").getValueAsString(); - } - - bool GeneralSettings::isShowStatisticsSet() const { - return this->getOption(statisticsOptionName).getHasOptionBeenSet(); - } - bool GeneralSettings::isBisimulationSet() const { return this->getOption(bisimulationOptionName).getHasOptionBeenSet(); } - GeneralSettings::Engine GeneralSettings::getEngine() const { - return engine; - } - - void GeneralSettings::setEngine(Engine newEngine) { - this->engine = newEngine; - } - - bool GeneralSettings::isPrismCompatibilityEnabled() const { - return this->getOption(prismCompatibilityOptionName).getHasOptionBeenSet(); - } - - storm::solver::MinMaxTechnique GeneralSettings::getMinMaxEquationSolvingTechnique() const { - std::string minMaxEquationSolvingTechnique = this->getOption(minMaxEquationSolvingTechniqueOptionName).getArgumentByName("name").getValueAsString(); - if (minMaxEquationSolvingTechnique == "valueIteration") { - return storm::solver::MinMaxTechnique::ValueIteration; - } else if (minMaxEquationSolvingTechnique == "policyIteration") { - return storm::solver::MinMaxTechnique::PolicyIteration; - } - STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown min/max equation solving technique '" << minMaxEquationSolvingTechnique << "'."); - } - - bool GeneralSettings::isMinMaxEquationSolvingTechniqueSet() const { - return this->getOption(minMaxEquationSolvingTechniqueOptionName).getHasOptionBeenSet(); - } - #ifdef STORM_HAVE_CARL bool GeneralSettings::isParametricSet() const { return this->getOption(parametricOptionName).getHasOptionBeenSet(); @@ -359,36 +113,12 @@ namespace storm { #endif void GeneralSettings::finalize() { - // Finalize engine. - std::string engineStr = this->getOption(engineOptionName).getArgumentByName("name").getValueAsString(); - if (engineStr == "sparse") { - engine = GeneralSettings::Engine::Sparse; - } else if (engineStr == "hybrid") { - engine = GeneralSettings::Engine::Hybrid; - } else if (engineStr == "dd") { - engine = GeneralSettings::Engine::Dd; - } else if (engineStr == "expl") { - engine = GeneralSettings::Engine::Exploration; - } else if (engineStr == "abs") { - engine = GeneralSettings::Engine::AbstractionRefinement; - } else { - STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown engine '" << engineStr << "'."); - } } bool GeneralSettings::check() const { - // Ensure that the model was given either symbolically or explicitly. - STORM_LOG_THROW(!isSymbolicSet() || !isExplicitSet(), storm::exceptions::InvalidSettingsException, "The model may be either given in an explicit or a symbolic format, but not both."); - - STORM_LOG_THROW(this->getEngine() == Engine::Sparse || !isExplicitSet(), storm::exceptions::InvalidSettingsException, "Cannot use explicit input models with this engine."); - return true; } - - bool GeneralSettings::isCudaSet() const { - return this->getOption(cudaOptionName).getHasOptionBeenSet(); - } } // namespace modules } // namespace settings -} // namespace storm \ No newline at end of file +} // namespace storm diff --git a/src/settings/modules/GeneralSettings.h b/src/settings/modules/GeneralSettings.h index 522d169af..1f7bf3445 100644 --- a/src/settings/modules/GeneralSettings.h +++ b/src/settings/modules/GeneralSettings.h @@ -7,17 +7,6 @@ #include "src/builder/ExplorationOrder.h" namespace storm { - namespace solver { - enum class EquationSolverType; - enum class LpSolverType; - enum class MinMaxTechnique; - enum class SmtSolverType; - } - - namespace dd { - enum class DdType; - } - namespace settings { namespace modules { @@ -26,17 +15,11 @@ namespace storm { */ class GeneralSettings : public ModuleSettings { public: - // An enumeration of all engines. - enum class Engine { - Sparse, Hybrid, Dd, Exploration, AbstractionRefinement - }; /*! - * Creates a new set of general settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of general settings. */ - GeneralSettings(storm::settings::SettingsManager& settingsManager); + GeneralSettings(); /*! * Retrieves whether the help option was set. @@ -74,20 +57,6 @@ namespace storm { */ double getPrecision() const; - /*! - * Retrieves whether the export-to-dot option was set. - * - * @return True if the export-to-dot option was set. - */ - bool isExportDotSet() const; - - /*! - * Retrieves the name in which to write the model in dot format, if the export-to-dot option was set. - * - * @return The name of the file in which to write the exported model. - */ - std::string getExportDotFilename() const; - /*! * Retrieves whether the config option was set. * @@ -102,58 +71,6 @@ namespace storm { */ std::string getConfigFilename() const; - /*! - * Retrieves whether the explicit option was set. - * - * @return True if the explicit option was set. - */ - bool isExplicitSet() const; - - /*! - * Retrieves the name of the file that contains the transitions if the model was given using the explicit - * option. - * - * @return The name of the file that contains the transitions. - */ - std::string getTransitionFilename() const; - - /*! - * Retrieves the name of the file that contains the state labeling if the model was given using the - * explicit option. - * - * @return The name of the file that contains the state labeling. - */ - std::string getLabelingFilename() const; - - /*! - * Retrieves whether the symbolic option was set. - * - * @return True if the symbolic option was set. - */ - bool isSymbolicSet() const; - - /*! - * Retrieves the name of the file that contains the symbolic model specification if the model was given - * using the symbolic option. - * - * @return The name of the file that contains the symbolic model specification. - */ - std::string getSymbolicModelFilename() const; - - /*! - * Retrieves whether the model exploration order was set. - * - * @return True if the model exploration option was set. - */ - bool isExplorationOrderSet() const; - - /*! - * Retrieves the exploration order if it was set. - * - * @return The chosen exploration order. - */ - storm::builder::ExplorationOrder getExplorationOrder() const; - /*! * Retrieves whether the property option was set. * @@ -168,91 +85,6 @@ namespace storm { */ std::string getProperty() const; - /*! - * Retrieves whether the transition reward option was set. - * - * @return True if the transition reward option was set. - */ - bool isTransitionRewardsSet() const; - - /*! - * Retrieves the name of the file that contains the transition rewards if the model was given using the - * explicit option. - * - * @return The name of the file that contains the transition rewards. - */ - std::string getTransitionRewardsFilename() const; - - /*! - * Retrieves whether the state reward option was set. - * - * @return True if the state reward option was set. - */ - bool isStateRewardsSet() const; - - /*! - * Retrieves the name of the file that contains the state rewards if the model was given using the - * explicit option. - * - * @return The name of the file that contains the state rewards. - */ - std::string getStateRewardsFilename() const; - - /*! - * Retrieves whether the choice labeling option was set. - * - * @return True iff the choice labeling option was set. - */ - bool isChoiceLabelingSet() const; - - /*! - * Retrieves the name of the file that contains the choice labeling - * if the model was given using the explicit option. - * - * @return The name of the file that contains the choice labeling. - */ - std::string getChoiceLabelingFilename() const; - - /*! - * Retrieves whether the counterexample option was set. - * - * @return True if the counterexample option was set. - */ - bool isCounterexampleSet() const; - - /*! - * Retrieves the name of the file to which the counterexample is to be written if the counterexample - * option was set. - * - * @return The name of the file to which the counterexample is to be written. - */ - std::string getCounterexampleFilename() const; - - /*! - * Retrieves whether the dont-fix-deadlocks option was set. - * - * @return True if the dont-fix-deadlocks option was set. - */ - bool isDontFixDeadlocksSet() const; - - /*! - * Overrides the option to not fix deadlocks by setting it to the specified value. As soon as the - * returned memento goes out of scope, the original value is restored. - * - * @param stateToSet The value that is to be set for the fix-deadlocks option. - * @return The memento that will eventually restore the original value. - */ - std::unique_ptr overrideDontFixDeadlocksSet(bool stateToSet); - - /*! - * Overrides the option to enable the PRISM compatibility mode by setting it to the specified value. As - * soon as the returned memento goes out of scope, the original value is restored. - * - * @param stateToSet The value that is to be set for the option. - * @return The memento that will eventually restore the original value. - */ - std::unique_ptr overridePrismCompatibilityMode(bool stateToSet); - /*! * Retrieves whether the timeout option was set. * @@ -267,62 +99,6 @@ namespace storm { */ uint_fast64_t getTimeoutInSeconds() const; - /*! - * Retrieves the selected equation solver. - * - * @return The selected convergence criterion. - */ - storm::solver::EquationSolverType getEquationSolver() const; - - /*! - * Retrieves whether a equation solver has been set. - * - * @return True iff an equation solver has been set. - */ - bool isEquationSolverSet() const; - - /*! - * Retrieves the selected LP solver. - * - * @return The selected LP solver. - */ - storm::solver::LpSolverType getLpSolver() const; - - /*! - * Retrieves the selected SMT solver. - * - * @return The selected SMT solver. - */ - storm::solver::SmtSolverType getSmtSolver() const; - - /*! - * Retrieves the selected library for DD-related operations. - * - * @return The selected library. - */ - storm::dd::DdType getDdLibraryType() const; - - /*! - * Retrieves whether the export-to-dot option was set. - * - * @return True if the export-to-dot option was set. - */ - bool isConstantsSet() const; - - /*! - * Retrieves the string that defines the constants of a symbolic model (given via the symbolic option). - * - * @return The string that defines the constants of a symbolic model. - */ - std::string getConstantDefinitionString() const; - - /*! - * Retrieves whether statistics are to be shown for counterexample generation. - * - * @return True iff statistics are to be shown for counterexample generation. - */ - bool isShowStatisticsSet() const; - /*! * Retrieves whether the option to perform bisimulation minimization is set. * @@ -330,32 +106,6 @@ namespace storm { */ bool isBisimulationSet() const; - /*! - * Retrieves whether the option to use CUDA is set. - * - * @return True iff the option was set. - */ - bool isCudaSet() const; - - /*! - * Retrieves the selected engine. - * - * @return The selected engine. - */ - Engine getEngine() const; - - /*! - * Sets the engine for further usage. - */ - void setEngine(Engine); - - /*! - * Retrieves whether the PRISM compatibility mode was enabled. - * - * @return True iff the PRISM compatibility mode was enabled. - */ - bool isPrismCompatibilityEnabled() const; - #ifdef STORM_HAVE_CARL /*! * Retrieves whether the option enabling parametric model checking is set. @@ -364,21 +114,7 @@ namespace storm { */ bool isParametricSet() const; #endif - /*! - * Retrieves whether a min/max equation solving technique has been set. - * - * @return True iff an equation solving technique has been set. - */ - bool isMinMaxEquationSolvingTechniqueSet() const; - - /*! - * Retrieves the selected min/max equation solving technique. - * - * @return The selected min/max equation solving technique. - */ - storm::solver::MinMaxTechnique getMinMaxEquationSolvingTechnique() const; - - + bool check() const override; void finalize() override; @@ -386,8 +122,6 @@ namespace storm { static const std::string moduleName; private: - Engine engine; - // Define the string names of the options as constants. static const std::string helpOptionName; static const std::string helpOptionShortName; @@ -396,43 +130,14 @@ namespace storm { static const std::string verboseOptionShortName; static const std::string precisionOptionName; static const std::string precisionOptionShortName; - static const std::string exportDotOptionName; - static const std::string exportMatOptionName; static const std::string configOptionName; static const std::string configOptionShortName; - static const std::string explicitOptionName; - static const std::string explicitOptionShortName; - static const std::string symbolicOptionName; - static const std::string symbolicOptionShortName; - static const std::string explorationOrderOptionName; - static const std::string explorationOrderOptionShortName; static const std::string propertyOptionName; static const std::string propertyOptionShortName; - static const std::string transitionRewardsOptionName; - static const std::string stateRewardsOptionName; - static const std::string choiceLabelingOptionName; - static const std::string counterexampleOptionName; - static const std::string counterexampleOptionShortName; - static const std::string dontFixDeadlockOptionName; - static const std::string dontFixDeadlockOptionShortName; static const std::string timeoutOptionName; static const std::string timeoutOptionShortName; - static const std::string eqSolverOptionName; - static const std::string lpSolverOptionName; - static const std::string smtSolverOptionName; - static const std::string constantsOptionName; - static const std::string constantsOptionShortName; - static const std::string statisticsOptionName; - static const std::string statisticsOptionShortName; static const std::string bisimulationOptionName; static const std::string bisimulationOptionShortName; - static const std::string engineOptionName; - static const std::string engineOptionShortName; - static const std::string ddLibraryOptionName; - static const std::string cudaOptionName; - static const std::string prismCompatibilityOptionName; - static const std::string prismCompatibilityOptionShortName; - static const std::string minMaxEquationSolvingTechniqueOptionName; #ifdef STORM_HAVE_CARL static const std::string parametricOptionName; diff --git a/src/settings/modules/GlpkSettings.cpp b/src/settings/modules/GlpkSettings.cpp index a459ddbb8..188c196eb 100644 --- a/src/settings/modules/GlpkSettings.cpp +++ b/src/settings/modules/GlpkSettings.cpp @@ -5,7 +5,7 @@ #include "src/settings/Argument.h" #include "src/settings/SettingsManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/solver/SolverSelectionOptions.h" namespace storm { @@ -16,7 +16,7 @@ namespace storm { const std::string GlpkSettings::integerToleranceOption = "inttol"; const std::string GlpkSettings::outputOptionName = "output"; - GlpkSettings::GlpkSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + GlpkSettings::GlpkSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, outputOptionName, true, "If set, the glpk output will be printed to the command line.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, integerToleranceOption, true, "Sets glpk's precision for integer variables.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to achieve.").setDefaultValueDouble(1e-06).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); } @@ -35,7 +35,7 @@ namespace storm { bool GlpkSettings::check() const { if (isOutputSet() || isIntegerToleranceSet()) { - STORM_LOG_WARN_COND(storm::settings::generalSettings().getLpSolver() == storm::solver::LpSolverType::Glpk, "glpk is not selected as the preferred LP solver, so setting options for glpk might have no effect."); + STORM_LOG_WARN_COND(storm::settings::getModule().getLpSolver() == storm::solver::LpSolverType::Glpk, "glpk is not selected as the preferred LP solver, so setting options for glpk might have no effect."); } return true; @@ -43,4 +43,4 @@ namespace storm { } // namespace modules } // namespace settings -} // namespace storm \ No newline at end of file +} // namespace storm diff --git a/src/settings/modules/GlpkSettings.h b/src/settings/modules/GlpkSettings.h index b58e91746..2f33009fa 100644 --- a/src/settings/modules/GlpkSettings.h +++ b/src/settings/modules/GlpkSettings.h @@ -13,11 +13,9 @@ namespace storm { class GlpkSettings : public ModuleSettings { public: /*! - * Creates a new set of glpk settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of glpk settings. */ - GlpkSettings(storm::settings::SettingsManager& settingsManager); + GlpkSettings(); /*! * Retrieves whether the output option was set. diff --git a/src/settings/modules/GmmxxEquationSolverSettings.cpp b/src/settings/modules/GmmxxEquationSolverSettings.cpp index fb7cbe307..cc81fb6f5 100644 --- a/src/settings/modules/GmmxxEquationSolverSettings.cpp +++ b/src/settings/modules/GmmxxEquationSolverSettings.cpp @@ -6,7 +6,7 @@ #include "src/settings/Argument.h" #include "src/settings/SettingsManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/solver/SolverSelectionOptions.h" namespace storm { @@ -22,7 +22,7 @@ namespace storm { const std::string GmmxxEquationSolverSettings::precisionOptionName = "precision"; const std::string GmmxxEquationSolverSettings::absoluteOptionName = "absolute"; - GmmxxEquationSolverSettings::GmmxxEquationSolverSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + GmmxxEquationSolverSettings::GmmxxEquationSolverSettings() : ModuleSettings(moduleName) { std::vector methods = {"bicgstab", "qmr", "gmres", "jacobi"}; this->addOption(storm::settings::OptionBuilder(moduleName, techniqueOptionName, true, "The method to be used for solving linear equation systems with the gmm++ engine. Available are {bicgstab, qmr, gmres, jacobi}.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the method to use.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(methods)).setDefaultValueString("gmres").build()).build()); @@ -109,11 +109,11 @@ namespace storm { // This list does not include the precision, because this option is shared with other modules. bool optionsSet = isLinearEquationSystemMethodSet() || isPreconditioningMethodSet() || isRestartIterationCountSet() | isMaximalIterationCountSet() || isConvergenceCriterionSet(); - STORM_LOG_WARN_COND(storm::settings::generalSettings().getEquationSolver() == storm::solver::EquationSolverType::Gmmxx || !optionsSet, "gmm++ is not selected as the preferred equation solver, so setting options for gmm++ might have no effect."); + STORM_LOG_WARN_COND(storm::settings::getModule().getEquationSolver() == storm::solver::EquationSolverType::Gmmxx || !optionsSet, "gmm++ is not selected as the preferred equation solver, so setting options for gmm++ might have no effect."); return true; } } // namespace modules } // namespace settings -} // namespace storm \ No newline at end of file +} // namespace storm diff --git a/src/settings/modules/GmmxxEquationSolverSettings.h b/src/settings/modules/GmmxxEquationSolverSettings.h index 8cb0761a8..71c7fcee1 100644 --- a/src/settings/modules/GmmxxEquationSolverSettings.h +++ b/src/settings/modules/GmmxxEquationSolverSettings.h @@ -22,11 +22,9 @@ namespace storm { enum class ConvergenceCriterion { Absolute, Relative }; /*! - * Creates a new set of gmm++ settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of gmm++ settings. */ - GmmxxEquationSolverSettings(storm::settings::SettingsManager& settingsManager); + GmmxxEquationSolverSettings(); /*! * Retrieves whether the linear equation system method has been set. diff --git a/src/settings/modules/GurobiSettings.cpp b/src/settings/modules/GurobiSettings.cpp index 837c631de..412578fe0 100644 --- a/src/settings/modules/GurobiSettings.cpp +++ b/src/settings/modules/GurobiSettings.cpp @@ -5,7 +5,7 @@ #include "src/settings/ArgumentBuilder.h" #include "src/settings/Argument.h" #include "src/settings/SettingsManager.h" -#include "src/settings/modules/GeneralSettings.h" +#include "src/settings/modules/MarkovChainSettings.h" #include "src/solver/SolverSelectionOptions.h" namespace storm { namespace settings { @@ -16,7 +16,7 @@ namespace storm { const std::string GurobiSettings::threadsOption = "threads"; const std::string GurobiSettings::outputOption = "output"; - GurobiSettings::GurobiSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + GurobiSettings::GurobiSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, threadsOption, true, "The number of threads that may be used by Gurobi.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count", "The number of threads.").setDefaultValueUnsignedInteger(1).build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, outputOption, true, "If set, the Gurobi output will be printed to the command line.").build()); @@ -46,7 +46,7 @@ namespace storm { bool GurobiSettings::check() const { if (isOutputSet() || isIntegerToleranceSet() || isNumberOfThreadsSet()) { - STORM_LOG_WARN_COND(storm::settings::generalSettings().getLpSolver() == storm::solver::LpSolverType::Gurobi, "Gurobi is not selected as the preferred LP solver, so setting options for Gurobi might have no effect."); + STORM_LOG_WARN_COND(storm::settings::getModule().getLpSolver() == storm::solver::LpSolverType::Gurobi, "Gurobi is not selected as the preferred LP solver, so setting options for Gurobi might have no effect."); } return true; @@ -54,4 +54,4 @@ namespace storm { } // namespace modules } // namespace settings -} // namespace storm \ No newline at end of file +} // namespace storm diff --git a/src/settings/modules/GurobiSettings.h b/src/settings/modules/GurobiSettings.h index ce7fcd78f..ccad8cbc0 100644 --- a/src/settings/modules/GurobiSettings.h +++ b/src/settings/modules/GurobiSettings.h @@ -13,11 +13,9 @@ namespace storm { class GurobiSettings : public ModuleSettings { public: /*! - * Creates a new set of Gurobi settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of Gurobi settings. */ - GurobiSettings(storm::settings::SettingsManager& settingsManager); + GurobiSettings(); /*! * Retrieves whether the integer tolerance has been set. diff --git a/src/settings/modules/IOSettings.cpp b/src/settings/modules/IOSettings.cpp new file mode 100644 index 000000000..80f9b3439 --- /dev/null +++ b/src/settings/modules/IOSettings.cpp @@ -0,0 +1,151 @@ +#include "src/settings/modules/IOSettings.h" + +#include "src/settings/SettingsManager.h" +#include "src/settings/SettingMemento.h" +#include "src/settings/Option.h" +#include "src/settings/OptionBuilder.h" +#include "src/settings/ArgumentBuilder.h" +#include "src/settings/Argument.h" +#include "src/exceptions/InvalidSettingsException.h" + +namespace storm { + namespace settings { + namespace modules { + + const std::string IOSettings::moduleName = "io"; + const std::string IOSettings::exportDotOptionName = "exportdot"; + const std::string IOSettings::exportMatOptionName = "exportmat"; + const std::string IOSettings::explicitOptionName = "explicit"; + const std::string IOSettings::explicitOptionShortName = "exp"; + const std::string IOSettings::symbolicOptionName = "symbolic"; + const std::string IOSettings::symbolicOptionShortName = "s"; + const std::string IOSettings::explorationOrderOptionName = "explorder"; + const std::string IOSettings::explorationOrderOptionShortName = "eo"; + const std::string IOSettings::transitionRewardsOptionName = "transrew"; + const std::string IOSettings::stateRewardsOptionName = "staterew"; + const std::string IOSettings::choiceLabelingOptionName = "choicelab"; + const std::string IOSettings::constantsOptionName = "constants"; + const std::string IOSettings::constantsOptionShortName = "const"; + const std::string IOSettings::prismCompatibilityOptionName = "prismcompat"; + const std::string IOSettings::prismCompatibilityOptionShortName = "pc"; + + IOSettings::IOSettings() : ModuleSettings(moduleName) { + this->addOption(storm::settings::OptionBuilder(moduleName, prismCompatibilityOptionName, false, "Enables PRISM compatibility. This may be necessary to process some PRISM models.").setShortName(prismCompatibilityOptionShortName).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, exportDotOptionName, "", "If given, the loaded model will be written to the specified file in the dot format.") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file to which the model is to be written.").build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, exportMatOptionName, "", "If given, the loaded model will be written to the specified file in the mat format.") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "the name of the file to which the model is to be writen.").build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, explicitOptionName, false, "Parses the model given in an explicit (sparse) representation.").setShortName(explicitOptionShortName) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("transition filename", "The name of the file from which to read the transitions.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("labeling filename", "The name of the file from which to read the state labeling.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, symbolicOptionName, false, "Parses the model given in a symbolic representation.").setShortName(symbolicOptionShortName) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file from which to read the symbolic model.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); + + std::vector explorationOrders = {"dfs", "bfs"}; + this->addOption(storm::settings::OptionBuilder(moduleName, explorationOrderOptionName, false, "Sets which exploration order to use.").setShortName(explorationOrderOptionShortName) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the exploration order to choose. Available are: dfs and bfs.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(explorationOrders)).setDefaultValueString("bfs").build()).build()); + + this->addOption(storm::settings::OptionBuilder(moduleName, transitionRewardsOptionName, false, "If given, the transition rewards are read from this file and added to the explicit model. Note that this requires the model to be given as an explicit model (i.e., via --" + explicitOptionName + ").") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the transition rewards.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, stateRewardsOptionName, false, "If given, the state rewards are read from this file and added to the explicit model. Note that this requires the model to be given as an explicit model (i.e., via --" + explicitOptionName + ").") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the state rewards.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, choiceLabelingOptionName, false, "If given, the choice labels are read from this file and added to the explicit model. Note that this requires the model to be given as an explicit model (i.e., via --" + explicitOptionName + ").") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the choice labels.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, constantsOptionName, false, "Specifies the constant replacements to use in symbolic models. Note that Note that this requires the model to be given as an symbolic model (i.e., via --" + symbolicOptionName + ").").setShortName(constantsOptionShortName) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("values", "A comma separated list of constants and their value, e.g. a=1,b=2,c=3.").setDefaultValueString("").build()).build()); + } + + bool IOSettings::isExportDotSet() const { + return this->getOption(exportDotOptionName).getHasOptionBeenSet(); + } + + std::string IOSettings::getExportDotFilename() const { + return this->getOption(exportDotOptionName).getArgumentByName("filename").getValueAsString(); + } + + bool IOSettings::isExplicitSet() const { + return this->getOption(explicitOptionName).getHasOptionBeenSet(); + } + + std::string IOSettings::getTransitionFilename() const { + return this->getOption(explicitOptionName).getArgumentByName("transition filename").getValueAsString(); + } + + std::string IOSettings::getLabelingFilename() const { + return this->getOption(explicitOptionName).getArgumentByName("labeling filename").getValueAsString(); + } + + bool IOSettings::isSymbolicSet() const { + return this->getOption(symbolicOptionName).getHasOptionBeenSet(); + } + + std::string IOSettings::getSymbolicModelFilename() const { + return this->getOption(symbolicOptionName).getArgumentByName("filename").getValueAsString(); + } + + bool IOSettings::isExplorationOrderSet() const { + return this->getOption(explorationOrderOptionName).getHasOptionBeenSet(); + } + + storm::builder::ExplorationOrder IOSettings::getExplorationOrder() const { + std::string explorationOrderAsString = this->getOption(explorationOrderOptionName).getArgumentByName("name").getValueAsString(); + if (explorationOrderAsString == "dfs") { + return storm::builder::ExplorationOrder::Dfs; + } else if (explorationOrderAsString == "bfs") { + return storm::builder::ExplorationOrder::Bfs; + } + STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown exploration order '" << explorationOrderAsString << "'."); + } + + bool IOSettings::isTransitionRewardsSet() const { + return this->getOption(transitionRewardsOptionName).getHasOptionBeenSet(); + } + + std::string IOSettings::getTransitionRewardsFilename() const { + return this->getOption(transitionRewardsOptionName).getArgumentByName("filename").getValueAsString(); + } + + bool IOSettings::isStateRewardsSet() const { + return this->getOption(stateRewardsOptionName).getHasOptionBeenSet(); + } + + std::string IOSettings::getStateRewardsFilename() const { + return this->getOption(stateRewardsOptionName).getArgumentByName("filename").getValueAsString(); + } + + bool IOSettings::isChoiceLabelingSet() const { + return this->getOption(choiceLabelingOptionName).getHasOptionBeenSet(); + } + + std::string IOSettings::getChoiceLabelingFilename() const { + return this->getOption(choiceLabelingOptionName).getArgumentByName("filename").getValueAsString(); + } + + std::unique_ptr IOSettings::overridePrismCompatibilityMode(bool stateToSet) { + return this->overrideOption(prismCompatibilityOptionName, stateToSet); + } + + bool IOSettings::isConstantsSet() const { + return this->getOption(constantsOptionName).getHasOptionBeenSet(); + } + + std::string IOSettings::getConstantDefinitionString() const { + return this->getOption(constantsOptionName).getArgumentByName("values").getValueAsString(); + } + + bool IOSettings::isPrismCompatibilityEnabled() const { + return this->getOption(prismCompatibilityOptionName).getHasOptionBeenSet(); + } + + void IOSettings::finalize() { + } + + bool IOSettings::check() const { + // Ensure that the model was given either symbolically or explicitly. + STORM_LOG_THROW(!isSymbolicSet() || !isExplicitSet(), storm::exceptions::InvalidSettingsException, "The model may be either given in an explicit or a symbolic format, but not both."); + return true; + } + + } // namespace modules + } // namespace settings +} // namespace storm diff --git a/src/settings/modules/IOSettings.h b/src/settings/modules/IOSettings.h new file mode 100644 index 000000000..eb1ced407 --- /dev/null +++ b/src/settings/modules/IOSettings.h @@ -0,0 +1,194 @@ +#ifndef STORM_SETTINGS_MODULES_IOSETTINGS_H_ +#define STORM_SETTINGS_MODULES_IOSETTINGS_H_ + +#include "storm-config.h" +#include "src/settings/modules/ModuleSettings.h" + +#include "src/builder/ExplorationOrder.h" + +namespace storm { + namespace settings { + namespace modules { + + /*! + * This class represents the markov chain settings. + */ + class IOSettings : public ModuleSettings { + public: + + /*! + * Creates a new set of IO settings. + */ + IOSettings(); + + /*! + * Retrieves whether the export-to-dot option was set. + * + * @return True if the export-to-dot option was set. + */ + bool isExportDotSet() const; + + /*! + * Retrieves the name in which to write the model in dot format, if the export-to-dot option was set. + * + * @return The name of the file in which to write the exported model. + */ + std::string getExportDotFilename() const; + + /*! + * Retrieves whether the explicit option was set. + * + * @return True if the explicit option was set. + */ + bool isExplicitSet() const; + + /*! + * Retrieves the name of the file that contains the transitions if the model was given using the explicit + * option. + * + * @return The name of the file that contains the transitions. + */ + std::string getTransitionFilename() const; + + /*! + * Retrieves the name of the file that contains the state labeling if the model was given using the + * explicit option. + * + * @return The name of the file that contains the state labeling. + */ + std::string getLabelingFilename() const; + + /*! + * Retrieves whether the symbolic option was set. + * + * @return True if the symbolic option was set. + */ + bool isSymbolicSet() const; + + /*! + * Retrieves the name of the file that contains the symbolic model specification if the model was given + * using the symbolic option. + * + * @return The name of the file that contains the symbolic model specification. + */ + std::string getSymbolicModelFilename() const; + + /*! + * Retrieves whether the model exploration order was set. + * + * @return True if the model exploration option was set. + */ + bool isExplorationOrderSet() const; + + /*! + * Retrieves the exploration order if it was set. + * + * @return The chosen exploration order. + */ + storm::builder::ExplorationOrder getExplorationOrder() const; + + /*! + * Retrieves whether the transition reward option was set. + * + * @return True if the transition reward option was set. + */ + bool isTransitionRewardsSet() const; + + /*! + * Retrieves the name of the file that contains the transition rewards if the model was given using the + * explicit option. + * + * @return The name of the file that contains the transition rewards. + */ + std::string getTransitionRewardsFilename() const; + + /*! + * Retrieves whether the state reward option was set. + * + * @return True if the state reward option was set. + */ + bool isStateRewardsSet() const; + + /*! + * Retrieves the name of the file that contains the state rewards if the model was given using the + * explicit option. + * + * @return The name of the file that contains the state rewards. + */ + std::string getStateRewardsFilename() const; + + /*! + * Retrieves whether the choice labeling option was set. + * + * @return True iff the choice labeling option was set. + */ + bool isChoiceLabelingSet() const; + + /*! + * Retrieves the name of the file that contains the choice labeling + * if the model was given using the explicit option. + * + * @return The name of the file that contains the choice labeling. + */ + std::string getChoiceLabelingFilename() const; + + /*! + * Overrides the option to enable the PRISM compatibility mode by setting it to the specified value. As + * soon as the returned memento goes out of scope, the original value is restored. + * + * @param stateToSet The value that is to be set for the option. + * @return The memento that will eventually restore the original value. + */ + std::unique_ptr overridePrismCompatibilityMode(bool stateToSet); + + /*! + * Retrieves whether the export-to-dot option was set. + * + * @return True if the export-to-dot option was set. + */ + bool isConstantsSet() const; + + /*! + * Retrieves the string that defines the constants of a symbolic model (given via the symbolic option). + * + * @return The string that defines the constants of a symbolic model. + */ + std::string getConstantDefinitionString() const; + + /*! + * Retrieves whether the PRISM compatibility mode was enabled. + * + * @return True iff the PRISM compatibility mode was enabled. + */ + bool isPrismCompatibilityEnabled() const; + + bool check() const override; + void finalize() override; + + // The name of the module. + static const std::string moduleName; + + private: + // Define the string names of the options as constants. + static const std::string exportDotOptionName; + static const std::string exportMatOptionName; + static const std::string explicitOptionName; + static const std::string explicitOptionShortName; + static const std::string symbolicOptionName; + static const std::string symbolicOptionShortName; + static const std::string explorationOrderOptionName; + static const std::string explorationOrderOptionShortName; + static const std::string transitionRewardsOptionName; + static const std::string stateRewardsOptionName; + static const std::string choiceLabelingOptionName; + static const std::string constantsOptionName; + static const std::string constantsOptionShortName; + static const std::string prismCompatibilityOptionName; + static const std::string prismCompatibilityOptionShortName; + }; + + } // namespace modules + } // namespace settings +} // namespace storm + +#endif /* STORM_SETTINGS_MODULES_IOSETTINGS_H_ */ diff --git a/src/settings/modules/MarkovChainSettings.cpp b/src/settings/modules/MarkovChainSettings.cpp new file mode 100644 index 000000000..d436463a4 --- /dev/null +++ b/src/settings/modules/MarkovChainSettings.cpp @@ -0,0 +1,179 @@ +#include "src/settings/modules/MarkovChainSettings.h" + +#include "src/settings/SettingsManager.h" +#include "src/settings/SettingMemento.h" +#include "src/settings/Option.h" +#include "src/settings/OptionBuilder.h" +#include "src/settings/ArgumentBuilder.h" +#include "src/settings/Argument.h" +#include "src/solver/SolverSelectionOptions.h" + +#include "src/storage/dd/DdType.h" + +#include "src/exceptions/InvalidSettingsException.h" + +namespace storm { + namespace settings { + namespace modules { + + const std::string MarkovChainSettings::moduleName = "markovchain"; + const std::string MarkovChainSettings::counterexampleOptionName = "counterexample"; + const std::string MarkovChainSettings::counterexampleOptionShortName = "cex"; + const std::string MarkovChainSettings::dontFixDeadlockOptionName = "nofixdl"; + const std::string MarkovChainSettings::dontFixDeadlockOptionShortName = "ndl"; + const std::string MarkovChainSettings::eqSolverOptionName = "eqsolver"; + const std::string MarkovChainSettings::lpSolverOptionName = "lpsolver"; + const std::string MarkovChainSettings::smtSolverOptionName = "smtsolver"; + const std::string MarkovChainSettings::statisticsOptionName = "statistics"; + const std::string MarkovChainSettings::statisticsOptionShortName = "stats"; + const std::string MarkovChainSettings::engineOptionName = "engine"; + const std::string MarkovChainSettings::engineOptionShortName = "e"; + const std::string MarkovChainSettings::ddLibraryOptionName = "ddlib"; + const std::string MarkovChainSettings::cudaOptionName = "cuda"; + const std::string MarkovChainSettings::minMaxEquationSolvingTechniqueOptionName = "minMaxEquationSolvingTechnique"; + + MarkovChainSettings::MarkovChainSettings() : ModuleSettings(moduleName) { + this->addOption(storm::settings::OptionBuilder(moduleName, counterexampleOptionName, false, "Generates a counterexample for the given PRCTL formulas if not satisfied by the model") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file to which the counterexample is to be written.").setDefaultValueString("-").setIsOptional(true).build()).setShortName(counterexampleOptionShortName).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, dontFixDeadlockOptionName, false, "If the model contains deadlock states, they need to be fixed by setting this option.").setShortName(dontFixDeadlockOptionShortName).build()); + + std::vector engines = {"sparse", "hybrid", "dd", "expl", "abs"}; + this->addOption(storm::settings::OptionBuilder(moduleName, engineOptionName, false, "Sets which engine is used for model building and model checking.").setShortName(engineOptionShortName) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the engine to use. Available are {sparse, hybrid, dd, expl, abs}.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(engines)).setDefaultValueString("sparse").build()).build()); + + std::vector linearEquationSolver = {"gmm++", "native"}; + this->addOption(storm::settings::OptionBuilder(moduleName, eqSolverOptionName, false, "Sets which solver is preferred for solving systems of linear equations.") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the solver to prefer. Available are: gmm++ and native.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(linearEquationSolver)).setDefaultValueString("gmm++").build()).build()); + + std::vector ddLibraries = {"cudd", "sylvan"}; + this->addOption(storm::settings::OptionBuilder(moduleName, ddLibraryOptionName, false, "Sets which library is preferred for decision-diagram operations.") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the library to prefer. Available are: cudd and sylvan.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(ddLibraries)).setDefaultValueString("cudd").build()).build()); + + std::vector lpSolvers = {"gurobi", "glpk"}; + this->addOption(storm::settings::OptionBuilder(moduleName, lpSolverOptionName, false, "Sets which LP solver is preferred.") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of an LP solver. Available are: gurobi and glpk.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(lpSolvers)).setDefaultValueString("glpk").build()).build()); + std::vector smtSolvers = {"z3", "mathsat"}; + this->addOption(storm::settings::OptionBuilder(moduleName, smtSolverOptionName, false, "Sets which SMT solver is preferred.") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of an SMT solver. Available are: z3 and mathsat.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(smtSolvers)).setDefaultValueString("z3").build()).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, statisticsOptionName, false, "Sets whether to display statistics if available.").setShortName(statisticsOptionShortName).build()); + this->addOption(storm::settings::OptionBuilder(moduleName, cudaOptionName, false, "Sets whether to use CUDA to speed up computation time.").build()); + + std::vector minMaxSolvingTechniques = {"policyIteration", "valueIteration"}; + this->addOption(storm::settings::OptionBuilder(moduleName, minMaxEquationSolvingTechniqueOptionName, false, "Sets which min/max linear equation solving technique is preferred.") + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of a min/max linear equation solving technique. Available are: valueIteration and policyIteration.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(minMaxSolvingTechniques)).setDefaultValueString("valueIteration").build()).build()); + } + + bool MarkovChainSettings::isCounterexampleSet() const { + return this->getOption(counterexampleOptionName).getHasOptionBeenSet(); + } + + std::string MarkovChainSettings::getCounterexampleFilename() const { + return this->getOption(counterexampleOptionName).getArgumentByName("filename").getValueAsString(); + } + + bool MarkovChainSettings::isDontFixDeadlocksSet() const { + return this->getOption(dontFixDeadlockOptionName).getHasOptionBeenSet(); + } + + std::unique_ptr MarkovChainSettings::overrideDontFixDeadlocksSet(bool stateToSet) { + return this->overrideOption(dontFixDeadlockOptionName, stateToSet); + } + + storm::solver::EquationSolverType MarkovChainSettings::getEquationSolver() const { + std::string equationSolverName = this->getOption(eqSolverOptionName).getArgumentByName("name").getValueAsString(); + if (equationSolverName == "gmm++") { + return storm::solver::EquationSolverType::Gmmxx; + } else if (equationSolverName == "native") { + return storm::solver::EquationSolverType::Native; + } + STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown equation solver '" << equationSolverName << "'."); + } + + bool MarkovChainSettings::isEquationSolverSet() const { + return this->getOption(eqSolverOptionName).getHasOptionBeenSet(); + } + + storm::solver::LpSolverType MarkovChainSettings::getLpSolver() const { + std::string lpSolverName = this->getOption(lpSolverOptionName).getArgumentByName("name").getValueAsString(); + if (lpSolverName == "gurobi") { + return storm::solver::LpSolverType::Gurobi; + } else if (lpSolverName == "glpk") { + return storm::solver::LpSolverType::Glpk; + } + STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown LP solver '" << lpSolverName << "'."); + } + + storm::solver::SmtSolverType MarkovChainSettings::getSmtSolver() const { + std::string smtSolverName = this->getOption(smtSolverOptionName).getArgumentByName("name").getValueAsString(); + if (smtSolverName == "z3") { + return storm::solver::SmtSolverType::Z3; + } else if (smtSolverName == "mathsat") { + return storm::solver::SmtSolverType::Mathsat; + } + STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown SMT solver '" << smtSolverName << "'."); + } + + storm::dd::DdType MarkovChainSettings::getDdLibraryType() const { + std::string ddLibraryAsString = this->getOption(ddLibraryOptionName).getArgumentByName("name").getValueAsString(); + if (ddLibraryAsString == "sylvan") { + return storm::dd::DdType::Sylvan; + } else { + return storm::dd::DdType::CUDD; + } + } + + bool MarkovChainSettings::isShowStatisticsSet() const { + return this->getOption(statisticsOptionName).getHasOptionBeenSet(); + } + + bool MarkovChainSettings::isCudaSet() const { + return this->getOption(cudaOptionName).getHasOptionBeenSet(); + } + + MarkovChainSettings::Engine MarkovChainSettings::getEngine() const { + return engine; + } + + void MarkovChainSettings::setEngine(Engine newEngine) { + this->engine = newEngine; + } + + storm::solver::MinMaxTechnique MarkovChainSettings::getMinMaxEquationSolvingTechnique() const { + std::string minMaxEquationSolvingTechnique = this->getOption(minMaxEquationSolvingTechniqueOptionName).getArgumentByName("name").getValueAsString(); + if (minMaxEquationSolvingTechnique == "valueIteration") { + return storm::solver::MinMaxTechnique::ValueIteration; + } else if (minMaxEquationSolvingTechnique == "policyIteration") { + return storm::solver::MinMaxTechnique::PolicyIteration; + } + STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown min/max equation solving technique '" << minMaxEquationSolvingTechnique << "'."); + } + + bool MarkovChainSettings::isMinMaxEquationSolvingTechniqueSet() const { + return this->getOption(minMaxEquationSolvingTechniqueOptionName).getHasOptionBeenSet(); + } + + void MarkovChainSettings::finalize() { + // Finalize engine. + std::string engineStr = this->getOption(engineOptionName).getArgumentByName("name").getValueAsString(); + if (engineStr == "sparse") { + engine = MarkovChainSettings::Engine::Sparse; + } else if (engineStr == "hybrid") { + engine = MarkovChainSettings::Engine::Hybrid; + } else if (engineStr == "dd") { + engine = MarkovChainSettings::Engine::Dd; + } else if (engineStr == "expl") { + engine = MarkovChainSettings::Engine::Exploration; + } else if (engineStr == "abs") { + engine = MarkovChainSettings::Engine::AbstractionRefinement; + } else { + STORM_LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unknown engine '" << engineStr << "'."); + } + } + + bool MarkovChainSettings::check() const { + return true; + } + + } // namespace modules + } // namespace settings +} // namespace storm diff --git a/src/settings/modules/MarkovChainSettings.h b/src/settings/modules/MarkovChainSettings.h new file mode 100644 index 000000000..5f8fe2153 --- /dev/null +++ b/src/settings/modules/MarkovChainSettings.h @@ -0,0 +1,176 @@ +#ifndef STORM_SETTINGS_MODULES_MARKOVCHAINSETTINGS_H_ +#define STORM_SETTINGS_MODULES_MARKOVCHAINSETTINGS_H_ + +#include "storm-config.h" +#include "src/settings/modules/ModuleSettings.h" + +#include "src/builder/ExplorationOrder.h" + +namespace storm { + namespace solver { + enum class EquationSolverType; + enum class LpSolverType; + enum class MinMaxTechnique; + enum class SmtSolverType; + } + + namespace dd { + enum class DdType; + } + + namespace settings { + namespace modules { + + /*! + * This class represents the markov chain settings. + */ + class MarkovChainSettings : public ModuleSettings { + public: + // An enumeration of all engines. + enum class Engine { + Sparse, Hybrid, Dd, Exploration, AbstractionRefinement + }; + + /*! + * Creates a new set of markov chain settings. + */ + MarkovChainSettings(); + + /*! + * Retrieves whether the counterexample option was set. + * + * @return True if the counterexample option was set. + */ + bool isCounterexampleSet() const; + + /*! + * Retrieves the name of the file to which the counterexample is to be written if the counterexample + * option was set. + * + * @return The name of the file to which the counterexample is to be written. + */ + std::string getCounterexampleFilename() const; + + /*! + * Retrieves whether the dont-fix-deadlocks option was set. + * + * @return True if the dont-fix-deadlocks option was set. + */ + bool isDontFixDeadlocksSet() const; + + /*! + * Overrides the option to not fix deadlocks by setting it to the specified value. As soon as the + * returned memento goes out of scope, the original value is restored. + * + * @param stateToSet The value that is to be set for the fix-deadlocks option. + * @return The memento that will eventually restore the original value. + */ + std::unique_ptr overrideDontFixDeadlocksSet(bool stateToSet); + + /*! + * Retrieves the selected equation solver. + * + * @return The selected convergence criterion. + */ + storm::solver::EquationSolverType getEquationSolver() const; + + /*! + * Retrieves whether a equation solver has been set. + * + * @return True iff an equation solver has been set. + */ + bool isEquationSolverSet() const; + + /*! + * Retrieves the selected LP solver. + * + * @return The selected LP solver. + */ + storm::solver::LpSolverType getLpSolver() const; + + /*! + * Retrieves the selected SMT solver. + * + * @return The selected SMT solver. + */ + storm::solver::SmtSolverType getSmtSolver() const; + + /*! + * Retrieves the selected library for DD-related operations. + * + * @return The selected library. + */ + storm::dd::DdType getDdLibraryType() const; + + /*! + * Retrieves whether statistics are to be shown for counterexample generation. + * + * @return True iff statistics are to be shown for counterexample generation. + */ + bool isShowStatisticsSet() const; + + /*! + * Retrieves whether the option to use CUDA is set. + * + * @return True iff the option was set. + */ + bool isCudaSet() const; + + /*! + * Retrieves the selected engine. + * + * @return The selected engine. + */ + Engine getEngine() const; + + /*! + * Sets the engine for further usage. + */ + void setEngine(Engine); + + /*! + * Retrieves whether a min/max equation solving technique has been set. + * + * @return True iff an equation solving technique has been set. + */ + bool isMinMaxEquationSolvingTechniqueSet() const; + + /*! + * Retrieves the selected min/max equation solving technique. + * + * @return The selected min/max equation solving technique. + */ + storm::solver::MinMaxTechnique getMinMaxEquationSolvingTechnique() const; + + + bool check() const override; + void finalize() override; + + // The name of the module. + static const std::string moduleName; + + private: + Engine engine; + + // Define the string names of the options as constants. + static const std::string counterexampleOptionName; + static const std::string counterexampleOptionShortName; + static const std::string dontFixDeadlockOptionName; + static const std::string dontFixDeadlockOptionShortName; + static const std::string eqSolverOptionName; + static const std::string lpSolverOptionName; + static const std::string smtSolverOptionName; + static const std::string statisticsOptionName; + static const std::string statisticsOptionShortName; + static const std::string engineOptionName; + static const std::string engineOptionShortName; + static const std::string ddLibraryOptionName; + static const std::string cudaOptionName; + static const std::string minMaxEquationSolvingTechniqueOptionName; + }; + + } // namespace modules + } // namespace settings +} // namespace storm + +#endif /* STORM_SETTINGS_MODULES_MARKOVCHAINSETTINGS_H_ */ diff --git a/src/settings/modules/ModuleSettings.cpp b/src/settings/modules/ModuleSettings.cpp index f99d50e35..1f7a2b7f3 100644 --- a/src/settings/modules/ModuleSettings.cpp +++ b/src/settings/modules/ModuleSettings.cpp @@ -10,7 +10,7 @@ namespace storm { namespace settings { namespace modules { - ModuleSettings::ModuleSettings(storm::settings::SettingsManager& settingsManager, std::string const& moduleName) : settingsManager(settingsManager), moduleName(moduleName) { + ModuleSettings::ModuleSettings(std::string const& moduleName) : moduleName(moduleName) { // Intentionally left empty. } @@ -19,10 +19,6 @@ namespace storm { } void ModuleSettings::finalize() { } - - storm::settings::SettingsManager const& ModuleSettings::getSettingsManager() const { - return this->settingsManager; - } void ModuleSettings::set(std::string const& name) { return this->getOption(name).setHasOptionBeenSet(); diff --git a/src/settings/modules/ModuleSettings.h b/src/settings/modules/ModuleSettings.h index 027664433..08c92909d 100644 --- a/src/settings/modules/ModuleSettings.h +++ b/src/settings/modules/ModuleSettings.h @@ -27,10 +27,9 @@ namespace storm { /*! * Constructs a new settings object. * - * @param settingsManager The manager responsible for these settings. * @param moduleName The name of the module for which to build the settings. */ - ModuleSettings(storm::settings::SettingsManager& settingsManager, std::string const& moduleName); + ModuleSettings(std::string const& moduleName); /*! * Checks whether the settings are consistent. If they are inconsistent, an exception is thrown. @@ -77,12 +76,6 @@ namespace storm { uint_fast64_t getPrintLengthOfLongestOption() const; protected: - /*! - * Retrieves the manager responsible for the settings. - * - * @return The manager responsible for the settings. - */ - storm::settings::SettingsManager const& getSettingsManager() const; /*! * Retrieves the option with the given long name. If no such option exists, an exception is thrown. @@ -132,8 +125,6 @@ namespace storm { void addOption(std::shared_ptr